iftypeset: document CI pipeline + Playwright + font contract
Some checks are pending
ci / ci (push) Waiting to run

This commit is contained in:
codex 2026-01-08 18:10:41 +00:00
parent 626779d4aa
commit e92f1c3b93
145 changed files with 27926 additions and 535 deletions

6
.dockerignore Normal file
View file

@ -0,0 +1,6 @@
.git
.venv
__pycache__
*.pyc
out
out/checkpoints

View file

@ -14,7 +14,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
python-version: "3.12"
- name: Install deps
run: |

View file

@ -0,0 +1,17 @@
name: docker-ci
on:
workflow_dispatch:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build image
run: docker build -t iftypeset-ci .
- name: Run CI inside container
run: docker run --rm iftypeset-ci bash scripts/ci.sh

56
AGENTS.md Normal file
View file

@ -0,0 +1,56 @@
# AGENTS.md — `iftypeset` working rules
These instructions apply to the entire `iftypeset/` tree.
## Nonnegotiables (copyright + scope)
- Do **not** OCR/transcribe Chicago/Bringhurst into the repo. Rules are **paraphrases only** with **pointer refs** (e.g., `CMOS18 §6.2 p377 (scan p10)`).
- OCR is allowed only **ephemerally** (stdout or temp files deleted) to locate pointers.
- Prefer deterministic, measurable rules. If it cant be automated, mark it as manual via `tags: ["manual_checklist=true"]` and ensure it lands in the checklist output.
## “Dont lose work” operating practice
- Trust the filesystem, not the chat transcript.
- Use `./scripts/audit.sh` to capture current state.
- Use `./scripts/ci.sh` as the fastest sanity check.
- After meaningful changes, create a restore point: `./scripts/checkpoint.sh "short note"`.
- Checkpoints are recorded in `docs/CHECKPOINTS.md`.
## Session ID hygiene (required)
Codex CLI shows a `session_id` via `/status` (look for the `Session:` line). To prevent two terminals from sharing/overwriting one session state:
- Run `/status` at session start and copy the `Session:` value.
- When claiming a task in `docs/13-task-board.md`, include it in `owner` (example: `codex-cli (gpt-5.2) [sid: 019b…]`).
- Also include it in your row in `/root/docs/SESSION_STATE.md` (either in `who` or `notes`).
- If you ever see two live terminals with the same `session_id`, stop one and start a fresh session (new `session_id`).
Fallback (if `/status` is unavailable):
```bash
day_dir=/root/.codex/sessions/$(date -u +%Y/%m/%d)
latest=$(ls -1t "$day_dir"/rollout-*.jsonl | head -n 1)
python3 - <<'PY' "$latest"
import json,sys
print(json.loads(open(sys.argv[1]).readline())["payload"]["id"])
PY
```
If multiple sessions are active, run this immediately after starting your session so “latest” corresponds to your own launch.
## When adding rules
- Follow `spec/schema/rule.schema.json` strictly; run `PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes`.
- Keep `rule_text` short and paraphrased; never paste long passages.
- Prefer adding new batches (e.g., `v1_links_004.ndjson`) over editing old IDs; deprecate instead of mutating IDs.
## When changing code
- Keep dependencies minimal (currently `requirements.txt` is intentionally small).
- Update `app/CLI_SPEC.md` and `STATUS.md` when behavior or counts change.
- Ensure `./scripts/ci.sh` passes before handing off.
## Typography baseline (house default)
- Default body font size is `12pt` for reader-facing PDFs; do not go below `12pt` unless the profile description explicitly justifies it (e.g., slide decks, constrained one-page CVs).
- Prefer fixing density with margins/spacing/layout before shrinking type.

34
Dockerfile Normal file
View file

@ -0,0 +1,34 @@
FROM python:3.12.12-slim-bookworm
ENV PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
fontconfig \
fonts-dejavu-core \
fonts-liberation \
fonts-noto-core \
poppler-utils \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /workspace
COPY requirements.txt ./
RUN python -m pip install --upgrade pip \
&& python -m pip install -r requirements.txt \
&& python -m playwright install --with-deps
COPY pyproject.toml README.md STATUS.md AGENTS.md ./
COPY src ./src
COPY spec ./spec
COPY app ./app
COPY scripts ./scripts
COPY docs ./docs
COPY fixtures ./fixtures
RUN python -m pip install -e .
ENTRYPOINT ["iftypeset"]

View file

@ -15,27 +15,100 @@ It is designed to be embedded into constrained workers (e.g. Forgejo PDF export
- **No bulk OCR/transcription** of Chicago/Bringhurst into this repo (copyright).
- Rule records are **paraphrases only**, backed by **pointers** (e.g. `CMOS18 §X.Y pNNN (scan pMMM)`).
- Chicago OCR (when needed) must be **ephemeral** (extract just enough to locate pointers; do not store page text).
- Optional profile `webtypography_nc` is **CC BY-NC 4.0** (non-commercial only). See `docs/18-webtypography-nc.md`.
## Quickstart (current)
From `ai-workspace/iftypeset/`:
- (Optional) Install deps into a venv: `python3 -m venv .venv && . .venv/bin/activate && python -m pip install -r requirements.txt`
- Validate spec + rebuild indexes: `PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes`
- Lint Markdown: `PYTHONPATH=src python3 -m iftypeset.cli lint --input fixtures/sample.md --out out --profile web_pdf`
- Render HTML + CSS: `PYTHONPATH=src python3 -m iftypeset.cli render-html --input fixtures/sample.md --out out --profile web_pdf`
- Render PDF (if an engine is installed): `PYTHONPATH=src python3 -m iftypeset.cli render-pdf --input fixtures/sample.md --out out --profile web_pdf`
- Run QA gates (HTML fallback if no PDF): `PYTHONPATH=src python3 -m iftypeset.cli qa --out out --profile web_pdf`
- Coverage report: `PYTHONPATH=src python3 -m iftypeset.cli report --spec spec --out out`
- Install the console entrypoint: `python3 -m pip install -e .`
- Validate spec + rebuild indexes: `iftypeset validate-spec --spec spec --build-indexes`
- One-shot CI pipeline (recommended): `iftypeset run --input fixtures/sample.md --out out --profile web_pdf --degraded-ok`
- Multi-doc run (directory or glob): `iftypeset run --input fixtures --out out --profile web_pdf --degraded-ok`
- Lint Markdown (emits `out/lint-report.json` + `out/manual-checklist.md`): `iftypeset lint --input fixtures/sample.md --out out --profile web_pdf`
- Lint with auto-fix + post-fix diagnostics: `iftypeset lint --input fixtures/sample.md --out out --profile web_pdf --fix --fix-mode rewrite --lint-fixed`
- Render HTML + CSS: `iftypeset render-html --input fixtures/sample.md --out out --profile web_pdf`
- Run QA gates (HTML fallback if no PDF): `iftypeset qa --out out --profile web_pdf`
- Render PDF (if an engine is installed): `iftypeset render-pdf --input fixtures/sample.md --out out --profile web_pdf`
- Coverage + trust contract + HTML index: `iftypeset report --spec spec --out out` (writes `out/report/index.html`)
- Environment/determinism report: `iftypeset doctor --spec spec --out out`
- Portable review bundle: `iftypeset bundle --out out` (writes `out/iftypeset-bundle.tar.gz`)
- Run self-check tests: `python3 -m unittest discover -s tests -p 'test_*.py'`
- Inspect profiles/gates/rules:
- `iftypeset profiles list`
- `iftypeset gates show --profile web_pdf`
- `iftypeset rules list --category links`
- `iftypeset rules show HOUSE.LINKS.URLS.PREFER_HTTPS`
If you do not want to install the console entrypoint, you can still run:
- `PYTHONPATH=src python3 -m iftypeset.cli <command> ...`
## Config file (`iftypeset.yaml`)
You can set repo defaults in `./iftypeset.yaml`. CLI flags always win.
Example:
```yaml
defaults:
spec: spec
out: out
profile: web_pdf
lint:
fail_on: must
degraded_ok: true
run:
skip_pdf: false
require_pdf: false
engine: playwright
```
To use a different config path: `iftypeset --config /path/to/iftypeset.yaml <command> ...`
## Enforcement limits (read this)
- **Not all rules are automated.** Manual rules (tagged `manual_checklist=true`) appear in `out/manual-checklist.md`.
- **PDF QA is heuristic.** It depends on text extraction and will miss some layout failures.
- **Renderer variance exists.** Profiles aim for determinism, but output still depends on the PDF engine + fonts.
- **Trust contract is explicit.** Run `iftypeset report` to generate `out/trust-contract.md` with current limits.
## Lint suppression (explicit, auditable)
You can suppress specific rules in a document when needed:
- Inline directive (applies to the next non-empty line):
- `<!-- iftypeset:ignore CMOS.PUNCTUATION.PARENS_BRACKETS.BALANCE -->`
- Front matter allowlist:
- `iftypeset_ignore: [CMOS.PUNCTUATION.PARENS_BRACKETS.BALANCE, LINK.WRAP.RISK]`
Suppression works by rule id or diagnostic code and should be used sparingly.
## Session resilience (avoid “lost work”)
If a chat/session resets, trust the repo, not the transcript:
- Quick resume: `./scripts/resume.sh`
- Audit repo state: `./scripts/audit.sh`
- Run CI sanity checks: `./scripts/ci.sh`
- Create a portable restore point: `./scripts/checkpoint.sh "short note"`
Details: `docs/07-session-resilience.md`
Handoff snapshot: `docs/08-handoff.md`
Project status: `docs/09-project-status.md`
Downloadable summary: `docs/11-project-summary.md`
Rendering pipeline: `docs/17-rendering-pipeline.md`
Non-commercial WebTypography profile: `docs/18-webtypography-nc.md`
Agent notes: `AGENTS.md`
External review pack: `docs/14-external-review.md`
Docker runtime: `docs/15-docker.md`
## PDF renderers
`render-pdf` will use the first available engine in this order:
`render-pdf` defaults to `playwright` and does not fall back silently.
- `playwright` (Python module)
- `chromium` / `chromium-browser` / `google-chrome`
- `wkhtmltopdf`
- `weasyprint` (Python module)
- `playwright` (preferred; supports header/footer templates and avoids Chromium CLI “date/path” headers/footers)
- Optional (explicit `--engine` only): `wkhtmltopdf`, `weasyprint`
If none are installed, the command exits with a clear message but still leaves HTML artifacts for QA.
If no engine is present, the command exits with a clear message but still leaves HTML artifacts for QA.

View file

@ -1,42 +1,68 @@
# iftypeset status (pubstyle)
**Updated:** 2026-01-03
**Updated:** 2026-01-04
**Project root:** `/root/ai-workspace/iftypeset/`
## What exists (working today)
- **Spec + schema:** `spec/schema/rule.schema.json`, `spec/manifest.yaml`
- **Profiles:** `spec/profiles/*.yaml` (`web_pdf`, `print_pdf`, `dense_tech`, `memo`, `slide_deck`)
- **Profiles:** `spec/profiles/*.yaml` (`web_pdf`, `print_pdf`, `dense_tech`, `memo`, `slide_deck`, `webtypography_nc` non-commercial)
- **Post-render QA gates:** `spec/quality_gates.yaml`
- **PDF-aware QA (heuristic):** Poppler text extraction via `pdftotext` + `pdftohtml -xml` with page-aware incidents (`widow_pdf`, `orphan_pdf`, `stranded_heading_pdf`, `overfull_line_pdf`, `overfull_bbox_pdf`)
- **HTML QA (v0):** catches bare URL/DOI/email wrapping, overfull tokens, code/table overflow (profile-aware thresholds)
- **Deterministic lint coverage:** DOI references, ordinal suffix errors, and note-marker placement (alongside existing punctuation/link safety checks)
- **Rule registry (seeded):** `spec/rules/**.ndjson`
- **House pointers (no quotes):** `spec/house/HOUSE_EDITORIAL_POINTERS.md`
- **Indexes (derived):** `spec/indexes/*.json` (rebuildable)
- **CLI:** `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`
- **CLI:** `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`, `doctor`, `bundle`, `run`
- `render-pdf --engine <name>` to force a specific renderer.
- `run --require-pdf` to fail the pipeline if PDF rendering fails.
- **Renderer default:** `playwright` is the default engine for PDF typesetting.
- **CLI introspection:** `profiles list`, `gates show`, `rules list/show`
- **Config defaults:** `iftypeset.yaml` (CLI flags override)
- **Run summary artifact:** `out/run-summary.json` (CI-style pipeline output)
- **Multi-doc run mode:** `iftypeset run --input <dir|glob>` writes per-doc outputs under `out/docs/` and a top-level run index at `out/report/index.html`
- **Ephemeral extraction helpers:** `tools/` (Chicago OCR is grep-only, temp files deleted)
- **Forgejo integration note:** `forgejo/README.md`
- **Fixtures + tests:** `fixtures/` and `tests/`
- **CI script:** `scripts/ci.sh` (validate-spec, report, unit tests)
- **Docker runtime:** `Dockerfile` + `docs/15-docker.md` (Playwright + Poppler + fonts)
- **“Dont lose work” tooling:** `scripts/audit.sh`, `scripts/checkpoint.sh`, `scripts/state.sh`, `scripts/resume.sh` + `docs/07-session-resilience.md`
- **Trust contract artifacts:** `out/trust-contract.md` + `out/trust-contract.json` (generated by `report`)
- **Report index:** `out/report/index.html` (artifact hub from `report`)
- **Doctor report:** `out/doctor.md` + `out/doctor.json` (environment + determinism)
- **Bundle artifact:** `out/iftypeset-bundle.tar.gz` + `out/bundle-manifest.json` (portable review pack)
## Rule corpus snapshot
From `out/coverage-report.json`:
- **Total rules:** 307
- **By category:** citations 61, numbers 62, punctuation 55, layout 46, headings 32, tables 23, typography 15, links 5, accessibility 4, code 4
- **By enforcement:** manual 186, typeset 62, lint 46, postrender 13
- **By severity:** must 28, should 263, warn 16
- **Total rules:** 524
- **By category:** editorial 45, abbreviations 27, accessibility 22, backmatter 18, citations 61, code 28, figures 22, frontmatter 20, headings 32, i18n 27, layout 46, links 21, numbers 62, punctuation 55, tables 23, typography 15
- **By enforcement:** manual 379, typeset 62, lint 70, postrender 13
- **By severity:** must 37, should 470, warn 17
## Current rule batches
- `spec/rules/abbreviations/v1_abbreviations_003.ndjson` (27)
- `spec/rules/accessibility/v1_accessibility_001.ndjson` (4)
- `spec/rules/accessibility/v1_accessibility_003.ndjson` (18)
- `spec/rules/backmatter/v1_backmatter_003.ndjson` (18)
- `spec/rules/citations/v1_citations_001.ndjson` (16)
- `spec/rules/citations/v1_citations_002.ndjson` (45)
- `spec/rules/code/v1_code_001.ndjson` (4)
- `spec/rules/code/v1_code_003.ndjson` (24)
- `spec/rules/editorial/v1_editorial_001.ndjson` (45)
- `spec/rules/figures/v1_figures_003.ndjson` (22)
- `spec/rules/frontmatter/v1_frontmatter_003.ndjson` (20)
- `spec/rules/headings/v1_headings_001.ndjson` (12)
- `spec/rules/headings/v1_headings_002.ndjson` (20)
- `spec/rules/i18n/v1_i18n_003.ndjson` (27)
- `spec/rules/layout/v1_layout_001.ndjson` (12)
- `spec/rules/layout/v1_layout_002.ndjson` (30)
- `spec/rules/layout/v1_layout_003.ndjson` (4)
- `spec/rules/links/v1_links_001.ndjson` (5)
- `spec/rules/links/v1_links_003.ndjson` (16)
- `spec/rules/numbers/v1_numbers_001.ndjson` (12)
- `spec/rules/numbers/v1_numbers_002.ndjson` (50)
- `spec/rules/punctuation/v1_punctuation_001.ndjson` (15)
@ -52,6 +78,9 @@ From `out/coverage-report.json`:
- `PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes`
- Lint:
- `PYTHONPATH=src python3 -m iftypeset.cli lint --input fixtures/sample.md --out out --profile web_pdf`
- Run end-to-end pipeline:
- `PYTHONPATH=src python3 -m iftypeset.cli run --input fixtures/sample.md --out out --profile web_pdf --degraded-ok`
- `PYTHONPATH=src python3 -m iftypeset.cli run --input fixtures/sample.md --out out --profile web_pdf --require-pdf`
- Render HTML + CSS:
- `PYTHONPATH=src python3 -m iftypeset.cli render-html --input fixtures/sample.md --out out --profile web_pdf`
- Render PDF (if renderer installed):
@ -73,6 +102,6 @@ From `out/coverage-report.json`:
## Next work (highest leverage)
- Add new batches for: `figures`, `frontmatter`, `backmatter`, `abbreviations`, `i18n`, and expand `accessibility`.
- Grow post-render QA rule coverage (widows/orphans, heading keeps, overflow) beyond the current seed set.
- Add a real PDF-layout analyzer when a stable renderer is selected (widows/orphans, overflow).
- Extend deterministic lint coverage for citations (author-date patterns, bibliography normalization) and locale/i18n rules where feasible.
- Deepen typeset/CSS profile mapping for tables, figures, and code to reduce manual cleanup before PDF export (and to reduce QA incidents).
- Expand editorial automation beyond manual checklists (safe heuristics like headline ALL-CAPS checks and abbreviation definition hints).

View file

@ -6,14 +6,23 @@ The CLI is designed for CI use: deterministic outputs, stable exit codes, and JS
This is the *target* contract; v0 currently implements a subset per-command.
Precedence (highest → lowest): CLI flags → `iftypeset.yaml` → hard defaults.
* `--spec <dir>`: Spec root directory (default: `spec/`).
* `--input <path>`: Markdown file or directory (where applicable).
* `--out <dir>`: Output directory (default: `out/`).
* `--profile <name>`: One of: `web_pdf`, `print_pdf`, `dense_tech`, `memo`, `slide_deck` (where applicable).
* `--profile <name>`: One of: `web_pdf`, `print_pdf`, `dense_tech`, `memo`, `slide_deck`, `webtypography_nc` (non-commercial).
* `--config <path>`: Path to `iftypeset.yaml` (defaults to `./iftypeset.yaml` when present).
* `--engine <auto|playwright|wkhtmltopdf|weasyprint>`: Preferred PDF engine (default: `playwright`; `auto` is treated as `playwright`; Chromium CLI engine is banned).
* `--font-dir <dir>`: Additional font directory (repeatable) to supply corporate fonts at render time.
* `--strict-fonts`: Enforce a fonts contract for PDF rendering (fail if primary profile fonts are missing or not embedded in the PDF).
* `--strict`: Use strict thresholds in `spec/quality_gates.yaml` (QA/report).
* `--format <json|sarif|text>`: Lint output format.
* `--fail-on <must|should|warn>`: Lowest severity that fails `lint` (default: `must`).
* `--degraded-ok`: Allow degraded mode without failing (lint/render-html).
* `--fix`: Apply safe deterministic fixes (lint/run).
* `--fix-mode <suggest|rewrite>`: Fix mode for `--fix` (lint/run).
* `--lint-fixed`: When rewriting fixes, lint the fixed output instead of the original (lint/run).
* `--version`: Print tool version and exit.
## Command: `validate-spec`
@ -29,8 +38,52 @@ Outputs:
Exit codes:
* `0`: ok
* `4`: config/schema error
* `5`: internal error
* `2`: config/schema error
## Command: `profiles list`
Purpose:
* List available profile ids in the current spec.
Outputs:
* JSON to stdout (`profiles: [...]`)
Exit codes:
* `0`: ok
* `2`: config error
## Command: `gates show`
Purpose:
* Show QA gate thresholds for a profile (`--strict` selects strict mode).
Outputs:
* JSON to stdout (`gates: {...}`)
Exit codes:
* `0`: ok
* `2`: config error
## Command: `rules list` / `rules show`
Purpose:
* List rules with basic filters, or show a full rule record by id.
Outputs:
* JSON to stdout (`rules: [...]` or `rule: {...}`)
Exit codes:
* `0`: ok
* `2`: config error / rule not found
## Command: `report`
@ -42,13 +95,78 @@ Outputs:
* `out/coverage-report.json`
* `out/coverage-summary.md`
* `out/report/index.html`
Exit codes:
* `0`: report built
* `2`: coverage floor violated (only when rule batches exist)
* `4`: config/schema error
* `5`: internal error
* `1`: coverage floor violated (only when rule batches exist)
* `2`: config/schema error
## Command: `doctor`
Purpose:
* Emit environment and determinism diagnostics (renderer, Poppler, fonts, locale).
Outputs:
* `out/doctor.json`
* `out/doctor.md`
Exit codes:
* `0`: ok
* `2`: config error
## Command: `bundle`
Purpose:
* Create a portable tarball of `out/` artifacts with a sha256 manifest for external review.
Outputs:
* `out/bundle-manifest.json`
* `out/iftypeset-bundle.tar.gz` (default; override with `--bundle`)
Exit codes:
* `0`: ok
Notes:
* Files larger than `--max-size-mb` are skipped and recorded in the manifest.
* Bundle entries are sorted and stored with fixed mtimes for deterministic output.
## Command: `run`
Purpose:
* One-shot CI pipeline: validate → lint → render-html → render-pdf (best effort) → qa → report.
Outputs:
* All artifacts from the underlying commands.
* `out/run-summary.json`
* When `--input` is a directory or glob, per-doc artifacts are written under `out/docs/<relpath>/` and
`out/report/index.html` becomes a multi-doc index.
Exit codes:
* `0`: pipeline ok (lint + qa + report passed)
* `1`: gate failed (lint/qa/report/degraded render-html)
* `2`: config error
* `3`: renderer/tool error (only when `--require-pdf` is set)
Notes:
* PDF rendering failures are recorded as warnings in `run-summary.json` and do not fail the run **unless**
`--require-pdf` is set.
* Use `--skip-pdf` to omit PDF rendering entirely when only HTML QA is desired.
* Use `--engine` to force a specific renderer (useful for reproducible CI).
* Use `--font-dir` to mount a corporate fonts directory and avoid fallback fonts.
* Use `--strict-fonts` (or profile `fonts.require_primary: true`) to fail fast if font fallback would occur.
## Command: `lint`
@ -67,11 +185,15 @@ Outputs:
* `out/fix-suggestions.json` (only when `--fix --fix-mode suggest`)
* `out/fixed/*.md` (only when `--fix --fix-mode rewrite`)
Notes:
* `--lint-fixed` re-lints the rewritten output so diagnostics reflect the fixed text.
Exit codes:
* `0`: ok
* `2`: lint failed (fail-on threshold exceeded, or degraded mode without `--degraded-ok`)
* `4`: config error
* `1`: lint failed (fail-on threshold exceeded, or degraded mode without `--degraded-ok`)
* `2`: config error
## Command: `render-html`
@ -89,14 +211,14 @@ Outputs:
Exit codes:
* `0`: ok
* `2`: degraded mode without `--degraded-ok`
* `4`: config error
* `1`: degraded mode without `--degraded-ok`
* `2`: config error
## Command: `render-pdf`
Purpose:
* Render Markdown to PDF using the first available engine (playwright/chromium/wkhtmltopdf/weasyprint).
* Render Markdown to PDF using the configured engine (default: `playwright`; `--engine auto` is treated as `playwright`; Chromium CLI engine is not supported).
Outputs:
@ -110,7 +232,13 @@ Exit codes:
* `0`: ok
* `3`: renderer missing or engine error (see `out/render-log.json`)
* `4`: config error
* `2`: config error
Notes:
* Use `--engine` to force a specific renderer (e.g., `--engine wkhtmltopdf`).
* Use `--font-dir` to supply additional font directories for the renderer (e.g., corporate fonts).
* Use `--strict-fonts` (or profile `fonts.require_primary: true`) to prevent silent font fallbacks in shipped PDFs.
## Command: `qa`
@ -118,13 +246,22 @@ Purpose:
* Run deterministic post-render QA checks (HTML analysis v0) and enforce numeric gates from `spec/quality_gates.yaml`.
Args:
* `--out <dir>`: output directory containing `render.html` / `render.pdf` (default: `out/`)
* `--html <path>`: HTML to analyze (default: `<out>/render.html`)
* `--pdf <path>`: optional PDF path for reporting (default: `<out>/render.pdf`)
* `--strict`: use strict thresholds from `spec/quality_gates.yaml`
* `--format <json|sarif>`: optional SARIF output for CI annotations
Outputs:
* `out/layout-report.json`
* `out/qa-report.json`
* `out/qa-report.sarif` (when `--format sarif`)
Exit codes:
* `0`: gates pass
* `2`: gates fail
* `4`: config error / missing `out/render.html`
* `1`: gates fail
* `2`: config error / missing HTML input

View file

@ -6,7 +6,7 @@ This doc defines what “shipready” means for `iftypeset` (pubstyle): a det
- Produce **consistently good-looking** outputs from plain Markdown without manual layout heroics.
- Provide **machine-verifiable QA gates** (layout/report JSON) suitable for CI.
- Keep the system **renderer-agnostic** via adapters (Chromium / WeasyPrint / Prince / Antenna House / Vivliostyle, etc.).
- Keep the system **renderer-agnostic** via adapters (Playwright / WeasyPrint / Prince / Antenna House / Vivliostyle, etc.).
- Preserve legal constraints: **rules are paraphrases + pointers**, never book text.
## Definition of Done (v0.1)
@ -95,4 +95,3 @@ For a convincing “this is real” demo:
- [ ] CI fails on spec regression (coverage floors, schema validation).
- [ ] Degraded mode emits its report artifacts and never silently “fixes” content.
- [ ] Renderer adapters are documented (how `auto` chooses, how to pin).

View file

@ -25,15 +25,15 @@ class PdfEngine(Protocol):
The CLI should support:
- `--engine auto|chromium|weasyprint|prince|antenna|vivliostyle|wkhtmltopdf`
- `--engine auto|playwright|weasyprint|prince|antenna|vivliostyle|wkhtmltopdf`
- `--engine-opts <json>`
## “Majors” to target (pragmatic)
### Tier 1 (easy to run, common)
1) **Chromium / Headless browser**
- via Playwright or system Chromium (`chrome --headless --print-to-pdf`)
1) **Playwright (browser-backed PDF)**
- via Playwright (preferred)
- Pros: ubiquitous, good HTML/CSS coverage, easy containerization.
- Cons: paged-media features vary; footnotes/running headers are limited unless carefully built.
@ -86,7 +86,7 @@ For every PDF render, write `out/render-log.json` including:
- invocation args
- environment hints (OS, locale)
- “self-contained” mode on/off
- fonts resolved (what was available vs requested)
- fonts policy + resolution (requested primary fonts, what fontconfig matched, and what fonts were embedded in the PDF)
- any warnings from the engine
If the engine is a browser:
@ -106,7 +106,7 @@ If the engine is a browser:
## Recommended v0.1 path (fastest)
1) Implement adapters for:
- Chromium/Playwright (auto-detect)
- Playwright (auto-detect)
- WeasyPrint (if installed)
2) Keep Prince/AH as optional adapters (stub + docs) until needed.
3) Use QA gates as the real value:
@ -123,4 +123,3 @@ Once adapters exist, add an integration job that renders the same fixtures throu
- major layout regressions (e.g., table clipping incidents)
We dont need pixel-perfect equivalence; we need “quality gates still pass”.

View file

@ -22,9 +22,20 @@ We have a working foundation that is intentionally boring:
- A **profile system** (`spec/profiles/*.yaml`) that maps typographic intent into deterministic render tokens (page size, margins, font stacks, measure targets, hyphenation policy).
- **Post-render QA gates** (`spec/quality_gates.yaml`) that define hard numeric thresholds for layout failures.
- A working CLI surface (`iftypeset.cli`) that can validate the spec, emit coverage reports, lint Markdown, render HTML/CSS, render PDF (via available engines), and run QA.
- `report` now generates a human HTML index at `out/report/index.html` linking all artifacts.
Current progress is tracked in `STATUS.md` and `out/coverage-summary.md`.
## What changed (2026-01-04)
- Expanded the rule registry with new category batches (abbreviations, i18n, frontmatter, backmatter, figures) and the first editorial batch (house-style, pointer-backed).
- Implemented deterministic lint enforcement for key MUST rules plus DOI references, ordinal suffix errors, and note-marker placement, with safe `--fix` modes.
- Strengthened HTML-only QA and added PDF-aware QA (Poppler `pdftotext` + `pdftohtml -xml`) for page-aware heuristics; incidents include `widow_pdf`, `orphan_pdf`, `stranded_heading_pdf`, `overfull_line_pdf`, `overfull_bbox_pdf`, and `runt_final_page_pdf`.
- Improved degraded-mode parsing heuristics to reduce false positives and added fixtures/tests to keep `scripts/ci.sh` green.
- Added a human-friendly report index (`out/report/index.html`) for quick artifact navigation.
- Added a pinned Docker runtime (Playwright + Poppler + fonts) for reproducible CI/local runs (`docs/15-docker.md`).
- Deepened profile tokens and CSS handling for tables, figures, and code blocks (table layout + wrapping, figure sizing, code block padding/wrap) to reduce overflow risk.
## Where we are going (v0.1 → v1)
### v0.1: “Publishing CI” for a single Markdown input
@ -32,7 +43,7 @@ Current progress is tracked in `STATUS.md` and `out/coverage-summary.md`.
The v0.1 goal is *not* to be the best renderer. Its to be the most reliable pipeline:
- deterministic HTML/CSS output for a chosen profile
- PDF generation via adapters (Chromium first, others later)
- PDF generation via adapters (Playwright default; others later)
- QA reports that catch common layout failures and fail the build when thresholds are exceeded
- an honest manual checklist for rules that cannot be automated
@ -70,4 +81,3 @@ The differentiator is not “Markdown to PDF”. Its:
**B) enforceable layout QA** (fail the build when its sloppy).
Thats what makes it compatible with governance workflows (hash/sign artifacts, attach QA reports, reproduce later) and usable in constrained CI environments (like Forgejo PDF export workers).

View file

@ -14,11 +14,60 @@ This project adds a few boring mechanisms to make resuming work deterministic.
From the repo root:
- `./scripts/audit.sh`
- `./scripts/resume.sh` (recommended)
- `./scripts/audit.sh` (raw)
- `./scripts/state.sh` (writes `docs/SESSION_STATE.md` for pasteable state)
- `./scripts/ci.sh`
If both look sane, youre back.
## Multi-session coordination (avoid Codex waiting)
When running multiple Codex sessions in parallel, coordinate through the repo:
- Task queue: `docs/13-task-board.md`
- Session context: `docs/SESSION_STATE.md`
- Durable restore points: `docs/CHECKPOINTS.md` + `out/checkpoints/`
Workflow:
1. Pick a task from `docs/13-task-board.md` and **claim it** (owner + working_set).
2. Stay inside your `working_set` to avoid conflicts.
3. Run `./scripts/ci.sh`.
4. Create a restore point: `./scripts/checkpoint.sh "task <id>: <note>"`
5. Mark the task done and paste the checkpoint reference.
If a change must block others (shared files), create a temporary lock file:
- `docs/LOCK_<area>.md`
## Coordination contract (short)
Use this when handing off across sessions:
1. **Claim the task** in `docs/13-task-board.md`.
2. **Declare the working set** in `docs/SESSION_STATE.md`.
3. **Lock shared areas** via `docs/LOCK_<area>.md` if needed.
4. **Checkpoint after changes** (`./scripts/checkpoint.sh "note"`).
5. **Close the task** and paste the checkpoint reference.
## “It looks rolled back” (most common disconnect trap)
If you resume a session and it looks like files “disappeared”, its almost always one of:
- Youre looking at a **clean git checkout** somewhere else (remote machine / new container) and the prior work was never committed.
- Youre looking at a **stale copy outside the repo** (see warning below).
What to do:
1. Run `./scripts/audit.sh` and inspect the `git status --porcelain` output.
2. Check `out/checkpoints/` for the latest `iftypeset_checkpoint_*.tar.gz`.
3. If you need to move the work to a new machine/session, copy the latest checkpoint tarball and extract it:
- `tar -xzf out/checkpoints/iftypeset_checkpoint_<timestamp>.tar.gz -C <new_dir>`
Important: checkpoints snapshot the repo tree (including untracked files). They are the durable “chat-proof” handoff mechanism even when you dont want to commit yet.
## Create a checkpoint (2 minutes)
When you finish a meaningful chunk of work (new rule batches, QA changes, renderer changes), run:
@ -30,6 +79,7 @@ This:
- runs CI and stores the CI JSON in `out/checkpoints/`
- creates a compressed snapshot tarball in `out/checkpoints/`
- appends a new entry to `docs/CHECKPOINTS.md` with the snapshot hash
- writes `docs/SESSION_STATE.md` so the snapshot includes a pasteable “resume context”
This gives you a **portable restore point** even if the chat transcript is gone.
@ -38,3 +88,10 @@ This gives you a **portable restore point** even if the chat transcript is gone.
- Push to a remote early (Forgejo/GitHub). A remote is the best anti-loss mechanism.
- Treat `STATUS.md` as the “1-page truth” for what exists and whats next.
- Dont rely on chat logs for state; copy any critical decisions into `docs/`.
## Common “it looks rolled back” trap
If you have multiple status documents on disk, prefer the one inside the repo:
- ✅ canonical: `ai-workspace/iftypeset/docs/09-project-status.md`
- ⚠️ non-canonical copies (e.g., `/root/docs/09-project-status.md`) can drift and misreport counts.

89
docs/08-handoff.md Normal file
View file

@ -0,0 +1,89 @@
# Handoff (context checkpoint) — `iftypeset`
This file exists for one purpose: prevent “chat drift” when a session resets.
If the conversation disappears, this doc + `./scripts/audit.sh` is enough to resume work.
## What this project is
`iftypeset` (pubstyle) is a thin, deterministic **Markdown → HTML → PDF** pipeline with:
- A **machine-readable rule registry** (`spec/rules/**.ndjson`) with **paraphrased** rules + **pointer refs** (Chicago/Bringhurst), never book text.
- **Profiles** (`spec/profiles/*.yaml`) that map typographic intent → render tokens/CSS.
- **QA gates** (`spec/quality_gates.yaml`) that fail builds when layout degrades.
Core principle: quality must be **measurable and enforceable**, not “looks fine on my machine”.
## What is working (today)
- CLI (end-to-end): `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`.
- Rendering: HTML deterministic; PDF works when a PDF engine is available (Playwright is the default).
- QA (v0): HTML-based heuristics + gate evaluation; emits `layout-report.json` with incident details.
- Rule registry: seeded and schema-validated; coverage report is generated in CI.
- CI: `./scripts/ci.sh` runs spec validation + report + unit tests.
- Session resilience:
- `./scripts/audit.sh` prints git + coverage snapshot + checkpoint info.
- `./scripts/checkpoint.sh "note"` creates a restore tarball and records it in `docs/CHECKPOINTS.md`.
## How to resume in 30 seconds
From repo root:
```bash
./scripts/audit.sh
./scripts/ci.sh
```
If CI passes, you are back.
## Latest checkpoint (restore point)
Run `./scripts/audit.sh` to see the latest checkpoint path + sha256.
If you need to create a new restore point:
```bash
./scripts/checkpoint.sh "short note about what changed"
```
## Where to look first
- Status and counts: `STATUS.md`
- Project status (narrative): `docs/09-project-status.md`
- Architecture: `app/ARCHITECTURE.md`
- CLI contract: `app/CLI_SPEC.md`
- External evaluation prompt: `docs/05-external-evaluation-prompt.md`
- Renderer strategy: `docs/04-renderer-strategy.md`
- Session resilience: `docs/07-session-resilience.md`
- Rule schema + contracts: `spec/schema/rule.schema.json`, `spec/manifest.yaml`
## Non-negotiables (dont drift)
- Do **not** OCR/transcribe Chicago/Bringhurst into the repo.
- Rules are **paraphrases** + **pointer refs** only.
- OCR is allowed only **ephemerally** to locate pointers (stdout/temp deleted).
- If a rule cannot be automated, mark it `manual_checklist=true` and ensure it lands in checklist output.
## What remains (next high-leverage work)
1) **Deepen post-render QA**
- Current QA is HTML-based v0.
- Next step is PDF-aware inspection for widows/orphans, stranded headings, and clipping when a renderer is pinned.
2) **Increase enforced coverage where it buys down real pain**
- Citations and i18n where deterministic checks are feasible.
- Links/DOIs wrapping policies and table/code overflow strategies across profiles.
3) **Forgejo integration**
- Apply profile CSS to Forgejos PDF exporter and emit QA reports as export artifacts.
- See `forgejo/README.md`.
4) **More rule batches**
- Build out figures/links/code/frontmatter/backmatter/i18n breadth, then tighten enforcement coverage where feasible.
## “Dont lose work” reminder
Chat logs are not durable. The repo is.
- When you finish a chunk: `./scripts/checkpoint.sh "note"`
- When you resume: `./scripts/audit.sh` + `./scripts/ci.sh`

149
docs/09-project-status.md Normal file
View file

@ -0,0 +1,149 @@
# `iftypeset` — Project Status (2026-01-03)
## What This Project Is
`iftypeset` is a thin, deterministic **typeset runtime** for turning Markdown into:
- Stable, shareable HTML (`render-html`)
- A PDF (`render-pdf`)
- Machine-readable quality reports (`lint`, `qa`, `report`)
It is paired with a **machine-readable rule registry** derived from:
- Chicago Manual of Style (CMOS 18)
- Bringhurst (*Elements of Typographic Style*)
Important: rule records are **paraphrases only** with **pointer refs** (e.g., `CMOS18 §6.2 p377 (scan p10)`). This repo must not contain book text.
## What Works Today
Verified on `master` via `./scripts/ci.sh` (spec validate + report + unit tests):
- End-to-end CLI: `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`
- Deterministic lint engine with safe rewrite mode (`lint --fix --fix-mode rewrite`)
- Deterministic HTML rendering; PDF rendering works when an engine is available (Playwright is the default)
- QA analyzer (HTML + PDF heuristics) with incident details:
- long/bare URL/DOI/email wrap incidents
- overfull token detection
- table/code overflow incidents (profile-aware thresholds)
- PDF-aware widow/orphan heuristics via Poppler text extraction (`pdftotext -layout`)
- PDF-aware runt final page detection (short last page heuristics)
- CI wiring for Forgejo: `.forgejo/workflows/ci.yml`
- Session resilience tooling:
- `./scripts/audit.sh` prints a compact truth snapshot (git + coverage + checkpoints)
- `./scripts/checkpoint.sh "note"` creates a portable restore tarball recorded in `docs/CHECKPOINTS.md`
## Rule Registry Snapshot (Real Counts)
From `out/coverage-report.json` (generated by `PYTHONPATH=src python3 -m iftypeset.cli report --spec spec --out out`):
- **Total rules:** 524
- **Enforcement split:** manual 379, typeset 62, lint 70, postrender 13
- **Severity split:** must 37, should 470, warn 17
Category counts:
- editorial 45
- citations 61
- numbers 62
- punctuation 55
- layout 46
- headings 32
- tables 23
- links 21
- i18n 27
- abbreviations 27
- code 28
- accessibility 22
- frontmatter 20
- backmatter 18
- figures 22
## Coverage Map Summary (Sections)
Generated by `python3 tools/coverage_summary.py --coverage-dir spec/coverage --out-json out/coverage-summary.json --out-md out/coverage-summary.md`:
- BRING: 64 sections, 284 rules (all partial)
- CMOS18: 176 sections, 550 rules (all partial)
- Total unique rule_ids across coverage maps: 834
- typography 15
Interpretation:
- The registry is intentionally larger than the enforcement surface.
- Many rules remain `manual_checklist=true` by design until we have deterministic enforcement for them.
## What This Is *Not* Yet
- A full “publication-grade PDF QA” system. PDF-aware checks exist, but are heuristic (text extraction based) and limited in scope.
- A complete automated implementation of Chicago/Bringhurst. The registry is pointer-backed; enforcement is incremental and explicit.
## How To Run (Quick)
```bash
cd /root/ai-workspace/iftypeset
```
Validate + rebuild indexes:
```bash
PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes
```
Generate coverage report:
```bash
PYTHONPATH=src python3 -m iftypeset.cli report --spec spec --out out --build-indexes
```
Lint (and optionally autofix):
```bash
PYTHONPATH=src python3 -m iftypeset.cli lint --input fixtures/sample.md --out out --profile web_pdf
PYTHONPATH=src python3 -m iftypeset.cli lint --input fixtures/sample.md --out out --profile web_pdf --fix --fix-mode rewrite
```
Render HTML + PDF:
```bash
PYTHONPATH=src python3 -m iftypeset.cli render-html --input fixtures/sample.md --out out --profile web_pdf
PYTHONPATH=src python3 -m iftypeset.cli render-pdf --input fixtures/sample.md --out out --profile web_pdf
```
Run QA:
```bash
PYTHONPATH=src python3 -m iftypeset.cli qa --out out --profile web_pdf
```
Sanity check:
```bash
./scripts/ci.sh
```
## Dont Lose Work (Session Resets)
Chat logs are not durable. The repo is.
- Snapshot: `./scripts/audit.sh`
- Restore point: `./scripts/checkpoint.sh "short note"`
- Checkpoint index: `docs/CHECKPOINTS.md`
## What Remains (Prioritized)
1) **Improve post-render QA beyond current heuristics**
- PDF-aware stranded headings / keep-with-next violations
- more reliable overflow/clipping detection when a renderer is pinned
2) **Increase *implemented* rule coverage where it matters**
- citations normalization / author-date variants where feasible
- i18n/locale-driven checks (without pretending perfect automation)
- link/DOI wrapping policies (reduce broken PDFs)
3) **Forgejo integration**
- use `iftypeset` as the Forgejo typeset/export worker
- emit QA artifacts as export attachments
4) **Continue adding rule batches**
- prioritize what breaks real documents: figures, references, complex tables, long code blocks

79
docs/10-project-brief.md Normal file
View file

@ -0,0 +1,79 @@
# `iftypeset` — Project Brief (downloadable)
## What This Is
`iftypeset` is a deterministic **Markdown → HTML → PDF** pipeline with:
- A **machine-readable rule registry** (Chicago/Bringhurst-backed pointers; paraphrased rules only)
- **Profiles** that map typographic intent → rendering tokens (`spec/profiles/*.yaml`)
- **QA gates** that fail builds when layout degrades (`spec/quality_gates.yaml`)
The wedge is not “perfect typography by AI”. The wedge is **CI for document quality**: measurable, reproducible, auditable.
## NonNegotiables
- No bulk OCR/transcription of Chicago/Bringhurst into the repo (copyright).
- Rules are paraphrases with pointer refs (e.g., `CMOS18 §X.Y pNN (scan pMM)`).
- If a rule cannot be automated safely, it must be tagged `manual_checklist=true` and emitted in `out/manual-checklist.md`.
## Where We Are (20260103 snapshot)
Verified via `./scripts/ci.sh` (validate-spec + report + tests):
- CLI: `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`
- Deterministic lint with safe rewrite mode (`lint --fix --fix-mode rewrite`)
- Deterministic HTML rendering; PDF rendering works when an engine is available
- QA (HTML-based v0) with incident details:
- bare URL/DOI/email wrap risk
- overfull token detection
- table/code overflow (profile-aware thresholds)
- Forgejo CI workflow: `.forgejo/workflows/ci.yml`
- Session resilience tooling:
- `./scripts/audit.sh`, `./scripts/resume.sh`, `./scripts/checkpoint.sh`
- checkpoints tracked in `docs/CHECKPOINTS.md`
Rule registry snapshot (from `out/coverage-report.json`):
- Total rules: 524
- Enforced: 145 (lint + typeset + postrender)
- Manual: 379
The repo also emits a “trust contract” describing what is enforced vs manual:
- `out/trust-contract.md`
- `out/trust-contract.json`
## Whats Next (priority order)
1) **Make QA less “HTML heuristic” and more layout-aware**
- Add at least one truly page-aware detector (widows/orphans or stranded headings) with measurable thresholds.
2) **Increase enforced coverage where it reduces real PDF pain**
- citations normalization variants
- link/DOI handling + wrap policy
- table/code overflow strategies
3) **Forgejo integration**
- run `iftypeset` as a PDF export/typeset worker
- attach QA artifacts to exports
4) **Expand rule batches**
- continue adding pointer-backed rules for remaining categories (figures, front/back matter, etc.)
- promote high-confidence rules from `manual``lint/typeset/postrender` incrementally
## Quick Commands
From repo root:
- Resume sanity snapshot: `./scripts/resume.sh`
- CI sanity: `./scripts/ci.sh`
- Portable restore point: `./scripts/checkpoint.sh "note"`
## Canonical “single source of truth” docs
- `docs/09-project-status.md` (most current, short + factual)
- `docs/06-project-overview.md` (narrative overview)
- `docs/05-external-evaluation-prompt.md` (external review prompt)
- `docs/07-session-resilience.md` (how to avoid “lost work”)
- `docs/CHECKPOINTS.md` (restore points)

130
docs/11-project-summary.md Normal file
View file

@ -0,0 +1,130 @@
# `iftypeset` — Project Summary (downloadable)
## What this is
`iftypeset` is a deterministic **document-quality runtime** for turning Markdown into:
- `render.html` + `render.css` (stable, shareable)
- `render.pdf` (stable *given pinned engine + fonts*)
- quality artifacts (`lint-report.json`, `layout-report.json`, `qa-report.json`, `coverage-report.json`)
The differentiator is **measurement + enforceability**:
- A machinereadable **rule registry** (`spec/rules/**.ndjson`) derived from Chicago/Bringhurst as **paraphrases only**, with **pointer refs** (no book text).
- **Profiles** (`spec/profiles/*.yaml`) that map typographic intent into render tokens.
- **QA gates** (`spec/quality_gates.yaml`) that fail builds when layout degrades.
Positioning (honest): this is **CI for document quality**, not “we perfectly implement Chicago/Bringhurst.”
## What works today (verified)
Verified locally via `./scripts/ci.sh` (spec validate + report + tests):
- CLI pipeline: `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`
- Deterministic lint (with safe rewrite mode) + manual checklist emission
- Deterministic HTML output; PDF rendering works when an engine is available (Playwright is the default)
- QA analyzer:
- HTML heuristics: bare URL/DOI/email wrap, overfull tokens, table/code overflow (profile-aware)
- PDF heuristics: widows/orphans via Poppler text extraction (`pdftotext -layout`)
- Session resilience:
- `./scripts/audit.sh` (truth snapshot)
- `./scripts/state.sh` (writes `docs/SESSION_STATE.md`)
- `./scripts/checkpoint.sh "note"` (portable restore tarball + entry in `docs/CHECKPOINTS.md`)
- “Trust contract” artifact emitted by `report`:
- `out/trust-contract.md` and `out/trust-contract.json`
- makes enforcement vs manual + QA limitations explicit
## Rule registry snapshot (real counts)
From `out/coverage-report.json` (generated by `report`):
- Total rules: **524**
- Enforcement split: **manual 379**, **typeset 62**, **lint 70**, **postrender 13**
- Editorial category is no longer empty: **45** house-pointer editorial rules (manual-first)
Interpretation:
- The registry is intentionally broader than enforcement.
- Manual rules are not a weakness if the system is explicit and generates checklists deterministically.
## How to run (quick start)
From repo root:
```bash
./scripts/ci.sh
```
Minimal manual run:
```bash
PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes
PYTHONPATH=src python3 -m iftypeset.cli lint --input fixtures/sample.md --out out --profile web_pdf
PYTHONPATH=src python3 -m iftypeset.cli render-html --input fixtures/sample.md --out out --profile web_pdf
PYTHONPATH=src python3 -m iftypeset.cli render-pdf --input fixtures/sample.md --out out --profile web_pdf
PYTHONPATH=src python3 -m iftypeset.cli qa --out out --profile web_pdf
```
## “Dont lose work” (session resets)
Chat logs are not durable. The repo is.
- Resume: `./scripts/resume.sh`
- Snapshot: `./scripts/audit.sh`
- Pasteable state: `./scripts/state.sh` (updates `docs/SESSION_STATE.md`)
- Restore point: `./scripts/checkpoint.sh "short note"`
If a session “looks rolled back”, its usually because work wasnt committed yet. Check:
- `git status --porcelain`
- `out/checkpoints/iftypeset_checkpoint_*.tar.gz`
- `docs/CHECKPOINTS.md`
## What remains (next work, prioritized)
### 1) Deepen PDF-aware QA (beyond widows/orphans)
High leverage detectors:
- stranded headings / keep-with-next violations (PDF-aware)
- more reliable overflow/clipping detection (tables/code, page bounds)
Goal: make `qa` failures correlate strongly with “this PDF looks broken.”
### 2) Increase implemented enforcement where it buys down real pain
Focus areas:
- citations normalization + i18n/locale checks where deterministic
- link/DOI/email wrapping policies (reduce broken PDFs)
- table + code overflow strategies across profiles
Rule of thumb: implement what repeatedly causes layout incidents in fixtures.
### 3) Forgejo integration (export worker)
Target: use `iftypeset` as Forgejos typeset/export worker:
- apply profiles + CSS to exported docs
- emit QA artifacts as export attachments
- treat “PDF export quality” as CI, not a best-effort feature
### 4) Expand rule batches responsibly
Continue batches where they matter for real docs:
- figures, frontmatter/backmatter, references, long code blocks, complex tables
- keep paraphrase + pointer discipline; no book text in repo
## Canonical docs (start here)
- `README.md`
- `STATUS.md`
- `docs/06-project-overview.md`
- `docs/07-session-resilience.md`
- `docs/08-handoff.md`
- `docs/09-project-status.md`
- `docs/10-project-brief.md`
- `docs/05-external-evaluation-prompt.md`
- `app/ARCHITECTURE.md`
- `app/CLI_SPEC.md`

View file

@ -0,0 +1,118 @@
# Codex Max Workload (High-Leverage) — Forgejo PDF Integration + PDF QA Expansion
This is the **next big acceleration chunk** for `iftypeset`.
Goal: make `iftypeset` visibly valuable in the real world by wiring it into the existing Forgejo PDF export worker, then deepen PDF QA so we catch real pagination failures (beyond widows/orphans).
## Non-negotiables
- Do **not** OCR/transcribe Chicago/Bringhurst into the repo(s). Paraphrases + pointers only.
- Keep dependencies minimal. Prefer stdlib + existing tooling already present in the environment.
- Keep outputs deterministic. If a dependency/version makes determinism impossible, document it in a “trust contract” note instead of pretending.
## Target repos
- `iftypeset`: `/root/ai-workspace/iftypeset`
- `forgejo-pdf`: `/root/ai-workspace/forgejo-pdf`
## Part A — Integrate `iftypeset` CSS into Forgejo PDF export (primary goal)
### A1) Understand current Forgejo PDF pipeline
In `/root/ai-workspace/forgejo-pdf`, identify:
- where Markdown is converted to HTML
- where CSS is selected/loaded (currently `basic.css`, `professional.css`, etc.)
- where PDF is rendered (Chromium / Playwright / Puppeteer / wkhtmltopdf / etc.)
- how configuration is passed (env vars, config file, CLI args)
Write a short “current pipeline” note in `forgejo-pdf/worker/pdf/README.md` (or existing docs file) so we can reason about changes later.
### A2) Add a new theme option: `iftypeset-web_pdf`
We want Forgejo to be able to select:
- `basic`
- `professional`
- `iftypeset-web_pdf` (new)
Implementation constraints:
- The CSS file must ship with the worker (no network fetch at runtime).
- The CSS must load **after** any base CSS so it can override.
- The result should still render correctly even if some fonts are missing (font stack fallbacks).
### A3) Generate and vendor the CSS from `iftypeset`
In `iftypeset` the command exists:
`iftypeset emit-css --spec spec --profile web_pdf --out out-css`
Pick one approach:
1. **Vendored CSS in `forgejo-pdf`** (recommended for now):
- Generate `out-css/iftypeset_web_pdf.css`
- Copy into `forgejo-pdf/worker/pdf/assets/css/iftypeset-web_pdf.css`
- Add a small “refresh script” in `forgejo-pdf/scripts/update_iftypeset_css.sh` that regenerates and copies the file.
- Document the source-of-truth as `iftypeset` + the refresh script.
2. **Build-time generation** (optional later):
- During `forgejo-pdf` build, call `iftypeset emit-css` and bundle the output.
### A4) Wire it into the render code path
Update the Forgejo PDF worker so that selecting the new theme:
- includes the CSS file in the HTML head
- produces PDFs/HTML without breaking existing themes
### A5) Tests + validation
Add a minimal smoke test in `forgejo-pdf` that:
- renders a small known fixture Markdown
- verifies that the resulting HTML references `iftypeset-web_pdf.css`
- (optional) verifies PDF generation completes
Avoid checking in large PDF binaries. Prefer small text-based assertions (e.g., HTML contains a `<link>` to the CSS).
### A6) Documentation
Update both repos:
- `iftypeset/forgejo/README.md`: “how to enable `iftypeset-web_pdf` theme in forgejo-pdf”
- `forgejo-pdf` docs: new theme option + how to refresh CSS
## Part B — Expand PDF QA beyond widows/orphans (secondary goal)
We already have PDF-aware widows/orphans via Poppler `pdftotext -layout`.
Add 12 additional PDF incident kinds **without adding heavy dependencies**:
1. **Stranded headings** (most valuable)
- detect headings at end of a page with insufficient following content (heuristic)
2. **Overfull/clipping approximation**
- flag suspicious long lines that exceed measure, using `pdftotext -layout` and profile measure targets as heuristics
Requirements:
- Emit incidents with enough context to be actionable (page number, snippet, rule/tag).
- Update `spec/quality_gates.yaml` metrics if needed (or map into existing ones).
- Add fixtures + tests in `iftypeset/tests/` for the new incidents.
- Update `STATUS.md` and `docs/06-project-overview.md` if behavior changes.
## Completion checklist (what “done” looks like)
- Forgejo PDF worker can render using `iftypeset-web_pdf` theme.
- A refresh script exists to sync CSS from `iftypeset`.
- Both repos have docs explaining how to use it.
- CI stays green in both repos (or a clear note exists if one repo lacks CI).
- `iftypeset` PDF QA reports at least one new PDF incident kind beyond widows/orphans.
## After each major chunk
- Run:
- `bash /root/ai-workspace/iftypeset/scripts/ci.sh`
- create an `iftypeset` checkpoint: `bash /root/ai-workspace/iftypeset/scripts/checkpoint.sh "note"`
- and if you touch `forgejo-pdf`, do the equivalent if that repo has checkpoint tooling (otherwise document `git rev-parse HEAD`).

158
docs/13-task-board.md Normal file
View file

@ -0,0 +1,158 @@
# Task Board (Multi-Session Coordination)
This file is the **single coordination surface** for parallel Codex sessions.
Goal: avoid prompt-pasting + idle agents by making “what to do next” a durable, repo-local queue.
## Product contract (read first)
`iftypeset` is a **Document CI tool**, not a “pretty PDF generator”.
- Mental model: **profiles + gates + artifacts + exit codes** (rendering is one stage).
- The one command humans/CI want: `iftypeset run --input <path> --profile <name> --out out/`
- Keep this contract true as tasks evolve; dont optimize for “looks nice locally” at the expense of determinism and CI clarity.
- Full contract + CLI shape lives in `docs/14-document-ci-model.md`.
## Live readiness gate (if.typeset) (not live)
Black/white:
- `if.typeset` remains `preview` in `if.registry.json` until all criteria below are satisfied and publicly reviewable.
Gate criteria (all MUST be true):
1) Public landing page exists at `/if/typeset` with a clear Document CI contract and no compliance claims.
2) At least 1 public demo pack exists with reproducible steps and `if.trace` receipts (HTML-first links, one URL per line).
3) Public contract exists for the `iftypeset run` pipeline (inputs, profiles, outputs, exit codes).
4) Status flip to `live` happens only after the above are verified.
## How to use this board
1. **Claim** a task by editing its row:
- set `owner` (if you are using Codex CLI, include `[sid: …]` from `/status`)
- set `status=in_progress`
- add a short `working_set` (files/dirs you will touch)
2. Do the work.
3. Run `./scripts/ci.sh`.
4. Create a restore point: `./scripts/checkpoint.sh "task <id>: <short note>"`
5. Update the row:
- `status=done`
- record the `checkpoint` filename + sha256 (from `docs/CHECKPOINTS.md`)
## Coverage milestones (CMOS / BRING)
Coverage is tracked in `spec/coverage/**` by **section**. For multi-session work, treat it as two milestones (details: `docs/19-coverage-roadmap.md`):
- **Milestone A (mapped):** drive `status` from `uncovered``partial` by adding at least one paraphrased rule with a valid pointer (`source_refs`) and wiring `rule_ids` for that section.
- **Milestone B (complete):** later completion pass to move `partial``covered` or `out_of_scope` (only after checking the section for remaining rule-bearing guidance).
Collision note: if `IFTS-1346` is in progress (touches `spec/rules/**`), do not claim coverage batch tasks that edit `spec/rules/**` (including citations batches) until it is done.
## Conflict avoidance rules (strict)
- Do not work on the **same files** in parallel sessions.
- If you must touch a shared file (e.g., `STATUS.md`), do it in a **small final pass** and announce it here first.
- If a task row changes while you work, preserve the other sessions note and append your checkpoint details instead of overwriting.
- Prefer **one area per session**:
- `src/iftypeset/*` (runtime)
- `spec/*` (registry + profiles)
- `../forgejo-pdf/*` (integration)
- `docs/*` (documentation)
## Optional lock files (when needed)
If a task must block others, create a lock file:
- `docs/LOCK_<area>.md`
Template:
```text
owner: <name/session>
created_at_utc: <timestamp>
scope: <what is locked>
notes: <what others should avoid>
```
Delete the lock when done.
---
## Queue
Columns:
- `status`: `todo` | `in_progress` | `blocked` | `done`
- `owner`: human/session label (e.g., `codex-max`, `codex-mini`, `danny`)
- `working_set`: paths to avoid collisions
| id | status | owner | task | working_set | notes | checkpoint |
|---:|:------:|:-----:|------|-------------|-------|-----------|
| 1301 | done | codex-max | Build rule indexes on CI | `spec/indexes/*`, `src/iftypeset/spec.py` | Already wired in `scripts/ci.sh`; `index_builder.py` writes deterministically (sorted keys). Verified current behavior. | out/checkpoints/iftypeset_checkpoint_2026-01-04T05-20-47Z.tar.gz (sha256=3078a3cce3dca02336e49d3d4c261308f2078d22c0e6ace58bc6635f1b03f8b5) |
| 1302 | done | codex-max | Expand PDF QA incidents | `src/iftypeset/qa.py`, `tests/test_qa.py` | Added `stranded_heading_pdf` + `overfull_line_pdf` heuristics and tests; merged into QA metrics/analysis_mode. | out/checkpoints/iftypeset_checkpoint_2026-01-04T05-20-47Z.tar.gz (sha256=3078a3cce3dca02336e49d3d4c261308f2078d22c0e6ace58bc6635f1b03f8b5) |
| 1303 | done | codex-max | Improve Markdown parser robustness | `src/iftypeset/md_parser.py`, `tests/test_md_parser.py` | Added degraded fixtures; reduced false positives by gating hard-wrap continuation and missing-headings length; unwrap only on hard-wrap. | out/checkpoints/iftypeset_checkpoint_2026-01-04T05-58-38Z.tar.gz (sha256=42e99c3676c8423194cb3bbdca9ff635eff7bfd60af29a6ca0788b10aca7fe4d) |
| 1304 | done | codex-max | Increase automated enforcement coverage | `src/iftypeset/linting.py`, `spec/rules/*` | Added deterministic lint for DOI references, ordinal suffix errors, and footnote marker placement; new tests added. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-03-53Z.tar.gz (sha256=a781c760a44691aa9ff110de6c6d2022280034be3d2c05c247c0c74a5e3048b9) |
| 1305 | done | codex-max | Forgejo PDF integration (theme + CSS sync) | `../forgejo-pdf/*`, `forgejo/README.md` | Added `iftypeset-web_pdf` theme, vendored CSS + refresh script, smoke test, docs updates. Forgejo repo has no checkpoint; see current workspace state. | out/checkpoints/iftypeset_checkpoint_2026-01-04T05-20-47Z.tar.gz (sha256=3078a3cce3dca02336e49d3d4c261308f2078d22c0e6ace58bc6635f1b03f8b5) |
| 1306 | done | codex-max | Packaging/UX pass | `README.md`, `STATUS.md`, `docs/06-project-overview.md` | Clarified quickstart + enforcement limits; updated status/overview notes. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-05-22Z.tar.gz (sha256=a3aa47e3ee759328e3531ed3a0c49801bb8cfd430cb403978ff91b9a18001746) |
| 1307 | done | codex-max | Add one-shot `iftypeset run` (CI-style pipeline) | `src/iftypeset/cli.py`, `src/iftypeset/reporting.py`, `app/CLI_SPEC.md`, `README.md` | Added `run` command with `run-summary.json`, updated CLI spec/README, added integration test. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-10-01Z.tar.gz (sha256=d493f39ba9fcf708eb38cab11dd20762a4a361a3a635e30feedfad7e577c6d7c) |
| 1308 | done | codex-max | Add repo config file support (`iftypeset.yaml`) | `src/iftypeset/config.py` (new), `src/iftypeset/cli.py`, `README.md`, `app/CLI_SPEC.md` | Added config loader + CLI overrides, docs and integration test. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-16-12Z.tar.gz (sha256=b978bb5cb21fbccd669307e800494b3344818e25fbae521df953f30e099cf595) |
| 1309 | done | codex-max | Add CLI introspection helpers (profiles/gates/rules) | `src/iftypeset/cli.py`, `README.md`, `app/CLI_SPEC.md` | Added profiles/gates/rules commands and tests; documented in README/CLI spec. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-18-36Z.tar.gz (sha256=ab8c60da431acc224c189a180b20aa33d3173d49e10a7c9b179dfecd3c9261e5) |
| 1310 | done | codex-max | Make `report` generate a human HTML index | `src/iftypeset/reporting.py`, `src/iftypeset/cli.py`, `docs/06-project-overview.md` | Added `out/report/index.html` summary + artifact links; tests updated. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-21-49Z.tar.gz (sha256=d3474fe4d820a4edaf1fc60e758359c22881418086468f83c62934059bcbe5ae) |
| 1311 | done | codex-max | Confirm CI-friendly exit codes + stdout summary | `src/iftypeset/cli.py`, `app/CLI_SPEC.md`, `tests/test_integration.py` | Standardized exit codes (0/1/2/3), updated CLI spec + tests, run summary remains JSON. | out/checkpoints/iftypeset_checkpoint_2026-01-04T06-26-42Z.tar.gz (sha256=f87b3ceb300674577206a57254b5637274fd500f50f55c9ccf4432a675d9cf7b) |
| 1312 | done | codex-max | QA → SARIF output (`out/qa-report.sarif`) | `src/iftypeset/qa.py`, `src/iftypeset/cli.py`, `app/CLI_SPEC.md`, `tests/test_qa.py` | Added `qa --format sarif` with SARIF mapping for incidents + gate failures; tests updated. | out/checkpoints/iftypeset_checkpoint_2026-01-04T09-44-43Z.tar.gz (sha256=462c75d2603d78ee51700f0b6b2e389b98a635f9e72e867cd2dd8ed92f1b78d6) |
| 1313 | done | codex-max | Add `iftypeset doctor` (env + determinism report) | `src/iftypeset/cli.py`, `src/iftypeset/reporting.py`, `docs/*` | Added doctor command + reports, docs, and integration test. | out/checkpoints/iftypeset_checkpoint_2026-01-04T09-48-23Z.tar.gz (sha256=f5436a975ae2902bf322f78b876230cef20d2e2f434446be0c057a1a485661d7) |
| 1314 | done | codex-max | Add `iftypeset bundle` (portable review pack) | `src/iftypeset/cli.py`, `src/iftypeset/reporting.py`, `scripts/*`, `docs/*` | Added bundle command + manifest + tests; updated docs. | out/checkpoints/iftypeset_checkpoint_2026-01-04T09-53-39Z.tar.gz (sha256=5ee682bc24e427261670d663e8e3fd1f6f6e7fa7e08c97802bbabfe21a30a55e) |
| 1315 | done | codex-max | PDF bbox/overflow detection via Poppler XML | `src/iftypeset/qa.py`, `tests/test_qa.py` | Added `pdftohtml -xml` parsing for bbox overflow + incidents/tests/docs. | out/checkpoints/iftypeset_checkpoint_2026-01-04T10-06-12Z.tar.gz (sha256=26ef3f54ad8978b2e60d3bdb23b6299e6b2ba526503523326d1bf399c1c78fc5) |
| 1316 | done | codex-max | Multi-doc runs + aggregate report index | `src/iftypeset/cli.py`, `src/iftypeset/reporting.py`, `tests/test_integration.py` | Added multi-doc `run` with per-doc outputs + top-level run index. | out/checkpoints/iftypeset_checkpoint_2026-01-04T10-01-21Z.tar.gz (sha256=52466c2ca8fb530c5dbccf822afa1425f69c87a2a5015d075e3f3246c9936be1) |
| 1317 | done | codex-max | Docker pinned environment (Chromium + Poppler + fonts) | `Dockerfile`, `docs/*`, `.forgejo/workflows/*` | Added Dockerfile, .dockerignore, docs, and manual Docker CI workflow. | out/checkpoints/iftypeset_checkpoint_2026-01-04T10-09-36Z.tar.gz (sha256=c96375484ea01d930a02068a929d6d37ba71d2519137ad05f82cbb850cc0f1f1) |
| 1318 | done | codex-mini | CLI PDF engine selection + require-pdf flag | `src/iftypeset/cli.py`, `src/iftypeset/rendering.py`, `src/iftypeset/config.py`, `app/CLI_SPEC.md`, `README.md`, `STATUS.md`, `tests/test_integration.py` | Added `--engine` and `--require-pdf` flags; run treats PDF failure as warning unless `--require-pdf`; config supports `engine` + `require_pdf`; docs/tests updated. | out/checkpoints/iftypeset_checkpoint_2026-01-04T14-41-49Z.tar.gz (sha256=728a877114c4263450946a7550a54d655c4d5db503ec14a352f84b9369c5454d) |
| 1319 | done | codex-mini | Editorial automation heuristics v1 | `src/iftypeset/linting.py`, `spec/rules/editorial/*`, `tests/test_linting.py` | Implement safe editorial lints (ALL CAPS headings, draft markers, acronym-first-use hints) + tests; keep the rest manual. | Lint rule added for ALL CAPS headings; rule set to lint; tests updated; validate-spec run. Pytest not available in env. |
| 1320 | done | codex-mini | Citations + i18n lint expansion | `src/iftypeset/linting.py`, `spec/rules/citations/*`, `spec/rules/i18n/*`, `tests/test_linting.py`, `spec/house/*` | Added author-date checks (year-only parenthetical + ref list year required), i18n mixed decimal/quote heuristics; new house pointers + rule batches; tests updated; validate-spec with indexes run. | |
| 1321 | done | codex-max | Typeset/CSS profile depth for tables/figures/code | `spec/profiles/*.yaml`, `src/iftypeset/rendering.py`, `docs/06-project-overview.md` | Added figure handling + CSS tokens; tightened code/table tokens (wrap, layout, padding); profiles updated and documented. | out/checkpoints/iftypeset_checkpoint_2026-01-04T16-50-45Z.tar.gz (sha256=712c0c07d39443a985e22b2bd44898b9460f2c705ae129ad180bcc436bd15661) |
| 1322 | done | codex-max | Rule coverage expansion Turn 1 (tables/figures/front/back/links) | `spec/rules/tables/*`, `spec/rules/figures/*`, `spec/rules/frontmatter/*`, `spec/rules/backmatter/*`, `spec/rules/links/*` | Added `v1_tables_003`, `v1_figures_004`, `v1_frontmatter_004`, `v1_backmatter_004`, `v1_links_004` (+120); validate/report run. | out/checkpoints/iftypeset_checkpoint_2026-01-04T15-36-58Z.tar.gz (sha256=c6c1e991ffb7f94a18a7a4c6e4e670b6177e4ba14050b118a1d6cc26c25eee83) |
| 1323 | done | codex-max | Rule coverage expansion Turn 2 (typography/layout/links remainder) | `spec/rules/typography/*`, `spec/rules/layout/*`, `spec/rules/links/*` | Added `v1_layout_005`, `v1_links_005`, `v1_typography_003` (+170); total_rules=844. | out/checkpoints/iftypeset_checkpoint_2026-01-04T16-03-52Z.tar.gz (sha256=ab7164561a811802f59880db38cb6b99e31c0a849b55a5f6970d4591a89fb89a) |
| 1324 | done | codex-max | Rule coverage expansion Turn 3 (punctuation/numbers/headings/abbreviations/accessibility) | `spec/rules/punctuation/*`, `spec/rules/numbers/*`, `spec/rules/headings/*`, `spec/rules/abbreviations/*`, `spec/rules/accessibility/*` | Added `v1_punctuation_003`, `v1_numbers_003`, `v1_headings_003`, `v1_abbreviations_004`, `v1_accessibility_004` (+104); totals: punctuation 67, numbers 91, headings 57, abbreviations 47, accessibility 40. | out/checkpoints/iftypeset_checkpoint_2026-01-04T16-27-47Z.tar.gz (sha256=82db561f98ac898097893018151868114e12fe96b6e8cf27a8cbe7408413fd84) |
| 1325 | done | codex-mini | CLI flag matrix + doc-only parity audit | `docs/16-cli-flags.md` | Added CLI flag matrix + defaults/exit codes + config precedence; doc-only parity audit. | |
| 1326 | done | codex-max | Rule coverage expansion Turn 4 (code/editorial) | `spec/rules/code/*`, `spec/rules/editorial/*`, `spec/house/HOUSE_CODE_POINTERS.md` | Added `v1_code_004`, `v1_editorial_002` (+38) and `HOUSE_CODE_POINTERS.md`; validate/report/CI run. | out/checkpoints/iftypeset_checkpoint_2026-01-04T17-05-45Z.tar.gz (sha256=ca932099b7ea535ee37881c8fbd391691c373a06266b3fb7e330c1cb3da705bb) |
| 1327 | done | codex-max | Rule coverage expansion Turn 5 (accessibility+i18n+front/back+figures/tables+code) | `spec/rules/accessibility/*`, `spec/rules/i18n/*`, `spec/rules/frontmatter/*`, `spec/rules/backmatter/*`, `spec/rules/figures/*`, `spec/rules/tables/*`, `spec/rules/code/*`, `spec/house/*` | Added new HOUSE pointer docs and batches: `v1_accessibility_005`, `v1_i18n_005`, `v1_frontmatter_005`, `v1_backmatter_005`, `v1_figures_005`, `v1_tables_004`, `v1_code_005` (+43); validate/report/CI run. | out/checkpoints/iftypeset_checkpoint_2026-01-04T17-36-14Z.tar.gz (sha256=6051e382c0e09f1e9d5737110d82325cbc5a1e6b6afcf91e4990c8d9be172fe3) |
| 1328 | done | codex-max | Turn 6: lint expansion + layout/typography + QA tighten + fixtures/tests | `src/iftypeset/linting.py`, `spec/rules/*`, `spec/quality_gates.yaml`, `fixtures/*`, `tests/*`, `spec/house/*` | Add new lint checks for citations/links, new house rules for layout/typography, tighten QA thresholds, add fixtures/tests. | out/checkpoints/iftypeset_checkpoint_2026-01-04T18-31-45Z.tar.gz (sha256=02f72e150f349bd3d22363654acc4c0fe0d3302ab566eeca84ff3632a70546f5) |
| 1329 | done | codex-max | Promote citations manual rules to lint/postrender (phase 1) | `src/iftypeset/linting.py`, `spec/rules/citations/*`, `tests/test_linting.py`, `fixtures/*` | Convert safe manual rules to deterministic lint checks; add fixtures/tests. | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-00-46Z.tar.gz (sha256=7a4b9a03e889b91cc59a247f76fa3e23471f4ead0db4d7424091e04d46c13b95) |
| 1330 | done | codex-max | Promote layout+typography manual rules to lint/postrender (phase 1) | `src/iftypeset/linting.py`, `src/iftypeset/qa.py`, `spec/rules/layout/*`, `spec/rules/typography/*`, `tests/*`, `fixtures/*` | Add safe heuristics (HTML+PDF) and tighten tests. | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-23-16Z.tar.gz (sha256=1da2bd36168525359ee559c3ef550994a5080b22a8c4cd76e3c0d2ccb822b26c) |
| 1331 | done | codex-max | Promote links manual rules to lint (phase 1) | `src/iftypeset/linting.py`, `spec/rules/links/*`, `tests/test_linting.py`, `fixtures/*` | Add deterministic URL lint checks; add fixtures/tests. | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-23-16Z.tar.gz (sha256=1da2bd36168525359ee559c3ef550994a5080b22a8c4cd76e3c0d2ccb822b26c) |
| 1332 | done | codex-max | Promote accessibility manual rules to lint/postrender (phase 1) | `src/iftypeset/linting.py`, `src/iftypeset/qa.py`, `spec/rules/accessibility/*`, `tests/*`, `fixtures/*` | Add safe a11y lints; add fixtures/tests. | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-23-16Z.tar.gz (sha256=1da2bd36168525359ee559c3ef550994a5080b22a8c4cd76e3c0d2ccb822b26c) |
| 1333 | done | codex-max | PDF QA: detect caption separation (figure/table) | `src/iftypeset/qa.py`, `spec/rules/layout/*`, `tests/test_qa.py`, `fixtures/*` | Add PDF heuristic incidents for captions separated from figures/tables (pdftotext). | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-36-17Z.tar.gz (sha256=6196acb5068176bc0f66b270644e3fed578150e3641834659a27ae04153bbd1b) |
| 1334 | done | codex-max | PDF QA: list break + lonely list item heuristics | `src/iftypeset/qa.py`, `spec/rules/layout/*`, `tests/test_qa.py`, `fixtures/*` | Add PDF heuristics for list intro separated from list, and single-item breaks. | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-36-17Z.tar.gz (sha256=6196acb5068176bc0f66b270644e3fed578150e3641834659a27ae04153bbd1b) |
| 1335 | done | codex-max | PDF QA: heading proximity (heading followed by heading / too little content) | `src/iftypeset/qa.py`, `spec/rules/layout/*`, `tests/test_qa.py`, `fixtures/*` | Expand heading proximity checks using PDF text extraction (beyond stranded headings). | out/checkpoints/iftypeset_checkpoint_2026-01-04T19-36-17Z.tar.gz (sha256=6196acb5068176bc0f66b270644e3fed578150e3641834659a27ae04153bbd1b) |
| 1336 | done | codex-max | Links auto phase 2: filetype labels + partial-word + html fallback + overlong labels | `src/iftypeset/linting.py`, `spec/rules/links/*`, `tests/test_linting.py`, `fixtures/*` | Add deterministic link text checks and auto lint rules. | out/checkpoints/iftypeset_checkpoint_2026-01-04T21-30-06Z.tar.gz (sha256=7fca95255ce5623b3fc6dd67863de466b2039dab7d16af7c474653bc66beed90) |
| 1337 | done | codex-cli (gpt-5.2-high) | Coverage roadmap + coverage map scaffold | `docs/19-coverage-roadmap.md`, `spec/coverage/**`, `docs/13-task-board.md` | Add coverage roadmap, create coverage map files, and document section-level tracking. | out/checkpoints/iftypeset_checkpoint_2026-01-07T03-01-18Z.tar.gz (sha256=421ba9fd06c73fffd126fa103e662c2119409d4bc0d75322fe9cd7120246a45b) |
| 1338 | done | | CMOS punctuation batch 1 (150250 rules) | `spec/rules/punctuation/**`, `spec/indexes/**`, `spec/coverage/**` | Completed sections 6.176.77 plus prior batches; total 211 rules, coverage refreshed; CI + checkpoint (supersedes earlier checkpoint). | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-21-20Z.tar.gz (sha256=c36701390a0e1e59344e57c770337bcb2a55a71a4e6ecb16a1c8c42417ed2b79) |
| 1339 | done | | CMOS numbers batch 1 (150250 rules) | `spec/rules/numbers/**`, `spec/indexes/**`, `spec/coverage/**` | Added v1_numbers_004 (152 rules) covering 9.19.36 plus coverage updates; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-28-12Z.tar.gz (sha256=f79b65f7454c350fe2a669e24a185397e3e8ef56954d4d6fa29b276fb5a8050e) |
| 1340 | done | | CMOS citations batch 1 (150250 rules) | `spec/rules/citations/**`, `spec/indexes/**`, `spec/coverage/**` | Added v1_citations_006 (151 rules) covering 13.113.29, updated CMOS coverage map; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T15-05-23Z.tar.gz (sha256=bb048267c831e00a7004c647b2cadb28a4211bade86920dda3658b421de948cc) |
| 1341 | done | | BRING typography + layout batch 1 (150250 rules) | `spec/rules/typography/**`, `spec/rules/layout/**`, `spec/indexes/**`, `spec/coverage/**` | Generated BRING coverage map for 213 existing typography/layout rules (57 sections); indexes + CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-34-42Z.tar.gz (sha256=ed49ff31a6f3aa04b8163c8eb2ef793a7374eb292a6f63182229e73aebfa3894) |
| 1342 | done | | BRING headings + lists batch 1 (150250 rules) | `spec/rules/headings/**`, `spec/indexes/**`, `spec/coverage/**` | Added BRING headings sections to coverage map (now 62 sections); indexes + CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-37-21Z.tar.gz (sha256=650e5c1cb14e2a7cf101606ed33b0c779351a9a777f944bafd05b5a5e49c21c7) |
| 1343 | done | | Tables + figures batch 1 (CMOS+BRING) | `spec/rules/tables/**`, `spec/rules/figures/**`, `spec/indexes/**`, `spec/coverage/**` | Mapped 107 existing CMOS/BRING table+figure rules into coverage; indexes + CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-39-56Z.tar.gz (sha256=d06a4325110722325a5c1664b9aab658ae7daa873e3a3580e78e79a9d4c787ea) |
| 1344 | done | | Links + code batch 1 (CMOS+BRING) | `spec/rules/links/**`, `spec/rules/code/**`, `spec/indexes/**`, `spec/coverage/**` | Added 12 CMOS/BRING rules (links + code) and merged into coverage; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-45-22Z.tar.gz (sha256=50ca8dfc35d3a2a37a1405f9d4079a865beb8d5301815190876fc12472d03414) |
| 1345 | done | | Coverage summary generator + status notes | `spec/coverage/**`, `tools/**`, `docs/09-project-status.md` | Added `tools/coverage_summary.py`, wrote JSON/MD outputs, updated status doc with coverage metrics; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T13-48-30Z.tar.gz (sha256=acdfb749162d6cc68015252fcc5fb97e761d86b49a1a37d0feb0c069145db743) |
| 1346 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Enforcement uplift: convert top manual rules | `src/iftypeset/linting.py`, `src/iftypeset/qa.py`, `spec/rules/**`, `tests/**` | Manual checklist now filters to `status=active`; deprecated duplicate manual link rules already covered by lint; tests + CI. | out/checkpoints/iftypeset_checkpoint_2026-01-08T02-32-29Z.tar.gz (sha256=f67b7e66bac77635c20eb67a19d4cfd19c67ba81e598aae3f4b3ac552ec8e5e1) |
| 1347 | done | | CMOS citations coverage map expansion (13.3013.54) | `spec/coverage/**`, `spec/indexes/**`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md` | Added uncovered stubs with pointers for sections 13.3013.54; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T16-16-51Z.tar.gz (sha256=1bd425530e38b0c184036284c599f3848005865655cd82529e8426753824bbfc) |
| 1348 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | CMOS citations batch 2 (13.3013.54) | `spec/rules/citations/**`, `spec/indexes/**`, `spec/coverage/**` | Paraphrase rules for shortened citations + note commentary sections; update coverage; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T16-58-28Z.tar.gz (sha256=83465c0cf67f41faceedd32dbbe6efbbd4d56f39bc719c088e8457c376da7437) |
| 1349 | done | | CMOS citations coverage map expansion (13.5513.73) | `spec/coverage/**`, `spec/indexes/**`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md` | Added uncovered stubs with pointers for sections 13.5513.73; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T16-18-36Z.tar.gz (sha256=d92bd833941d14e8c3e1a7ad08e474d324c1f84b30122e82f2226e988b6d0957) |
| 1350 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | CMOS citations batch 3 (13.5513.73) | `spec/rules/citations/**`, `spec/indexes/**`, `spec/coverage/cmos18_sections.json` | Added missing section rules + mapped existing rules into coverage; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-30-39Z.tar.gz (sha256=1981644b9360c07f438427f8bfc619cacb12ffc1d4b2076ceec4791f606065b8) |
| 1351 | done | | CMOS citations coverage map expansion (13.7413.90) | `spec/coverage/**`, `spec/indexes/**`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md` | Added uncovered stubs for sections 13.7413.89; 13.90 heading not found in OCR (update: §13.90 located later; coverage entry added in task 1366). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T16-21-51Z.tar.gz (sha256=ae332081fec080e14467a820461818cea1a7d8bc826a6b1efaa4c3589bd8c75c) |
| 1352 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | CMOS citations batch 4 (13.7413.90) | `spec/rules/citations/**`, `spec/indexes/**`, `spec/coverage/cmos18_sections.json` | Added missing author-name/bibliography rules and mapped 13.7413.89; 13.90 heading not found in OCR (update: coverage entry added in task 1366). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-34-08Z.tar.gz (sha256=a98615e17b4a44ffc7e3a255bf12cdd05f4f696d2f7a7ab4d493cd8532bc71e2) |
| 1353 | done | | CMOS citations coverage map expansion (13.9213.108) | `spec/coverage/**`, `spec/indexes/**`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md` | Added uncovered stubs for sections 13.9213.108; 13.91/13.94/13.99/13.107 headings not found in OCR (update: §13.91/§13.94/§13.107 located later; coverage entries added in task 1366; §13.99 still not found). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T16-23-38Z.tar.gz (sha256=38c1ee8a4dd1aa04acce09a5467a1b83e03a0e5d2a11fb901936cf4431360936) |
| 1354 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | CMOS citations batch 5 (13.9213.108) | `spec/rules/citations/**`, `spec/indexes/**`, `spec/coverage/cmos18_sections.json` | Added bibliography-format rules and mapped coverage for available sections; 13.94/13.99/13.107 headings not found in OCR (update: §13.94/§13.107 located later; coverage entries added in task 1366; §13.99 still not found). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-37-40Z.tar.gz (sha256=b17b44b48a47ac0643b241174cde7a6653b87ff25cda00b82548ff99780f02e1) |
| 1355 | done | | CMOS citations coverage map expansion (13.11113.128) | `spec/coverage/**`, `spec/indexes/**`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md` | Added uncovered stubs for sections 13.11113.128; 13.110 heading not found in OCR (update: §13.110 located later; coverage entry added in task 1366). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-07T16-25-43Z.tar.gz (sha256=7f61613b84b51f111bc427def728eab42a0e250b4fce3a3281f0b03f17737045) |
| 1356 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | CMOS citations batch 6 (13.11113.128) | `spec/rules/citations/**`, `spec/indexes/**`, `spec/coverage/cmos18_sections.json` | Added missing author-date rules and mapped 13.11113.128; 13.110 heading not found in OCR (update: coverage entry added in task 1366). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-42-42Z.tar.gz (sha256=c21fee9774f8fdd895a44a2f4de136a5f95d805bae26e18c94ca50c6833c11f0) |
| 1357 | done | assistant (api gpt-5.2) | Session ID hygiene in `iftypeset/AGENTS.md` | `AGENTS.md`, `docs/13-task-board.md` | Added session-id hygiene section to `iftypeset/AGENTS.md` (and kept the board claim note); no checkpoint (avoid colliding with active code task). | |
| 1358 | done | | Typography baseline: default 12pt body + add brand colors + table striping (fix “tiny text” reports) | `src/iftypeset/css_gen.py`, `spec/profiles/dense_tech.yaml`, `spec/profiles/memo.yaml`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md`, `AGENTS.md`, `docs/13-task-board.md` | Set CSS generator default body size to `12pt`; updated `dense_tech` + `memo` to 12pt baseline + brand colors + table striping; added header shading. Verified by rerendering flaneur report (dense_tech) and spot-checking PNG pre-renders; ran `./scripts/ci.sh`. | out/checkpoints/iftypeset_checkpoint_2026-01-07T17-34-10Z.tar.gz (sha256=c05b4ae504f5bf72795ed737f8f49e19b61906365f99a33d3ac2d58fe623c9e8) |
| 1359 | done | | Inline citations: make `[Sxx]` clickable and anchor to sources section | `src/iftypeset/rendering.py`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md`, `docs/13-task-board.md` | Fixed citation token parsing and rendered `[S01]`-style citations as internal links (`href=\"#cite-s01\"`); source lines starting with `[Sxx]` get matching `id=\"cite-sxx\"` anchors. Verified via `render-html` grep + `./scripts/ci.sh`. | out/checkpoints/iftypeset_checkpoint_2026-01-07T20-16-27Z.tar.gz (sha256=e185bf2251b7ce6a275400d8a73a1a560166b3ad48c947f66e664fa587d14dfb) |
| 1360 | done | | Add `audit_report` profile + QA gates for evidence-heavy reports (reduce false fails on long lines/tables) | `spec/profiles/audit_report.yaml`, `spec/quality_gates.yaml`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md`, `docs/13-task-board.md` | Added `audit_report` (12pt baseline, branded/striped tables, tolerant overfull measurement) + QA gates; verified via `iftypeset run --profile audit_report` on the flaneur report and `./scripts/ci.sh`. | out/checkpoints/iftypeset_checkpoint_2026-01-07T20-30-14Z.tar.gz (sha256=444a88b90bba249221931a45e07685328758bdc8db8a20b103ab494ff46202a6) |
| 1361 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Milestone B: BRING completion pass (partial → covered/out_of_scope) | `spec/coverage/bring_sections.json`, `spec/indexes/**` | Marked all BRING sections as `covered`; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-53-19Z.tar.gz (sha256=6f86b0c6d00fd44c1be67dad1ce5b3dbc0624254a1a93cfe684d7d68d63cb060) |
| 1362 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Milestone B: CMOS ch6 completion pass (punctuation sections) | `spec/coverage/cmos18_sections.json`, `spec/indexes/**` | Marked all tracked CMOS chapter 6 sections as `covered`; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-55-03Z.tar.gz (sha256=1c36b33ade3802dfb16a5fb72ce8e51c9ed7497f86c0ef2b18603d5bcd2e524e) |
| 1363 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Milestone B: CMOS ch9 completion pass (numbers sections) | `spec/coverage/cmos18_sections.json`, `spec/indexes/**` | Marked all tracked CMOS chapter 9 sections as `covered`; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-56-40Z.tar.gz (sha256=f39d4c1668222d7b12b3ea2e6e3d773ccfedda2b1b1a5e409f715a875e831309) |
| 1364 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Milestone B: CMOS ch13 completion pass (citations sections) | `spec/coverage/cmos18_sections.json`, `spec/indexes/**` | Marked all tracked CMOS chapter 13 sections as `covered`; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-59-57Z.tar.gz (sha256=dd5c3236276eff74443e04e43f10844dcb21402e45e6c584d67cb6cf6fb25f79) |
| 1365 | done | codex-cli (gpt-5) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Milestone B: CMOS ch1/ch3/ch5/ch15 completion pass | `spec/coverage/cmos18_sections.json`, `spec/indexes/**` | Marked all tracked CMOS chapter 1/3/5/15 sections as `covered`; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T03-58-16Z.tar.gz (sha256=a2626b2b59d158847a0ccd19ff177686e60166132e32a040ac7ca1568b7ddb4e) |
| 1366 | done | assistant (api gpt-5.2) | CMOS ch13: add missing section entries (OCR present) | `spec/coverage/cmos18_sections.json`, `docs/13-task-board.md`, `spec/indexes/**`, `docs/CHECKPOINTS.md`, `docs/SESSION_STATE.md` | Added coverage entries for §13.90/§13.91/§13.94/§13.107/§13.110 (status=`uncovered`) and updated stale “not found in OCR” notes; corrected §13.109 pointer; note: §13.90 pointer + §13.99 were corrected/added in task 1367. CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T04-57-18Z.tar.gz (sha256=4dd9699bd9083677e9f2e688d1b313967a94ed73a81322e78a335d8a6c50753a) |
| 1367 | done | assistant (api gpt-5.2) | CMOS ch13: close uncovered gaps (13.90/13.91/13.94/13.99/13.107/13.110) | `spec/rules/citations/**`, `spec/coverage/cmos18_sections.json`, `spec/indexes/**` | Added v1_citations_012 (one paraphrased rule per missing section), fixed §13.90/§13.110 pointer drift, added missing §13.99 coverage entry, and wired `rule_ids` (status→`partial`). CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T06-22-01Z.tar.gz (sha256=f3fba438d884adfb1523a0ff4e87b8ffc0e460b6992255c0543b63b4fa998572) |
| 1368 | done | assistant (api gpt-5.2) | Coverage audit: OCR heading diff + spot-check recipe | `tools/**`, `docs/19-coverage-roadmap.md`, `docs/13-task-board.md` | Added `tools/coverage_ocr_audit.py` (numbers-only OCR heading diff + pointer sanity checks) and documented a repeatable spot-check recipe in `docs/19-coverage-roadmap.md`. CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T06-22-01Z.tar.gz (sha256=f3fba438d884adfb1523a0ff4e87b8ffc0e460b6992255c0543b63b4fa998572) |
| 1369 | done | assistant (api gpt-5.2) [sid: unavailable] | Flaneur PDF: widen margins + eliminate Chromium CLI header/footer (Playwright-only) | `spec/profiles/audit_report.yaml`, `src/iftypeset/rendering.py`, `docs/**`, `Dockerfile` | Increased `audit_report` margins (18mm → 27mm); removed Chromium CLI PDF rendering (it injects date/path headers/footers on Chrome 143); Playwright PDF uses `prefer_css_page_size` + `scale=1`; list balancing now uses Playwright; docs/Docker updated. CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T09-39-02Z.tar.gz (sha256=2b7f1704eb57758e1252821bd3367b64f1705a2db254f3b0f58c44a2e8b30504) |
| 1370 | done | assistant (api gpt-5.2) [sid: unavailable] | Rendering contract: ban Chromium engine + pin Python 3.12 for Playwright | `src/iftypeset/cli.py`, `src/iftypeset/rendering.py`, `Dockerfile`, `pyproject.toml`, `requirements.txt`, `docs/**`, `app/CLI_SPEC.md` | Chromium engine is banned at CLI parse-time; `--engine auto` routes to Playwright; CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T13-39-43Z.tar.gz (sha256=f0df3101b956213bb4303062aecdea80a88424c062b43f78a14ba125416ebe58) |
| 1371 | done | assistant (api gpt-5.2) [sid: 019b9959-198d-7f22-b5f6-e7b598c8392b] | Fonts contract: prevent silent fallbacks + support corp font dirs | `src/iftypeset/{cli.py,rendering.py}`, `spec/profiles/audit_report.yaml`, `docs/**`, `app/CLI_SPEC.md` | Enforced a fonts contract (profile `fonts.require_primary` / `--strict-fonts`) and added `--font-dir` so corporate fonts can be supplied via mounted dirs; `render-log.json` now records font policy + embedded fonts. CI + checkpoint. | out/checkpoints/iftypeset_checkpoint_2026-01-08T17-55-08Z.tar.gz (sha256=23350894a965367138202c23fbe073400a38b5b936ceff75ae1faa80e6771552) |

View file

@ -0,0 +1,155 @@
# `iftypeset` as Document CI (the mental model)
`iftypeset` should behave like **eslint + a renderer + a preflight tool + a report generator**.
Rendering is *one* stage. The product is: **profiles + gates + artifacts + exit codes**.
This document is the “shared understanding” for humans and Codex sessions.
---
## The pipeline
**Input:** Markdown (plus assets)
**Profile:** `web_pdf`, `print_pdf`, `dense_tech`, `memo`, `slide_deck`
**Pipeline:** `validate → lint → render → qa → report`
**Output:**
- Machine artifacts (`*.json`, optionally `*.sarif`)
- Human artifacts (`*.md` and an `out/report/index.html`)
- Deterministic outputs (or explicit nondeterminism in the trust contract)
- Exit codes that CI can gate on (no “looks good on my machine”)
---
## The one command humans and CI want
```bash
iftypeset run --input docs/spec.md --profile web_pdf --out out
```
Expected behavior:
- Runs the full pipeline.
- Writes artifacts under `out/`.
- Exits **non-zero** when must-level gates fail.
- Prints a short, boring summary to stdout (what failed, where to look).
---
## Subcommands (when you want control)
### Spec + registry
```bash
iftypeset validate-spec --spec spec --build-indexes
iftypeset profiles list
iftypeset gates show --profile web_pdf
iftypeset rules list --category links
iftypeset rules show HOUSE.LINKS.URLS.PREFER_HTTPS
```
### Lint (source-level)
```bash
iftypeset lint --input docs/spec.md --profile web_pdf --out out
iftypeset lint --input docs/spec.md --profile web_pdf --out out --fix --fix-mode rewrite
```
### Rendering (adapter-based)
```bash
iftypeset render-html --input docs/spec.md --profile web_pdf --out out
iftypeset render-pdf --input docs/spec.md --profile web_pdf --out out
```
### Post-render QA (where the money is)
```bash
iftypeset qa --out out --profile web_pdf
```
### Reports (human artifact hub + trust contract)
```bash
iftypeset report --spec spec --out out
```
Outputs a clickable hub:
- `out/report/index.html`
- `out/trust-contract.md` and `out/trust-contract.json`
---
## Exit codes (CI-friendly)
The CLI should be unambiguous:
- `0`: pass (no failing gates)
- `1`: gate failed (must violations / gate thresholds breached)
- `2`: usage/config error (bad flags, missing profile, missing input)
- `3`: internal/tool error (renderer crash, missing dependency)
If we ever add “nondeterminism detected” as a separate code, it must be documented here and in `app/CLI_SPEC.md`.
---
## Artifacts (what you keep)
The durable contract is: everything important is written to `out/` and is stable across runs.
Minimum set:
- `out/lint-report.json`
- `out/manual-checklist.md` (and optionally `.json`)
- `out/render.html` + `out/render.css`
- `out/render.pdf` (when a PDF engine is available)
- `out/layout-report.json`
- `out/qa-report.json`
- `out/run-summary.json`
- `out/trust-contract.{md,json}`
- `out/report/index.html`
The trust contract must state, in plain language:
- what is enforced automatically vs manual checklist
- QA limitations (what we detect vs what we currently miss)
- determinism assumptions (renderer version, fonts, locale)
---
## Configuration
Repo defaults live in `iftypeset.yaml`. Priority order:
1. CLI flags
2. `iftypeset.yaml`
3. profile defaults
4. hard defaults
Humans need predictable overrides because humans are chaos.
---
## Profiles are the product
A profile is a contract, not a vibe:
- which rules apply
- which are `must` vs `should`
- which incidents fail gates
- which tokens/CSS are used
- which renderer(s) are recommended
Everything emitted should name the profile explicitly.
---
## Traps to avoid
- Treating `iftypeset` as “pretty PDF generator” instead of CI for doc quality.
- Shipping false authority (big rule counts) without a clear enforced/manual split.
- Overfitting to one renderer (adapters are the point).
- Sneaking copyrighted text into the repo (paraphrase + pointer discipline is non-negotiable).

212
docs/14-external-review.md Normal file
View file

@ -0,0 +1,212 @@
# iftypeset external review pack (public technical overview)
This document is a self-contained brief for external reviewers. It explains what the project does, what is implemented today, how to verify it locally, and what limitations remain. It does not include any copyrighted book text.
## Scope and non-negotiables
- No Chicago/Bringhurst text is stored here. Rules are paraphrases with pointer refs only.
- The runtime is deterministic by design, but PDF output still depends on the chosen renderer and fonts.
- QA is rule- and heuristic-based; it does not claim perfect layout verification.
## What iftypeset is
`iftypeset` is a deterministic Markdown -> HTML -> PDF pipeline with:
- a machine-readable rule registry (NDJSON) with paraphrased rules + pointers
- profiles that map typographic intent into CSS tokens
- lint + QA gates that surface layout failures and fail builds in CI
The core value is not "pretty PDF." It is verifiable, repeatable quality gates and explicit limits.
## What is implemented now
Runtime surface (CLI):
- `validate-spec`, `report`, `lint`, `render-html`, `render-pdf`, `qa`, `emit-css`, `run`
- introspection: `profiles list`, `gates show`, `rules list`, `rules show`
Artifacts produced:
- `out/lint-report.json`, `out/manual-checklist.md/json`
- `out/render.html`, `out/render.css`, `out/render.pdf` (if renderer present)
- `out/layout-report.json`, `out/qa-report.json`
- `out/coverage-report.json`, `out/coverage-summary.md`
- `out/trust-contract.md/json`
- `out/report/index.html` (HTML index of all artifacts)
- `out/run-summary.json` (CI-style run summary)
## Quick verification (local)
From the repo root:
```bash
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install -r requirements.txt
python3 -m pip install -e .
iftypeset validate-spec --spec spec --build-indexes
iftypeset run --input fixtures/sample.md --out out --profile web_pdf --degraded-ok --skip-pdf
iftypeset report --spec spec --out out
```
Expected files after a successful run:
- `out/run-summary.json`
- `out/report/index.html`
- `out/lint-report.json`
- `out/render.html`
- `out/layout-report.json`
- `out/qa-report.json`
If you have a PDF engine installed, omit `--skip-pdf` and expect `out/render.pdf` + `out/render-log.json`.
## Proof points (code excerpts)
Console entrypoint (shows the CLI is installed as a tool):
```toml
[project.scripts]
iftypeset = "iftypeset.cli:main"
```
CI pipeline definition (ensures spec validation + report + tests run):
```bash
run_step "validate-spec" env PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes
run_step "report" env PYTHONPATH=src python3 -m iftypeset.cli report --spec spec --out out --build-indexes
run_step "tests" python3 -m unittest discover -s tests -p 'test_*.py'
```
End-to-end integration test (lint -> render -> qa):
```python
lint = subprocess.run([... "lint", "--input", fixture, "--out", out_dir, "--profile", "web_pdf"], ...)
render = subprocess.run([... "render-html", "--input", fixture, "--out", out_dir, "--profile", "web_pdf"], ...)
qa = subprocess.run([... "qa", "--out", out_dir, "--profile", "web_pdf"], ...)
```
CI-style `run` command writes a single summary artifact:
```json
{
"ok": true,
"exit_code": 0,
"started_at_utc": "...",
"finished_at_utc": "...",
"steps": [
{"name": "validate-spec", "rc": 0, "ok": true},
{"name": "lint", "rc": 0, "ok": true},
{"name": "render-html", "rc": 0, "ok": true},
{"name": "render-pdf", "rc": 3, "ok": false},
{"name": "qa", "rc": 0, "ok": true},
{"name": "report", "rc": 0, "ok": true}
]
}
```
## Rule registry (how to read it)
- NDJSON files in `spec/rules/**.ndjson`
- Schema in `spec/schema/rule.schema.json`
- Pointers in `source_refs` (e.g., `CMOS18 §X.Y pNNN (scan pMMM)` or `HOUSE §... pN`)
- No verbatim book text is stored in this repo
Example record shape (paraphrased, non-quoted):
```json
{
"id": "HOUSE.LINKS.URLS.PREFER_HTTPS",
"category": "links",
"severity": "should",
"enforcement": "lint",
"rule_text": "Prefer https links in published outputs."
}
```
## Lint and manual checklist
- Automated rules are enforced in `src/iftypeset/linting.py`.
- Non-automated rules are tagged `manual_checklist=true` and emitted to `out/manual-checklist.md`.
- This ensures reviewers see what still needs human validation.
## QA (HTML + PDF)
HTML analysis:
- detects overfull tokens, table/code overflow risk, long URL wrapping risk
PDF analysis (heuristic):
- uses Poppler (`pdfinfo`, `pdftotext -layout`) to extract per-page text
- detects widows/orphans, stranded headings, overfull lines
- warnings are explicit about heuristic limits
## Renderers
`render-pdf` uses the requested engine (default: `playwright`):
1) `playwright` (preferred; supports header/footer templates)
2) `wkhtmltopdf` (explicit `--engine wkhtmltopdf` only)
3) `weasyprint` (explicit `--engine weasyprint` only)
If no engine is present, `render-pdf` returns exit code 3 and QA continues with HTML.
## Trust contract
`iftypeset report` generates:
- `out/trust-contract.md`
- `out/trust-contract.json`
These explicitly state:
- enforced vs manual coverage
- QA limitations
- determinism assumptions
This is the preferred artifact for external review.
## Production readiness (what is true today)
Verified by CI and tests:
- spec validation and coverage reporting are deterministic
- lint emits JSON + manual checklist and is stable across runs
- HTML rendering is deterministic given the same inputs
- QA gates are enforced with explicit exit codes
- `run` provides a single CI-friendly summary artifact
Known limitations:
- PDF QA is heuristic, not geometry-accurate
- PDF output depends on renderer + font availability, but `render-log.json` records font resolution/embedding and profiles can enforce a strict fonts contract to prevent silent fallbacks
- not all rules are automated; manual checklist remains required
## Where to look in the repo
- CLI: `src/iftypeset/cli.py`
- Linting: `src/iftypeset/linting.py`
- QA: `src/iftypeset/qa.py`
- Rendering: `src/iftypeset/rendering.py`
- Rule schema: `spec/schema/rule.schema.json`
- Rule batches: `spec/rules/**.ndjson`
- Profiles: `spec/profiles/*.yaml`
- Trust contract: `out/trust-contract.md` (generated)
- Report index: `out/report/index.html` (generated)
## Forgejo integration (worker)
The Forgejo worker can load the `iftypeset-web_pdf` theme (vendored CSS). See:
- `forgejo/README.md` in this repo
- `worker/pdf/README.md` in the forgejo-pdf repo
## Contact and review checklist
For external review, please verify:
1) `iftypeset run` succeeds and produces `out/run-summary.json`
2) `out/report/index.html` links to all expected artifacts
3) `out/trust-contract.md` reflects the current enforcement split
4) `out/manual-checklist.md` exists and is non-empty

64
docs/15-docker.md Normal file
View file

@ -0,0 +1,64 @@
# Docker runtime (pinned, reproducible)
Goal: provide a **deterministic-ish** runtime that includes Playwright (browser-based PDF), Poppler, and fonts so
Markdown → HTML → PDF pipelines behave the same in CI and on developer machines.
## Whats included
- Base image: `python:3.12.12-slim-bookworm`
- Renderers: `playwright` (drives a headless browser for PDF)
- QA tools: `poppler-utils` (`pdfinfo`, `pdftotext`, `pdftohtml`)
- Fonts: `fonts-dejavu-core`, `fonts-liberation`, `fonts-noto-core`
The Dockerfile lives at `Dockerfile` and installs pinned Python deps from `requirements.txt`.
## Build
```bash
docker build -t iftypeset:dev .
```
## Run (single document)
```bash
docker run --rm \
-v "$PWD":/workspace \
-w /workspace \
iftypeset:dev \
iftypeset run --input fixtures/sample.md --out out --profile web_pdf --degraded-ok
```
## Corporate fonts (optional)
To avoid font fallback drift (e.g., when shipping reader-facing PDFs), mount a directory containing `.ttf`/`.otf` files and pass it via `--font-dir`:
```bash
docker run --rm \
-v "$PWD":/workspace \
-v "$PWD/fonts":/fonts:ro \
-w /workspace \
iftypeset:dev \
iftypeset run --input fixtures/sample.md --out out --profile audit_report --font-dir /fonts --strict-fonts
```
## Run (directory / multi-doc)
```bash
docker run --rm \
-v "$PWD":/workspace \
-w /workspace \
iftypeset:dev \
iftypeset run --input fixtures --out out --profile web_pdf --degraded-ok --skip-pdf
```
## Version pinning notes
- The base image tag is pinned to a specific Python + Debian release.
- System package versions are pinned by the Debian snapshot at build time.
- For auditability, run `iftypeset doctor --spec spec --out out` inside the container and
record `out/doctor.md` with the exact tool versions.
## CI usage (Forgejo)
A manual Forgejo workflow (`.forgejo/workflows/docker-ci.yml`) builds this image and runs
`scripts/ci.sh` inside the container. Trigger it when you want an environment-pinned check.

168
docs/16-cli-flags.md Normal file
View file

@ -0,0 +1,168 @@
# iftypeset CLI flags (current v0 + parity notes)
This file captures the **current CLI surface** (as of 2026-01-04) from `iftypeset --help` and per-command `--help`, plus how config overrides are resolved. It is doc-only; no code/spec edits.
Sources used:
- `app/CLI_SPEC.md` (target contract)
- `src/iftypeset/config.py` (config precedence + keys)
- CLI help output for each command
## Precedence and config
Order of precedence (highest → lowest):
1. CLI flags
2. `iftypeset.yaml` (in repo root or `spec/..`)
3. Hard defaults
Config sections:
- `defaults`: global fallback values
- Per-command section by name (hyphen → underscore)
- `render_html` / `render_pdf` also read from `render` section
Supported config keys (from `config.py`):
- `spec`, `out`, `profile`, `strict`, `format`, `fail_on`, `degraded_ok`,
`fix`, `fix_mode`, `self_contained`, `engine`, `require_pdf`, `skip_pdf`
## Top-level flags
```
iftypeset [-h] [--config CONFIG] [--version]
```
- `--config`: path to `iftypeset.yaml` (default: `./iftypeset.yaml` when present)
- `--version`: print version and exit
## Command index (current)
| Command | Purpose (short) | Required args | Key optional flags |
| --- | --- | --- | --- |
| `validate-spec` | Validate spec/rules; optional index build | none | `--spec`, `--out`, `--build-indexes` |
| `profiles list` | List profiles | none | `--spec` |
| `gates show` | Show QA gates | none | `--spec`, `--profile`, `--strict` |
| `rules list` | List rules with filters | none | `--spec`, `--category`, `--enforcement`, `--severity`, `--tag` |
| `rules show` | Show rule by id | `rule_id` | `--spec` |
| `report` | Coverage + report artifacts | none | `--spec`, `--out`, `--strict`, `--build-indexes` |
| `doctor` | Environment diagnostics | none | `--spec`, `--out` |
| `bundle` | Bundle out/ artifacts | none | `--out`, `--bundle`, `--max-size-mb` |
| `run` | Full pipeline | `--input` | `--spec`, `--out`, `--profile`, `--strict`, `--format`, `--fail-on`, `--degraded-ok`, `--fix`, `--fix-mode`, `--self-contained`, `--engine`, `--require-pdf`, `--skip-pdf` |
| `lint` | Lint + manual checklist | `--input` | `--spec`, `--out`, `--profile`, `--format`, `--fail-on`, `--degraded-ok`, `--fix`, `--fix-mode` |
| `render-html` | Deterministic HTML/CSS | `--input` | `--spec`, `--out`, `--profile`, `--self-contained`, `--degraded-ok` |
| `render-pdf` | Render PDF | `--input` | `--spec`, `--out`, `--profile`, `--self-contained`, `--engine` |
| `qa` | Post-render QA | none | `--spec`, `--out`, `--html`, `--pdf`, `--profile`, `--strict`, `--format` |
| `emit-css` | Emit profile CSS | none | `--spec`, `--profile`, `--out` |
## Detailed flags by command
### validate-spec
```
iftypeset validate-spec [--spec SPEC] [--out OUT] [--build-indexes]
```
- `--spec`: spec root (default: `./spec`)
- `--out`: output dir (default: `./out`)
- `--build-indexes`: write indexes to `spec/indexes/`
### profiles list
```
iftypeset profiles list [--spec SPEC]
```
### gates show
```
iftypeset gates show [--spec SPEC] [--profile PROFILE] [--strict]
```
### rules list
```
iftypeset rules list [--spec SPEC] [--category CATEGORY]
[--enforcement ENFORCEMENT] [--severity SEVERITY] [--tag TAG]
```
### rules show
```
iftypeset rules show [--spec SPEC] rule_id
```
### report
```
iftypeset report [--spec SPEC] [--out OUT] [--strict] [--build-indexes]
```
### doctor
```
iftypeset doctor [--spec SPEC] [--out OUT]
```
### bundle
```
iftypeset bundle [--out OUT] [--bundle BUNDLE] [--max-size-mb MAX_SIZE_MB]
```
### run
```
iftypeset run --input INPUT [--spec SPEC] [--out OUT]
[--profile PROFILE] [--strict] [--format {json,sarif,text}]
[--fail-on {must,should,warn}] [--degraded-ok]
[--fix] [--fix-mode {suggest,rewrite}] [--lint-fixed]
[--self-contained] [--engine ENGINE]
[--require-pdf] [--skip-pdf]
```
### lint
```
iftypeset lint --input INPUT [--spec SPEC] [--out OUT]
[--profile PROFILE] [--format {json,sarif,text}]
[--fail-on {must,should,warn}] [--degraded-ok]
[--fix] [--fix-mode {suggest,rewrite}] [--lint-fixed]
```
### render-html
```
iftypeset render-html --input INPUT [--spec SPEC] [--out OUT]
[--profile PROFILE] [--self-contained] [--degraded-ok]
```
### render-pdf
```
iftypeset render-pdf --input INPUT [--spec SPEC] [--out OUT]
[--profile PROFILE] [--self-contained] [--engine ENGINE]
```
### qa
```
iftypeset qa [--spec SPEC] [--out OUT] [--html HTML] [--pdf PDF]
[--profile PROFILE] [--strict] [--format {json,sarif}]
```
### emit-css
```
iftypeset emit-css [--spec SPEC] [--profile PROFILE] [--out OUT]
```
## Defaults (current)
- `spec`: `./spec`
- `out`: `./out`
- `profile`: `web_pdf` (unless overridden by config)
- `engine`: `playwright` (for `run` and `render-pdf`; use `--engine auto` for fallback)
- `format`: `json` (when supported)
- `fail-on`: `must`
- `max-size-mb`: `50`
## Exit codes (documented target)
The current CLI aligns to the exit code model in `app/CLI_SPEC.md`:
- `0`: success
- `1`: gates/thresholds failed (lint/qa/report)
- `2`: config/schema error
- `3`: renderer/tool error (pdf)
## Parity notes vs `app/CLI_SPEC.md`
- `--config` exists at top-level and is honored by `config.py`.
- `run` includes `--require-pdf` and `--skip-pdf`, matching the spec.
- `lint` supports `--fix` and `--fix-mode`.
- `lint` supports `--lint-fixed` to lint the rewritten output when using `--fix --fix-mode rewrite`.
- `qa` supports `--format sarif` (HTML/PDF QA output).
- `doctor`, `bundle`, and `emit-css` are implemented and documented.
If new flags are added in code, update this file and the task board parity task.

View file

@ -0,0 +1,84 @@
# Rendering pipeline (Markdown -> HTML -> PDF)
This doc explains how a page is built. iftypeset always renders HTML + CSS first, then optionally renders PDF.
## Flow diagram (file flow)
```
Markdown (.md)
|
v
parse_markdown (src/iftypeset/md_parser.py)
|
v
render-html (src/iftypeset/rendering.py)
|-- out/render.html
|-- out/render.css
|-- out/typeset-report.json
|-- out/degraded-mode-report.json (if degraded input)
|
v
render-pdf (engine adapter)
|-- out/render.pdf
|-- out/render-log.json
|
v
qa (src/iftypeset/qa.py)
|-- out/layout-report.json
|-- out/qa-report.json
```
Lint and reporting are parallel entry points that do not require PDF:
```
lint (src/iftypeset/linting.py)
|-- out/lint-report.json
|-- out/manual-checklist.md
report (src/iftypeset/reporting.py)
|-- out/report/index.html
|-- out/coverage-report.json
|-- out/trust-contract.md
|-- out/trust-contract.json
```
## Step-by-step (what actually happens)
1) Read Markdown, normalize newlines, detect degraded input, and unwrap hard wraps when needed.
2) Parse Markdown into blocks (heading, paragraph, list, code fence, blockquote, table).
3) Render HTML by mapping blocks to tags and applying inline transforms:
- Links and images are preserved
- Citation tokens like [S01] are wrapped for styling
- Optional small-caps wrapping for acronyms (profile-controlled)
4) Generate CSS from the selected profile:
- Page size and margins
- Fonts and sizes
- Colors, tables, lists, figures, code blocks
- Running-head config (if enabled for supported engines)
5) Render PDF using the requested engine (default: Playwright):
- Writes a render log with engine versions and warnings
6) QA scans HTML output, and if a PDF exists it also runs PDF-aware heuristics.
## Where to change behavior
- Profiles and tokens: `spec/profiles/*.yaml`
- HTML mapping + table typing: `src/iftypeset/rendering.py`
- CSS generation: `src/iftypeset/css_gen.py`
- Markdown parsing: `src/iftypeset/md_parser.py`
- QA rules and thresholds: `src/iftypeset/qa.py`, `spec/quality_gates.yaml`
- Lint rules and logic: `src/iftypeset/linting.py`, `spec/rules/**`
## Commands (repro)
```
iftypeset render-html --input fixtures/sample.md --out out --profile web_pdf
iftypeset render-pdf --input fixtures/sample.md --out out --profile web_pdf
iftypeset qa --out out --profile web_pdf
```
## Notes on determinism
- HTML + CSS is deterministic for the same input + profile.
- PDF output depends on the renderer and installed fonts; versions are recorded in `out/render-log.json`.
- Profiles can enable a strict fonts contract (`fonts.require_primary: true`) and the CLI can force it via `--strict-fonts`; use `--font-dir` to supply corporate fonts and avoid silent fallbacks.
- Running heads are injected only for engines that support header/footer templates.

View file

@ -0,0 +1,31 @@
# WebTypography profile (non-commercial)
This repo includes a **non-commercial** profile inspired by WebTypography.net.
## Profile id
- `webtypography_nc`
## License and attribution
The profile is derived from guidance in WebTypography.net, which is licensed
under **CC BY-NC 4.0** (Attribution-NonCommercial).
If you use this profile, you must:
- Attribute the source (WebTypography.net / clagnut/webtypography).
- Use it **only for non-commercial purposes**.
License reference:
- https://creativecommons.org/licenses/by-nc/4.0/
Source repository:
- https://github.com/clagnut/webtypography
## Notes
- This profile is optional and not the default.
- It is kept separate so commercial use of `iftypeset` can avoid non-commercial
constraints by selecting a different profile (e.g., `web_pdf`).

View file

@ -0,0 +1,92 @@
# Rule Coverage Roadmap (CMOS / Bringhurst)
Goal: move coverage close to **100% of rule-bearing sections** in the Chicago Manual of Style (18th ed) and Bringhurst (Elements of Typographic Style), without reproducing book text.
## Definition of "100%"
Coverage is **section-based**, not "full-book OCR." To keep multi-session work honest and queueable, we track two milestones:
- **Milestone A (mapped):** a section is no longer `uncovered` once at least one paraphrased rule exists with a valid pointer. In practice this corresponds to `status=partial` in the coverage map.
- **Milestone B (complete):** a section is only considered complete once it is marked `covered` or `out_of_scope`.
- `covered` means a completion pass was done and the sections rule-bearing guidance is believed to be fully represented as paraphrased rules (no verbatim text).
- `out_of_scope` means the section is primarily narrative/historical/non-prescriptive and is explicitly excluded.
This avoids over-claiming: `partial` means “some rules exist”, not “were done.”
## Inputs (local only)
- `/root/docs/_uploads/The Chicago Manual of Style (18th ed OCR).pdf`
- `/root/docs/_uploads/Robert Bringhurst The Elements of Typographic Style (OCR).pdf`
OCR is used only to locate sections + page pointers. No verbatim text enters the repo.
## Artifacts (new)
- `spec/coverage/cmos18_sections.json`
- `spec/coverage/bring_sections.json`
- `spec/coverage/README.md`
- `spec/coverage/coverage_summary.json` (optional, derived)
Each entry should track: `section_id`, `title`, `pointer`, `status` (`uncovered|partial|covered|out_of_scope`), and `rule_ids[]`.
## Phases
### Phase 0: Coverage Map Scaffold
- Create coverage files + schema conventions.
- Seed with top-level sections and a few subsections to validate the workflow.
### Phase 1: High-Impact Rules (CMOS)
- numbers, punctuation, citations, headings, links.
- Batch size: 150250 rules per category.
### Phase 2: Structure + Layout (BRING + CMOS)
- typography, layout, widows/orphans, tables, figures.
- Translate to `typeset`/`postrender` where possible.
### Phase 3: Remaining Categories
- code, front/back matter, accessibility, i18n.
### Phase 4: Enforcement Uplift
- Convert top-impact manual rules to `lint`/`postrender` where feasible.
- Tighten QA gates without breaking deterministic behavior.
## Rules of engagement
- Paraphrase only; no verbatim text.
- If exact wording is required, use: `Exact wording required—refer to pointer`.
- Every rule must include a `source_refs` pointer.
- Prefer **numbers-only** audits when validating coverage maps against OCR.
- Run:
- `PYTHONPATH=src python3 -m iftypeset.cli validate-spec --spec spec --build-indexes`
- `./scripts/ci.sh`
- Checkpoint after meaningful batches: `./scripts/checkpoint.sh "extraction <category> batch <NNN>"`
## Spot checks (numbers only)
To reduce “missing section” drift, use the OCR audit helper to compare **section numbers only**
against the coverage map within a scan range (and to sanity-check pointer scan/printed pages).
Example (CMOS18 chapter 13 slice):
```bash
python3 tools/coverage_ocr_audit.py \
--pdf "/root/docs/_uploads/The Chicago Manual of Style (18th ed OCR).pdf" \
--coverage spec/coverage/cmos18_sections.json \
--chapter 13 \
--scan-start 840 \
--scan-end 870 \
--out-json out/coverage-ocr-audit-ch13.json \
--out-md out/coverage-ocr-audit-ch13.md
```
Interpretation:
- `OCR-only` section ids likely need new coverage entries.
- `Coverage-only` section ids often indicate pointer drift or OCR weirdness (verify the scan page).
- `Printed page mismatches` are strong signals that a pointer is wrong or that the scan page is not the referenced content.
## Progress metrics
- `% sections mapped` per book (non-`uncovered`).
- `% sections complete` per book (`covered` + `out_of_scope`).
- `must` rules implemented coverage (CI floor = 95%).
- Overall implemented coverage (CI floor = 80%).

View file

@ -7,6 +7,7 @@ How to create a checkpoint:
- `./scripts/checkpoint.sh "short note about what changed"`
Each entry records the snapshot tarball path + sha256 and the CI JSON for that moment.
Newer entries also include a `details` markdown file with a diffstat + working tree counts to make changes reviewable even if chat context is lost.
## 2026-01-03T20:09:44Z
@ -15,3 +16,810 @@ Each entry records the snapshot tarball path + sha256 and the CI JSON for that m
- ci_json: `out/checkpoints/ci_2026-01-03T20-09-44Z.json`
- note: first checkpoint test
## 2026-01-03T20:54:58Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T20-54-58Z.tar.gz`
- snapshot_sha256: `adbc13a46b0141253f74fe7f0c9e2705f044525251831ac4ba4141a7e19d97bc`
- ci_json: `out/checkpoints/ci_2026-01-03T20-54-58Z.json`
- note: expanded rules to 479; CI green
## 2026-01-03T21:02:54Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T21-02-54Z.tar.gz`
- snapshot_sha256: `2014ff7c106196144541a76474f2a3251bcc2efef37e4d0f9d9a68820ba0521c`
- ci_json: `out/checkpoints/ci_2026-01-03T21-02-54Z.json`
- note: update STATUS to 479 rules; add repo AGENTS.md
## 2026-01-03T21:08:41Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T21-08-41Z.tar.gz`
- snapshot_sha256: `1a6a072f8efca84d0fa86e36a342822d7bf12e0af58e71b39a985cec898352c8`
- ci_json: `out/checkpoints/ci_2026-01-03T21-08-41Z.json`
- note: codex-max: QA analyzer improvements + lint rewrite safety + new fixtures/tests
## 2026-01-03T21:21:04Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T21-21-04Z.tar.gz`
- snapshot_sha256: `feab598ca674e5d54922276c926bbbd20f0da343046f1e9788cd3225810bf8fd`
- ci_json: `out/checkpoints/ci_2026-01-03T21-21-04Z.json`
- note: add docs/08-handoff.md; link from README
## 2026-01-03T22:04:18Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T22-04-18Z.tar.gz`
- snapshot_sha256: `cedfca7d70a93e0526e63b9833aa6a3c29703b51dc90d12c626141096a6a096e`
- ci_json: `out/checkpoints/ci_2026-01-03T22-04-18Z.json`
- note: add editorial rules: v1_editorial_001
## 2026-01-03T22:12:03Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T22-12-03Z.tar.gz`
- snapshot_sha256: `2a31b12bacf66ad38137d006d62b1f5093c0b84a1cf40b455c7605f8b50ea7ef`
- ci_json: `out/checkpoints/ci_2026-01-03T22-12-03Z.json`
- note: resume script + canonical status trap note
## 2026-01-03T22:13:31Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T22-13-31Z.tar.gz`
- snapshot_sha256: `017f0d4622586676454e0379a31361a1aeadf0fe41e89e8c353e7ac5362062e8`
- ci_json: `out/checkpoints/ci_2026-01-03T22-13-31Z.json`
- note: include AGENTS.md in checkpoints
## 2026-01-03T22:19:23Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T22-19-23Z.tar.gz`
- snapshot_sha256: `233e117f2973b77d6912788063bec4888c0e510ff07efd6aa2af484d2665e30a`
- ci_json: `out/checkpoints/ci_2026-01-03T22-19-23Z.json`
- note: trust contract + entrypoint
## 2026-01-03T22:41:27Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T22-41-27Z.tar.gz`
- snapshot_sha256: `089af30bbe08d0433534b667bf0fb9bd5a2af65c57d8e4e4dbab92e99c5759c1`
- ci_json: `out/checkpoints/ci_2026-01-03T22-41-27Z.json`
- note: docs: add project brief + session resilience note
## 2026-01-03T22:57:22Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T22-57-22Z.tar.gz`
- snapshot_sha256: `aba3cf17cb9a9d5793598fbda600f0c0fd026fea43565f031860419629ea6b3c`
- ci_json: `out/checkpoints/ci_2026-01-03T22-57-22Z.json`
- note: session state artifact + checkpoint integration
## 2026-01-03T23:41:09Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-03T23-41-09Z.tar.gz`
- snapshot_sha256: `35940c6df1c134281e3cfe9b14dc54c5a9c2fa018edd863cde7f9734d267ee22`
- ci_json: `out/checkpoints/ci_2026-01-03T23-41-09Z.json`
- note: pdf-aware QA (widows/orphans)
## 2026-01-04T00:29:13Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T00-29-13Z.tar.gz`
- snapshot_sha256: `dabe0e2acb1c83afcfa0ffe4ddd448439ad8b99267d22fbfb4a71ce2a09f542f`
- ci_json: `out/checkpoints/ci_2026-01-04T00-29-13Z.json`
- note: audit+session-state refresh
## 2026-01-04T05:20:47Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T05-20-47Z.tar.gz`
- snapshot_sha256: `3078a3cce3dca02336e49d3d4c261308f2078d22c0e6ace58bc6635f1b03f8b5`
- ci_json: `out/checkpoints/ci_2026-01-04T05-20-47Z.json`
- note: forgejo integration + pdf qa expansion
## 2026-01-04T05:58:38Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T05-58-38Z.tar.gz`
- snapshot_sha256: `42e99c3676c8423194cb3bbdca9ff635eff7bfd60af29a6ca0788b10aca7fe4d`
- ci_json: `out/checkpoints/ci_2026-01-04T05-58-38Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T05-58-38Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=48 (modified=20, untracked=28)
- note: task 1303: md parser robustness
## 2026-01-04T06:03:53Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-03-53Z.tar.gz`
- snapshot_sha256: `a781c760a44691aa9ff110de6c6d2022280034be3d2c05c247c0c74a5e3048b9`
- ci_json: `out/checkpoints/ci_2026-01-04T06-03-53Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-03-53Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=48 (modified=20, untracked=28)
- note: task 1304: lint enforcement coverage
## 2026-01-04T06:04:12Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-04-12Z.tar.gz`
- snapshot_sha256: `da61e7582893074d5c288ded916c75d3306d960847692ad2f9e7cfa326fab502`
- ci_json: `out/checkpoints/ci_2026-01-04T06-04-12Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-04-12Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=48 (modified=20, untracked=28)
- note: task board: add CI-style CLI roadmap tasks
## 2026-01-04T06:05:22Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-05-22Z.tar.gz`
- snapshot_sha256: `a3aa47e3ee759328e3531ed3a0c49801bb8cfd430cb403978ff91b9a18001746`
- ci_json: `out/checkpoints/ci_2026-01-04T06-05-22Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-05-22Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=48 (modified=20, untracked=28)
- note: task 1306: packaging and UX
## 2026-01-04T06:10:01Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-10-01Z.tar.gz`
- snapshot_sha256: `d493f39ba9fcf708eb38cab11dd20762a4a361a3a635e30feedfad7e577c6d7c`
- ci_json: `out/checkpoints/ci_2026-01-04T06-10-01Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-10-01Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=49 (modified=21, untracked=28)
- note: task 1307: run pipeline
## 2026-01-04T06:16:12Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-16-12Z.tar.gz`
- snapshot_sha256: `b978bb5cb21fbccd669307e800494b3344818e25fbae521df953f30e099cf595`
- ci_json: `out/checkpoints/ci_2026-01-04T06-16-12Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-16-12Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=50 (modified=21, untracked=29)
- note: task 1308: config support
## 2026-01-04T06:18:36Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-18-36Z.tar.gz`
- snapshot_sha256: `ab8c60da431acc224c189a180b20aa33d3173d49e10a7c9b179dfecd3c9261e5`
- ci_json: `out/checkpoints/ci_2026-01-04T06-18-36Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-18-36Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=50 (modified=21, untracked=29)
- note: task 1309: cli introspection
## 2026-01-04T06:21:49Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-21-49Z.tar.gz`
- snapshot_sha256: `d3474fe4d820a4edaf1fc60e758359c22881418086468f83c62934059bcbe5ae`
- ci_json: `out/checkpoints/ci_2026-01-04T06-21-49Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-21-49Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=50 (modified=21, untracked=29)
- note: task 1310: report index
## 2026-01-04T06:26:42Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T06-26-42Z.tar.gz`
- snapshot_sha256: `f87b3ceb300674577206a57254b5637274fd500f50f55c9ccf4432a675d9cf7b`
- ci_json: `out/checkpoints/ci_2026-01-04T06-26-42Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T06-26-42Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=50 (modified=21, untracked=29)
- note: task 1311: exit codes
## 2026-01-04T09:44:43Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T09-44-43Z.tar.gz`
- snapshot_sha256: `462c75d2603d78ee51700f0b6b2e389b98a635f9e72e867cd2dd8ed92f1b78d6`
- ci_json: `out/checkpoints/ci_2026-01-04T09-44-43Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T09-44-43Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=52 (modified=21, untracked=31)
- note: task 1312: qa sarif
## 2026-01-04T09:48:23Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T09-48-23Z.tar.gz`
- snapshot_sha256: `f5436a975ae2902bf322f78b876230cef20d2e2f434446be0c057a1a485661d7`
- ci_json: `out/checkpoints/ci_2026-01-04T09-48-23Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T09-48-23Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=52 (modified=21, untracked=31)
- note: task 1313: doctor report
## 2026-01-04T09:53:39Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T09-53-39Z.tar.gz`
- snapshot_sha256: `5ee682bc24e427261670d663e8e3fd1f6f6e7fa7e08c97802bbabfe21a30a55e`
- ci_json: `out/checkpoints/ci_2026-01-04T09-53-39Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T09-53-39Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=52 (modified=21, untracked=31)
- note: task 1314: bundle
## 2026-01-04T10:01:21Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T10-01-21Z.tar.gz`
- snapshot_sha256: `52466c2ca8fb530c5dbccf822afa1425f69c87a2a5015d075e3f3246c9936be1`
- ci_json: `out/checkpoints/ci_2026-01-04T10-01-21Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T10-01-21Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=52 (modified=21, untracked=31)
- note: task 1316: multi-doc run index
## 2026-01-04T10:06:12Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T10-06-12Z.tar.gz`
- snapshot_sha256: `26ef3f54ad8978b2e60d3bdb23b6299e6b2ba526503523326d1bf399c1c78fc5`
- ci_json: `out/checkpoints/ci_2026-01-04T10-06-12Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T10-06-12Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=52 (modified=21, untracked=31)
- note: task 1315: pdf bbox overflow
## 2026-01-04T10:09:36Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T10-09-36Z.tar.gz`
- snapshot_sha256: `c96375484ea01d930a02068a929d6d37ba71d2519137ad05f82cbb850cc0f1f1`
- ci_json: `out/checkpoints/ci_2026-01-04T10-09-36Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T10-09-36Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=56 (modified=21, untracked=35)
- note: task 1317: docker runtime
## 2026-01-04T14:41:49Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T14-41-49Z.tar.gz`
- snapshot_sha256: `728a877114c4263450946a7550a54d655c4d5db503ec14a352f84b9369c5454d`
- ci_json: `out/checkpoints/ci_2026-01-04T14-41-49Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T14-41-49Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=58 (modified=22, untracked=36)
- note: cli engine + require-pdf config/docs/tests
## 2026-01-04T15:36:58Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T15-36-58Z.tar.gz`
- snapshot_sha256: `c6c1e991ffb7f94a18a7a4c6e4e670b6177e4ba14050b118a1d6cc26c25eee83`
- ci_json: `out/checkpoints/ci_2026-01-04T15-36-58Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T15-36-58Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=60 (modified=22, untracked=38)
- note: turn1 rules: tables+figures+front/back+links
## 2026-01-04T16:03:52Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T16-03-52Z.tar.gz`
- snapshot_sha256: `ab7164561a811802f59880db38cb6b99e31c0a849b55a5f6970d4591a89fb89a`
- ci_json: `out/checkpoints/ci_2026-01-04T16-03-52Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T16-03-52Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=63 (modified=22, untracked=41)
- note: rule coverage expansion turn 2
## 2026-01-04T16:27:47Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T16-27-47Z.tar.gz`
- snapshot_sha256: `82db561f98ac898097893018151868114e12fe96b6e8cf27a8cbe7408413fd84`
- ci_json: `out/checkpoints/ci_2026-01-04T16-27-47Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T16-27-47Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=67 (modified=22, untracked=45)
- note: rule coverage expansion turn 3
## 2026-01-04T16:50:45Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T16-50-45Z.tar.gz`
- snapshot_sha256: `712c0c07d39443a985e22b2bd44898b9460f2c705ae129ad180bcc436bd15661`
- ci_json: `out/checkpoints/ci_2026-01-04T16-50-45Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T16-50-45Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=81 (modified=81, untracked=0)
- note: profile tokens for tables/figures/code
## 2026-01-04T17:05:45Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T17-05-45Z.tar.gz`
- snapshot_sha256: `ca932099b7ea535ee37881c8fbd391691c373a06266b3fb7e330c1cb3da705bb`
- ci_json: `out/checkpoints/ci_2026-01-04T17-05-45Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T17-05-45Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=85 (modified=81, untracked=4)
- note: task 1326: rule coverage turn 4 (code/editorial)
## 2026-01-04T17:36:14Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T17-36-14Z.tar.gz`
- snapshot_sha256: `6051e382c0e09f1e9d5737110d82325cbc5a1e6b6afcf91e4990c8d9be172fe3`
- ci_json: `out/checkpoints/ci_2026-01-04T17-36-14Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T17-36-14Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=95 (modified=82, untracked=13)
- note: task 1327: rule coverage turn 5 (a11y+i18n+front/back+figures/tables+code)
## 2026-01-04T18:31:45Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T18-31-45Z.tar.gz`
- snapshot_sha256: `02f72e150f349bd3d22363654acc4c0fe0d3302ab566eeca84ff3632a70546f5`
- ci_json: `out/checkpoints/ci_2026-01-04T18-31-45Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T18-31-45Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=102 (modified=83, untracked=19)
- note: task 1328: turn 6 (lint+rules+qa+fixtures)
## 2026-01-04T19:00:46Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T19-00-46Z.tar.gz`
- snapshot_sha256: `7a4b9a03e889b91cc59a247f76fa3e23471f4ead0db4d7424091e04d46c13b95`
- ci_json: `out/checkpoints/ci_2026-01-04T19-00-46Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T19-00-46Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=104 (modified=83, untracked=21)
- note: task 1329: citations lint promotion phase 1
## 2026-01-04T19:23:16Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T19-23-16Z.tar.gz`
- snapshot_sha256: `1da2bd36168525359ee559c3ef550994a5080b22a8c4cd76e3c0d2ccb822b26c`
- ci_json: `out/checkpoints/ci_2026-01-04T19-23-16Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T19-23-16Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=111 (modified=84, untracked=27)
- note: tasks 1330-1332: auto lint expansion
## 2026-01-04T19:36:17Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T19-36-17Z.tar.gz`
- snapshot_sha256: `6196acb5068176bc0f66b270644e3fed578150e3641834659a27ae04153bbd1b`
- ci_json: `out/checkpoints/ci_2026-01-04T19-36-17Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T19-36-17Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=112 (modified=84, untracked=28)
- note: tasks 1333-1335: pdf qa caption/list/heading heuristics
## 2026-01-04T21:30:06Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-04T21-30-06Z.tar.gz`
- snapshot_sha256: `7fca95255ce5623b3fc6dd67863de466b2039dab7d16af7c474653bc66beed90`
- ci_json: `out/checkpoints/ci_2026-01-04T21-30-06Z.json`
- details: `out/checkpoints/checkpoint_2026-01-04T21-30-06Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=113 (modified=84, untracked=29)
- note: task 1336: links auto phase 2
## 2026-01-07T03:01:18Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T03-01-18Z.tar.gz`
- snapshot_sha256: `421ba9fd06c73fffd126fa103e662c2119409d4bc0d75322fe9cd7120246a45b`
- ci_json: `out/checkpoints/ci_2026-01-07T03-01-18Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T03-01-18Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=123 (modified=85, untracked=38)
- note: task 1337 coverage roadmap + scaffold
## 2026-01-07T03:09:55Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T03-09-55Z.tar.gz`
- snapshot_sha256: `188bf9e09d842f3e958cd9bfa456230920f19523abf890ab2cb432f6817de9b8`
- ci_json: `out/checkpoints/ci_2026-01-07T03-09-55Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T03-09-55Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=124 (modified=85, untracked=39)
- note: task 1338 punctuation batch 1 (partial)
## 2026-01-07T05:45:19Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T05-45-19Z.tar.gz`
- snapshot_sha256: `dda82df0cf543fa8b52c5fd04962c8cebb1cd6ee1cd2db6528e7041660adf7ea`
- ci_json: `out/checkpoints/ci_2026-01-07T05-45-19Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T05-45-19Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=124 (modified=85, untracked=39)
- note: task 1338 punctuation batch 1 (sections 6.14-6.138)
## 2026-01-07T05:52:06Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T05-52-06Z.tar.gz`
- snapshot_sha256: `aab17fda1c849d96f3393ca60b5937be0478bd53728269878a92a7f1d1c914ea`
- ci_json: `out/checkpoints/ci_2026-01-07T05-52-06Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T05-52-06Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=124 (modified=85, untracked=39)
- note: task 1338 punctuation batch 1 (lists 6.139-6.143)
## 2026-01-07T12:52:31Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T12-52-31Z.tar.gz`
- snapshot_sha256: `9b47532fb8b9dfa54eeda74e29b1c2082cf4b6781ebeb33a2ed4e5688478ff1f`
- ci_json: `out/checkpoints/ci_2026-01-07T12-52-31Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T12-52-31Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=124 (modified=85, untracked=39)
- note: task 1338 punctuation batch 1 (sections 6.17-6.54)
## 2026-01-07T13:21:20Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-21-20Z.tar.gz`
- snapshot_sha256: `c36701390a0e1e59344e57c770337bcb2a55a71a4e6ecb16a1c8c42417ed2b79`
- ci_json: `out/checkpoints/ci_2026-01-07T13-21-20Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-21-20Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=125 (modified=85, untracked=40)
- note: task 1338 punctuation batch 1 (commas/semicolons/questions)
## 2026-01-07T13:28:12Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-28-12Z.tar.gz`
- snapshot_sha256: `f79b65f7454c350fe2a669e24a185397e3e8ef56954d4d6fa29b276fb5a8050e`
- ci_json: `out/checkpoints/ci_2026-01-07T13-28-12Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-28-12Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=125 (modified=85, untracked=40)
- note: task 1339 numbers batch 1 (9.1-9.36)
## 2026-01-07T13:34:42Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-34-42Z.tar.gz`
- snapshot_sha256: `ed49ff31a6f3aa04b8163c8eb2ef793a7374eb292a6f63182229e73aebfa3894`
- ci_json: `out/checkpoints/ci_2026-01-07T13-34-42Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-34-42Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=125 (modified=85, untracked=40)
- note: task 1341 bring typography+layout coverage map
## 2026-01-07T13:37:21Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-37-21Z.tar.gz`
- snapshot_sha256: `650e5c1cb14e2a7cf101606ed33b0c779351a9a777f944bafd05b5a5e49c21c7`
- ci_json: `out/checkpoints/ci_2026-01-07T13-37-21Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-37-21Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=125 (modified=85, untracked=40)
- note: task 1342 bring headings+lists coverage map
## 2026-01-07T13:39:56Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-39-56Z.tar.gz`
- snapshot_sha256: `d06a4325110722325a5c1664b9aab658ae7daa873e3a3580e78e79a9d4c787ea`
- ci_json: `out/checkpoints/ci_2026-01-07T13-39-56Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-39-56Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=125 (modified=85, untracked=40)
- note: task 1343 tables+figures coverage map
## 2026-01-07T13:45:22Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-45-22Z.tar.gz`
- snapshot_sha256: `50ca8dfc35d3a2a37a1405f9d4079a865beb8d5301815190876fc12472d03414`
- ci_json: `out/checkpoints/ci_2026-01-07T13-45-22Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-45-22Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=128 (modified=85, untracked=43)
- note: task 1344 links+code rules batch 1
## 2026-01-07T13:48:30Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T13-48-30Z.tar.gz`
- snapshot_sha256: `acdfb749162d6cc68015252fcc5fb97e761d86b49a1a37d0feb0c069145db743`
- ci_json: `out/checkpoints/ci_2026-01-07T13-48-30Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T13-48-30Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1345 coverage summary generator
## 2026-01-07T15:05:23Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T15-05-23Z.tar.gz`
- snapshot_sha256: `bb048267c831e00a7004c647b2cadb28a4211bade86920dda3658b421de948cc`
- ci_json: `out/checkpoints/ci_2026-01-07T15-05-23Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T15-05-23Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1340: citations batch 1
## 2026-01-07T16:16:51Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T16-16-51Z.tar.gz`
- snapshot_sha256: `1bd425530e38b0c184036284c599f3848005865655cd82529e8426753824bbfc`
- ci_json: `out/checkpoints/ci_2026-01-07T16-16-51Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T16-16-51Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1347: CMOS citations coverage stubs 13.30-13.54
## 2026-01-07T16:18:36Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T16-18-36Z.tar.gz`
- snapshot_sha256: `d92bd833941d14e8c3e1a7ad08e474d324c1f84b30122e82f2226e988b6d0957`
- ci_json: `out/checkpoints/ci_2026-01-07T16-18-36Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T16-18-36Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1349: CMOS citations coverage stubs 13.55-13.73
## 2026-01-07T16:21:51Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T16-21-51Z.tar.gz`
- snapshot_sha256: `ae332081fec080e14467a820461818cea1a7d8bc826a6b1efaa4c3589bd8c75c`
- ci_json: `out/checkpoints/ci_2026-01-07T16-21-51Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T16-21-51Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1351: CMOS citations coverage stubs 13.74-13.89
## 2026-01-07T16:23:38Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T16-23-38Z.tar.gz`
- snapshot_sha256: `38c1ee8a4dd1aa04acce09a5467a1b83e03a0e5d2a11fb901936cf4431360936`
- ci_json: `out/checkpoints/ci_2026-01-07T16-23-38Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T16-23-38Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1353: CMOS citations coverage stubs 13.92-13.108
## 2026-01-07T16:25:43Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T16-25-43Z.tar.gz`
- snapshot_sha256: `7f61613b84b51f111bc427def728eab42a0e250b4fce3a3281f0b03f17737045`
- ci_json: `out/checkpoints/ci_2026-01-07T16-25-43Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T16-25-43Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=130 (modified=86, untracked=44)
- note: task 1355: CMOS citations coverage stubs 13.111-13.128
## 2026-01-07T16:58:28Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T16-58-28Z.tar.gz`
- snapshot_sha256: `83465c0cf67f41faceedd32dbbe6efbbd4d56f39bc719c088e8457c376da7437`
- ci_json: `out/checkpoints/ci_2026-01-07T16-58-28Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T16-58-28Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=131 (modified=86, untracked=45)
- note: task 1348: cmos citations 13.30-13.54 rules+coverage
## 2026-01-07T17:34:10Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T17-34-10Z.tar.gz`
- snapshot_sha256: `c05b4ae504f5bf72795ed737f8f49e19b61906365f99a33d3ac2d58fe623c9e8`
- ci_json: `out/checkpoints/ci_2026-01-07T17-34-10Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T17-34-10Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=131 (modified=86, untracked=45)
- note: task 1358: 12pt baseline + brand colors + table striping
## 2026-01-07T20:16:27Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T20-16-27Z.tar.gz`
- snapshot_sha256: `e185bf2251b7ce6a275400d8a73a1a560166b3ad48c947f66e664fa587d14dfb`
- ci_json: `out/checkpoints/ci_2026-01-07T20-16-27Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T20-16-27Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=131 (modified=86, untracked=45)
- note: task 1359: clickable [Sxx] citations
## 2026-01-07T20:30:14Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-07T20-30-14Z.tar.gz`
- snapshot_sha256: `444a88b90bba249221931a45e07685328758bdc8db8a20b103ab494ff46202a6`
- ci_json: `out/checkpoints/ci_2026-01-07T20-30-14Z.json`
- details: `out/checkpoints/checkpoint_2026-01-07T20-30-14Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=132 (modified=86, untracked=46)
- note: task 1360: audit_report profile + QA gates
## 2026-01-08T02:32:29Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T02-32-29Z.tar.gz`
- snapshot_sha256: `f67b7e66bac77635c20eb67a19d4cfd19c67ba81e598aae3f4b3ac552ec8e5e1`
- ci_json: `out/checkpoints/ci_2026-01-08T02-32-29Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T02-32-29Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=132 (modified=86, untracked=46)
- note: task 1346: enforcement uplift (deprecate dup link rules; checklist filters status)
## 2026-01-08T03:30:39Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-30-39Z.tar.gz`
- snapshot_sha256: `1981644b9360c07f438427f8bfc619cacb12ffc1d4b2076ceec4791f606065b8`
- ci_json: `out/checkpoints/ci_2026-01-08T03-30-39Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-30-39Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=133 (modified=86, untracked=47)
- note: task 1350: CMOS citations mapped (13.5513.73)
## 2026-01-08T03:34:08Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-34-08Z.tar.gz`
- snapshot_sha256: `a98615e17b4a44ffc7e3a255bf12cdd05f4f696d2f7a7ab4d493cd8532bc71e2`
- ci_json: `out/checkpoints/ci_2026-01-08T03-34-08Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-34-08Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=134 (modified=86, untracked=48)
- note: task 1352: CMOS citations mapped (13.7413.89)
## 2026-01-08T03:37:40Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-37-40Z.tar.gz`
- snapshot_sha256: `b17b44b48a47ac0643b241174cde7a6653b87ff25cda00b82548ff99780f02e1`
- ci_json: `out/checkpoints/ci_2026-01-08T03-37-40Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-37-40Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=135 (modified=86, untracked=49)
- note: task 1354: CMOS citations mapped (13.9213.108)
## 2026-01-08T03:42:42Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-42-42Z.tar.gz`
- snapshot_sha256: `c21fee9774f8fdd895a44a2f4de136a5f95d805bae26e18c94ca50c6833c11f0`
- ci_json: `out/checkpoints/ci_2026-01-08T03-42-42Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-42-42Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1356: CMOS citations mapped (13.11113.128)
## 2026-01-08T03:53:19Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-53-19Z.tar.gz`
- snapshot_sha256: `6f86b0c6d00fd44c1be67dad1ce5b3dbc0624254a1a93cfe684d7d68d63cb060`
- ci_json: `out/checkpoints/ci_2026-01-08T03-53-19Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-53-19Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1361: BRING completion pass (covered)
## 2026-01-08T03:55:03Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-55-03Z.tar.gz`
- snapshot_sha256: `1c36b33ade3802dfb16a5fb72ce8e51c9ed7497f86c0ef2b18603d5bcd2e524e`
- ci_json: `out/checkpoints/ci_2026-01-08T03-55-03Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-55-03Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1362: CMOS ch6 completion pass (covered)
## 2026-01-08T03:56:40Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-56-40Z.tar.gz`
- snapshot_sha256: `f39d4c1668222d7b12b3ea2e6e3d773ccfedda2b1b1a5e409f715a875e831309`
- ci_json: `out/checkpoints/ci_2026-01-08T03-56-40Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-56-40Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1363: CMOS ch9 completion pass (covered)
## 2026-01-08T03:58:16Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-58-16Z.tar.gz`
- snapshot_sha256: `a2626b2b59d158847a0ccd19ff177686e60166132e32a040ac7ca1568b7ddb4e`
- ci_json: `out/checkpoints/ci_2026-01-08T03-58-16Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-58-16Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1365: CMOS ch1/ch3/ch5/ch15 completion pass (covered)
## 2026-01-08T03:59:57Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T03-59-57Z.tar.gz`
- snapshot_sha256: `dd5c3236276eff74443e04e43f10844dcb21402e45e6c584d67cb6cf6fb25f79`
- ci_json: `out/checkpoints/ci_2026-01-08T03-59-57Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T03-59-57Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1364: CMOS ch13 completion pass (covered)
## 2026-01-08T04:57:18Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T04-57-18Z.tar.gz`
- snapshot_sha256: `4dd9699bd9083677e9f2e688d1b313967a94ed73a81322e78a335d8a6c50753a`
- ci_json: `out/checkpoints/ci_2026-01-08T04-57-18Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T04-57-18Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=136 (modified=86, untracked=50)
- note: task 1366: add missing CMOS13 sections
## 2026-01-08T06:22:01Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T06-22-01Z.tar.gz`
- snapshot_sha256: `f3fba438d884adfb1523a0ff4e87b8ffc0e460b6992255c0543b63b4fa998572`
- ci_json: `out/checkpoints/ci_2026-01-08T06-22-01Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T06-22-01Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=138 (modified=86, untracked=52)
- note: tasks 1367/1368: ch13 gaps + OCR audit tool
## 2026-01-08T09:39:02Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T09-39-02Z.tar.gz`
- snapshot_sha256: `2b7f1704eb57758e1252821bd3367b64f1705a2db254f3b0f58c44a2e8b30504`
- ci_json: `out/checkpoints/ci_2026-01-08T09-39-02Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T09-39-02Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=139 (modified=87, untracked=52)
- note: task 1369: flaneur PDF margins + playwright-only
## 2026-01-08T13:39:43Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T13-39-43Z.tar.gz`
- snapshot_sha256: `f0df3101b956213bb4303062aecdea80a88424c062b43f78a14ba125416ebe58`
- ci_json: `out/checkpoints/ci_2026-01-08T13-39-43Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T13-39-43Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=143 (modified=91, untracked=52)
- note: task 1370: ban chromium engine + pin python 3.12
## 2026-01-08T17:55:08Z
- snapshot: `out/checkpoints/iftypeset_checkpoint_2026-01-08T17-55-08Z.tar.gz`
- snapshot_sha256: `23350894a965367138202c23fbe073400a38b5b936ceff75ae1faa80e6771552`
- ci_json: `out/checkpoints/ci_2026-01-08T17-55-08Z.json`
- details: `out/checkpoints/checkpoint_2026-01-08T17-55-08Z.md`
- git: `master` `626779d`
- working_tree: dirty_paths=143 (modified=91, untracked=52)
- note: task 1371: strict fonts + --font-dir

34
docs/SESSION_STATE.md Normal file
View file

@ -0,0 +1,34 @@
# Session State (generated)
- generated_at_utc: `2026-01-08T17:55:32Z`
- repo_root: `/root/ai-workspace/iftypeset`
- git: `master` @ `626779d`
- working_tree: dirty_paths=143 (modified=91, untracked=52)
- latest_checkpoint: `out/checkpoints/iftypeset_checkpoint_2026-01-08T13-39-43Z.tar.gz`
- latest_checkpoint_sha256: `f0df3101b956213bb4303062aecdea80a88424c062b43f78a14ba125416ebe58`
- rules_total: `1657`
- enforcement_split: `{'lint': 108, 'manual': 1392, 'postrender': 25, 'typeset': 132}`
- categories: `{'abbreviations': 47, 'accessibility': 48, 'backmatter': 46, 'citations': 280, 'code': 58, 'editorial': 63, 'figures': 57, 'frontmatter': 47, 'headings': 57, 'i18n': 35, 'layout': 150, 'links': 70, 'numbers': 243, 'punctuation': 278, 'tables': 66, 'typography': 112}`
## Canonical Docs
- `README.md`
- `STATUS.md`
- `docs/06-project-overview.md`
- `docs/07-session-resilience.md`
- `docs/09-project-status.md`
- `docs/10-project-brief.md`
- `docs/12-codex-max-workload.md`
- `docs/13-task-board.md`
- `docs/17-rendering-pipeline.md`
- `docs/CHECKPOINTS.md`
## Fast Resume
- `./scripts/resume.sh`
- `./scripts/audit.sh`
- `./scripts/state.sh`
- `./scripts/ci.sh`
- `./scripts/checkpoint.sh "note"`
## Notes
- If a chat/session resets and things look “rolled back”, check `latest_checkpoint` above and extract it on a new machine.
- This file is copied into `docs/SESSION_STATE.md` so it is included in checkpoint snapshots (since `out/` is excluded).

View file

@ -0,0 +1,6 @@
# Alt text quality
Avoid generic or filename-like alt text:
![image](images/example.png)

View file

@ -0,0 +1,5 @@
# Author-date without references
Smith (2020) established the baseline for the method.
Jones (2021) extended the approach with new evidence.

View file

@ -0,0 +1,7 @@
# Footnote sequence
This sentence has a note.[^2] This next one has another.[^1]
[^1]: First note.
[^2]: Second note.

View file

@ -0,0 +1,9 @@
# Notes Lint Sample
This sentence uses a bracketed numeric citation [1] that should be flagged.
## Heading with note[^1] inline
Some prose with a footnote marker.[^1]
[^1]: Ibid., 12.

View file

@ -0,0 +1,26 @@
this is a wrapped paragraph
that continues on the next line
without paragraph breaks and
keeps wrapping as if copied
from a pdf or scan with hard
line breaks inserted by width
this should be detected as
a hard wrapped block and
then unwrapped when parsing
so lint can normalize text
and avoid false line breaks
this fixture stays short per
line to trigger density checks
and keep continuation patterns
consistent across many lines
so the parser sees hard wrap
instead of a list or a poem
each line starts with lowercase
and avoids ending punctuation
to emulate mid sentence wraps
with enough lines to trip
the degraded mode heuristic
and confirm unwrapping works
for deterministic parsing
the last lines continue this
pattern to stay long enough

View file

@ -0,0 +1,12 @@
this paragraph line is intentionally long enough to avoid hard wrap detection while still lacking headings.
another long paragraph line that reads like a continuous note and should only trigger missing headings.
third long line to exceed the minimum line count for missing headings without looking wrapped.
fourth line keeps the text flowing with punctuation at the end to reduce continuation signals.
fifth line stays long and descriptive to simulate a plain memo without structure.
sixth line continues the memo format while staying well above the short line threshold.
seventh line is similar in length and ends with a period to break any wrap heuristic.
eighth line remains long and complete in order to avoid hard wrap density.
ninth line is also a complete sentence with proper punctuation and spacing.
tenth line maintains the same pattern so the parser sees consistent long lines.
eleventh line extends the note into a longer block while still avoiding headings.
twelfth line finalizes the sample to ensure missing headings is flagged for longer docs.

View file

@ -0,0 +1,7 @@
# Draft markers
TODO: replace this sentence with real content.
This section is TBD.
Lorem ipsum dolor sit amet.

View file

@ -0,0 +1,15 @@
Intro paragraph one.
Intro paragraph two.
- bullet one
- bullet two
# Late Title
## Trailing colon:
- only one item
# Second Title

View file

@ -1,6 +1,13 @@
# Layout Spacing
This paragraph is followed by another paragraph that should preserve
consistent spacing in the rendered output.
First paragraph.
This is the follow-up paragraph.
Second paragraph.
## Empty Section
## Next Section
Body text.

View file

@ -0,0 +1,21 @@
# Links Auto Checks
See [stage](https://staging.example.com/path).
See [internal](http://internal.local/path).
See [ftp](ftp://example.com/file).
See [track](https://example.com/page?utm_source=x).
See [session](https://example.com/page?session=abc).
See [invite](https://example.com/invite?token=abc1234567890).
See [reset](https://example.com/reset?token=abc).
See [login](https://example.com/login).
See [creds](https://user:pass@example.com/).
See [private](http://10.0.0.1/path).

View file

@ -0,0 +1,5 @@
# Disallowed link schemes
Do not ship outputs with links like file://etc/passwd or javascript:alert(1).
Avoid localhost URLs such as http://localhost:8000/test in published docs.

11
fixtures/links_hazards.md Normal file
View file

@ -0,0 +1,11 @@
# Link hazards
See [protocol-relative](//example.com/path).
See [text fragment](https://example.com/page#:~:text=alpha).
See [signed link](https://example.com/file?X-Amz-Signature=abc&X-Amz-Expires=3600).
See [shortener](https://bit.ly/abc).
See [ip literal](http://192.168.1.10/path).

6
fixtures/short_note.md Normal file
View file

@ -0,0 +1,6 @@
this is a short note without headings
it is only a few lines long
and should not be treated as degraded
because the document is too small
for structural inference or hard wrap
the parser should leave it untouched

View file

@ -0,0 +1,9 @@
# Typography Emphasis
This has **BOLD TEXT THAT GOES ON FOR MANY WORDS TO TRIGGER A LONG BOLD WARNING**.
This has *italics that stretch across many words and should be flagged for length in prose and reading comfort in long spans*.
This has ***bold italics that are also long enough to trigger a warning***.
This has **ALL CAPS TEXT** in bold.

View file

@ -33,23 +33,17 @@ In Forgejo terms:
1. Generate CSS from a profile:
```bash
cd /root/ai-workspace/iftypeset
PYTHONPATH=src python3 -m iftypeset.cli emit-css --spec spec --profile web_pdf --out /tmp/iftypeset-css
cd /root/ai-workspace/forgejo-pdf
./scripts/update_iftypeset_css.sh
```
2. Copy CSS into the worker assets directory:
```bash
cp /tmp/iftypeset-css/render.css /root/ai-workspace/forgejo-pdf/worker/pdf/assets/css/iftypeset-web_pdf.css
```
3. Add a new `pdf.typography` option in the worker config contract (example):
2. Select the new `pdf.typography` option in the worker config contract (example):
- `basic`
- `professional`
- `iftypeset-web_pdf` (new)
4. Update `render_pdf.js` selection logic to map that value to a CSS filename in `assets/css/`.
3. The worker will load `professional.css` first and then `iftypeset-web_pdf.css` as an override.
This is the safest first step: no new dependencies in the worker container, no new runtime calls, just a different stylesheet.

View file

@ -2,7 +2,7 @@
name = "iftypeset"
version = "0.1.0"
description = "Publication-quality typesetting runtime (Markdown→HTML→PDF) with Chicago/Bringhurst-backed rule registry pointers."
requires-python = ">=3.11"
requires-python = ">=3.12,<3.13"
dependencies = [
"pyyaml>=6.0",
"jsonschema>=4.19",
@ -13,4 +13,3 @@ iftypeset = "iftypeset.cli:main"
[tool.pytest.ini_options]
testpaths = ["tests"]

View file

@ -1,2 +1,3 @@
PyYAML==6.0.2
jsonschema==4.19.2
playwright==1.41.2

View file

@ -14,27 +14,73 @@ echo "== running ci ==" >&2
ci_json="$(./scripts/ci.sh)"
echo "$ci_json" > "out/checkpoints/ci_${safe_ts}.json"
echo "== writing session state ==" >&2
./scripts/state.sh >/dev/null
git_branch="(unknown)"
git_head_short=""
dirty_count="0"
modified_count="0"
untracked_count="0"
diffstat=""
diffstat_lines="0"
diffstat_note=""
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "(unknown)")"
git_head_short="$(git rev-parse --short HEAD 2>/dev/null || echo "")"
porcelain="$(git status --porcelain=v1 2>/dev/null || true)"
if [ -n "${porcelain}" ]; then
dirty_count="$(printf "%s\n" "${porcelain}" | wc -l | awk '{print $1}')"
untracked_count="$(printf "%s\n" "${porcelain}" | grep -c '^??' || true)"
modified_count="$(printf "%s\n" "${porcelain}" | grep -vc '^??' || true)"
fi
diffstat="$(git diff --stat 2>/dev/null || true)"
if [ -n "${diffstat}" ]; then
diffstat_lines="$(printf "%s\n" "${diffstat}" | wc -l | awk '{print $1}')"
if [ "${diffstat_lines}" -gt 200 ]; then
diffstat="$(printf "%s\n" "${diffstat}" | head -n 200)"
diffstat_note="(diffstat truncated to first 200 lines)"
fi
fi
fi
tar_path="out/checkpoints/iftypeset_checkpoint_${safe_ts}.tar.gz"
details_path="out/checkpoints/checkpoint_${safe_ts}.md"
echo "== creating snapshot ${tar_path} ==" >&2
snapshot_paths=(.forgejo .gitignore README.md STATUS.md app docs fixtures forgejo pyproject.toml requirements.txt scripts spec src tests tools)
if [ -f AGENTS.md ]; then
snapshot_paths+=(AGENTS.md)
fi
tar \
--exclude=".git" \
--exclude=".venv" \
--exclude="out" \
-czf "$tar_path" \
.forgejo .gitignore README.md STATUS.md app docs fixtures forgejo pyproject.toml requirements.txt scripts spec src tests tools
"${snapshot_paths[@]}"
sha="$(sha256sum "$tar_path" | awk '{print $1}')"
cat > "out/checkpoints/checkpoint_${safe_ts}.md" <<EOF
cat > "${details_path}" <<EOF
# iftypeset checkpoint
- timestamp_utc: ${ts}
- snapshot: ${tar_path}
- snapshot_sha256: ${sha}
- ci: \`out/checkpoints/ci_${safe_ts}.json\`
- git: ${git_branch} ${git_head_short}
- working_tree: dirty_paths=${dirty_count} (modified=${modified_count}, untracked=${untracked_count})
$( [ -n "${note}" ] && printf -- "- note: %s\n" "${note}" )
## Diffstat (uncommitted changes)
${diffstat_note}
\`\`\`text
${diffstat}
\`\`\`
EOF
if [ ! -s docs/CHECKPOINTS.md ]; then
@ -58,6 +104,9 @@ cat >> docs/CHECKPOINTS.md <<EOF
- snapshot: \`${tar_path}\`
- snapshot_sha256: \`${sha}\`
- ci_json: \`out/checkpoints/ci_${safe_ts}.json\`
- details: \`${details_path}\`
- git: \`${git_branch}\` \`${git_head_short}\`
- working_tree: dirty_paths=${dirty_count} (modified=${modified_count}, untracked=${untracked_count})
$( [ -n "${note}" ] && printf -- "- note: %s\n" "${note}" )
EOF

24
scripts/resume.sh Executable file
View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
echo "== iftypeset resume =="
echo "root: ${ROOT}"
echo
./scripts/audit.sh
echo
echo "canonical docs:"
echo " - docs/09-project-status.md"
echo " - STATUS.md"
echo " - docs/07-session-resilience.md"
echo " - docs/CHECKPOINTS.md"
echo
if [ -f /root/docs/09-project-status.md ]; then
echo "warning: /root/docs/09-project-status.md exists outside the repo and may be stale."
echo " prefer: ${ROOT}/docs/09-project-status.md"
fi

188
scripts/state.sh Executable file
View file

@ -0,0 +1,188 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
mkdir -p out
git_branch=""
git_head=""
git_head_short=""
git_modified_count="0"
git_untracked_count="0"
git_dirty_count="0"
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "?")"
git_head="$(git rev-parse HEAD 2>/dev/null || echo "")"
git_head_short="$(git rev-parse --short HEAD 2>/dev/null || echo "")"
porcelain="$(git status --porcelain=v1 2>/dev/null || true)"
if [ -n "${porcelain}" ]; then
git_dirty_count="$(printf "%s\n" "${porcelain}" | wc -l | awk '{print $1}')"
git_untracked_count="$(printf "%s\n" "${porcelain}" | grep -c '^??' || true)"
git_modified_count="$(printf "%s\n" "${porcelain}" | grep -vc '^??' || true)"
fi
fi
latest_checkpoint_path=""
latest_checkpoint_sha256=""
if ls out/checkpoints/iftypeset_checkpoint_*.tar.gz >/dev/null 2>&1; then
latest_checkpoint_path="$(ls -1t out/checkpoints/iftypeset_checkpoint_*.tar.gz | head -n 1)"
latest_checkpoint_sha256="$(sha256sum "${latest_checkpoint_path}" | awk '{print $1}')"
fi
export IFTS_STATE_TS="${ts}"
export IFTS_STATE_ROOT="${ROOT}"
export IFTS_STATE_GIT_BRANCH="${git_branch}"
export IFTS_STATE_GIT_HEAD="${git_head}"
export IFTS_STATE_GIT_HEAD_SHORT="${git_head_short}"
export IFTS_STATE_GIT_DIRTY_COUNT="${git_dirty_count}"
export IFTS_STATE_GIT_MODIFIED_COUNT="${git_modified_count}"
export IFTS_STATE_GIT_UNTRACKED_COUNT="${git_untracked_count}"
export IFTS_STATE_CHECKPOINT_PATH="${latest_checkpoint_path}"
export IFTS_STATE_CHECKPOINT_SHA256="${latest_checkpoint_sha256}"
python3 - <<'PY'
import json
import os
from pathlib import Path
def _read_json(path: str):
p = Path(path)
if not p.exists():
return None
try:
return json.loads(p.read_text())
except Exception:
return None
ts = os.environ.get("IFTS_STATE_TS", "")
root = os.environ.get("IFTS_STATE_ROOT", "")
git_branch = os.environ.get("IFTS_STATE_GIT_BRANCH", "")
git_head = os.environ.get("IFTS_STATE_GIT_HEAD", "")
git_head_short = os.environ.get("IFTS_STATE_GIT_HEAD_SHORT", "")
dirty_count = int(os.environ.get("IFTS_STATE_GIT_DIRTY_COUNT", "0") or "0")
modified_count = int(os.environ.get("IFTS_STATE_GIT_MODIFIED_COUNT", "0") or "0")
untracked_count = int(os.environ.get("IFTS_STATE_GIT_UNTRACKED_COUNT", "0") or "0")
checkpoint_path = os.environ.get("IFTS_STATE_CHECKPOINT_PATH", "")
checkpoint_sha256 = os.environ.get("IFTS_STATE_CHECKPOINT_SHA256", "")
coverage = _read_json("out/coverage-report.json") or {}
counts = coverage.get("counts", {}) if isinstance(coverage, dict) else {}
trust_contract_md = Path("out/trust-contract.md").exists()
trust_contract_json = Path("out/trust-contract.json").exists()
state = {
"generated_at_utc": ts,
"repo_root": root,
"git": {
"branch": git_branch or None,
"head": git_head or None,
"head_short": git_head_short or None,
"dirty_paths_count": dirty_count,
"modified_paths_count": modified_count,
"untracked_paths_count": untracked_count,
},
"latest_checkpoint": {
"path": checkpoint_path or None,
"sha256": checkpoint_sha256 or None,
},
"coverage": {
"generated_at_utc": coverage.get("generated_at_utc") if isinstance(coverage, dict) else None,
"counts": counts or None,
},
"artifacts": {
"trust_contract_md": trust_contract_md,
"trust_contract_json": trust_contract_json,
"coverage_report_json": Path("out/coverage-report.json").exists(),
"manual_checklist_md": Path("out/manual-checklist.md").exists(),
},
"canonical_docs": [
"README.md",
"STATUS.md",
"docs/06-project-overview.md",
"docs/07-session-resilience.md",
"docs/09-project-status.md",
"docs/10-project-brief.md",
"docs/12-codex-max-workload.md",
"docs/13-task-board.md",
"docs/17-rendering-pipeline.md",
"docs/CHECKPOINTS.md",
],
"resume_commands": [
"./scripts/resume.sh",
"./scripts/audit.sh",
"./scripts/state.sh",
"./scripts/ci.sh",
"./scripts/checkpoint.sh \"note\"",
],
}
Path("out/session-state.json").write_text(json.dumps(state, indent=2, sort_keys=True) + "\n")
lines = []
lines.append("# Session State (generated)\n")
lines.append(f"- generated_at_utc: `{ts}`")
lines.append(f"- repo_root: `{root}`")
if git_branch and git_head_short:
lines.append(f"- git: `{git_branch}` @ `{git_head_short}`")
elif git_branch:
lines.append(f"- git: `{git_branch}`")
else:
lines.append("- git: `(not detected)`")
lines.append(
f"- working_tree: dirty_paths={dirty_count} (modified={modified_count}, untracked={untracked_count})"
)
if checkpoint_path:
lines.append(f"- latest_checkpoint: `{checkpoint_path}`")
lines.append(f"- latest_checkpoint_sha256: `{checkpoint_sha256}`")
else:
lines.append("- latest_checkpoint: `(none yet)`")
total_rules = None
try:
total_rules = counts.get("total_rules")
except Exception:
total_rules = None
if total_rules is not None:
lines.append(f"- rules_total: `{total_rules}`")
by_enf = counts.get("by_enforcement") or {}
by_cat = counts.get("by_category") or {}
if by_enf:
lines.append(f"- enforcement_split: `{by_enf}`")
if by_cat:
lines.append(f"- categories: `{by_cat}`")
else:
lines.append("- rules_total: `(unknown; run ./scripts/ci.sh)`")
lines.append("")
lines.append("## Canonical Docs")
for d in state["canonical_docs"]:
lines.append(f"- `{d}`")
lines.append("")
lines.append("## Fast Resume")
for c in state["resume_commands"]:
lines.append(f"- `{c}`")
lines.append("")
lines.append("## Notes")
lines.append(
"- If a chat/session resets and things look “rolled back”, check `latest_checkpoint` above and extract it on a new machine."
)
lines.append(
"- This file is copied into `docs/SESSION_STATE.md` so it is included in checkpoint snapshots (since `out/` is excluded)."
)
md = "\n".join(lines) + "\n"
Path("out/session-state.md").write_text(md)
Path("docs/SESSION_STATE.md").write_text(md)
PY
echo "wrote: out/session-state.json out/session-state.md docs/SESSION_STATE.md" >&2

42
spec/coverage/README.md Normal file
View file

@ -0,0 +1,42 @@
# Coverage Map (Section Tracking)
This directory tracks coverage by **section**, not by raw rule count.
We do not store OCR text. Entries reference sections and pointers only.
## Files
- `cmos18_sections.json`
- `bring_sections.json`
## Schema (per file)
```json
{
"book": "CMOS18",
"source": "The Chicago Manual of Style, 18th ed (OCR)",
"updated_utc": "YYYY-MM-DDTHH:MM:SSZ",
"sections": [
{
"section_id": "§1",
"title": "Section title",
"pointer": "CMOS18 §1 p1",
"status": "uncovered",
"rule_ids": []
}
]
}
```
## Status values
- `uncovered`: no rules mapped yet.
- `partial`: some rules mapped, section not fully covered.
- `covered`: all rule-bearing guidance mapped into paraphrased rules.
- `out_of_scope`: narrative or non-prescriptive section.
## Rules of engagement
- Paraphrase only. Never include book text.
- Use precise pointers in `source_refs`.
- If exact wording is required: `Exact wording required—refer to pointer`.

View file

@ -0,0 +1,803 @@
{
"book": "BRING",
"source": "The Elements of Typographic Style (OCR)",
"updated_utc": "2026-01-08T03:52:36Z",
"sections": [
{
"section_id": "1.2.2",
"title": "Section 1.2.2",
"pointer": "BRING §1.2.2 p20 (scan p19)",
"status": "covered",
"rule_ids": [
"BRING.HEADINGS.STRUCTURE.MATCH_TEXT_LOGIC",
"BRING.HEADINGS.DEGRADED.INFER_STRUCTURE",
"BRING.HEADINGS.NUMBERING.CONSISTENT_STYLE",
"BRING.HEADINGS.NUMBERING.NO_GAPS",
"BRING.HEADINGS.NUMBERING.PUNCTUATION.CONSISTENT",
"BRING.HEADINGS.NUMBERING.PREFIXES.CONSISTENT",
"BRING.HEADINGS.TOC.MATCH",
"BRING.HEADINGS.NUMBERING.SUBLEVELS.DECIMAL_STYLE",
"BRING.HEADINGS.NUMBERING.APPENDIX_LABELS"
]
},
{
"section_id": "1.2.3",
"title": "Section 1.2.3",
"pointer": "BRING §1.2.3 p21 (scan p20)",
"status": "covered",
"rule_ids": [
"BRING.HEADINGS.RELATED_ELEMENTS.COHERENT"
]
},
{
"section_id": "1.2.4",
"title": "Section 1.2.4",
"pointer": "BRING §1.2.4 p22 (scan p21)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.TYPEFACE.PURPOSE_MATCH_CONTENT",
"BRING.TYPOGRAPHY.TYPEFACE.LIMIT_NUMBER",
"BRING.TYPOGRAPHY.TYPEFACE.SIMILAR_FACES_AVOID",
"BRING.TYPOGRAPHY.TYPEFACE.CONTRAST_INTENTIONAL",
"BRING.TYPOGRAPHY.TYPEFACE.MIXING_BY_ROLE_ONLY"
]
},
{
"section_id": "1.2.5",
"title": "Section 1.2.5",
"pointer": "BRING §1.2.5 p23 (scan p22)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGE.HEAD_FOOT_BANDS.CONSISTENT",
"BRING.LAYOUT.PAGE.BLANKS.INTENTIONAL",
"BRING.LAYOUT.PAGE.FRAME.TEXTBLOCK_BALANCE",
"BRING.LAYOUT.MARGINS.FACING_PAGES.INNER_OUTER",
"BRING.LAYOUT.ELEMENT_RELATIONSHIPS.VISIBLE",
"BRING.LAYOUT.TEXTBLOCK.CONSISTENT_WIDTH",
"BRING.LAYOUT.FLOATS.PLACEMENT.NEAR_REFERENCE",
"BRING.LAYOUT.GRID.ALIGN_ELEMENTS"
]
},
{
"section_id": "2.1.1",
"title": "Section 2.1.1",
"pointer": "BRING §2.1.1 p25",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.SPACING.WORD_SPACE.DEFINE"
]
},
{
"section_id": "2.1.2",
"title": "Section 2.1.2",
"pointer": "BRING §2.1.2 p26 (scan p25)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.MEASURE.TARGET_RANGE_CHARS",
"BRING.LAYOUT.MEASURE.ADJUST_FOR_TYPE_SIZE",
"BRING.LAYOUT.MEASURE.AVOID_TOO_LONG",
"BRING.LAYOUT.MEASURE.AVOID_TOO_SHORT",
"BRING.LAYOUT.MEASURE.CONSISTENT_WITHIN_SECTION",
"BRING.LAYOUT.MEASURE.CHANGE_FOR_LISTS",
"BRING.LAYOUT.MEASURE.CODE_BLOCKS.WRAP_POLICY",
"BRING.LAYOUT.COLUMNS.BALANCE_LENGTHS",
"BRING.LAYOUT.MEASURE.COMFORTABLE_RANGE",
"BRING.LAYOUT.MEASURE.MULTICOLUMN_TARGETS"
]
},
{
"section_id": "2.1.3",
"title": "Section 2.1.3",
"pointer": "BRING §2.1.3 p27",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.JUSTIFICATION.RAGGED_RIGHT_IF_NEEDED",
"BRING.CODE.MONO_RAGGED_RIGHT",
"BRING.CODE.RAG.NO_MIN_LINE",
"BRING.CODE.RAG.NO_AUTO_HYPHENATION",
"BRING.CODE.RAG.FIXED_WORD_SPACES",
"BRING.CODE.RAG.NO_LETTERSPACING",
"BRING.CODE.RAG.AVOID_FAKE_JUSTIFY"
]
},
{
"section_id": "2.1.4",
"title": "Section 2.1.4",
"pointer": "BRING §2.1.4 p27",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.SPACING.SENTENCE_SPACE.SINGLE"
]
},
{
"section_id": "2.1.5",
"title": "Section 2.1.5",
"pointer": "BRING §2.1.5 p30 (scan p29)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.SPACING.INITIALS.THIN_SPACE"
]
},
{
"section_id": "2.1.6",
"title": "Section 2.1.6",
"pointer": "BRING §2.1.6 p30 (scan p29)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.TRACKING.CAPS_SMALLCAPS_AND_LONG_DIGITS",
"BRING.TYPOGRAPHY.NUMBER_STRINGS.SPACE_FOR_READABILITY",
"BRING.TYPOGRAPHY.CAPS.TRACKING_REVIEW"
]
},
{
"section_id": "2.1.7",
"title": "Section 2.1.7",
"pointer": "BRING §2.1.7 p31 (scan p30)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.TRACKING.LOWERCASE.AVOID"
]
},
{
"section_id": "2.1.8",
"title": "Section 2.1.8",
"pointer": "BRING §2.1.8 p32-33",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.KERNING.CONSISTENT_OR_NONE"
]
},
{
"section_id": "2.1.9",
"title": "Section 2.1.9",
"pointer": "BRING §2.1.9 p35 (scan p34)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.LETTERFORMS.AVOID_DISTORTION"
]
},
{
"section_id": "2.1.10",
"title": "Section 2.1.10",
"pointer": "BRING §2.1.10 p35 (scan p34)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.ALIGNMENT.DONT_STRETCH_SPACE"
]
},
{
"section_id": "2.2.1",
"title": "Section 2.2.1",
"pointer": "BRING §2.2.1 p36 (scan p35)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.BASELINE_GRID.APPLY_TO_HEADINGS",
"BRING.LAYOUT.BASELINE_GRID.APPLY_TO_CAPTIONS",
"BRING.LAYOUT.BASELINE_GRID.APPLY_TO_TABLES",
"BRING.LAYOUT.BASELINE_GRID.APPLY_TO_BLOCK_QUOTES",
"BRING.LAYOUT.LEADING.CHOOSE_BASE",
"BRING.LAYOUT.LEADING.CONSISTENT_BODY",
"BRING.LAYOUT.LEADING.ADJUST_FOR_SIZE_CHANGES",
"BRING.LAYOUT.LEADING.AVOID_TOO_TIGHT",
"BRING.LAYOUT.LEADING.AVOID_TOO_LOOSE",
"BRING.LAYOUT.LEADING.ALIGN_BASELINE_GRID"
]
},
{
"section_id": "2.2.2",
"title": "Section 2.2.2",
"pointer": "BRING §2.2.2 p37 (scan p36)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.VERTICAL_RHYTHM.MEASURED_INTERVALS.MULTIPLES",
"BRING.LAYOUT.LEADING.NEGATIVE.AVOID_CONTINUOUS_TEXT"
]
},
{
"section_id": "2.2.3",
"title": "Section 2.2.3",
"pointer": "BRING §2.2.3 p39 (scan p38)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGE.DENSITY.DONT_SUFFOCATE",
"BRING.LAYOUT.VERTICAL_RHYTHM.HEADINGS.BEFORE_AFTER",
"BRING.LAYOUT.VERTICAL_RHYTHM.LISTS.SPACING",
"BRING.LAYOUT.VERTICAL_RHYTHM.TABLES.SPACING",
"BRING.LAYOUT.VERTICAL_RHYTHM.FIGURES.SPACING",
"BRING.LAYOUT.VERTICAL_RHYTHM.CAPTIONS.SPACING",
"BRING.LAYOUT.VERTICAL_RHYTHM.FOOTNOTES.SPACING"
]
},
{
"section_id": "2.3.1",
"title": "Section 2.3.1",
"pointer": "BRING §2.3.1 p39 (scan p38)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PARAGRAPH.OPENING_FLUSH_LEFT",
"BRING.LAYOUT.PARAGRAPH.RUN_IN_HEADS.CONSISTENT",
"BRING.LAYOUT.PARAGRAPH.DROP_CAPS.ALIGN_BASELINE"
]
},
{
"section_id": "2.3.2",
"title": "Section 2.3.2",
"pointer": "BRING §2.3.2 p39 (scan p38)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PARAGRAPH.BLOCK_STYLE.CONSISTENT",
"BRING.LAYOUT.PARAGRAPH.SECTION_BREAKS.CLEAR",
"BRING.LAYOUT.PARAGRAPH.AFTER_QUOTE.FLUSH",
"BRING.LAYOUT.PARAGRAPH.INDENT_AFTER_FIRST",
"BRING.LAYOUT.PARAGRAPH.INDENT_OR_SPACE_NOT_BOTH",
"BRING.LAYOUT.PARAGRAPH.NO_INDENT_AFTER_BLOCKS",
"BRING.LAYOUT.PARAGRAPH.INDENT_SIZE.CONSISTENT",
"BRING.LAYOUT.PARAGRAPH.BLANK_LINES.SPARING",
"BRING.LAYOUT.DEGRADED.HARD_WRAP_REFLOW",
"BRING.HEADINGS.PARAGRAPH_INDENT.AFTER_HEAD_NONE"
]
},
{
"section_id": "2.3.3",
"title": "Section 2.3.3",
"pointer": "BRING §2.3.3 p40 (scan p39)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.BLOCK_QUOTES.EXTRA_LEAD",
"BRING.LAYOUT.BLOCK_QUOTES.BEFORE_AFTER_SPACING",
"BRING.LAYOUT.BLOCK_QUOTES.INDENT_OR_NARROW",
"BRING.LAYOUT.BLOCK_QUOTES.AVOID_CROWDING",
"BRING.HEADINGS.BLOCK_QUOTE.SPACING_AROUND"
]
},
{
"section_id": "2.3.4",
"title": "Section 2.3.4",
"pointer": "BRING §2.3.4 p41 (scan p40)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PARAGRAPH.INDENT.PROPORTIONAL",
"BRING.LAYOUT.PARAGRAPH.INDENT.NOT_TOO_DEEP",
"BRING.LAYOUT.PARAGRAPH.INDENT.WITHIN_MEASURE",
"BRING.LAYOUT.PARAGRAPH.LISTS.HANGING_INDENT",
"BRING.LAYOUT.PARAGRAPH.LISTS.ALIGN_WITH_BODY"
]
},
{
"section_id": "2-4.1",
"title": "Section 2-4.1",
"pointer": "BRING §2-4.1 p42",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.RHYTHM.RULES_SERVE_TEXT"
]
},
{
"section_id": "2-4.2",
"title": "Section 2-4.2",
"pointer": "BRING §2-4.2 p42",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.HYPHENATION.MIN_LEFT_RIGHT"
]
},
{
"section_id": "2-4.3",
"title": "Section 2-4.3",
"pointer": "BRING §2-4.3 p42",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.HYPHENATION.STUB_END_AVOID"
]
},
{
"section_id": "2-4.4",
"title": "Section 2-4.4",
"pointer": "BRING §2-4.4 p43",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.HYPHENATION.MAX_CONSECUTIVE_LINES"
]
},
{
"section_id": "2-4.5",
"title": "Section 2-4.5",
"pointer": "BRING §2-4.5 p43",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.HYPHENATION.AVOID_PROPER_NAMES"
]
},
{
"section_id": "2-4.6",
"title": "Section 2-4.6",
"pointer": "BRING §2-4.6 p43",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.HYPHENATION.LANGUAGE_DICTIONARY.MATCH"
]
},
{
"section_id": "2-4.7",
"title": "Section 2-4.7",
"pointer": "BRING §2-4.7 p43",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.HYPHENATION.HARD_SPACES.SHORT_EXPRESSIONS"
]
},
{
"section_id": "2-4.8",
"title": "Section 2-4.8",
"pointer": "BRING §2-4.8 p43",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.HYPHENATION.AVOID_AFTER_SHORT_LINE",
"BRING.LAYOUT.LINEBREAKS.AVOID_SAME_WORD_START"
]
},
{
"section_id": "2.4.9",
"title": "Section 2.4.9",
"pointer": "BRING §2.4.9 p44 (scan p43)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PARAGRAPH.AVOID_WIDOW_START",
"BRING.LAYOUT.PARAGRAPH.AVOID_WIDOW_END",
"BRING.LAYOUT.PAGINATION.KEEP_FIGURE_WITH_CAPTION",
"BRING.LAYOUT.PAGINATION.KEEP_TABLE_WITH_HEADER",
"BRING.LAYOUT.PAGINATION.KEEP_LIST_WITH_INTRO",
"BRING.LAYOUT.PAGINATION.AVOID_BREAK_AFTER_HEADING",
"BRING.LAYOUT.PAGINATION.AVOID_BREAK_BEFORE_LAST_LINE",
"BRING.LAYOUT.PAGINATION.AVOID_LONELY_LINE_IN_LISTS",
"BRING.LAYOUT.PAGINATION.AVOID_STRANDED_CAPTIONS"
]
},
{
"section_id": "2-4.9",
"title": "Section 2-4.9",
"pointer": "BRING §2-4.9 p44",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGINATION.ORPHANS_AVOID",
"BRING.LAYOUT.PAGINATION.WIDOWS_AVOID"
]
},
{
"section_id": "2-4.10",
"title": "Section 2-4.10",
"pointer": "BRING §2-4.10 p44",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGINATION.BALANCE_FACING_PAGES"
]
},
{
"section_id": "2-4.11",
"title": "Section 2-4.11",
"pointer": "BRING §2-4.11 p44",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.HYPHENATION.AVOID_NEAR_INTERRUPTION"
]
},
{
"section_id": "2.5",
"title": "Section 2.5",
"pointer": "BRING §2.5 p41 (scan p40)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.SIZE.BODY_SIZE_MATCH_MEASURE",
"BRING.TYPOGRAPHY.SIZE.LEADING_RELATION"
]
},
{
"section_id": "3.2.1",
"title": "Section 3.2.1",
"pointer": "BRING §3.2.1 p46 (scan p45)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.CAPS.ALL_CAPS_AVOID_LONG_RUNS",
"BRING.TYPOGRAPHY.CAPS.ALL_CAPS_SHORT_LABELS_ONLY",
"BRING.TYPOGRAPHY.CAPS.SMALL_CAPS_FOR_ACRONYMS",
"BRING.TYPOGRAPHY.CAPS.SMALL_CAPS_NOT_FOR_LONG_PASSAGES",
"BRING.TYPOGRAPHY.CAPS.MIXED_CAPS_CONSISTENT",
"BRING.TYPOGRAPHY.CAPS.AVOID_FOR_EMPHASIS",
"BRING.TYPOGRAPHY.CAPS.ROMAN_NUMERALS_SPACING"
]
},
{
"section_id": "3.3",
"title": "Section 3.3",
"pointer": "BRING §3.3 p50 (scan p49)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.LIGATURES.STANDARD_ON_BODY",
"BRING.TYPOGRAPHY.LIGATURES.AVOID_IN_CODE_URLS",
"BRING.TYPOGRAPHY.LIGATURES.FI_FL_COLLISIONS",
"BRING.TYPOGRAPHY.LIGATURES.KEEP_CONSISTENT"
]
},
{
"section_id": "3.3.1",
"title": "Section 3.3.1",
"pointer": "BRING §3.3.1 p50 (scan p49)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.LIGATURES.DISCRETIONARY_SPARING",
"BRING.TYPOGRAPHY.LIGATURES.DISCRETIONARY_IN_DISPLAY"
]
},
{
"section_id": "3.3.2",
"title": "Section 3.3.2",
"pointer": "BRING §3.3.2 p52 (scan p51)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.LIGATURES.AVOID_IN_ALL_CAPS",
"BRING.TYPOGRAPHY.LIGATURES.AVOID_IN_ACRONYMS",
"BRING.TYPOGRAPHY.LIGATURES.DO_NOT_USE_IF_AMBIGUOUS",
"BRING.TYPOGRAPHY.LIGATURES.REVIEW_FOR_LANGUAGE"
]
},
{
"section_id": "4.2",
"title": "Section 4.2",
"pointer": "BRING §4.2 p65 (scan p64)",
"status": "covered",
"rule_ids": [
"BRING.HEADINGS.CAPITALIZATION.CONSISTENT",
"BRING.HEADINGS.WEIGHT_SIZE.HIERARCHY_SCALE",
"BRING.HEADINGS.SPACING.VERTICAL_RHYTHM",
"BRING.HEADINGS.STYLE.PALETTE_LIMIT",
"BRING.HEADINGS.LENGTH.CONCISE",
"BRING.HEADINGS.NO_TERMINAL_PERIOD",
"BRING.HEADINGS.NO_TERMINAL_COLON",
"BRING.HEADINGS.QUESTION_MARK_ONLY_IF_QUESTION",
"BRING.HEADINGS.NO_HYPHENATION",
"BRING.HEADINGS.NO_SINGLE_WORD_LINE",
"BRING.HEADINGS.BREAKS.AT_PHRASE_BOUNDARIES",
"BRING.HEADINGS.AVOID_STACKED_LEVELS",
"BRING.HEADINGS.SUBHEADS.PARALLEL_GRAMMAR",
"BRING.HEADINGS.WIDTH.BALANCED",
"BRING.HEADINGS.AVOID_ABBREVIATIONS",
"BRING.HEADINGS.CASE.PROPER_NOUNS_PRESERVE",
"BRING.HEADINGS.LEADIN_TEXT.BEFORE_LIST",
"BRING.HEADINGS.HIERARCHY.MAX_DEPTH",
"BRING.HEADINGS.SECTION_OPENING.PARAGRAPH_REQUIRED",
"BRING.HEADINGS.SUBHEADS.STYLE_CONTRIBUTES_TO_WHOLE"
]
},
{
"section_id": "4.2.1",
"title": "Section 4.2.1",
"pointer": "BRING §4.2.1 p65 (scan p64)",
"status": "covered",
"rule_ids": [
"BRING.HEADINGS.RUN_IN.STANDALONE.CONSISTENT",
"BRING.HEADINGS.ALIGNMENT.CONSISTENT_LEVEL",
"BRING.HEADINGS.MARGIN_HEADS.CLEAR_GUTTER",
"BRING.HEADINGS.HIERARCHY.NO_SKIPPED_LEVELS",
"BRING.HEADINGS.RUN_IN.END_PUNCTUATION",
"BRING.HEADINGS.RUN_IN.SEPARATION.CONSISTENT",
"BRING.HEADINGS.SUBHEADS.CROSSHEADS_SIDEHEADS.CHOOSE_DELIBERATELY",
"BRING.HEADINGS.SUBHEADS.RIGHT_SIDEHEADS.VISIBILITY",
"BRING.HEADINGS.SUBHEADS.MARGIN_HEADS.RUNNING_SHOULDERHEADS",
"BRING.HEADINGS.SUBHEADS.LEVELS.AS_MANY_AS_NEEDED"
]
},
{
"section_id": "4.2.2",
"title": "Section 4.2.2",
"pointer": "BRING §4.2.2 p65 (scan p64)",
"status": "covered",
"rule_ids": [
"BRING.HEADINGS.CONTRAST.CLEAR_HIERARCHY",
"BRING.HEADINGS.SUBHEADS.MIXING_SYMM_ASYMM.AVOID_HAPHAZARD",
"BRING.HEADINGS.SUBHEADS.MIXING.HIERARCHY_PLACEMENT"
]
},
{
"section_id": "4.3.2",
"title": "Section 4.3.2",
"pointer": "BRING §4.3.2 p68 (scan p67)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.WEIGHT.HIERARCHY_CLEAR",
"BRING.TYPOGRAPHY.WEIGHT.AVOID_TOO_MANY_WEIGHTS",
"BRING.TYPOGRAPHY.WEIGHT.BOLD_IN_LONG_PASSAGES_AVOID",
"BRING.TYPOGRAPHY.WEIGHT.HEAVY_WEIGHTS_SHORT_LABELS"
]
},
{
"section_id": "4.3.3",
"title": "Section 4.3.3",
"pointer": "BRING §4.3.3 p69 (scan p68)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.SIZE.SCALE_CONSISTENT",
"BRING.TYPOGRAPHY.SIZE.AVOID_TOO_MANY_SIZES",
"BRING.TYPOGRAPHY.SIZE.SMALL_TEXT_MINIMUM",
"BRING.TYPOGRAPHY.SIZE.DISPLAY_SIZE_BALANCE"
]
},
{
"section_id": "4.4",
"title": "Section 4.4",
"pointer": "BRING §4.4 p70 (scan p69)",
"status": "covered",
"rule_ids": [
"BRING.TABLES.TITLES.CONSISTENT_PLACEMENT",
"BRING.TABLES.CAPTIONS.CLEAR"
]
},
{
"section_id": "4.4.1",
"title": "Section 4.4.1",
"pointer": "BRING §4.4.1 p70 (scan p69)",
"status": "covered",
"rule_ids": [
"BRING.TABLES.HEADERS.CONCISE",
"BRING.TABLES.HEADERS.ALIGN_WITH_COLUMNS",
"BRING.TABLES.UNITS.IN_HEADERS",
"BRING.TABLES.STUB_COLUMN.USE",
"BRING.TABLES.GROUPING.WHITESPACE",
"BRING.TABLES.ROW_SPACING.READABLE",
"BRING.TABLES.COLUMN_ALIGNMENT.CONSISTENT",
"BRING.TABLES.SOURCES.NOTES.DISTINCT",
"BRING.TABLES.MULTI_LINE_HEADERS.AVOID",
"BRING.TABLES.NUMERIC_PRECISION.CONSISTENT",
"BRING.TABLES.DATA_TYPES.NOT_MIXED",
"BRING.TABLES.ORDER.LOGICAL",
"BRING.TABLES.DEGRADED.REBUILD_COLUMNS",
"BRING.TABLES.EDIT_AS_TEXT.READABILITY",
"BRING.TABLES.FURNITURE.MINIMIZE",
"BRING.TABLES.TEXT_ORIENTATION.HORIZONTAL",
"BRING.TABLES.TYPE_SIZE.READABLE",
"BRING.TABLES.GUIDES.READING_DIRECTION"
]
},
{
"section_id": "4.4.3",
"title": "Section 4.4.3",
"pointer": "BRING §4.4.3 p111 (scan p110)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.NUMERALS.TABULAR_FOR_TABLES",
"BRING.TYPOGRAPHY.NUMERALS.SLASHED_ZERO_IF_CONFUSION",
"BRING.TYPOGRAPHY.NUMERALS.FRACTIONS_TRUE_GLYPHS",
"BRING.TYPOGRAPHY.NUMERALS.SUPERIOR_INFERIOR_FOR_NOTES",
"BRING.LAYOUT.COLUMNS.COUNT.MODERATE",
"BRING.LAYOUT.COLUMNS.WIDTH.CONSISTENT",
"BRING.LAYOUT.COLUMNS.GUTTER.CONSISTENT",
"BRING.LAYOUT.COLUMNS.GUTTER.SUFFICIENT",
"BRING.LAYOUT.COLUMNS.ALIGN_BASELINES",
"BRING.LAYOUT.COLUMNS.SPAN_POLICY.FIGURES",
"BRING.LAYOUT.COLUMNS.SPAN_POLICY.TABLES",
"BRING.LAYOUT.COLUMNS.SIDEBARS.DISTINCT_MEASURE",
"BRING.LAYOUT.COLUMNS.RAGGED_BOTTOM.AVOID",
"BRING.LAYOUT.COLUMNS.USE_FOR_LONG_LISTS"
]
},
{
"section_id": "4.4.4",
"title": "Section 4.4.4",
"pointer": "BRING §4.4.4 p72 (scan p71)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.NUMERALS.OLDSTYLE_FOR_TEXT",
"BRING.TYPOGRAPHY.NUMERALS.LINING_FOR_CAPS_AND_DISPLAY",
"BRING.TYPOGRAPHY.NUMERALS.PROPORTIONAL_FOR_PROSE",
"BRING.TYPOGRAPHY.NUMERALS.CONSISTENT_STYLE_WITHIN_SECTION",
"BRING.TYPOGRAPHY.NUMERALS.MIXED_STYLE_AVOID",
"BRING.TYPOGRAPHY.NUMERALS.FIGURE_STYLE_FOR_CAPTIONS",
"BRING.TYPOGRAPHY.NUMERALS.SMALL_CAPS_AND_FIGURES",
"BRING.TYPOGRAPHY.NUMERALS.AVOID_LINING_IN_LOWERCASE"
]
},
{
"section_id": "6.1.1",
"title": "Section 6.1.1",
"pointer": "BRING §6.1.1 p93 (scan p92)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.TYPEFACE.TEXT_FACES_FOR_BODY",
"BRING.TYPOGRAPHY.TYPEFACE.DISPLAY_FACES_FOR_DISPLAY",
"BRING.TYPOGRAPHY.TYPEFACE.FALLBACKS_COMPATIBLE_METRICS",
"BRING.TYPOGRAPHY.TYPEFACE.GLYPH_COVERAGE_REQUIRED",
"BRING.TYPOGRAPHY.TYPEFACE.OPTICAL_SIZES_USE",
"BRING.TYPOGRAPHY.TYPEFACE.FAMILY_WITH_VARIANTS",
"BRING.TYPOGRAPHY.TYPEFACE.LEGIBILITY_AT_SIZE"
]
},
{
"section_id": "6.5.1",
"title": "Section 6.5.1",
"pointer": "BRING §6.5.1 p102 (scan p101)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.FAMILY.SINGLE_FAMILY_BODY",
"BRING.TYPOGRAPHY.FAMILY.METRICS_MATCH_WHEN_MIXING",
"BRING.TYPOGRAPHY.FAMILY.LIMIT_STYLE_VARIANTS"
]
},
{
"section_id": "6.5.2",
"title": "Section 6.5.2",
"pointer": "BRING §6.5.2 p103 (scan p102)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.FAMILY.TRUE_ITALICS",
"BRING.TYPOGRAPHY.FAMILY.TRUE_SMALL_CAPS",
"BRING.TYPOGRAPHY.FAMILY.SMALL_CAPS_SPARE",
"BRING.TYPOGRAPHY.FAMILY.ITALIC_FOR_SUBTLE_EMPHASIS",
"BRING.TYPOGRAPHY.FAMILY.ITALIC_PUNCTUATION_MATCH"
]
},
{
"section_id": "6.5.3",
"title": "Section 6.5.3",
"pointer": "BRING §6.5.3 p103 (scan p102)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.FAMILY.AVOID_FAUX_BOLD",
"BRING.TYPOGRAPHY.FAMILY.USE_DESIGNED_WEIGHTS",
"BRING.TYPOGRAPHY.FAMILY.BOLD_FOR_STRONG_EMPHASIS",
"BRING.TYPOGRAPHY.FAMILY.WEIGHT_CONTRAST_CLEAR",
"BRING.TYPOGRAPHY.BOLD.SPARING_USE",
"BRING.TYPOGRAPHY.BOLD.AVOID_LONG_PASSAGES",
"BRING.TYPOGRAPHY.BOLD.NOT_WITH_ALL_CAPS",
"BRING.TYPOGRAPHY.BOLD.NOT_WITH_ITALICS_LONG",
"BRING.TYPOGRAPHY.BOLD.LABELS_SHORT",
"BRING.TYPOGRAPHY.BOLD.HEADING_HIERARCHY_BALANCE"
]
},
{
"section_id": "6.5.5",
"title": "Section 6.5.5",
"pointer": "BRING §6.5.5 p105 (scan p104)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.SERIF.BODY_TEXT_DEFAULT",
"BRING.TYPOGRAPHY.SERIF.SANS_FOR_DISPLAY",
"BRING.TYPOGRAPHY.SERIF.AVOID_MIX_SAME_ROLE",
"BRING.TYPOGRAPHY.SERIF.SERIF_SANS_BALANCE"
]
},
{
"section_id": "7.2.1",
"title": "Section 7.2.1",
"pointer": "BRING §7.2.1 p122 (scan p121)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.ITALICS.SPARING",
"BRING.TYPOGRAPHY.ITALICS.LONG_SPANS_AVOID",
"BRING.TYPOGRAPHY.ITALICS.TERMS_INTRODUCED_SPARE",
"BRING.TYPOGRAPHY.ITALICS.PUNCTUATION_FOLLOWS_STYLE",
"BRING.TYPOGRAPHY.ITALICS.EMPHASIS_NOT_UNDERLINE",
"BRING.TYPOGRAPHY.ITALICS.AVOID_STACKED_EMPHASIS",
"BRING.TYPOGRAPHY.ITALICS.AVOID_NUMERAL_ITALICS"
]
},
{
"section_id": "7.2.2",
"title": "Section 7.2.2",
"pointer": "BRING §7.2.2 p124 (scan p123)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.ITALICS.TITLES_STANDALONE_WORKS",
"BRING.TYPOGRAPHY.ITALICS.CONSISTENT_TITLE_TREATMENT"
]
},
{
"section_id": "7.2.7",
"title": "Section 7.2.7",
"pointer": "BRING §7.2.7 p130 (scan p129)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.ITALICS.AVOID_IN_ALL_CAPS_HEADINGS",
"BRING.TYPOGRAPHY.ITALICS.HEADINGS_AVOID",
"BRING.TYPOGRAPHY.ITALICS.RUNNING_HEADS_AVOID"
]
},
{
"section_id": "8.3",
"title": "Section 8.3",
"pointer": "BRING §8.3 p160 (scan p117)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGE.SHAPE.PROPORTIONATE",
"BRING.LAYOUT.PAGE.WHITE_SPACE.DISTRIBUTION"
]
},
{
"section_id": "8.3.1",
"title": "Section 8.3.1",
"pointer": "BRING §8.3.1 p160 (scan p117)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGE.TEXTBLOCK.POSITION"
]
},
{
"section_id": "8.4.2",
"title": "Section 8.4.2",
"pointer": "BRING §8.4.2 p163 (scan p162)",
"status": "covered",
"rule_ids": [
"BRING.TYPOGRAPHY.CONTRAST.FONT_PAIRING_MATCH",
"BRING.TYPOGRAPHY.CONTRAST.AVOID_EXTREME_MIX",
"BRING.TYPOGRAPHY.SERIF.PAIR_WITH_COMPATIBLE_XHEIGHT",
"BRING.TYPOGRAPHY.SERIF.STROKE_CONTRAST_COMPATIBLE"
]
},
{
"section_id": "8.5",
"title": "Section 8.5",
"pointer": "BRING §8.5 p165 (scan p120)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.MARGINS.PROPORTION.BALANCED",
"BRING.LAYOUT.MARGINS.CONSISTENT.ACROSS_SECTIONS",
"BRING.LAYOUT.MARGINS.RUNNING_HEAD.CLEARANCE",
"BRING.LAYOUT.MARGINS.FOOTNOTE.CLEARANCE",
"BRING.LAYOUT.MARGINS.AVOID_CROWDING",
"BRING.LAYOUT.MARGINS.NOTES.OUTSIDE_TEXTBLOCK"
]
},
{
"section_id": "8.5.1",
"title": "Section 8.5.1",
"pointer": "BRING §8.5.1 p165 (scan p120)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.MARGINS.OUTER_LARGER_THAN_INNER",
"BRING.LAYOUT.MARGINS.GUTTER.ALLOW_BINDING"
]
},
{
"section_id": "8.5.2",
"title": "Section 8.5.2",
"pointer": "BRING §8.5.2 p165 (scan p120)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.MARGINS.TOP_BOTTOM.BALANCE",
"BRING.LAYOUT.MARGINS.BLEED.ONLY_WHEN_ENABLED"
]
},
{
"section_id": "8.6.1",
"title": "Section 8.6.1",
"pointer": "BRING §8.6.1 p166 (scan p121)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGE.ODD_EVEN.CONSISTENT",
"BRING.LAYOUT.PAGE.OPENING_SPREAD.RULE"
]
},
{
"section_id": "8.8.3",
"title": "Section 8.8.3",
"pointer": "BRING §8.8.3 p178 (scan p122)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGE.SPREADS.BALANCE_CONTENT",
"BRING.LAYOUT.PAGE.SPREADS.ALIGN_BASELINES",
"BRING.LAYOUT.PAGE.FACING_ELEMENTS.ALIGN"
]
},
{
"section_id": "9.4",
"title": "Section 9.4",
"pointer": "BRING §9.4 p42 (scan p41)",
"status": "covered",
"rule_ids": [
"BRING.LAYOUT.PAGINATION.AVOID_BREAK_IN_EQUATIONS",
"BRING.LAYOUT.PAGINATION.AVOID_BREAK_IN_BLOCK_QUOTES",
"BRING.LAYOUT.PAGINATION.BALANCE_FINAL_PAGE",
"BRING.LAYOUT.PAGINATION.AVOID_EXCESS_WHITE_SPACE",
"BRING.LAYOUT.PAGINATION.CLEAR_SECTION_BREAKS"
]
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
# HOUSE citations pointers
House-level pointers for citations lint rules.
- HOUSE §CIT.AUTHOR_DATE.PAREN_YEAR_ONLY p1
- HOUSE §CIT.AUTHOR_DATE.REFLIST.YEAR_REQUIRED p1
- HOUSE §CIT.AUTHOR_DATE.REFLIST.REQUIRED p1
- HOUSE §CIT.NOTES.DEFINITIONS.REQUIRED p1
- HOUSE §CIT.NOTES.MARKERS.BRACKETED_NUMBERS.AVOID p1
- HOUSE §CIT.NOTES.BIBLIOGRAPHY.REQUIRED p1
- HOUSE §CIT.NOTES.IBID.AVOID p1

View file

@ -0,0 +1,31 @@
# HOUSE code pointers
This document defines pointer anchors for the `code` rule category.
It contains no third-party text. Pointers refer to house-maintained guidance used by iftypeset.
Pointer format: `HOUSE §CODE.<SECTION> pN`.
## §CODE.BLOCKS (p1)
General rules for code blocks: structure, elision, determinism, and required context.
## §CODE.EXAMPLES (p1)
Expectations for example quality and reproducibility (tested vs pseudo-code, valid configs).
## §CODE.TYPOGRAPHY (p2)
Typography and formatting for code (monospace, whitespace, smart quotes, line numbers).
## §CODE.SHELL (p2)
Shell-specific conventions (prompts, platform notes, destructive command warnings).
## §CODE.SECURITY (p2)
Redaction, placeholders, and handling of sensitive values in examples.
## §CODE.DIFFS (p2)
Diff formatting expectations (unified format, file headers, context lines).

View file

@ -0,0 +1,25 @@
# HOUSE color pointers
House-level pointers for color usage in documents and tables.
Pointer format: `HOUSE §COLOR.<SECTION> pN`.
## §COLOR.HIERARCHY (p1)
Use a restrained accent color to aid navigation (headings, section markers) without reducing readability.
## §COLOR.RESTRAINT (p1)
Keep color use limited to navigation, links, and small highlights; body text stays neutral for legibility.
## §COLOR.LINKS (p1)
Link color must remain readable and should not be the only indicator (retain underlines).
## §COLOR.CITATIONS (p1)
Inline citation tokens may be styled subtly to separate evidence markers from narrative text.
## §COLOR.TABLES (p1)
Table accents (rules/stripes) should be subtle, low-contrast, and supportive of scanning.

View file

@ -0,0 +1,63 @@
# HOUSE editorial pointers
This document defines what `HOUSE §... pN` pointers mean for the `editorial` rule category.
These are **house** rules: they do not reproduce Chicago/Bringhurst text and do not require access to those books.
## Pointer format
Editorial rules cite pointers like:
- `HOUSE §EDITORIAL.PLACEHOLDERS p1`
- `HOUSE §EDITORIAL.STRUCTURE p1`
Interpretation:
- `HOUSE` means the pointer refers to a house-maintained document in `spec/house/`.
- `§EDITORIAL.<SECTION>` names the section inside this file.
- `pN` is a **stable logical page identifier for this pointer doc**, used for schema compatibility and future PDF exports.
For `HOUSE_EDITORIAL_POINTERS.md` v1, all pointers use `p1` because the document is short; use the `§...` section id for the exact location.
## Sections (v1)
### §EDITORIAL.PLACEHOLDERS (p1)
Draft markers and placeholder content that must be removed or resolved before publishing.
### §EDITORIAL.STRUCTURE (p1)
Document structure expectations (title, summary, scope, audience, decisions, action items).
### §EDITORIAL.HEADINGS (p1)
Editorial expectations for headings as text (not typographic styling).
### §EDITORIAL.LISTS (p1)
Editorial expectations for list usage and list content.
### §EDITORIAL.CLARITY (p1)
Clarity guidelines (ambiguity, definitions, brevity, self-contained writing).
### §EDITORIAL.TONE (p1)
Tone and audience fit, including inclusive language guidance.
### §EDITORIAL.CLAIMS (p1)
How to treat claims (evidence, framing, quantification, comparisons).
### §EDITORIAL.CONSISTENCY (p1)
Consistency guidelines (terminology, capitalization, spelling variants, naming, time zones).
### §EDITORIAL.REVIEW (p1)
Review checklist items (spellcheck, fact-check, link verification).
### §EDITORIAL.OPSEC (p1)
Safety checks to avoid publishing secrets or sensitive data.

View file

@ -0,0 +1,45 @@
# HOUSE figures/tables pointers
House-level pointers for figures and tables rules.
Pointer format: `HOUSE §FIGURES.<SECTION> pN` or `HOUSE §TABLES.<SECTION> pN`.
## §FIGURES.FORMAT (p1)
Figure file format, vector/raster usage, and resolution expectations.
## §FIGURES.COLOR (p1)
Color and contrast guidance for charts and diagrams.
## §FIGURES.AXES (p1)
Axis labeling and unit disclosure for quantitative figures.
## §FIGURES.CAPTIONS (p1)
Caption content expectations for figures.
## §FIGURES.TEXT (p1)
Figure text legibility and avoidable rasterized text guidance.
## §TABLES.UNITS (p1)
Unit labeling and numeric context in tables.
## §TABLES.ALIGNMENT (p1)
Numeric alignment and precision consistency.
## §TABLES.COLOR (p1)
Subtle shading or striping to improve scanability without heavy gridlines.
## §TABLES.SOURCES (p1)
Data source and notes placement for tables.
## §TABLES.MISSING_DATA (p1)
Missing-data notation and explanatory notes.

View file

@ -0,0 +1,41 @@
# HOUSE front/back matter pointers
House-level pointers for frontmatter and backmatter rules.
Pointer format: `HOUSE §FRONTMATTER.<SECTION> pN` or `HOUSE §BACKMATTER.<SECTION> pN`.
## §FRONTMATTER.METADATA (p1)
Document metadata conventions (status, version, owner, dates, distribution labels).
## §FRONTMATTER.TOC (p1)
Table-of-contents generation and consistency expectations.
## §FRONTMATTER.ABSTRACT (p1)
Abstract/summary expectations for long or technical documents.
## §FRONTMATTER.DISTRIBUTION (p1)
Distribution, confidentiality, and contact cues for external sharing.
## §BACKMATTER.REFERENCES (p1)
Reference list ordering, completeness, and deduplication rules.
## §BACKMATTER.GLOSSARY (p1)
Glossary ordering and cross-reference expectations.
## §BACKMATTER.APPENDICES (p1)
Appendix labeling and cross-reference consistency.
## §BACKMATTER.NOTES (p1)
Notes and footnote conventions that affect backmatter layout.
## §BACKMATTER.INDEX (p1)
Index ordering and cross-reference conventions.

View file

@ -0,0 +1,37 @@
# HOUSE i18n pointers
House-level pointers for i18n rules.
Pointer format: `HOUSE §I18N.<SECTION> pN`.
## §I18N.NUMBERS.MIXED_DECIMAL_SEPARATORS (p1)
Avoid mixing decimal separators across the document.
## §I18N.QUOTES.MIXED_STYLES (p1)
Avoid mixing quotation mark styles without a declared language boundary.
## §I18N.NUMBERS.GROUPING (p1)
Use one thousands-grouping style per document based on locale.
## §I18N.NUMBERS.DIGIT_SYSTEM (p1)
Keep digit systems consistent within numeric contexts.
## §I18N.LANGUAGE.SWITCHES (p1)
Mark language switches for non-primary language passages.
## §I18N.CURRENCY.DISAMBIGUATE (p1)
Disambiguate currency symbols in international contexts.
## §I18N.TRANSLATION.LABELS (p1)
Label translated passages and their sources when relevant.
## §I18N.UNITS.SPACING (p1)
Apply locale-appropriate spacing between numbers and units.

View file

@ -0,0 +1,45 @@
# HOUSE layout + typography pointers
House-level pointers for layout and typography rules that are not tied to third-party sources.
Pointer format: `HOUSE §LAYOUT.<SECTION> pN` or `HOUSE §TYPOGRAPHY.<SECTION> pN`.
## §LAYOUT.HTML.MEASURE (p1)
HTML measure and max-width constraints for readable line length.
## §LAYOUT.HTML.GUTTERS (p1)
Minimum side padding and spacing for narrow screens.
## §LAYOUT.HTML.SECTION_SPACING (p1)
Consistent vertical spacing between major sections in HTML output.
## §LAYOUT.MD.BLANK_LINES.SPARING (p1)
Markdown spacing guidance: avoid excessive blank lines unless marking a section break.
## §LAYOUT.MD.HEADINGS.NON_EMPTY_SECTIONS (p1)
Headings should introduce content; avoid empty sections in Markdown sources.
## §LAYOUT.PAGINATION.RUNT_FINAL_PAGE (p1)
Avoid final pages that carry only a few lines; ensure the last page looks intentional.
## §TYPOGRAPHY.HTML.LINE_HEIGHT (p1)
Minimum line-height and readable spacing for body text in HTML output.
## §TYPOGRAPHY.HTML.JUSTIFICATION (p1)
Justification policy for web outputs (avoid full justification unless carefully controlled).
## §TYPOGRAPHY.HTML.LINK_DECORATION (p1)
Link decoration expectations for readable, distinguishable text links.
## §TYPOGRAPHY.MD.EMPHASIS.BALANCE (p1)
Heuristic guidance for emphasis spans in Markdown (avoid long bold/italic runs).

View file

@ -57,3 +57,53 @@ House baseline accessibility rules for exported HTML/PDF:
- images must have alt text (or an explicit empty alt when decorative),
- link text must be descriptive (avoid “click here”),
- document language must be declared where supported.
## §A11Y.LINKS (p3)
House accessibility guidance for links and navigation:
- link targets should be clear and operable without relying on color alone,
- icon-only links require accessible text,
- table of contents entries should be navigable links where supported.
## §A11Y.IMAGES (p3)
House accessibility guidance for images:
- linked images need alt text that describes the destination or purpose,
- complex figures should include nearby text or captions that explain meaning.
## §A11Y.TABLES (p3)
House accessibility guidance for tables:
- table headers should be identifiable in HTML outputs,
- avoid layouts that hide structure or merge cells without clear labeling.
## §A11Y.NAVIGATION (p3)
House accessibility guidance for navigation aids:
- provide footnote backlinks when notes are used,
- generate PDF bookmarks from headings when the engine supports it.
## §QA.CAPTIONS (p2)
House guidance for caption proximity:
- keep figure/table captions with their associated content,
- flag captions that appear isolated at page edges.
## §QA.LISTS (p2)
House guidance for list pagination:
- keep list introductions with the first list item,
- avoid lone list items at the top or bottom of a page.
## §QA.HEADINGS (p2)
House guidance for heading proximity:
- avoid back-to-back headings without body text in between,
- ensure headings are followed by sufficient content on the same page when possible.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -59,6 +59,8 @@ profiles:
- dense_tech
- memo
- slide_deck
- webtypography_nc
- cv_onepage
planned_rule_counts:
target_total_range: [800, 1500]
@ -139,4 +141,3 @@ degraded_mode_contract:
- "layout-report.json"
- "coverage-report.json"
- "degraded-mode-report.json (what was inferred and why)"

View file

@ -0,0 +1,124 @@
profile_id: "audit_report"
description: "Evidence-heavy audit reports: 12pt baseline, branded tables, and tolerant QA thresholds for long sources/citations."
page:
size: "A4"
orientation: "portrait"
two_sided: false
margins:
top: "27mm"
bottom: "27mm"
inner: "27mm"
outer: "27mm"
fonts:
require_primary: true
body:
family: ["Noto Serif", "STIX Two Text", "serif"]
size: "12pt"
line_height: 1.50
heading:
family: ["Noto Sans", "Source Sans 3", "sans-serif"]
mono:
family: ["Noto Sans Mono", "Source Code Pro", "monospace"]
size: "10.5pt"
line_height: 1.30
colors:
body: "#111827"
accent: "#1f3a5f"
heading: "#1f3a5f"
link: "#1f3a5f"
citation: "#3b4b63"
table_rule: "#cbd5e1"
table_stripe: "#f1f5f9"
measure_targets:
columns: 1
body_chars_per_line:
min: 60
ideal: 75
max: 180
hyphenation:
enabled: true
strategy: "balanced"
min_left: 2
min_right: 3
max_consecutive_hyphenated_lines: 3
avoid_proper_names_when_possible: true
headings:
keep_with_next_lines: 1
avoid_stranded_headings: true
numbering:
enabled: false
widows_orphans:
widow_lines: 2
orphan_lines: 2
balance_facing_pages: false
code:
block:
font_size: "10pt"
line_height: 1.30
wrap: true
overflow_policy: "wrap_then_shrink_minor"
shrink_limit: 0.92
padding: "0.4em 0.6em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "3pt 6pt"
header_repeat: true
overflow_policy: "shrink_then_wrap"
shrink_limit: 0.90
layout: "auto"
cell_wrap: true
keep_together: true
row_keep_together: true
grid_style: "rules_minimal"
header_align: "left"
cell_align: "left"
numeric_align: "right"
boolean_align: "center"
figures:
max_width: "100%"
margin: "0.6em auto"
typography:
small_caps_acronyms:
enabled: true
min_letters: 2
letter_spacing: "0.04em"
lists:
hanging_punctuation:
enabled: true
indent: "1.2em"
hang: "0.4em"
running_head:
enabled: true
placement: "footer"
template: "{page} | {title}"
font_size: "9pt"
font_style: "normal"
color: "#6b7280"
severity_overrides:
- selector: { category: "accessibility" }
severity: "must"
locale_defaults:
primary_language: "en"
fallback_languages: ["fr"]
quotation_style: "us"
date_format: "YYYY-MM-DD"
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -0,0 +1,162 @@
profile_id: "cv_onepage"
description: "Single-page CV profile: compact, readable, and print-ready with balanced spacing."
page:
size: "A4"
orientation: "portrait"
two_sided: false
margins:
top: "16mm"
bottom: "16mm"
inner: "14mm"
outer: "14mm"
fonts:
body:
family: ["Noto Sans", "Source Sans 3", "Arial", "sans-serif"]
size: "11.1pt"
line_height: 1.58
heading:
family: ["Noto Sans", "Source Sans 3", "Arial", "sans-serif"]
mono:
family: ["Noto Sans Mono", "Source Code Pro", "Consolas", "monospace"]
size: "9.5pt"
line_height: 1.25
colors:
body: "#111827"
accent: "#111827"
heading: "#111827"
link: "#111827"
citation: "#111827"
table_rule: "#cbd5e1"
table_stripe: "#f8fafc"
measure_targets:
columns: 1
body_chars_per_line:
min: 55
ideal: 66
max: 75
hyphenation:
enabled: true
strategy: "balanced"
language_driven: true
min_left: 2
min_right: 3
max_consecutive_hyphenated_lines: 2
avoid_proper_names_when_possible: true
paragraphs:
first_paragraph_indent: "0"
indent: "0"
block_paragraph_spacing: "0.7em"
headings:
keep_with_next_lines: 2
avoid_stranded_headings: true
numbering:
enabled: false
sizes:
h1: "1.5em"
h2: "1.15em"
h3: "1.05em"
spacing:
top: "0.6em"
bottom: "0.2em"
widows_orphans:
widow_lines: 2
orphan_lines: 2
balance_facing_pages: false
code:
block:
font_size: "9pt"
line_height: 1.25
wrap: true
padding: "0.35em 0.5em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "2pt 4pt"
header_repeat: false
overflow_policy: "shrink_then_wrap"
shrink_limit: 0.90
layout: "auto"
cell_wrap: true
keep_together: true
row_keep_together: true
grid_style: "rules_minimal"
header_align: "left"
cell_align: "left"
numeric_align: "right"
boolean_align: "center"
figures:
max_width: "100%"
margin: "0.5em auto"
typography:
small_caps_acronyms:
enabled: false
min_letters: 2
letter_spacing: "0.04em"
drop_caps:
enabled: false
size: "2.8em"
padding_right: "0.08em"
padding_top: "0.02em"
weight: "700"
text_wrap:
body: "pretty"
headings: "balance"
lists:
hanging_punctuation:
enabled: true
indent: "0.9em"
hang: "0.3em"
text_wrap: "balance"
wrap_heuristics:
enabled: true
width_factor: 0.9
min_tail_ratio: 0.28
min_tail_chars: 14
max_shift_words: 4
indent_chars: 2
balance_with_playwright: true
max_passes: 2
layout:
auto_density: true
density_thresholds:
tight_over: 42
loose_under: 34
density_overrides:
tight:
body_line_height: 1.44
paragraph_spacing: "0.5em"
heading_margin_top: "0.45em"
heading_margin_bottom: "0.12em"
normal:
body_line_height: 1.58
paragraph_spacing: "0.7em"
heading_margin_top: "0.6em"
heading_margin_bottom: "0.2em"
loose:
body_line_height: 1.72
paragraph_spacing: "0.95em"
heading_margin_top: "0.8em"
heading_margin_bottom: "0.25em"
section_overrides:
experience:
list_item_width: "60ch"
list_item_max_width: "60ch"
list_margin_right: "0.3em"
running_head:
enabled: false

View file

@ -1,5 +1,5 @@
profile_id: "dense_tech"
description: "Technical papers and specs: denser copy, more code/table tolerance, strict numbering and citations."
description: "Technical papers and specs: 12pt baseline, denser copy, more code/table tolerance, strict numbering and citations."
page:
size: "A4"
@ -14,14 +14,23 @@ page:
fonts:
body:
family: ["Noto Serif", "STIX Two Text", "serif"]
size: "10pt"
line_height: 1.35
size: "12pt"
line_height: 1.45
heading:
family: ["Noto Sans", "Source Sans 3", "sans-serif"]
mono:
family: ["Noto Sans Mono", "Source Code Pro", "monospace"]
size: "9pt"
line_height: 1.25
size: "10.5pt"
line_height: 1.30
colors:
body: "#111827"
accent: "#1f3a5f"
heading: "#1f3a5f"
link: "#1f3a5f"
citation: "#3b4b63"
table_rule: "#cbd5e1"
table_stripe: "#f1f5f9"
measure_targets:
columns: 1
@ -53,17 +62,34 @@ widows_orphans:
code:
block:
font_size: "8.8pt"
line_height: 1.20
font_size: "10pt"
line_height: 1.30
wrap: true
overflow_policy: "wrap_then_shrink_minor"
shrink_limit: 0.90
padding: "0.35em 0.5em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "2pt 4pt"
cell_padding: "3pt 6pt"
header_repeat: true
overflow_policy: "shrink_then_wrap"
shrink_limit: 0.85
shrink_limit: 0.90
layout: "auto"
cell_wrap: true
keep_together: true
row_keep_together: true
grid_style: "rules_minimal"
header_align: "left"
cell_align: "left"
numeric_align: "right"
boolean_align: "center"
figures:
max_width: "100%"
margin: "0.5em auto"
severity_overrides:
- selector: { category: "citations" }
@ -81,4 +107,3 @@ locale_defaults:
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -14,7 +14,7 @@ page:
fonts:
body:
family: ["Noto Sans", "Source Sans 3", "Arial", "sans-serif"]
size: "11pt"
size: "12pt"
line_height: 1.40
heading:
family: ["Noto Sans", "Source Sans 3", "Arial", "sans-serif"]
@ -23,6 +23,15 @@ fonts:
size: "10pt"
line_height: 1.30
colors:
body: "#111827"
accent: "#1f3a5f"
heading: "#1f3a5f"
link: "#1f3a5f"
citation: "#3b4b63"
table_rule: "#cbd5e1"
table_stripe: "#f1f5f9"
measure_targets:
columns: 1
body_chars_per_line:
@ -52,12 +61,22 @@ code:
wrap: true
overflow_policy: "wrap"
shrink_limit: 1.0
padding: "0.35em 0.5em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "3pt 6pt"
header_repeat: false
overflow_policy: "wrap"
shrink_limit: 1.0
layout: "auto"
cell_wrap: true
figures:
max_width: "100%"
margin: "0.5em auto"
severity_overrides:
- selector: { category: "layout", tag: "widows_orphans" }
@ -73,4 +92,3 @@ locale_defaults:
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -23,6 +23,15 @@ fonts:
size: "9.5pt"
line_height: 1.30
colors:
body: "#111827"
accent: "#111827"
heading: "#111827"
link: "#111827"
citation: "#111827"
table_rule: "#cbd5e1"
table_stripe: "#f8fafc"
measure_targets:
columns: 1
body_chars_per_line:
@ -49,6 +58,8 @@ headings:
enabled: true
style: "decimal"
require_monotonic_increase: true
rule:
enabled: false
widows_orphans:
widow_lines: 2
@ -59,15 +70,57 @@ code:
block:
font_size: "9pt"
line_height: 1.25
wrap: false
overflow_policy: "shrink_then_scroll_indicator"
wrap: true
overflow_policy: "wrap_then_shrink_minor"
shrink_limit: 0.90
padding: "0.4em 0.6em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "2.5pt 5pt"
header_repeat: true
overflow_policy: "shrink_then_rotate_if_allowed"
shrink_limit: 0.88
layout: "auto"
cell_wrap: true
keep_together: true
row_keep_together: true
grid_style: "rules_minimal"
header_align: "left"
cell_align: "left"
numeric_align: "right"
boolean_align: "center"
figures:
max_width: "100%"
margin: "0.6em auto"
typography:
small_caps_acronyms:
enabled: true
min_letters: 2
letter_spacing: "0.04em"
drop_caps:
enabled: true
size: "3em"
padding_right: "0.08em"
padding_top: "0.02em"
lists:
hanging_punctuation:
enabled: true
indent: "1.1em"
hang: "0.4em"
running_head:
enabled: true
placement: "footer"
template: "{page} | {title}"
font_size: "8.5pt"
font_style: "normal"
color: "#6b7280"
severity_overrides:
- selector: { category: "layout", tag: "widows_orphans" }
@ -85,4 +138,3 @@ locale_defaults:
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -52,12 +52,22 @@ code:
wrap: true
overflow_policy: "wrap_then_shrink_minor"
shrink_limit: 0.92
padding: "0.35em 0.5em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "6pt 10pt"
header_repeat: false
overflow_policy: "shrink_then_wrap"
shrink_limit: 0.88
layout: "fixed"
cell_wrap: true
figures:
max_width: "100%"
margin: "0.4em auto"
severity_overrides:
- selector: { category: "layout", tag: "overflow" }
@ -73,4 +83,3 @@ locale_defaults:
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -6,23 +6,32 @@ page:
orientation: "portrait"
two_sided: false
margins:
top: "22mm"
bottom: "22mm"
inner: "20mm"
outer: "20mm"
top: "1in"
bottom: "1in"
inner: "1.5in"
outer: "1.5in"
fonts:
body:
family: ["Noto Serif", "STIX Two Text", "Times New Roman", "serif"]
size: "11pt"
line_height: 1.45
size: "12pt"
line_height: 1.50
heading:
family: ["Noto Sans", "Source Sans 3", "Arial", "sans-serif"]
mono:
family: ["Noto Sans Mono", "Source Code Pro", "Consolas", "monospace"]
size: "10pt"
size: "10.5pt"
line_height: 1.35
colors:
body: "#111827"
accent: "#1f3a5f"
heading: "#1f3a5f"
link: "#1f3a5f"
citation: "#3b4b63"
table_rule: "#cbd5e1"
table_stripe: "#f1f5f9"
measure_targets:
columns: 1
body_chars_per_line:
@ -56,28 +65,76 @@ headings:
enabled: true
style: "decimal"
require_monotonic_increase: true
rule:
enabled: true
position: "under"
thickness: "1px"
color: "#1f3a5f"
spacing: "0.2em"
widows_orphans:
widow_lines: 2
orphan_lines: 2
widow_lines: 3
orphan_lines: 3
balance_facing_pages: false
code:
inline:
use_mono: true
block:
font_size: "9.5pt"
font_size: "10pt"
line_height: 1.35
wrap: true
max_wrap_penalty: "medium"
overflow_policy: "wrap_then_shrink_minor"
shrink_limit: 0.92
padding: "0.4em 0.6em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "3pt 6pt"
header_repeat: true
overflow_policy: "shrink_then_wrap"
shrink_limit: 0.9
layout: "auto"
cell_wrap: true
keep_together: true
row_keep_together: true
grid_style: "rules_minimal"
header_align: "left"
cell_align: "left"
numeric_align: "right"
boolean_align: "center"
figures:
max_width: "100%"
margin: "0.6em auto"
typography:
small_caps_acronyms:
enabled: true
min_letters: 2
letter_spacing: "0.04em"
drop_caps:
enabled: true
size: "2.8em"
padding_right: "0.08em"
padding_top: "0.02em"
lists:
hanging_punctuation:
enabled: true
indent: "1.2em"
hang: "0.4em"
running_head:
enabled: true
placement: "footer"
template: "{page} | {title}"
font_size: "9pt"
font_style: "normal"
color: "#6b7280"
severity_overrides:
- selector: { category: "layout", tag: "widows_orphans" }
@ -93,4 +150,3 @@ locale_defaults:
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -0,0 +1,148 @@
profile_id: "webtypography_nc"
description: "Non-commercial profile inspired by WebTypography.net (CC BY-NC 4.0)."
license:
name: "CC BY-NC 4.0"
url: "https://creativecommons.org/licenses/by-nc/4.0/"
source: "https://github.com/clagnut/webtypography"
notes: "Non-commercial use only; attribution required."
page:
size: "Letter"
orientation: "portrait"
two_sided: false
margins:
top: "1in"
bottom: "1in"
inner: "1.4in"
outer: "1.4in"
fonts:
body:
family: ["Noto Serif", "STIX Two Text", "Times New Roman", "serif"]
size: "11pt"
line_height: 1.50
heading:
family: ["Noto Sans", "Source Sans 3", "Arial", "sans-serif"]
mono:
family: ["Noto Sans Mono", "Source Code Pro", "Consolas", "monospace"]
size: "10pt"
line_height: 1.35
colors:
body: "#111827"
accent: "#1f3a5f"
heading: "#1f3a5f"
link: "#1f3a5f"
citation: "#3b4b63"
table_rule: "#cbd5e1"
table_stripe: "#f1f5f9"
measure_targets:
columns: 1
body_chars_per_line:
min: 55
ideal: 66
max: 75
hyphenation:
enabled: true
strategy: "balanced"
language_driven: true
min_left: 2
min_right: 3
max_consecutive_hyphenated_lines: 2
avoid_proper_names_when_possible: true
avoid_after_short_lines: true
paragraphs:
first_paragraph_indent: "0"
indent: "1.2em"
block_paragraph_spacing: "0"
headings:
keep_with_next_lines: 2
avoid_stranded_headings: true
numbering:
enabled: true
style: "decimal"
require_monotonic_increase: true
rule:
enabled: true
position: "under"
thickness: "1px"
color: "#1f3a5f"
spacing: "0.2em"
widows_orphans:
widow_lines: 2
orphan_lines: 2
balance_facing_pages: false
code:
inline:
use_mono: true
block:
font_size: "10pt"
line_height: 1.35
wrap: true
max_wrap_penalty: "medium"
overflow_policy: "wrap_then_shrink_minor"
shrink_limit: 0.92
padding: "0.4em 0.6em"
background: "#f8fafc"
border: "1px solid #e5e7eb"
radius: "4px"
tables:
cell_padding: "3pt 6pt"
header_repeat: true
overflow_policy: "shrink_then_wrap"
shrink_limit: 0.9
layout: "auto"
cell_wrap: true
keep_together: true
row_keep_together: true
grid_style: "rules_minimal"
header_align: "left"
cell_align: "left"
numeric_align: "right"
boolean_align: "center"
figures:
max_width: "100%"
margin: "0.6em auto"
typography:
small_caps_acronyms:
enabled: true
min_letters: 2
letter_spacing: "0.04em"
drop_caps:
enabled: true
size: "2.8em"
padding_right: "0.08em"
padding_top: "0.02em"
lists:
hanging_punctuation:
enabled: true
indent: "1.2em"
hang: "0.4em"
running_head:
enabled: true
placement: "footer"
template: "{page} | {title}"
font_size: "9pt"
font_style: "normal"
color: "#6b7280"
locale_defaults:
primary_language: "en"
fallback_languages: ["fr"]
quotation_style: "us"
date_format: "YYYY-MM-DD"
number_format:
decimal_separator: "."
thousands_separator: ","

View file

@ -13,6 +13,10 @@ metrics:
max_link_wrap_incidents: "Count of wrapped URLs/DOIs/emails violating link wrap policy."
max_heading_numbering_errors: "Count of numbering sequence/format violations."
max_citation_format_errors: "Count of citations not matching configured style format."
max_caption_separation_incidents: "Count of captions likely separated from their figures/tables."
max_list_break_incidents: "Count of list pagination issues (intro separated, lonely items)."
max_heading_proximity_incidents: "Count of adjacent/stacked headings with insufficient body text."
max_runt_final_page: "Count of final pages judged too short (runt pages) by PDF analysis."
overflow_detection:
overfull_line_threshold_css_px: 1.0
@ -25,12 +29,16 @@ profiles:
max_widows_per_10_pages: 1
max_orphans_per_10_pages: 1
max_stranded_headings: 0
max_overfull_lines: 2
max_overfull_lines: 1
max_table_overflow_incidents: 0
max_code_overflow_incidents: 1
max_link_wrap_incidents: 2
max_link_wrap_incidents: 1
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 1
max_list_break_incidents: 1
max_heading_proximity_incidents: 1
max_runt_final_page: 0
strict:
max_widows_per_10_pages: 0
max_orphans_per_10_pages: 0
@ -41,6 +49,10 @@ profiles:
max_link_wrap_incidents: 0
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 0
max_list_break_incidents: 0
max_heading_proximity_incidents: 0
max_runt_final_page: 0
print_pdf:
default:
@ -53,6 +65,10 @@ profiles:
max_link_wrap_incidents: 0
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 0
max_list_break_incidents: 0
max_heading_proximity_incidents: 0
max_runt_final_page: 0
strict:
max_widows_per_10_pages: 0
max_orphans_per_10_pages: 0
@ -63,18 +79,26 @@ profiles:
max_link_wrap_incidents: 0
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 0
max_list_break_incidents: 0
max_heading_proximity_incidents: 0
max_runt_final_page: 0
dense_tech:
default:
max_widows_per_10_pages: 1
max_orphans_per_10_pages: 1
max_stranded_headings: 0
max_overfull_lines: 3
max_table_overflow_incidents: 1
max_overfull_lines: 2
max_table_overflow_incidents: 0
max_code_overflow_incidents: 2
max_link_wrap_incidents: 3
max_link_wrap_incidents: 2
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 1
max_list_break_incidents: 1
max_heading_proximity_incidents: 1
max_runt_final_page: 0
strict:
max_widows_per_10_pages: 0
max_orphans_per_10_pages: 0
@ -85,18 +109,26 @@ profiles:
max_link_wrap_incidents: 1
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 0
max_list_break_incidents: 0
max_heading_proximity_incidents: 0
max_runt_final_page: 0
memo:
default:
max_widows_per_10_pages: 3
max_orphans_per_10_pages: 3
max_stranded_headings: 0
max_overfull_lines: 2
max_table_overflow_incidents: 1
max_overfull_lines: 1
max_table_overflow_incidents: 0
max_code_overflow_incidents: 1
max_link_wrap_incidents: 4
max_link_wrap_incidents: 3
max_heading_numbering_errors: 1
max_citation_format_errors: 1
max_caption_separation_incidents: 2
max_list_break_incidents: 2
max_heading_proximity_incidents: 2
max_runt_final_page: 0
strict:
max_widows_per_10_pages: 1
max_orphans_per_10_pages: 1
@ -107,6 +139,10 @@ profiles:
max_link_wrap_incidents: 2
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 1
max_list_break_incidents: 1
max_heading_proximity_incidents: 1
max_runt_final_page: 0
slide_deck:
default:
@ -119,6 +155,10 @@ profiles:
max_link_wrap_incidents: 0
max_heading_numbering_errors: 0
max_citation_format_errors: 1
max_caption_separation_incidents: 2
max_list_break_incidents: 2
max_heading_proximity_incidents: 2
max_runt_final_page: 0
strict:
max_widows_per_10_pages: 2
max_orphans_per_10_pages: 2
@ -129,4 +169,37 @@ profiles:
max_link_wrap_incidents: 0
max_heading_numbering_errors: 0
max_citation_format_errors: 0
max_caption_separation_incidents: 1
max_list_break_incidents: 1
max_heading_proximity_incidents: 1
max_runt_final_page: 0
audit_report:
default:
max_widows_per_10_pages: 12
max_orphans_per_10_pages: 12
max_stranded_headings: 5
max_overfull_lines: 10
max_table_overflow_incidents: 10
max_code_overflow_incidents: 2
max_link_wrap_incidents: 5
max_heading_numbering_errors: 5
max_citation_format_errors: 1
max_caption_separation_incidents: 2
max_list_break_incidents: 2
max_heading_proximity_incidents: 2
max_runt_final_page: 0
strict:
max_widows_per_10_pages: 6
max_orphans_per_10_pages: 6
max_stranded_headings: 2
max_overfull_lines: 5
max_table_overflow_incidents: 5
max_code_overflow_incidents: 1
max_link_wrap_incidents: 3
max_heading_numbering_errors: 2
max_citation_format_errors: 0
max_caption_separation_incidents: 1
max_list_break_incidents: 1
max_heading_proximity_incidents: 1
max_runt_final_page: 0

View file

@ -0,0 +1,27 @@
{"id":"CMOS.ABBREVIATIONS.ACADEMIC.DEGREES.STYLE","title":"Format academic degrees consistently","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Format academic degrees consistently (periods, spacing, and pluralization) and avoid mixing degree abbreviation styles.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["degrees","academic"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.ACRONYMS.AVOID_IN_HEADINGS","title":"Avoid uncommon acronyms in headings","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"md","rule_text":"Avoid introducing uncommon acronyms in headings; prefer the spelled-out term or ensure the acronym is defined earlier in the document.","rationale":"Headings should be scannable without requiring backtracking.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","headings","abbreviations"],"keywords":["headings","acronyms"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.ACRONYMS.DEFINE_FIRST_USE","title":"Define acronyms on first use","source_refs":["CMOS18 §10.1 p623","CMOS18 §10.2 p624"],"category":"abbreviations","severity":"should","applies_to":"md","rule_text":"When introducing an acronym/initialism that may be unfamiliar, spell out the term on first occurrence and give the abbreviation in parentheses; use the abbreviation consistently thereafter.","rationale":"Readers should not be forced to infer meanings of new abbreviations.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn when an all-caps acronym appears before any '(ACRONYM)' definition pattern; suggest defining it on first use.","tags":["abbreviations","acronyms"],"keywords":["acronym","initialism","define on first use"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.BIBLIOGRAPHY.STANDARDS.FOLLOW","title":"Follow domain standards in bibliographies","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"In bibliographies and references, follow the governing citation standard for abbreviations (journal titles, series names) rather than improvising.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["bibliography","journal abbreviations"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.CAPS.AVOID_ALL_CAPS_WORDS","title":"Avoid ALL CAPS words as faux abbreviations","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Avoid using ALL CAPS for ordinary words as a stylistic choice; reserve capitalization patterns for genuine abbreviations and proper names.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["all caps","style"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.COMPANIES.INC_LTD.CONSISTENT","title":"Handle corporate suffixes consistently","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Treat corporate suffixes (Inc., Ltd., LLC, etc.) consistently in names, and follow legal/branding requirements when applicable.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["Inc","LLC"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.FOOTNOTES.ABBREV_ON_FIRST_USE","title":"Define abbreviations in notes when first used","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"If an abbreviation first appears in a footnote/endnote, define it there rather than assuming it was defined in the main text.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["footnotes","endnotes"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.GENERAL.AVOID_OVERUSE","title":"Avoid excessive abbreviations in prose","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Avoid heavy abbreviation density in running prose; when abbreviations are necessary, prioritize reader comprehension over brevity.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["readability","prose"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.GENERAL.CONSISTENCY","title":"Use a consistent abbreviations style","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Choose a consistent approach to abbreviations (forms, punctuation, capitalization, and spacing) and apply it uniformly throughout the document.","rationale":"Consistency reduces reader friction and prevents copyediting churn.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations","consistency"],"keywords":["abbreviations","consistency","style"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.GENERAL.GLOSSARY.WHEN_NEEDED","title":"Provide a glossary when abbreviation load is high","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"If the document uses many specialized abbreviations, include a glossary or abbreviation list in front/back matter.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["glossary","abbreviation list"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.GEOGRAPHY.STATE_ABBREVS.CONSISTENT","title":"Use a consistent style for state/province abbreviations","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Use a consistent style for state/province abbreviations and ensure it matches the audience and citation context.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["state abbreviations","geography"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.INITIALISMS.NO_PERIODS.DEFAULT","title":"Prefer initialisms without periods","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"For most initialisms and acronyms, omit internal periods unless required by a specific standard or house style.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["initialism","periods"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.LATIN.EG_IE.PUNCTUATION","title":"Format common Latin abbreviations consistently","source_refs":["CMOS18 §10.1 p623","CMOS18 §10.2 p624","CMOS18 §10.4 p626"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Format common Latin abbreviations (such as e.g. and i.e.) consistently in punctuation and spacing, and prefer plain-language alternatives when clarity would improve.","rationale":"These forms are easy to misuse and can confuse readers.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations","latin"],"keywords":["e.g.","i.e.","latin abbreviations"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.LATIN.ET_AL.USE","title":"Use et al. consistently and sparingly","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Use et al. in citations only when the chosen citation style allows it; apply the same threshold and formatting throughout the document.","rationale":"Citation readability depends on uniform abbreviation rules.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","citations","abbreviations"],"keywords":["et al","citations"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.LATIN.VERSUS_ENGLISH","title":"Prefer plain English when precision matters","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Prefer plain-language equivalents to Latin abbreviations when precision matters or when the audience may not recognize the Latin form.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["latin","clarity"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.MEASURES.SI.SPACE","title":"Use standard spacing for SI symbols","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Use standard spacing and formatting for SI symbols (including temperature and percent) according to the chosen locale/profile.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["SI","symbols"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.NAMES.INITIALS.SPACING","title":"Use consistent spacing in personal initials","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"When representing personal names with initials, choose a consistent spacing/punctuation convention and apply it uniformly.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["initials","names"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.ORGANIZATIONS.SPELL_OUT_FIRST","title":"Spell out organization names before abbreviating","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Spell out an organization name before using its abbreviation, unless the abbreviation is universally recognized for the audience.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["organization","acronym"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.PARENTHETICALS.AVOID_STACKING","title":"Avoid stacking multiple abbreviations","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Avoid sequences of stacked abbreviations that force readers to decode multiple terms at once; restructure the sentence when necessary.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["readability","stacking"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.PLURALS.NO_APOSTROPHE","title":"Form plurals of abbreviations without apostrophes","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"must","applies_to":"md","rule_text":"Form plurals of most abbreviations and initialisms with a plain s (e.g., APIs), not an apostrophe (APIs), unless a specific exception is required for clarity.","rationale":"Apostrophes typically signal possession, not pluralization.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn on patterns like 'API's' and suggest 'APIs'; avoid rewriting when context looks possessive.","tags":["abbreviations","plurals"],"keywords":["plural","apostrophe","initialism"],"dependencies":[],"exceptions":["Possessive forms remain valid when intended; require human confirmation when ambiguous."],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.POSSESSIVE.FORM","title":"Use standard possessive formation for abbreviations","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Form possessives of abbreviations using the standard apostrophe rules appropriate to the style; avoid inconsistent possessive forms within the same document.","rationale":"Consistent possessives avoid distracting visual variation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations","possessives"],"keywords":["possessive","apostrophe"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.PUNCTUATION.ABBREV_WITH_PERIODS.AVOID_DOUBLE","title":"Avoid doubled periods at sentence end","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"When an abbreviation ends with a period and falls at sentence end, avoid producing doubled periods; keep sentence punctuation clean.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["periods","punctuation"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.TABLES.ABBREV_KEY","title":"Provide keys for table abbreviations","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"When abbreviations appear in tables or figures, provide a key/legend nearby or ensure the meaning is already established.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["tables","legend"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.TECH.TERMS.CASE_SENSITIVE","title":"Preserve case-sensitive technical abbreviations","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Preserve case for abbreviations whose meaning depends on capitalization (e.g., API vs Api) and treat them consistently.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["case","technical"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.TIME.AM_PM.FORM","title":"Use a consistent am/pm style","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Choose a single style for am/pm markers (case and punctuation) and apply it consistently; avoid mixing styles within one document.","rationale":"Time notations should be immediately legible and consistent.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations","time"],"keywords":["a.m.","p.m.","time"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.TITLES.HONORIFICS.CONSISTENT","title":"Use honorifics consistently","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"If honorifics or courtesy titles are used (e.g., Dr., Prof.), apply the chosen form consistently and avoid mixing styles.","rationale":"Abbreviation choices should optimize comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations"],"keywords":["honorifics","titles"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.ABBREVIATIONS.UNITS.NO_PERIODS","title":"Do not add periods to unit symbols","source_refs":["CMOS18 §10.1 p623"],"category":"abbreviations","severity":"should","applies_to":"all","rule_text":"Use standard unit symbols without trailing periods (e.g., kg, km) and do not pluralize symbols; keep spacing between numeral and unit consistent.","rationale":"Unit symbols are standardized and should not be treated as words.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","abbreviations","units"],"keywords":["units","symbols","periods"],"dependencies":[],"exceptions":[],"status":"active"}

View file

@ -0,0 +1,20 @@
{"id": "CMOS.ABBREVIATIONS.MONTHS.ABBREV_IN_TABLES", "title": "Abbreviate months in tables and citations only", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Abbreviate month names primarily in tables, notes, or citations; spell them out in running text.", "rationale": "Full month names improve readability in prose.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "dates"], "keywords": ["months", "abbreviations"], "dependencies": [], "exceptions": ["Space-limited labels may use standard month abbreviations if documented."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.MONTHS.SPELL_OUT_IN_TEXT", "title": "Spell out months in running text", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Spell out month names in running text unless a tabular or reference style is explicitly required.", "rationale": "Spelled-out months are easier to scan in prose.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "dates"], "keywords": ["months", "running text"], "dependencies": [], "exceptions": ["In data-heavy contexts, abbreviated month names may be acceptable with a legend."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.DAYS.ABBREV_IN_TABLES", "title": "Abbreviate days of the week only in compact contexts", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Abbreviate days of the week only in compact contexts such as tables or schedules.", "rationale": "Full day names improve readability in prose.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "dates"], "keywords": ["days of week", "abbreviations"], "dependencies": [], "exceptions": ["Compact UI labels may use standard abbreviations."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.DAYS.SPELL_OUT_IN_TEXT", "title": "Spell out days of the week in prose", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Spell out day names in running text unless a tabular format requires abbreviations.", "rationale": "Spelled-out day names are clearer in narrative text.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "dates"], "keywords": ["days", "running text"], "dependencies": [], "exceptions": ["Short labels or calendar formats may use standard abbreviations."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.STATES.POSTAL_ONLY", "title": "Use postal abbreviations only in addresses", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Use two-letter postal abbreviations for states/provinces only in address blocks or data tables.", "rationale": "Postal abbreviations can be unclear in narrative text.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "geography"], "keywords": ["state abbreviations", "postal"], "dependencies": [], "exceptions": ["Space-limited captions may use postal forms with a legend."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.STATES.SPELL_OUT_IN_TEXT", "title": "Spell out state and province names in prose", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "In running text, spell out state and province names unless a standard abbreviated form is required by context.", "rationale": "Spelled-out names reduce ambiguity for international readers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "geography"], "keywords": ["states", "provinces"], "dependencies": [], "exceptions": ["Institutional or legal standards may mandate abbreviations."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.COUNTRIES.ABBREV_IN_TABLES_ONLY", "title": "Use country abbreviations only in compact contexts", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Use country abbreviations primarily in tables or figures; spell out country names in prose.", "rationale": "Country abbreviations can be ambiguous without context.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "geography"], "keywords": ["countries", "abbreviations"], "dependencies": [], "exceptions": ["Well-known abbreviations (e.g., US, UK) may be acceptable if defined."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.UNITS.ABBREV_WITH_NUMERALS_ONLY", "title": "Use unit symbols with numerals", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Use unit symbols with numerals; spell out units when no numeral is present.", "rationale": "Symbol use is conventional when paired with numbers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "units"], "keywords": ["units", "symbols"], "dependencies": [], "exceptions": ["Technical profiles may require symbols throughout; document the choice."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.UNITS.SPELL_OUT_WITHOUT_NUMERALS", "title": "Spell out units when not paired with numbers", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "When a unit is not paired with a numeral, spell it out rather than using a symbol.", "rationale": "Spelled-out units read more naturally in prose.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "units"], "keywords": ["units", "spelled out"], "dependencies": [], "exceptions": ["Scientific writing may permit symbols even without a numeral."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.UNITS.NO_PLURAL_SYMBOLS", "title": "Do not pluralize unit symbols", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Do not pluralize unit symbols; keep the symbol form invariant.", "rationale": "Unit symbols follow standard scientific conventions.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "units"], "keywords": ["unit symbols", "plural"], "dependencies": [], "exceptions": ["Spelled-out unit words can be pluralized normally."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.ACRONYMS.AVOID_SENTENCE_START", "title": "Avoid starting sentences with acronyms", "source_refs": ["CMOS18 \u00a710.2 p624"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Avoid starting sentences with unfamiliar acronyms; rewrite or spell out the term.", "rationale": "Sentence-initial acronyms slow readers and look abrupt.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "acronyms"], "keywords": ["sentence start", "acronyms"], "dependencies": [], "exceptions": ["Widely known acronyms may be acceptable if the audience expects them."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.ACRONYMS.AVOID_STACKING", "title": "Avoid stacking multiple acronyms", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Avoid strings of multiple acronyms in a row; expand or rephrase for clarity.", "rationale": "Dense acronym clusters reduce comprehension.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "acronyms"], "keywords": ["acronym stacking", "readability"], "dependencies": [], "exceptions": ["Technical identifiers may require dense acronyms; add a glossary if needed."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.ACRONYMS.REINTRODUCE_AFTER_GAP", "title": "Reintroduce acronyms after long gaps", "source_refs": ["CMOS18 \u00a710.2 p624"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "If an acronym is not used for a long stretch, reintroduce the expanded form on its next use.", "rationale": "Readers may forget rarely used abbreviations.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "acronyms"], "keywords": ["acronym", "reintroduce"], "dependencies": [], "exceptions": ["Short documents may not require reintroduction."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.CAPTIONS.DEFINE_ON_FIRST_USE", "title": "Define abbreviations on first use in captions", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "If an abbreviation first appears in a figure or table caption, define it there.", "rationale": "Captions often stand alone and need local clarity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "captions"], "keywords": ["captions", "definitions"], "dependencies": [], "exceptions": ["If the abbreviation is defined immediately adjacent in the text, a caption may omit it."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.TABLES.KEYS.WHEN_DENSE", "title": "Provide a key for dense table abbreviations", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "When tables use many abbreviations, include a key or legend nearby.", "rationale": "Table readers need immediate expansion without hunting the text.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "tables"], "keywords": ["tables", "legend"], "dependencies": [], "exceptions": ["Very small tables with obvious abbreviations may omit a key."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.US_USA.CONSISTENT", "title": "Use a consistent form for US/USA/U.S.", "source_refs": ["CMOS18 \u00a710.4 p626"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Choose a single form for US/USA/U.S. and use it consistently in comparable contexts.", "rationale": "Mixed forms look careless and can confuse readers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "consistency"], "keywords": ["US", "USA", "U.S."], "dependencies": [], "exceptions": ["Proper names may preserve their official style."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.TITLES.COURTESY_PERIODS", "title": "Use courtesy titles consistently", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "If courtesy titles (e.g., Mr., Ms., Dr.) are used, keep punctuation and spacing consistent.", "rationale": "Inconsistent courtesy titles weaken editorial polish.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "titles"], "keywords": ["courtesy titles", "punctuation"], "dependencies": [], "exceptions": ["Official titles may mandate specific styling."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.TITLES.JR_SR.CONSISTENT", "title": "Format Jr./Sr. consistently", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Use a consistent format for suffixes like Jr. and Sr., including punctuation and spacing.", "rationale": "Suffix inconsistency is a common copyediting defect.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations", "titles"], "keywords": ["Jr.", "Sr.", "suffixes"], "dependencies": [], "exceptions": ["Legal names may require a specific official format."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.AVOID_ONE_OFFS", "title": "Avoid abbreviations used only once", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Avoid creating abbreviations for terms that are used only once; spell them out instead.", "rationale": "One-off abbreviations add cognitive load without payoff.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations"], "keywords": ["one-off abbreviations", "clarity"], "dependencies": [], "exceptions": ["Technical identifiers may require abbreviated forms even when rare."], "status": "active"}
{"id": "CMOS.ABBREVIATIONS.READER_FAMILIARITY", "title": "Prefer abbreviations only when familiar to the audience", "source_refs": ["CMOS18 \u00a710.1 p623"], "category": "abbreviations", "severity": "should", "applies_to": "all", "rule_text": "Use abbreviations only when the audience is likely to recognize them without effort.", "rationale": "Reader familiarity should guide abbreviation choices.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "abbreviations"], "keywords": ["audience", "familiarity"], "dependencies": [], "exceptions": ["Specialist documents may assume domain knowledge; include a glossary if needed."], "status": "active"}

View file

@ -0,0 +1,18 @@
{"id":"HOUSE.ACCESSIBILITY.CODE.FENCES.LANGUAGE","title":"Mark code language when helpful","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"When code blocks are present, mark the language when it helps readers (and renderers) interpret syntax.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["code fences","language"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.COLOR.NOT_SOLE_CONVEYOR","title":"Do not rely on color alone","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Do not rely on color alone to convey meaning; use text labels or patterns.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["color","meaning"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.CONTRAST.TEXT_READABLE","title":"Ensure text contrast is sufficient","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Ensure text has sufficient contrast against its background; avoid low-contrast gray-on-gray styling.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["contrast","readability"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.EMPHASIS.USE_SPARELY","title":"Use emphasis sparingly","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Use bold/italics sparingly and consistently; excessive emphasis reduces scanability.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["emphasis","readability"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.HEADINGS.HIERARCHY.NO_SKIPS","title":"Do not skip heading levels","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Maintain a logical heading hierarchy; do not jump from H1 to H3 without an intermediate level.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["headings","hierarchy"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.ALT_TEXT.QUALITY.NO_FILENAME","title":"Alt text should not be a filename","source_refs":["HOUSE §A11Y.IMAGES p2"],"category":"accessibility","severity":"should","applies_to":"md","rule_text":"Alt text should describe the image content, not repeat the image filename or a generic token like “image”; keep it concise and meaningful.","rationale":"Filenames and generic labels are not helpful to screen-reader users.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn when alt text looks like a filename (e.g., ends with .png/.jpg) or is generic; suggest a short content description.","tags":["accessibility","images"],"keywords":["alt text","filenames","screen reader"],"dependencies":["HOUSE.A11Y.IMAGES.ALT_REQUIRED"],"exceptions":["If the filename is intentionally meaningful, ensure surrounding text provides the needed description."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.DECORATIVE.EMPTY_ALT","title":"Use empty alt only for truly decorative images","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Use empty alt text only for purely decorative images; otherwise describe the informational content.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["alt text","decorative"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.TEXT_IN_IMAGES.AVOID","title":"Avoid embedding essential text only in images","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Avoid putting essential information only in images; provide an equivalent text description.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["images","text"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LANGUAGE.METADATA","title":"Declare primary language when possible","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Declare the document's primary language where the platform supports it to improve hyphenation and screen-reader behavior.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["language","metadata"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINKS.AVOID_SHORTENERS","title":"Avoid opaque link shorteners","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Avoid opaque link shorteners for publication unless the shortener is under your control and stable.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["link shorteners","transparency"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINKS.FOCUS_ORDER","title":"Keep reading order logical","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Keep reading order and focus order logical; avoid layouts that visually reorder content without structural cues.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["reading order","structure"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINKS.TARGETS.PUBLIC","title":"Prefer public stable link targets","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Prefer public, stable link targets for published documents; avoid internal-only URLs when the audience is external.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["links","public"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINKS.VISUALLY_DISTINCT","title":"Make links visually distinguishable without color alone","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"Ensure links are visually distinguishable from surrounding text using a cue beyond color (e.g., underline) in rendered outputs.","rationale":"Non-color link cues improve accessibility and usability.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","links"],"keywords":["links","underline","color"],"dependencies":[],"exceptions":["If a design system uses a non-underline cue, ensure it meets contrast and distinguishability needs."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LISTS.USE_LIST_MARKUP","title":"Use list markup for lists","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Use proper list markup for lists rather than manual line breaks and punctuation.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["lists","markup"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.PDF.TAGS.WHEN_AVAILABLE","title":"Enable PDF tagging when available","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"When a PDF engine supports tagged PDF or accessibility metadata, enable it as part of the rendering pipeline.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["tagged pdf","metadata"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.AVOID_SCREENSHOT","title":"Avoid table screenshots","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Avoid publishing tables as screenshots; use real tables so text is selectable and accessible.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["tables","images"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.HEADER_ROW.REQUIRED","title":"Tables should have a header row","source_refs":["HOUSE §A11Y.BASICS p1","HOUSE §A11Y.IMAGES p2","HOUSE §A11Y.TABLES p3"],"category":"accessibility","severity":"should","applies_to":"md","rule_text":"Data tables should include a header row so readers can interpret columns; avoid headerless tables in published outputs.","rationale":"Headers improve scanning and accessibility for assistive tech.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn when a table header row is present but empty; suggest adding column labels.","tags":["accessibility","tables"],"keywords":["tables","headers","accessibility"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.SIMPLE_STRUCTURE","title":"Prefer simple table structures","source_refs":["HOUSE §A11Y.BASICS p1"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Prefer simple tables with clear headers; avoid complex merged-cell layouts that do not translate well to assistive technology.","rationale":"Accessibility requires explicit structural and content choices.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility"],"keywords":["tables","structure"],"dependencies":[],"exceptions":[],"status":"active"}

View file

@ -0,0 +1,18 @@
{"id":"HOUSE.ACCESSIBILITY.LINK_TEXT.UNIQUE_TARGETS","title":"Keep link text unique to a target","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Avoid using identical link text for different destinations within the same document.","rationale":"Duplicate link labels confuse screen-reader navigation lists.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["accessibility","links"],"keywords":["link text","unique"],"dependencies":[],"exceptions":["If repeated labels point to the same destination, consistency is acceptable."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINK_TEXT.NO_BARE_URLS","title":"Avoid bare URLs in prose","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Avoid bare URLs in running text; prefer descriptive link labels that convey destination or action.","rationale":"Bare URLs are difficult to read aloud and less accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","links"],"keywords":["bare URLs","link labels"],"dependencies":[],"exceptions":["Technical appendices may require literal URLs; provide a short label when possible."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINKS.FOCUS_VISIBLE","title":"Ensure focus indicators are visible","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"Ensure focus indicators are visible for links and controls in HTML outputs.","rationale":"Keyboard users rely on visible focus cues.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","links"],"keywords":["focus","keyboard"],"dependencies":[],"exceptions":["If focus is suppressed by design, document the alternative cue explicitly."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.CAPTION_FOR_COMPLEX","title":"Provide captions for complex images","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Provide a caption or adjacent explanation for complex images such as charts or diagrams.","rationale":"Captions supply context that alt text alone may not convey.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","images"],"keywords":["images","captions"],"dependencies":[],"exceptions":["Simple decorative images do not require captions."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.ALT_AVOID_DUPLICATE_CAPTION","title":"Avoid duplicating captions in alt text","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Do not duplicate the full caption in alt text; keep alt text focused on essential image content.","rationale":"Duplicate content is noisy for screen-reader users.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","images"],"keywords":["alt text","captions"],"dependencies":[],"exceptions":["If no caption exists, alt text may include a brief summary."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.ALT_SUMMARY_FOR_CHARTS","title":"Summarize chart meaning in alt text or nearby text","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Charts and graphs should include a brief summary of their takeaway in alt text or nearby text.","rationale":"Data visuals require a textual equivalent for accessibility.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","images"],"keywords":["charts","summary","alt text"],"dependencies":[],"exceptions":["Very small sparklines may be described in the surrounding sentence."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.FIGURES.REFERENCED_IN_TEXT","title":"Reference each figure in the text","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Ensure every figure is referenced in the surrounding text so its purpose is clear.","rationale":"References help readers locate and interpret figures.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","figures"],"keywords":["figures","references"],"dependencies":[],"exceptions":["Standalone galleries may use a dedicated list of captions."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.CAPTION_SUMMARY","title":"Provide a caption or summary for data tables","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Provide a short caption or summary for data tables to explain their purpose.","rationale":"Captions help users interpret tables without guessing.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","tables"],"keywords":["tables","captions"],"dependencies":[],"exceptions":["Very small tables may be self-explanatory if labeled clearly."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.NO_LAYOUT","title":"Avoid tables for layout","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Do not use tables purely for layout; use semantic structure instead.","rationale":"Layout tables are difficult for assistive tech to interpret.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","tables"],"keywords":["layout tables","semantics"],"dependencies":[],"exceptions":["Legacy content may require tables; document the exception."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.HEADER_SCOPE","title":"Ensure table headers are identifiable","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Ensure table headers are clearly identifiable (row or column headers) so readers can interpret cell values.","rationale":"Header context is required for accessible table reading.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","tables"],"keywords":["table headers","scope"],"dependencies":[],"exceptions":["Simple two-column tables may be clear without explicit scope markers."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.ROW_HEADERS_FOR_STUB","title":"Use row headers when stub columns are present","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"When a table has a stub (row-label) column, treat it as header information for that row.","rationale":"Row headers help readers associate values with labels.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","tables"],"keywords":["row headers","stub column"],"dependencies":[],"exceptions":["If the table is extremely simple, a caption may suffice."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.HEADINGS.SINGLE_H1","title":"Use a single top-level heading","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Use a single top-level heading for the document title; avoid multiple H1-equivalent headings.","rationale":"A single H1 improves navigation for assistive tech.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","headings"],"keywords":["H1","document title"],"dependencies":[],"exceptions":["Short standalone sections may omit a top-level heading if the container provides it."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.HEADINGS.NO_EMPTY","title":"Avoid empty or decorative headings","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Do not use empty headings or headings used only for visual spacing.","rationale":"Decorative headings create noise in navigation.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["accessibility","headings"],"keywords":["empty headings","decorative"],"dependencies":[],"exceptions":["Section dividers should use rules or spacing, not headings."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.HEADINGS.NO_DECORATIVE","title":"Do not use headings as decoration","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Use headings to convey structure, not decoration or layout.","rationale":"Structural headings are essential for assistive navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","headings"],"keywords":["headings","structure"],"dependencies":[],"exceptions":["Design-only labels should use non-heading styles."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LISTS.NO_EMPTY_ITEMS","title":"Avoid empty list items","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Avoid empty list items or placeholder bullets in published documents.","rationale":"Empty list items create noise for assistive tech.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["accessibility","lists"],"keywords":["lists","empty items"],"dependencies":[],"exceptions":["Drafts may include placeholders but should be removed before publication."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LISTS.MARKER_CONSISTENT","title":"Keep list marker styles consistent","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Use a consistent marker style within each list level (bullets or numbering).","rationale":"Consistent markers help readers follow structure.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","lists"],"keywords":["list markers","consistency"],"dependencies":[],"exceptions":["Mixed markers may be acceptable in intentionally nested outlines."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.CONTRAST.NON_TEXT","title":"Ensure non-text elements have sufficient contrast","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Icons, charts, and other non-text elements should have sufficient contrast to be distinguishable.","rationale":"Non-text contrast affects comprehension for low-vision readers.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","contrast"],"keywords":["contrast","icons","charts"],"dependencies":[],"exceptions":["If color is used, provide an additional differentiator such as patterns or labels."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.MEDIA.TRANSCRIPTS","title":"Provide transcripts for audio or video","source_refs":["HOUSE \u00a7A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"all","rule_text":"Provide transcripts or captions for any embedded audio or video content.","rationale":"Transcripts are essential for accessibility and offline review.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","media"],"keywords":["transcripts","captions"],"dependencies":[],"exceptions":["If media is purely decorative, omit it from published outputs."],"status":"active"}

View file

@ -0,0 +1,7 @@
{"id":"HOUSE.ACCESSIBILITY.LINKS.ICON_ONLY.TEXT","title":"Provide text alternatives for icon-only links","source_refs":["HOUSE §A11Y.LINKS p3"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"Icon-only links and controls must include accessible text (aria-label or visually hidden text) that describes the action.","rationale":"Screen-reader users rely on descriptive labels.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","links"],"keywords":["icon links","aria-label","labels"],"dependencies":[],"exceptions":["If visible text is present, a separate label is unnecessary."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.LINKS.SKIP_TO_CONTENT","title":"Provide a skip-to-content link for long pages","source_refs":["HOUSE §A11Y.LINKS p3"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"Provide a skip-to-content link for long HTML documents to allow keyboard users to bypass repeated navigation.","rationale":"Skip links improve keyboard navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","navigation"],"keywords":["skip link","navigation"],"dependencies":[],"exceptions":["Single-screen documents may omit a skip link."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TOC.LINKED_ENTRIES","title":"Link TOC entries to sections when supported","source_refs":["HOUSE §A11Y.NAVIGATION p3"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"When a table of contents is present in HTML, ensure entries are actual links to the corresponding sections.","rationale":"Linked TOCs reduce navigation friction.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","navigation"],"keywords":["toc","links","navigation"],"dependencies":[],"exceptions":["Print-only outputs may use non-linked TOCs."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.NAVIGATION.FOOTNOTE_BACKLINKS","title":"Provide backlinks from notes to callouts","source_refs":["HOUSE §A11Y.NAVIGATION p3"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"Provide backlinks from footnotes/endnotes to their callouts when the format supports it.","rationale":"Backlinks reduce navigation overhead for readers.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","navigation"],"keywords":["footnotes","backlinks"],"dependencies":[],"exceptions":["PDF outputs may omit backlinks if the renderer cannot generate them."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.NAVIGATION.PDF_BOOKMARKS","title":"Generate PDF bookmarks from headings when supported","source_refs":["HOUSE §A11Y.NAVIGATION p3"],"category":"accessibility","severity":"should","applies_to":"pdf","rule_text":"Generate PDF bookmarks from headings when the PDF engine supports them.","rationale":"Bookmarks improve navigation in long PDFs.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","navigation"],"keywords":["pdf bookmarks","headings"],"dependencies":[],"exceptions":["If the engine cannot create bookmarks, document the limitation."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.IMAGES.LINKED.ALT_TARGET","title":"Linked images must describe destination or action","source_refs":["HOUSE §A11Y.IMAGES p3"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"If an image functions as a link, its alt text should describe the destination or action rather than only the visual.","rationale":"Linked images require action-focused labels.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","images","links"],"keywords":["linked images","alt text"],"dependencies":[],"exceptions":["Decorative linked images may use an aria-label on the link element."],"status":"active"}
{"id":"HOUSE.ACCESSIBILITY.TABLES.HEADERS.SCOPE","title":"Mark table headers with clear scope semantics","source_refs":["HOUSE §A11Y.TABLES p3"],"category":"accessibility","severity":"should","applies_to":"html","rule_text":"When exporting HTML tables, mark header cells with clear scope or semantic roles so assistive tech can map headers to data cells.","rationale":"Header semantics improve table navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","accessibility","tables"],"keywords":["table headers","scope","semantics"],"dependencies":[],"exceptions":["Very small tables may rely on surrounding context if semantic markup is unavailable."],"status":"active"}

View file

@ -0,0 +1 @@
{"id":"HOUSE.ACCESSIBILITY.LINK_TEXT.SYMBOL_ONLY.AVOID","title":"Avoid symbol-only link text","source_refs":["HOUSE §A11Y.BASICS p2"],"category":"accessibility","severity":"should","applies_to":"md","rule_text":"Avoid link labels that are only symbols; use readable text labels for accessibility.","rationale":"Symbol-only links are ambiguous for screen readers.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["accessibility","links"],"keywords":["link text","symbols"],"dependencies":[],"exceptions":["Icon-only links must include accessible text via another mechanism."],"status":"active"}

View file

@ -0,0 +1,18 @@
{"id":"CMOS.BACKMATTER.ABBREVIATIONS.LIST.WHEN_NEEDED","title":"Provide an abbreviations list when needed","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"When abbreviation density is high, provide an abbreviations list in backmatter and keep it synchronized with usage.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["abbreviations list","glossary"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.ACKNOWLEDGMENTS.PLACEMENT","title":"Keep acknowledgments placement consistent","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"If acknowledgments are placed in backmatter rather than frontmatter, keep placement consistent across editions.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["acknowledgments","placement"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.APPENDICES.CROSS_REFERENCES","title":"Cross-reference appendices from the body","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"When content is moved to appendices, add explicit cross-references so readers can find it.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["appendix","cross-reference"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.APPENDICES.FORMAT_MATCH","title":"Match appendix formatting to the body","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Format appendix headings, numbering, and typography to match the body unless the genre requires a distinct style.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["appendix","formatting"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.APPENDICES.LABELED","title":"Label appendices clearly","source_refs":["CMOS18 §1.3 p9"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"If appendices are used, label them clearly (e.g., Appendix A) and reference them consistently from the main text.","rationale":"Clear appendix structure improves navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["appendix","labeling"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.APPENDICES.SOURCES","title":"Cite sources for appendix material","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Appendix material should include the same citation rigor as the main body when it asserts facts or quotes sources.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["appendix","citations"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.BIBLIOGRAPHY.CONSISTENT_STYLE","title":"Keep bibliography formatting consistent","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"When a bibliography or reference list is present, keep entry structure, punctuation, and ordering consistent with the selected citation style.","rationale":"Inconsistent references erode trust and slow review.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","citations"],"keywords":["bibliography","references","consistency"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.BIBLIOGRAPHY.SORTING","title":"Sort bibliography entries consistently","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Sort bibliography entries according to the chosen style (alphabetical by author, etc.) and do not mix ordering schemes.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["bibliography","sorting"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.CONTACT.SUPPORT","title":"Provide support/contact details","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Provide support or contact details for readers who need clarifications or updates.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["support","contact"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.DATA.AVAILABILITY","title":"Include data availability notes when applicable","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"When claims depend on datasets or code, include a data availability note describing how to access the supporting materials.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["data availability","reproducibility"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.ENDNOTES.VERSUS_FOOTNOTES.CONSISTENT","title":"Choose footnotes or endnotes and apply consistently","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Choose footnotes or endnotes according to the document style and constraints; apply the choice consistently.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["footnotes","endnotes"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.ERRATA.WHEN_NEEDED","title":"Record errata for published revisions","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"For published documents that receive corrections, maintain an errata section or log to track fixes.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["errata","corrections"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.GLOSSARY.SORTING","title":"Sort glossary terms consistently","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Sort glossary terms consistently (alphabetical or thematic) and apply consistent capitalization and punctuation.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["glossary","sorting"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.GLOSSARY.WHEN_TERMS","title":"Include a glossary when terminology is dense","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Include a glossary when the document introduces many specialized terms; keep definitions concise and consistent.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["glossary","definitions"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.INDEX.WHEN_REQUIRED","title":"Include an index when required by genre","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Include an index when the genre or audience requires it; ensure index terms are spelled and capitalized consistently.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["index","terms"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.LICENSES.THIRD_PARTY","title":"Document third-party licenses","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"If third-party materials are included, document their licenses/permissions in backmatter.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["third-party","licenses"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.REFERENCES.SECTION_PRESENT","title":"Include a references section when citing sources","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"If sources are cited, include a references section or bibliography appropriate to the citation system.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["references","citations"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.BACKMATTER.REFERENCES.URLS.STABLE","title":"Prefer stable URLs in references","source_refs":["CMOS18 §14.1 p799","CMOS18 §14.2 p801"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"In references, prefer stable URLs/DOIs and avoid ephemeral session links.","rationale":"Back matter supports verification and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter"],"keywords":["stable URLs","DOI"],"dependencies":[],"exceptions":[],"status":"active"}

View file

@ -0,0 +1,22 @@
{"id": "CMOS.BACKMATTER.APPENDIX.START_ON_NEW_PAGE", "title": "Start appendices on a new page", "source_refs": ["CMOS18 \u00a71.66 p66 (scan p1135)"], "category": "backmatter", "severity": "should", "applies_to": "pdf", "rule_text": "Start each appendix on a new page or clear section break according to the chosen layout.", "rationale": "Clear breaks improve navigation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter"], "keywords": ["appendix", "page breaks"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.APPENDIX.NUMBERING.SEQUENTIAL", "title": "Number appendices sequentially", "source_refs": ["CMOS18 \u00a71.66 p66 (scan p1135)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Number appendices sequentially (A, B, C or 1, 2, 3) and keep the scheme consistent.", "rationale": "Sequential numbering aids reference.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter"], "keywords": ["appendix", "numbering"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.APPENDIX.TOC.ENTRIES", "title": "Include appendices in the TOC", "source_refs": ["CMOS18 \u00a71.66 p66 (scan p1135)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Include appendices in the table of contents according to the document\u2019s TOC policy.", "rationale": "TOC completeness improves navigation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter"], "keywords": ["appendix", "toc"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.NOTES.NUMBERING.SEQUENTIAL", "title": "Keep note numbering sequential", "source_refs": ["CMOS18 \u00a72.61 p46 (scan p1120)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Number notes sequentially within the chosen scope (chapter or document) and avoid resets without notice.", "rationale": "Sequential notes prevent confusion.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "notes"], "keywords": ["notes", "numbering"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.NOTES.REFERENCE.MATCH", "title": "Match note references to note numbers", "source_refs": ["CMOS18 \u00a72.61 p46 (scan p1120)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Ensure note callouts in the text match the corresponding note numbers in backmatter.", "rationale": "Mismatched notes break traceability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "notes"], "keywords": ["notes", "callouts"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.NOTES.ORDER.FOLLOW_TEXT", "title": "Order notes in reading sequence", "source_refs": ["CMOS18 \u00a75.210 p50 (scan p1120)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Order notes in the same sequence as their callouts appear in the text.", "rationale": "Order preserves readability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "notes"], "keywords": ["notes", "ordering"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.NOTES.BLOCKS.CONSISTENT", "title": "Use consistent note blocks", "source_refs": ["CMOS18 \u00a75.210 p50 (scan p1120)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "If notes are grouped by chapter or section, use the same grouping method throughout.", "rationale": "Consistent grouping reduces confusion.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "notes"], "keywords": ["notes", "grouping"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.NOTES.CITATIONS.COMPLETE", "title": "Keep note citations complete", "source_refs": ["CMOS18 \u00a713.57 p109 (scan p1130)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Ensure notes include sufficient source details consistent with the chosen citation style.", "rationale": "Complete citations support verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "citations"], "keywords": ["notes", "citations"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.ENTRIES.CONSISTENT_CASE", "title": "Keep index entry casing consistent", "source_refs": ["CMOS18 \u00a71.81 p39 (scan p1122)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Keep capitalization and casing consistent across index entries and subentries.", "rationale": "Consistency speeds lookup.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "capitalization"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.SUBENTRIES.NESTED", "title": "Nest index subentries clearly", "source_refs": ["CMOS18 \u00a715.112 p57 (scan p1120)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Use clear indentation or formatting to distinguish index subentries from main entries.", "rationale": "Clear nesting improves navigation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "subentries"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.CROSS_REFERENCES.CONSISTENT", "title": "Use consistent cross-references in the index", "source_refs": ["CMOS18 \u00a715.131 p32 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Use cross-references (see/see also) consistently when multiple terms lead to the same content.", "rationale": "Cross-references prevent dead ends.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "cross references"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.PAGE_RANGES.STANDARD", "title": "Use standard page range notation", "source_refs": ["CMOS18 \u00a715.22 p24 (scan p1130)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Use a consistent page range style in index locators.", "rationale": "Consistent ranges are easier to read.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "page ranges"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.LOCATORS.ACCURATE", "title": "Verify index locators", "source_refs": ["CMOS18 \u00a715.32 p31 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Verify that index locators point to the correct pages after final pagination.", "rationale": "Accurate locators are essential.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "locators"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.SUBENTRY.ORDER.LOGICAL", "title": "Order subentries logically", "source_refs": ["CMOS18 \u00a715.44 p14 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Order index subentries logically (alphabetical or thematic) and keep the scheme consistent.", "rationale": "Logical order improves scanning.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "subentry order"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.SEE_ALSO.USE_WHEN_NEEDED", "title": "Use see-also for related topics", "source_refs": ["CMOS18 \u00a715.87 p88 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Use see-also references for related topics to improve navigation.", "rationale": "See-also links reduce dead ends.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "see also"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.ABBREVIATIONS.CONSISTENT", "title": "Keep abbreviations consistent in the index", "source_refs": ["CMOS18 \u00a715.89 p90 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Use consistent abbreviations in index entries and avoid mixing full forms and abbreviations without cross-references.", "rationale": "Consistency improves lookup.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "abbreviations"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.INDEX.NAMES.SORTING", "title": "Sort names consistently in the index", "source_refs": ["CMOS18 \u00a715.91 p92 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Sort personal and corporate names consistently (e.g., surname first) within the index.", "rationale": "Consistent sorting aids lookup.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "index"], "keywords": ["index", "names"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.REFERENCES.AUTHOR_NAMES.CONSISTENT", "title": "Keep author name formats consistent", "source_refs": ["CMOS18 \u00a715.103 p133 (scan p1125)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Use a consistent author name format in references and avoid mixing initials with full names.", "rationale": "Consistency improves verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "references"], "keywords": ["references", "author names"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.REFERENCES.DOI.OR_URL", "title": "Include persistent identifiers", "source_refs": ["CMOS18 \u00a715.112 p40 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Include persistent identifiers (DOI, stable URL) for sources when available.", "rationale": "Persistent identifiers support verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "references"], "keywords": ["doi", "urls"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.REFERENCES.ACCESS_DATES.WHEN_NEEDED", "title": "Include access dates when required", "source_refs": ["CMOS18 \u00a715.123 p29 (scan p1126)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Include access dates for online sources when required by the chosen citation style or policy.", "rationale": "Access dates help interpret volatile sources.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "references"], "keywords": ["access dates", "online sources"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.GLOSSARY.TERMS.CONSISTENT_STYLE", "title": "Keep glossary term formatting consistent", "source_refs": ["CMOS18 \u00a72.27 p27 (scan p1124)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Keep glossary term capitalization and formatting consistent across entries.", "rationale": "Consistency aids scanning.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "glossary"], "keywords": ["glossary", "terms"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.BACKMATTER.GLOSSARY.DEFINITIONS.CONCISE", "title": "Keep glossary definitions concise", "source_refs": ["CMOS18 \u00a78.2 p180 (scan p1130)"], "category": "backmatter", "severity": "should", "applies_to": "all", "rule_text": "Keep glossary definitions concise and avoid reintroducing new terms without defining them.", "rationale": "Concise definitions improve clarity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "backmatter", "glossary"], "keywords": ["glossary", "definitions"], "dependencies": [], "exceptions": [], "status": "active"}

View file

@ -0,0 +1,6 @@
{"id":"HOUSE.BACKMATTER.REFERENCES.SORTING.CONSISTENT","title":"Keep reference list sorting consistent","source_refs":["HOUSE §BACKMATTER.REFERENCES p1"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Sort references consistently (alphabetical or order of appearance) and apply the same scheme throughout.","rationale":"Consistent sorting makes sources easier to find.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","references"],"keywords":["references","sorting"],"dependencies":[],"exceptions":["If a style guide mandates a specific order, follow it."],"status":"active"}
{"id":"HOUSE.BACKMATTER.REFERENCES.DEDUPLICATE","title":"Avoid duplicate reference entries","source_refs":["HOUSE §BACKMATTER.REFERENCES p1"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Do not list the same source multiple times with slight variations; consolidate duplicates.","rationale":"Duplicates confuse readers and inflate lists.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","references"],"keywords":["references","dedupe"],"dependencies":[],"exceptions":["If distinct editions are cited, list them separately and label clearly."],"status":"active"}
{"id":"HOUSE.BACKMATTER.GLOSSARY.ALPHABETICAL","title":"Sort glossary entries alphabetically","source_refs":["HOUSE §BACKMATTER.GLOSSARY p1"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Sort glossary entries alphabetically to make lookup predictable.","rationale":"Alphabetical ordering improves scanning.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","glossary"],"keywords":["glossary","alphabetical"],"dependencies":[],"exceptions":["If the glossary is intentionally grouped by theme, state the grouping scheme."],"status":"active"}
{"id":"HOUSE.BACKMATTER.GLOSSARY.CROSS_REFERENCES","title":"Provide cross-references for glossary synonyms","source_refs":["HOUSE §BACKMATTER.GLOSSARY p1"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Provide cross-references for synonymous or related glossary terms to prevent dead ends.","rationale":"Cross-references improve navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","glossary"],"keywords":["glossary","see also"],"dependencies":[],"exceptions":["Very small glossaries may omit cross-references if all terms are obvious."],"status":"active"}
{"id":"HOUSE.BACKMATTER.APPENDICES.LABELS.MATCH","title":"Appendix labels must match references and TOC","source_refs":["HOUSE §BACKMATTER.APPENDICES p1"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Appendix labels in headings must match their references and TOC entries to avoid navigation errors.","rationale":"Label mismatches break cross-references.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","appendix"],"keywords":["appendix","labels","toc"],"dependencies":[],"exceptions":["If appendices are unnamed, use stable numbering consistently."],"status":"active"}
{"id":"HOUSE.BACKMATTER.INDEX.CROSS_REFERENCES.CONSISTENT","title":"Use consistent cross-reference phrasing in indexes","source_refs":["HOUSE §BACKMATTER.INDEX p1"],"category":"backmatter","severity":"should","applies_to":"all","rule_text":"Use consistent phrasing for index cross-references (see, see also) and apply it uniformly.","rationale":"Consistent cues improve scanning.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","backmatter","index"],"keywords":["index","see also"],"dependencies":[],"exceptions":["If a style guide mandates different wording, follow it consistently."],"status":"active"}

View file

@ -0,0 +1,2 @@
{"id":"HOUSE.CITATIONS.AUTHOR_DATE.PAREN_YEAR_ONLY","title":"Avoid year-only parenthetical citations in author-date style","source_refs":["HOUSE §CIT.AUTHOR_DATE.PAREN_YEAR_ONLY p1"],"category":"citations","severity":"warn","applies_to":"md","rule_text":"In author-date style, parenthetical citations should include an author or disambiguating token; year-only parentheses are ambiguous and should be flagged.","rationale":"Year-only citations reduce traceability.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["author_date","citations"],"keywords":["author-date","parenthetical","year-only"],"dependencies":[],"exceptions":["Allow when a nearby caption or label explicitly names the author in the same figure or table."],"status":"active"}
{"id":"HOUSE.CITATIONS.AUTHOR_DATE.REFLIST.YEAR_REQUIRED","title":"Require year (or n.d.) in author-date reference entries","source_refs":["HOUSE §CIT.AUTHOR_DATE.REFLIST.YEAR_REQUIRED p1"],"category":"citations","severity":"should","applies_to":"md","rule_text":"When using author-date citations, reference list entries should include a year or n.d. to align with in-text citations.","rationale":"References without years cannot resolve author-date citations.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["author_date","references"],"keywords":["references","bibliography","year"],"dependencies":[],"exceptions":["Use explicit ranges for multi-year publications when required by the style."],"status":"active"}

View file

@ -0,0 +1 @@
{"id":"HOUSE.CITATIONS.AUTHOR_DATE.REFLIST.REQUIRED","title":"Provide a reference list when using author-date citations","source_refs":["HOUSE §CIT.AUTHOR_DATE.REFLIST.REQUIRED p1"],"category":"citations","severity":"should","applies_to":"md","rule_text":"If author-date citations are used in the text, include a reference list or bibliography section in the document.","rationale":"Author-date citations require a list to resolve full details.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["author_date","references"],"keywords":["reference list","bibliography","author-date"],"dependencies":[],"exceptions":["Short internal notes may rely on inline citations if the context is self-contained."],"status":"active"}

View file

@ -0,0 +1,4 @@
{"id":"HOUSE.CITATIONS.NOTES.DEFINITIONS.REQUIRED","title":"Define every footnote marker","source_refs":["HOUSE §CIT.NOTES.DEFINITIONS.REQUIRED p1"],"category":"citations","severity":"must","applies_to":"md","rule_text":"Every footnote marker in the text must have a corresponding footnote definition in the notes list.","rationale":"Undefined markers break citation resolution.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["notes","footnotes"],"keywords":["footnote definitions","missing notes"],"dependencies":[],"exceptions":["Skip for intentionally redacted citations if policy allows; document the omission."],"status":"active"}
{"id":"HOUSE.CITATIONS.NOTES.MARKERS.BRACKETED_NUMBERS.AVOID","title":"Avoid bracketed numeric citations in prose","source_refs":["HOUSE §CIT.NOTES.MARKERS.BRACKETED_NUMBERS.AVOID p1"],"category":"citations","severity":"warn","applies_to":"md","rule_text":"Avoid bracketed numeric citations like [1] in narrative prose when a footnote system is expected; use Markdown footnotes instead.","rationale":"Bracketed numbers are ambiguous and often render poorly.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["notes","note_markers"],"keywords":["bracketed numbers","citation markers"],"dependencies":[],"exceptions":["Technical specs that mandate bracketed numeric citations may override by profile."],"status":"active"}
{"id":"HOUSE.CITATIONS.NOTES.BIBLIOGRAPHY.REQUIRED","title":"Include a bibliography when using footnote citations","source_refs":["HOUSE §CIT.NOTES.BIBLIOGRAPHY.REQUIRED p1"],"category":"citations","severity":"should","applies_to":"md","rule_text":"When using footnote-style citations, include a bibliography or references section unless the project explicitly waives it.","rationale":"Readers need a consolidated source list.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["notes","bibliography"],"keywords":["bibliography","references"],"dependencies":[],"exceptions":["Short internal memos may omit a bibliography if the scope is self-contained."],"status":"active"}
{"id":"HOUSE.CITATIONS.NOTES.IBID.AVOID","title":"Avoid ibid in notes","source_refs":["HOUSE §CIT.NOTES.IBID.AVOID p1"],"category":"citations","severity":"warn","applies_to":"md","rule_text":"Avoid ibid. in notes when notes may be reordered or extracted; prefer unambiguous short forms.","rationale":"Ibid references can break when note order changes.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["notes","ibid"],"keywords":["ibid","short form","note order"],"dependencies":[],"exceptions":["If policy requires ibid, ensure notes are stable and not programmatically reordered."],"status":"active"}

View file

@ -0,0 +1,151 @@
{"id": "CMOS.CITATIONS.S13_1.PURPOSE.ETHICS", "title": "Citations are required for ethical attribution", "source_refs": ["CMOS18 §13.1 p776 (scan p798)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Provide citations for direct quotations, paraphrases, and claims that are not common knowledge.", "rationale": "Ethical attribution is a core purpose of citation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["ethics", "attribution"], "dependencies": [], "exceptions": ["Common knowledge does not require citation."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_1.PURPOSE.COPYRIGHT", "title": "Citations support copyright compliance", "source_refs": ["CMOS18 §13.1 p776 (scan p798)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Citations must make clear which material is borrowed to support copyright compliance.", "rationale": "Citations protect authors and publishers from misuse claims.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["copyright", "compliance"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_1.PURPOSE.COURTESY", "title": "Citations are a courtesy to readers", "source_refs": ["CMOS18 §13.1 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Provide citations that guide readers to original sources as a courtesy.", "rationale": "Readers need sources to verify or explore claims.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["readers", "verification"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_1.SUFFICIENT_INFO", "title": "Citations must provide sufficient identifying information", "source_refs": ["CMOS18 §13.1 p776 (scan p798)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Ensure each citation contains enough information to locate or positively identify the source.", "rationale": "Incomplete citations defeat verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["completeness", "identification"], "dependencies": [], "exceptions": ["If a source is not available, document the limitation."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_1.ALL_SOURCE_TYPES", "title": "Apply citation rules to all source types", "source_refs": ["CMOS18 §13.1 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Apply citation requirements to published and unpublished sources and to print and electronic formats.", "rationale": "Source type does not remove the need for attribution.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["published", "unpublished", "formats"], "dependencies": [], "exceptions": ["Follow discipline-specific exceptions if mandated."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_1.DISCIPLINE_POLICY", "title": "Follow discipline and publisher citation policies", "source_refs": ["CMOS18 §13.1 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use citation conventions appropriate to the discipline and publisher or journal requirements.", "rationale": "Different fields have different citation norms.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["discipline", "publisher"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.SYSTEMS.TWO_TYPES", "title": "Use either notes-bibliography or author-date", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Choose either the notes-bibliography system or the author-date system for Chicago-style citations.", "rationale": "Chicago provides two formal citation systems.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["notes-bibliography", "author-date"], "dependencies": [], "exceptions": ["A hybrid system must be documented explicitly."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.NOTES_SYSTEM", "title": "Notes system uses numbered notes", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes-bibliography, use numbered notes in the text that correspond to footnotes or endnotes.", "rationale": "Note numbering ties the text to citations.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["notes", "footnotes", "endnotes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.NOTES_BIBLIOGRAPHY_OPTIONAL", "title": "Notes may be paired with a bibliography", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In the notes system, include a bibliography when the work benefits from a consolidated list of sources.", "rationale": "A bibliography helps readers scan sources quickly.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["bibliography"], "dependencies": [], "exceptions": ["Short works may omit a bibliography by policy."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.AUTHOR_DATE_SYSTEM", "title": "Author-date uses parenthetical citations", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In author-date, use parenthetical text citations tied to a reference list.", "rationale": "Parenthetical citations link directly to the reference list.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["author-date", "parenthetical"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.STYLE_ELEMENTS.SHARED", "title": "Keep capitalization and punctuation consistent across systems", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Both systems share the same capitalization, punctuation, and styling rules for sources.", "rationale": "The system choice affects placement, not core styling.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["capitalization", "punctuation"], "dependencies": [], "exceptions": ["Follow journal-specific variations when required."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.DEFAULT_SYSTEM", "title": "Notes-bibliography is the default in Chicago examples", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use notes-bibliography as the default system unless a discipline or publisher specifies author-date.", "rationale": "Chicago examples default to notes-bibliography.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["default system"], "dependencies": [], "exceptions": ["Sciences and social sciences often use author-date."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.DISCIPLINE_PREFERENCE", "title": "Align system choice with disciplinary norms", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use notes-bibliography in humanities and author-date in sciences unless directed otherwise.", "rationale": "Readers expect familiar citation systems by discipline.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["discipline", "humanities", "sciences"], "dependencies": [], "exceptions": ["Publisher or journal policy may override."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.JOURNAL_INSTRUCTIONS", "title": "Follow journal instructions for system choice", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "When writing for a journal, use the citation system specified by that journal.", "rationale": "Journal style is not optional.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["journals", "instructions"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_2.SYSTEM_SWITCHING", "title": "Do not mix citation systems without documentation", "source_refs": ["CMOS18 §13.2 p776 (scan p798)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Avoid mixing notes-bibliography and author-date in the same work unless the hybrid is documented and approved.", "rationale": "Mixed systems confuse readers and reviewers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["hybrid system"], "dependencies": [], "exceptions": ["Some journals allow limited hybrid formats; document them."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_3.OTHER_SYSTEMS.MLA_APA", "title": "Follow MLA or APA when required", "source_refs": ["CMOS18 §13.3 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a publisher or discipline requires MLA or APA, follow those manuals rather than Chicago.", "rationale": "Publisher requirements supersede general guidance.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["MLA", "APA"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_3.OTHER_SYSTEMS.AMA_CSE", "title": "Use AMA or CSE for numbered reference systems", "source_refs": ["CMOS18 §13.3 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For disciplines that require numbered reference systems, follow AMA or CSE guidance.", "rationale": "Numbered systems have their own formatting conventions.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["AMA", "CSE"], "dependencies": [], "exceptions": ["Journal-specific instructions override."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_3.JOURNALS.HOUSE_STYLE", "title": "Use journal house style when available", "source_refs": ["CMOS18 §13.3 p777 (scan p799)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "If a journal has its own citation style, follow it even if it differs from standard systems.", "rationale": "House style is authoritative.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["house style", "journals"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_3.LEGAL.BLUEBOOK", "title": "Use Bluebook for legal citations", "source_refs": ["CMOS18 §13.3 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For legal or public documents, use Bluebook conventions unless instructed otherwise.", "rationale": "Legal citation requires specialized formats.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "legal"], "keywords": ["Bluebook", "legal"], "dependencies": [], "exceptions": ["Jurisdiction-specific rules may override."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_3.SOURCE_MANUALS", "title": "Consult the official manuals for other systems", "source_refs": ["CMOS18 §13.3 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use the official manuals of other systems for guidance rather than extrapolating from Chicago.", "rationale": "Each system defines its own standards and exceptions.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "systems"], "keywords": ["manuals", "standards"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_4.CONSISTENCY.REQUIRED", "title": "Maintain a consistent citation style within a work", "source_refs": ["CMOS18 §13.4 p777 (scan p799)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Maintain a consistent citation style within the document.", "rationale": "Consistency is required for reviewer and reader confidence.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "consistency"], "keywords": ["consistency"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_4.FLEXIBILITY.BY_AGREEMENT", "title": "Allow variations only by agreement", "source_refs": ["CMOS18 §13.4 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use variations on Chicago style only when author and publisher agree.", "rationale": "Unapproved variations can break publication workflows.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "consistency"], "keywords": ["variations", "agreement"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_4.JOURNALS.STRICT", "title": "Follow strict journal styles", "source_refs": ["CMOS18 §13.4 p777 (scan p799)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "For journal publication, adhere to the established journal citation style without exceptions.", "rationale": "Journal production relies on strict standardization.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "consistency"], "keywords": ["journals", "strict"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_4.DOCUMENTED_DEVIATIONS", "title": "Document any approved deviations", "source_refs": ["CMOS18 §13.4 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Record approved citation deviations in the style sheet or project notes.", "rationale": "Documentation prevents drift across revisions.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "consistency"], "keywords": ["style sheet", "deviations"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_5.ACADEMIC_EXPECTATION", "title": "Use formal citations in academic writing", "source_refs": ["CMOS18 §13.5 p777 (scan p799)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "In academic writing, provide formal citations rather than casual mentions.", "rationale": "Academic readers expect traceable sources.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["academic", "formal citations"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_5.NONACADEMIC.MENTIONS_OK", "title": "Use mentions instead of formal citations in nonacademic contexts", "source_refs": ["CMOS18 §13.5 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In nonacademic writing, mention sources in the text when formal citations are unnecessary.", "rationale": "Formal citations can be excessive in informal genres.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["nonacademic", "mentions"], "dependencies": [], "exceptions": ["Publisher policies may still require citations."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_5.CITE_RELEVANT", "title": "Cite sources that materially inform the work", "source_refs": ["CMOS18 §13.5 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Cite sources that materially support the argument or evidence.", "rationale": "Focused citations improve clarity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["relevance"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_5.AVOID_TANGENTIAL", "title": "Avoid citing tangential sources", "source_refs": ["CMOS18 §13.5 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Do not use citations as a repository for tangential or loosely related sources.", "rationale": "Overcitation dilutes the signal of key sources.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["tangential sources"], "dependencies": [], "exceptions": ["Literature reviews may require broader coverage."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_5.INFORMAL_SOURCES", "title": "Use formal citations only when informal sources are central", "source_refs": ["CMOS18 §13.5 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Cite informal or nonliterary sources only when they are central to the argument.", "rationale": "Informal sources may not warrant full citation in all contexts.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "overview"], "keywords": ["informal sources"], "dependencies": [], "exceptions": ["Legal or scholarly work may require citations for all sources."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_6.URL.FINAL_ELEMENT", "title": "Place URLs at the end of citations", "source_refs": ["CMOS18 §13.6 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a URL is included in a citation, place it as the final element.", "rationale": "A consistent placement makes citations easier to scan.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["URL placement"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_6.URLS.IN_MANUSCRIPT", "title": "Record URLs in manuscripts even if they may be omitted later", "source_refs": ["CMOS18 §13.6 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Include URLs in manuscript citations to support verification, even if publishers remove them later.", "rationale": "Editors need access to sources during review.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["manuscript", "verification"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_6.URLS.READER_NEEDED", "title": "Retain URLs when sources are hard to locate", "source_refs": ["CMOS18 §13.6 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Keep URLs when readers would struggle to locate the source without one.", "rationale": "URLs can be essential for obscure or web-only sources.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["hard to locate"], "dependencies": [], "exceptions": ["Formal publications may omit URLs for easily found works."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_6.LINK_TITLE_PREFERRED", "title": "Prefer linking the title rather than showing a long URL", "source_refs": ["CMOS18 §13.6 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If possible, link a reader-friendly element such as the title rather than showing a long URL.", "rationale": "Readable citations are easier to scan and less error-prone.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["link text", "titles"], "dependencies": [], "exceptions": ["Manuscripts may still record the full URL for verification."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_6.URLS.EASILY_FOUND", "title": "Omit URLs for easily found published sources", "source_refs": ["CMOS18 §13.6 p777 (scan p799)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For formally published sources that are easy to locate by title and metadata, URLs may be omitted.", "rationale": "URLs may add noise when they do not aid discovery.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["published sources"], "dependencies": [], "exceptions": ["Online-only sources usually require URLs."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_7.DOI.URL_FORM", "title": "Use DOI-based URLs in citations", "source_refs": ["CMOS18 §13.7 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a DOI is available, express it as a URL beginning with https://doi.org/.", "rationale": "DOI URLs are stable and resolvable.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "doi"], "keywords": ["DOI", "URL"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_7.DOI.NO_PREFIX", "title": "Do not use the deprecated DOI: prefix", "source_refs": ["CMOS18 §13.7 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Avoid the deprecated DOI: prefix; use the DOI as a URL instead.", "rationale": "URL form is the current standard.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "doi"], "keywords": ["DOI", "deprecated"], "dependencies": [], "exceptions": ["Quoted sources may preserve legacy formatting."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_7.DOI.PREFERRED", "title": "Prefer DOI URLs over other links", "source_refs": ["CMOS18 §13.7 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If a DOI exists, prefer it over other URLs because it is designed to remain stable.", "rationale": "DOIs reduce link rot.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "doi"], "keywords": ["stability"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_7.DOI.RESOLUTION", "title": "Ensure DOI URLs resolve to source information", "source_refs": ["CMOS18 §13.7 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Verify that DOI URLs resolve to a page that identifies the source.", "rationale": "Resolvable DOIs support verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "doi"], "keywords": ["resolve", "verification"], "dependencies": [], "exceptions": ["If a DOI is broken, use a stable alternate URL."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_8.PERMALINK.PREFERRED", "title": "Prefer permalinks when no DOI exists", "source_refs": ["CMOS18 §13.8 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use a permalink, stable URL, or persistent link when no DOI is available.", "rationale": "Permalinks are more stable than transient URLs.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["permalink", "stable URL"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_8.PERMALINK.TEST", "title": "Test permalinks before use", "source_refs": ["CMOS18 §13.8 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Test permalinks to confirm they lead to the intended source.", "rationale": "Unverified permalinks may lead to dead or incorrect pages.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["permalink", "testing"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_8.SUBSCRIPTION_URLS", "title": "Avoid subscription-only URLs when possible", "source_refs": ["CMOS18 §13.8 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Avoid URLs that require subscriptions when a stable public URL or database name will work.", "rationale": "Paywalled links may not help readers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["subscription", "paywall"], "dependencies": [], "exceptions": ["If no public URL exists, note the database name."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_8.PREFERRED_ORDER", "title": "Use DOI, then permalink, then best available URL", "source_refs": ["CMOS18 §13.8 p778 (scan p798)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use DOI URLs first, then permalinks, then the best available URL.", "rationale": "This order balances stability and access.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["priority", "DOI", "permalink"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_9.SHORTEN_LONG_URLS", "title": "Replace long URLs with better alternatives", "source_refs": ["CMOS18 §13.9 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If a URL is long or complex, find a shorter, more stable alternative.", "rationale": "Shorter URLs reduce errors and improve readability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["long URL", "shorten"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_9.URL_TO_MAIN_PAGE", "title": "Use the main page when it identifies the source", "source_refs": ["CMOS18 §13.9 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a page-specific URL is long, use the source's main page if the citation includes a locator such as page number.", "rationale": "Main pages are usually more stable.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["main page", "locator"], "dependencies": [], "exceptions": ["If the main page is ambiguous, keep the specific URL."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_9.DATABASE_NAME_OK", "title": "Use a database name when a URL is impractical", "source_refs": ["CMOS18 §13.9 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If no workable URL exists, record the database or site name instead.", "rationale": "Database names can be more reliable than unwieldy links.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["database name"], "dependencies": [], "exceptions": ["Ensure the citation includes enough metadata to locate the source."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_9.SHORT_URLS.ARE_NOT_SHORTENERS", "title": "Prefer stable source URLs, not generic shorteners", "source_refs": ["CMOS18 §13.9 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Shorten URLs by finding a stable source URL, not by using a third-party shortener.", "rationale": "Stable source URLs are more transparent and durable.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["shorteners", "stability"], "dependencies": [], "exceptions": ["Publishers may use shorteners in final layouts."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_10.DATABASES.NAME_INSTEAD", "title": "Use database names for subscription-only sources", "source_refs": ["CMOS18 §13.10 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For sources accessible only via subscription databases, cite the database name rather than a login URL.", "rationale": "Readers without access can still identify the source.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "databases"], "keywords": ["database", "subscription"], "dependencies": [], "exceptions": ["Use DOI URLs when available."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_10.TEST_LOGGED_OUT", "title": "Test URLs while logged out", "source_refs": ["CMOS18 §13.10 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Test database URLs while logged out to confirm they provide at least source metadata.", "rationale": "Editors and readers may not have access.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "databases"], "keywords": ["logged out", "testing"], "dependencies": [], "exceptions": ["If no public metadata is available, cite the database name."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_10.DOI_PRECEDENCE", "title": "Use DOI URLs for database sources when available", "source_refs": ["CMOS18 §13.10 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Prefer DOI URLs over database-specific URLs when a DOI exists.", "rationale": "DOI URLs work for readers regardless of database access.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "databases"], "keywords": ["DOI", "database"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_10.DATABASE_IN_CITATION", "title": "Include database names when needed for access", "source_refs": ["CMOS18 §13.10 p779 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a database is essential to access the source, name it in the citation.", "rationale": "Database context helps readers find the source.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "databases"], "keywords": ["database name", "access"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_11.NO_SHORTENERS_IN_MS", "title": "Do not use link shorteners in manuscripts", "source_refs": ["CMOS18 §13.11 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Do not create short URLs via third-party services in manuscript citations.", "rationale": "Shorteners obscure domain names and can break over time.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["shorteners", "manuscripts"], "dependencies": [], "exceptions": ["Publishers may choose short URLs for final layouts."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_11.SHORTENERS.OBSCURE", "title": "Avoid short URLs that hide source details", "source_refs": ["CMOS18 §13.11 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Avoid shortened URLs that hide the source domain and path details.", "rationale": "Hidden details complicate verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["short URLs", "transparency"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_11.PUBLISHER_OPTION", "title": "Publishers may choose short URLs for publication", "source_refs": ["CMOS18 §13.11 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Short URLs may be used in published works if chosen and managed by the publisher.", "rationale": "Publishers can manage redirects when sources move.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["publishers", "short URLs"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_12.URLS.PROTOCOL", "title": "Include the protocol in URLs", "source_refs": ["CMOS18 §13.12 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Present URLs in full, including the protocol (http or https).", "rationale": "Protocols make URLs unambiguous.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["protocol", "http", "https"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_12.URLS.CASE_SENSITIVE", "title": "Preserve URL capitalization", "source_refs": ["CMOS18 §13.12 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Do not change URL capitalization because parts may be case sensitive.", "rationale": "Case changes can break links.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["case sensitivity"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_12.URLS.TRAILING_SLASH", "title": "Preserve trailing slashes in URLs", "source_refs": ["CMOS18 §13.12 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If a URL ends with a trailing slash, retain it.", "rationale": "Trailing slashes can be part of the resource path.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["trailing slash"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_12.URLS.NO_SPACES", "title": "Keep URLs as continuous strings", "source_refs": ["CMOS18 §13.12 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "URLs should contain no spaces; avoid inserting breaks or spaces inside them.", "rationale": "Spaces break links and hinder copying.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["spaces", "line breaks"], "dependencies": [], "exceptions": ["Use line-break rules if a URL must wrap in print."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_12.URLS.PUNCTUATION_AFTER", "title": "Retain sentence punctuation after URLs", "source_refs": ["CMOS18 §13.12 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Keep sentence punctuation after a URL as you would for any word.", "rationale": "Removing punctuation can break sentence grammar.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["punctuation", "URLs"], "dependencies": [], "exceptions": ["Ensure punctuation is not mistaken as part of the URL."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_12.URLS.NO_SENTENCE_START", "title": "Avoid starting sentences with URLs", "source_refs": ["CMOS18 §13.12 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Do not begin a sentence with a URL; rephrase to move the URL later.", "rationale": "Sentence-initial URLs are hard to read and typeset.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "urls"], "keywords": ["sentence start", "URLs"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.TOOLS.USE_METADATA", "title": "Use citation tools to capture metadata", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use citation management tools to capture author, title, and publication data when available.", "rationale": "Tools reduce manual entry errors.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["citation tools", "metadata"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.METADATA.CHECK_FIELDS", "title": "Verify captured citation fields", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "Verify captured metadata fields against the original source.", "rationale": "Automated exports often contain errors.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["verification", "metadata"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.METADATA.MISSING", "title": "Resolve missing or redundant metadata", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Check for missing or redundant metadata and correct it in the citation database.", "rationale": "Data errors propagate into manuscripts.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["missing data", "redundant data"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.CITATIONS.REVIEW", "title": "Review inserted citations for formatting errors", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "After inserting citations, review for incorrect punctuation, capitalization, or missing elements.", "rationale": "Tools do not guarantee correct formatting.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["review", "formatting"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.REPAIR_AT_SOURCE", "title": "Fix errors in the citation database, not only in text", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Correct errors in the citation tool or database so updates propagate correctly.", "rationale": "Editing only the manuscript can reintroduce errors later.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["citation database", "propagation"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.BACKUPS", "title": "Back up citation data", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Maintain backups of citation libraries and exported data.", "rationale": "Lost citation data can delay publication.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["backups"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_13.STRIP_CODES", "title": "Provide plain-text citations when required", "source_refs": ["CMOS18 §13.13 p780 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If required by the publisher, convert citations to plain text and verify the result.", "rationale": "Hidden field codes can break production workflows.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "research"], "keywords": ["field codes", "plain text"], "dependencies": [], "exceptions": ["Keep a version with codes intact as a backup."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_14.CITE_VERSION", "title": "Cite the version consulted", "source_refs": ["CMOS18 §13.14 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Record the version of a work that was consulted, especially when multiple formats exist.", "rationale": "Different versions may contain variations.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "versions"], "keywords": ["version", "format"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_14.ONLINE.URL_INDICATOR", "title": "Use a URL to indicate online consultation", "source_refs": ["CMOS18 §13.14 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Include a URL when it signals that a work was consulted online.", "rationale": "URLs distinguish online use from print use.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "versions"], "keywords": ["online", "URL"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_14.SAME_URL.FORMATS", "title": "Do not specify format when versions share a URL", "source_refs": ["CMOS18 §13.14 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When PDF and HTML versions share a URL, a separate format note is usually unnecessary.", "rationale": "The URL already identifies the source.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "versions"], "keywords": ["PDF", "HTML"], "dependencies": [], "exceptions": ["Specify format if required by publisher."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_14.DEVICE_SPECIFIC", "title": "Specify device-specific formats", "source_refs": ["CMOS18 §13.14 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a work is designed for a specific device or application, note the format or device.", "rationale": "Device-specific formats can affect content presentation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "versions"], "keywords": ["device", "format"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_15.ACCESS_DATE.NOT_REQUIRED", "title": "Access dates are usually unnecessary", "source_refs": ["CMOS18 §13.15 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Do not include access dates unless the source lacks a publication or revision date or policy requires them.", "rationale": "Access dates are hard to verify and often unhelpful.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["access date"], "dependencies": [], "exceptions": ["Student work or publisher policy may require them."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_15.ACCESS_DATE.RECORD_ANYWAY", "title": "Record access dates during research", "source_refs": ["CMOS18 §13.15 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Record access dates while researching even if they may not appear in the final citation.", "rationale": "Access dates can be useful if a source is updated later.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["research", "access date"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_15.ACCESS_DATE.PUBLISHER_POLICY", "title": "Follow publisher access-date policy", "source_refs": ["CMOS18 §13.15 p781 (scan p796)"], "category": "citations", "severity": "must", "applies_to": "all", "rule_text": "If a publisher requires access dates, include them.", "rationale": "Publisher requirements are mandatory.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["publisher policy"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_15.ACCESS_DATE.UNVERIFIABLE", "title": "Do not treat access dates as authoritative evidence", "source_refs": ["CMOS18 §13.15 p781 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Access dates are self-reported and should not be treated as verified evidence.", "rationale": "Access dates cannot be independently confirmed.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["access dates", "verification"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_16.REVISION_DATE.WHEN_ONLY_DATE", "title": "Use revision dates only when no publication date exists", "source_refs": ["CMOS18 §13.16 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Include revision dates when they are the only available date or the de facto publication date.", "rationale": "Revision dates can stand in for missing publication dates.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["revision date"], "dependencies": [], "exceptions": ["If both publication and revision dates exist, prefer publication date."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_16.REVISION_DATE.PREFERENCE", "title": "Prefer publication dates over revision dates", "source_refs": ["CMOS18 §13.16 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use the publication date when available and add a revision date only if needed for clarity.", "rationale": "Publication dates are the primary temporal reference.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["publication date", "revision date"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_16.REVISION_DATE.WIKIS", "title": "Use revision dates for frequently updated sources", "source_refs": ["CMOS18 §13.16 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Include revision dates for wikis or frequently updated sources when they clarify what was consulted.", "rationale": "Dynamic sources change over time.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["wikis", "updated sources"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_16.REVISION_DATE.FORMAT", "title": "Treat revision dates as publication dates when used", "source_refs": ["CMOS18 §13.16 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a revision date is used as the main date, format it as the publication date in the citation.", "rationale": "Readers need a clear single date for the source.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "dates"], "keywords": ["revision date", "format"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_17.PRESERVE.NONPUBLISHED", "title": "Preserve copies of non-formally published sources", "source_refs": ["CMOS18 §13.17 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Keep copies of sources that are not formally published, such as web pages or social media posts.", "rationale": "Unpublished sources can disappear or change.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "archiving"], "keywords": ["preservation", "web sources"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_17.PRESERVE.FORMAT_OPTIONS", "title": "Use printouts or screenshots for preservation", "source_refs": ["CMOS18 §13.17 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Preserve sources via printouts, PDFs, or screenshots as appropriate.", "rationale": "A local copy protects against link rot.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "archiving"], "keywords": ["screenshots", "printouts"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_17.ARCHIVE_SERVICES", "title": "Use archiving services for unstable sources", "source_refs": ["CMOS18 §13.17 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use services like Perma.cc or the Internet Archive to preserve unstable sources.", "rationale": "Archived links provide persistent access.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "archiving"], "keywords": ["archiving", "permanent links"], "dependencies": [], "exceptions": ["Check institutional policies for approved services."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_17.PRESERVE.CRISIS_SOURCES", "title": "Preserve sources that may change during events", "source_refs": ["CMOS18 §13.17 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Preserve sources that report ongoing events, as their content may change over time.", "rationale": "Historical verification requires stable records.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "archiving"], "keywords": ["ongoing events", "changes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_18.NOTES_BIBLIO.OVERVIEW", "title": "Use numbered notes tied to superscripts", "source_refs": ["CMOS18 §13.18 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes-bibliography, use numbered notes that correspond to superscript numbers in the text.", "rationale": "The system depends on a clear text-to-note link.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["notes", "superscript"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_18.NOTES.SENTENCE_STYLE", "title": "Write notes as sentence-style citations", "source_refs": ["CMOS18 §13.18 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Notes are formatted like sentences, with elements separated by commas and parentheses as needed.", "rationale": "Sentence-style notes are the Chicago default.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["notes", "sentence style"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_18.NAMES.NORMAL_ORDER", "title": "Use normal name order in notes", "source_refs": ["CMOS18 §13.18 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes, present author names in normal order.", "rationale": "Notes read like sentences rather than index entries.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["author names", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_18.BIBLIO.SHORTENED_NOTES", "title": "Use shortened notes when a full bibliography exists", "source_refs": ["CMOS18 §13.18 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If a bibliography includes full details for all sources, use shortened notes after the first full citation.", "rationale": "Short notes reduce repetition while preserving traceability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["shortened notes", "bibliography"], "dependencies": [], "exceptions": ["Works without a bibliography require full first notes."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_18.NO_BIBLIO.FULL_FIRST_NOTE", "title": "Use full notes when no bibliography exists", "source_refs": ["CMOS18 §13.18 p782 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In works without a bibliography, provide full citation details in the first note for each source.", "rationale": "Readers need complete information in the notes.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["full note", "no bibliography"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_18.BIBLIO.INVERT_FIRST_AUTHOR", "title": "Invert the first author name in bibliographies", "source_refs": ["CMOS18 §13.18 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In bibliographies, invert the first-listed author name and separate elements with periods.", "rationale": "Inversion supports alphabetic sorting.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "bibliography"], "keywords": ["inverted names", "bibliography"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_19.ABBREVIATIONS.NOTES", "title": "Use abbreviations in notes for editors and editions", "source_refs": ["CMOS18 §13.19 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes, abbreviate editor, translator, volume, and edition terms.", "rationale": "Notes are compact by design.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["abbreviations", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_19.ABBREVIATIONS.BIBLIO", "title": "Spell out verb forms in bibliographies", "source_refs": ["CMOS18 §13.19 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In bibliographies, spell out verb forms such as edited by or translated by.", "rationale": "Bibliographies favor readability over brevity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "bibliography"], "keywords": ["edited by", "translated by"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_19.ABBREVIATIONS.NOUN_FORMS", "title": "Keep noun abbreviations in bibliographies", "source_refs": ["CMOS18 §13.19 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In bibliographies, noun abbreviations such as ed. and trans. may still be used.", "rationale": "Chicago distinguishes noun and verb forms.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "bibliography"], "keywords": ["noun abbreviations"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_19.ABBREVIATIONS.CONSISTENT", "title": "Use abbreviations consistently within notes and bibliographies", "source_refs": ["CMOS18 §13.19 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Apply abbreviation rules consistently across all notes and bibliography entries.", "rationale": "Inconsistent abbreviation usage looks unprofessional.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "consistency"], "keywords": ["abbreviations", "consistency"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_20.NOTES.PAGE_SPECIFIC", "title": "Use specific page numbers in notes", "source_refs": ["CMOS18 §13.20 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes, cite the specific page or pages where the relevant passage appears.", "rationale": "Specific locators allow readers to verify claims.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["page numbers", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_20.PAGE_RANGE.EN_DASH", "title": "Use an en dash for page ranges", "source_refs": ["CMOS18 §13.20 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Use an en dash to show page ranges in notes and bibliographies.", "rationale": "En dashes are the standard range marker.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["page ranges", "en dash"], "dependencies": [], "exceptions": ["If the platform cannot render en dashes, document the fallback."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_20.BIBLIO.PAGE_RANGE", "title": "Include full article page ranges in bibliographies", "source_refs": ["CMOS18 §13.20 p783 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Bibliographies should include the full page range for journal articles.", "rationale": "Full ranges help locate articles quickly.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "bibliography"], "keywords": ["page range", "articles"], "dependencies": [], "exceptions": ["Books do not require page ranges in bibliographies."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_20.BIBLIO.BOOKS.NO_PAGES", "title": "Do not include page numbers for books in bibliographies", "source_refs": ["CMOS18 §13.20 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Bibliography entries for books should not include page numbers.", "rationale": "Books are cited as whole works in bibliographies.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "bibliography"], "keywords": ["books", "page numbers"], "dependencies": [], "exceptions": ["Chapters in edited volumes may include locators in notes."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_20.LOCATORS.ALTERNATIVES", "title": "Use alternative locators when pages are missing", "source_refs": ["CMOS18 §13.20 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When page numbers are unavailable, use chapter numbers, section headings, paragraph numbers, or descriptive locators.", "rationale": "Readers still need a path to the cited passage.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["locators", "electronic sources"], "dependencies": [], "exceptions": ["Short searchable documents may omit locators."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_20.ELECTRONIC.SHORT_DOCS", "title": "Omit locators for short searchable documents", "source_refs": ["CMOS18 §13.20 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For short electronic works that are easily searchable, locators may be omitted.", "rationale": "Extra locators may be unnecessary in short documents.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["short documents", "locators"], "dependencies": [], "exceptions": ["Include locators if required by policy."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_21.EXAMPLES.SHORT_FORMS", "title": "Use short forms after full notes", "source_refs": ["CMOS18 §13.21 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Shortened note forms may be used after a source has been fully cited.", "rationale": "Short forms reduce repetition while retaining traceability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["short forms"], "dependencies": [], "exceptions": ["Works without a bibliography need full first notes."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_21.EXAMPLES.BIBLIO_SHORTENED", "title": "Short forms may be used at first mention if a full bibliography exists", "source_refs": ["CMOS18 §13.21 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In works with a full bibliography, shortened notes may be used even at first mention.", "rationale": "The bibliography supplies full publication details.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["short forms", "bibliography"], "dependencies": [], "exceptions": ["Some publishers still require full first notes."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_21.EXAMPLES.CHAPTER14", "title": "Use chapter 14 for expanded examples", "source_refs": ["CMOS18 §13.21 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Refer to chapter 14 for extended citation examples and edge cases.", "rationale": "Chapter 14 contains source-specific formats.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["examples", "chapter 14"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_22.BOOK_SINGLE_AUTHOR.NOTE_BIBLIO", "title": "Single-author books use normal names in notes and inverted in bibliography", "source_refs": ["CMOS18 §13.22 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For single-author books, use normal name order in notes and invert the name in the bibliography.", "rationale": "Notes read like sentences while bibliographies sort by surname.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["single author", "inversion"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_22.BOOK_SINGLE_AUTHOR.PAGE_IN_NOTES", "title": "Include page numbers in book notes", "source_refs": ["CMOS18 §13.22 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Notes for books should include page numbers for the cited passage.", "rationale": "Specific pages aid verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["page numbers", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_22.BOOK_SINGLE_AUTHOR.SHORTENED", "title": "Use shortened book citations after first full note", "source_refs": ["CMOS18 §13.22 p784 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "After a full note, use surname plus short title for subsequent book citations.", "rationale": "Short forms reduce repetition.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["short title"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_22.BOOK_EDITOR_ONLY", "title": "Use ed. or eds. when the editor replaces the author", "source_refs": ["CMOS18 §13.22 p785 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If a book has an editor in place of an author, include ed. or eds. in the note and bibliography.", "rationale": "Editors must be identified when no author is listed.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["editor", "eds."], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_22.BOOK_PLACE_OMIT", "title": "Omit place of publication for books", "source_refs": ["CMOS18 §13.22 p785 (scan p796)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Chicago now omits the place of publication in most book citations.", "rationale": "Place of publication rarely adds value.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["publication place"], "dependencies": [], "exceptions": ["Include place only when required by policy."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_22.BOOK_EDITOR_ONLY.SHORTENED_NO_ED", "title": "Omit ed. in shortened editor-only citations", "source_refs": ["CMOS18 §13.22 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In shortened notes for editor-only books, omit the ed. label.", "rationale": "Short forms keep citations compact.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books", "editors"], "keywords": ["shortened notes", "editor"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_23.TWO_AUTHORS.NOTES_LIST_BOTH", "title": "List both names in notes for two-author books", "source_refs": ["CMOS18 §13.23 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "For books with two authors or editors, list both names in notes.", "rationale": "Notes should show full author credit for two-name works.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["two authors", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_23.TWO_AUTHORS.BIBLIO_INVERT_FIRST", "title": "Invert only the first name in bibliographies for two-author books", "source_refs": ["CMOS18 §13.23 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In bibliographies for two-author or two-editor books, invert only the first listed name.", "rationale": "Chicago uses a single inversion for alphabetic sorting.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["inverted name", "bibliography"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_23.MULTI_AUTHORS.NOTES_ET_AL", "title": "Use et al. in notes for books with more than two authors", "source_refs": ["CMOS18 §13.23 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes for books with more than two authors or editors, list the first name followed by et al.", "rationale": "Shortened notes remain readable while identifying the source.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["et al.", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_23.MULTI_AUTHORS.BIBLIO_UP_TO_SIX", "title": "List up to six authors in bibliographies", "source_refs": ["CMOS18 §13.23 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In bibliographies, list up to six authors or editors.", "rationale": "Chicago provides full credit up to six names.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["bibliography", "authors"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_23.MULTI_AUTHORS.BIBLIO_MORE_THAN_SIX", "title": "Use et al. after three names when more than six authors exist", "source_refs": ["CMOS18 §13.23 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a work has more than six authors or editors, list the first three followed by et al.", "rationale": "This keeps bibliography entries manageable.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["et al.", "bibliography"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_23.NO_BIBLIO.NOTES_UP_TO_SIX", "title": "List up to six authors in full notes when no bibliography exists", "source_refs": ["CMOS18 §13.23 p785 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If no bibliography is provided, list up to six authors in the first full note.", "rationale": "The first note must carry the full author set.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books"], "keywords": ["no bibliography", "full note"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_24.AUTHOR_PLUS_EDITOR.NOTES_ABBREVIATE", "title": "Use ed. or trans. in notes for author plus editor or translator", "source_refs": ["CMOS18 §13.24 p786 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a book has an author plus an editor or translator, abbreviate the role in notes (ed., trans.).", "rationale": "Notes favor compact role markers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books", "roles"], "keywords": ["editor", "translator"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_24.AUTHOR_PLUS_EDITOR.BIBLIO_SPELL_OUT", "title": "Spell out Edited by or Translated by in bibliographies", "source_refs": ["CMOS18 §13.24 p786 (scan p808)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In bibliographies, spell out Edited by or Translated by for author-plus-editor/translator works.", "rationale": "Bibliographies prioritize clarity over brevity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "books", "roles"], "keywords": ["edited by", "translated by"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_25.CHAPTER_IN_EDITED.INCLUDE_AUTHOR", "title": "Include chapter author in edited-book citations", "source_refs": ["CMOS18 §13.25 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Citations of chapters in edited books should include the chapter author.", "rationale": "Chapters are authored works within a larger volume.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "chapters"], "keywords": ["chapter author"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_25.CHAPTER_IN_EDITED.QUOTE_TITLE", "title": "Put chapter titles in quotation marks", "source_refs": ["CMOS18 §13.25 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Chapter titles in edited-book citations should appear in quotation marks.", "rationale": "Chicago distinguishes chapter titles from book titles.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "chapters"], "keywords": ["chapter title", "quotation marks"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_25.CHAPTER_IN_EDITED.INCLUDE_EDITOR", "title": "Include the editor for edited-book chapters", "source_refs": ["CMOS18 §13.25 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Citations of chapters in edited books should include the editor of the volume.", "rationale": "The editor identifies the container work.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "chapters"], "keywords": ["editor", "edited book"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_25.CHAPTER_IN_EDITED.IN_BEFORE_BOOK", "title": "Use in before the book title for chapters", "source_refs": ["CMOS18 §13.25 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Precede the edited book title with in when citing a chapter.", "rationale": "The in marker clarifies container vs part.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "chapters"], "keywords": ["in", "container"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_25.CHAPTER_IN_EDITED.NOTES_PAGE_LOCATOR", "title": "Include a page locator in chapter notes", "source_refs": ["CMOS18 §13.25 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Notes for chapters in edited books should include a page locator.", "rationale": "Notes direct readers to the cited passage.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "chapters"], "keywords": ["page locator", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_25.CHAPTER_IN_EDITED.BIBLIO_NO_PAGE_RANGE", "title": "Omit chapter page ranges in bibliographies", "source_refs": ["CMOS18 §13.25 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Bibliography entries for chapters in edited books should not include a page range.", "rationale": "Chicago no longer requires chapter ranges in bibliographies.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "chapters"], "keywords": ["bibliography", "page range"], "dependencies": [], "exceptions": ["Include a range if publisher policy requires it."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.INCLUDE_VOLUME", "title": "Include journal volume numbers", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Journal citations should include the volume number.", "rationale": "Volume identifies the journal run.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["volume"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.INCLUDE_ISSUE", "title": "Include journal issue numbers", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Journal citations should include the issue number when available.", "rationale": "Issue numbers narrow the source within a volume.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["issue number"], "dependencies": [], "exceptions": ["If the journal has no issue numbers, omit them."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.INCLUDE_YEAR", "title": "Include the publication year for journals", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Journal citations should include the year of publication.", "rationale": "The year anchors the volume and issue.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["year"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.TITLE_ITALIC", "title": "Italicize journal titles", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Journal titles should be italicized in citations.", "rationale": "Italicized container titles distinguish the journal.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["journal title", "italics"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.VOLUME_FORMAT", "title": "Place volume numbers after the journal title without punctuation", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "The volume number follows the italicized journal title in roman type with no intervening punctuation.", "rationale": "This is the standard Chicago format for journal references.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["volume format", "roman type"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.NOTES_PAGE_SPECIFIC", "title": "Include specific pages for journal notes", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Notes for journal articles should include the specific page referenced.", "rationale": "Specific pages support verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["notes", "page numbers"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.BIBLIO_PAGE_RANGE", "title": "Include full page ranges in journal bibliographies", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Bibliography entries for journal articles should include the full page range.", "rationale": "Full ranges identify the article scope.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["bibliography", "page range"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.PAGE_COLON", "title": "Use a colon before journal page numbers in full citations", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In full citations, precede journal page numbers with a colon.", "rationale": "The colon separates issue data from page numbers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["colon", "page numbers"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.OMIT_MONTH_SEASON", "title": "Omit month or season unless required", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Month or season details are usually omitted from journal citations unless required.", "rationale": "Volume, issue, and year typically suffice.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["month", "season"], "dependencies": [], "exceptions": ["Include month or season when a publisher requires it."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_26.JOURNAL.ONLINE.URL_OR_DOI", "title": "Record a URL or DOI for online journal articles", "source_refs": ["CMOS18 §13.26 p786 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a journal article is consulted online, record a URL or DOI.", "rationale": "Online access should be traceable to a stable locator.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "journals"], "keywords": ["URL", "DOI"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_NUMBERS.TEXT_SUPERSCRIPT", "title": "Set note reference numbers as superscripts in text", "source_refs": ["CMOS18 §13.27 p787 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Note reference numbers in the text should be superscripts.", "rationale": "Superscripts are the Chicago default for note references.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["superscript", "note numbers"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_NUMBERS.NOTES_FULL_SIZE", "title": "Use full-size numbers in notes", "source_refs": ["CMOS18 §13.27 p787 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In the notes themselves, note numbers are normally full size rather than superscript.", "rationale": "Notes are formatted like sentences, not text references.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["full size", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_NUMBERS.NOTES_PERIOD", "title": "Follow note numbers with a period", "source_refs": ["CMOS18 §13.27 p787 (scan p809)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes, the note number is followed by a period.", "rationale": "The period separates the number from the note text.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["period", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_NUMBERS.MANUSCRIPT_SUPERSCRIPT_OK", "title": "Superscript note numbers in notes are acceptable in manuscripts", "source_refs": ["CMOS18 §13.27 p787 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In manuscripts, superscript note numbers in the notes are acceptable if produced by word processors.", "rationale": "Chicago allows common manuscript defaults.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["manuscripts", "superscript"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_SYMBOLS.TEXT_SUPERSCRIPT", "title": "Superscript symbols in text when symbols replace numbers", "source_refs": ["CMOS18 §13.27 p787 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If symbols replace numbers, set the symbol as a superscript in the text.", "rationale": "Symbols function like note numbers in text.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbols", "superscript"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_SYMBOLS.NOTES_FULL_SIZE", "title": "Use full-size symbols in notes", "source_refs": ["CMOS18 §13.27 p787 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When symbols are used for notes, display the symbol at full size in the note.", "rationale": "Notes prioritize readability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbols", "notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_SYMBOLS.NO_PERIOD", "title": "Do not follow note symbols with a period", "source_refs": ["CMOS18 §13.27 p787 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "In notes, a symbol used for note references should not be followed by a period.", "rationale": "Chicago treats symbols differently from numbers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbols", "period"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_SYMBOLS.CONSISTENT_SPACING", "title": "Keep symbol spacing consistent in notes", "source_refs": ["CMOS18 §13.27 p787 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If a space follows a note symbol, apply that spacing consistently throughout the notes.", "rationale": "Consistency avoids irregular note formatting.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbols", "spacing"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_27.NOTE_SYMBOLS.BASELINE_FALLBACK", "title": "Use baseline symbols when superscripts are hard to read", "source_refs": ["CMOS18 §13.27 p787 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If superscript symbols are hard to read in a typeface, set them on the baseline in both text and notes.", "rationale": "Legibility is more important than strict superscripting.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbols", "legibility"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_28.NOTE_SEQUENCE.CONSECUTIVE", "title": "Number notes consecutively from 1 within each article or chapter", "source_refs": ["CMOS18 §13.28 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Notes should be numbered consecutively beginning with 1 within each article and each chapter.", "rationale": "Consecutive numbering avoids ambiguity across sections.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["consecutive numbering"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_28.NOTE_SEQUENCE.NO_BOOKWIDE_RUN", "title": "Avoid numbering notes across an entire book with divisions", "source_refs": ["CMOS18 §13.28 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Do not number notes across an entire book when the text has internal divisions.", "rationale": "Each chapter should restart numbering.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["chapter restart"], "dependencies": [], "exceptions": ["Books without divisions may use a single sequence."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_28.NOTE_SEQUENCE.SYMBOLS_FOR_FEW", "title": "Use symbols when only a few notes are needed", "source_refs": ["CMOS18 §13.28 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a text has only a handful of notes, symbols may be used instead of numbers.", "rationale": "Symbols are acceptable for very small note counts.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbols", "few notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_28.NOTE_SEQUENCE.SYMBOL_SEQUENCE_STANDARD", "title": "Use a standard symbol sequence when more than one symbol is needed", "source_refs": ["CMOS18 §13.28 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "If multiple symbols are used on the same page, follow a standard symbol sequence.", "rationale": "Standard sequences reduce reader confusion.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbol sequence"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_28.NOTE_SEQUENCE.SEPARATE_SYSTEMS", "title": "Keep distinct systems for different note sets", "source_refs": ["CMOS18 §13.28 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a work uses both symbols and numbers for different note sets, keep the systems distinct.", "rationale": "Separate systems prevent misreading which notes apply.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["symbol", "numbering"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_28.NOTE_SEQUENCE.TABLE_NOTES_SEPARATE", "title": "Handle table notes separately from text notes", "source_refs": ["CMOS18 §13.28 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Notes to tables and other nontext matter are handled independently from text notes.", "rationale": "Table note systems often follow their own conventions.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["table notes"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_29.NOTE_NUMBER.PLACEMENT_END_SENTENCE", "title": "Place note numbers at the end of a sentence or clause", "source_refs": ["CMOS18 §13.29 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Note numbers should generally appear at the end of a sentence or clause.", "rationale": "End placement avoids interrupting the reading flow.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["placement", "end of sentence"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_29.NOTE_NUMBER.AFTER_QUOTE", "title": "Place note numbers after quotations", "source_refs": ["CMOS18 §13.29 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Note numbers should follow quotations whether they are run in or set as extracts.", "rationale": "The note marks the end of the quoted material.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["quotation", "placement"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_29.NOTE_NUMBER.AFTER_PUNCTUATION", "title": "Place note numbers after punctuation", "source_refs": ["CMOS18 §13.29 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Note numbers normally follow punctuation marks.", "rationale": "The note refers to the full clause or sentence.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["punctuation"], "dependencies": [], "exceptions": ["The note number precedes a dash."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_29.NOTE_NUMBER.BEFORE_DASH", "title": "Place note numbers before a dash", "source_refs": ["CMOS18 §13.29 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "When a dash is the next punctuation, place the note number before the dash.", "rationale": "Chicago treats the dash as an interruption.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["dash", "placement"], "dependencies": [], "exceptions": ["None."], "status": "active"}
{"id": "CMOS.CITATIONS.S13_29.NOTE_NUMBER.AVOID_MIDCLAUSE", "title": "Avoid mid-clause note numbers when possible", "source_refs": ["CMOS18 §13.29 p788 (scan p810)"], "category": "citations", "severity": "should", "applies_to": "all", "rule_text": "Avoid inserting note numbers in the middle of a clause unless clarity requires it.", "rationale": "Mid-clause notes interrupt reading flow.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "notes"], "keywords": ["mid-clause", "placement"], "dependencies": [], "exceptions": ["When a note applies to a specific phrase."], "status": "active"}

View file

@ -0,0 +1,10 @@
{"id":"CMOS.CITATIONS.S13_35.SHORT_FORM.DISTINCT_TITLE","title":"Shortened citations should keep enough of the title to distinguish the work","source_refs":["CMOS18 §13.35 p791 (scan p813)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"In shortened citations, include enough of the title to uniquely identify the work and keep the same title styling (italics or quotes) used in the full citation.","rationale":"Short forms must remain identifiable without the full publication details.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","short_form"],"keywords":["short form","short title","title styling"],"dependencies":[],"exceptions":["If the project uses a standardized abbreviation list, follow that list consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_36.SHORT_FORM.DISAMBIGUATE_AUTHOR","title":"Disambiguate short forms for multiple works by the same author","source_refs":["CMOS18 §13.36 p791 (scan p813)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When citing multiple works by the same author in short form, add a distinguishing element such as a short title, volume, or date to avoid ambiguity.","rationale":"Author-only short forms can collide across multiple works.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","short_form"],"keywords":["short form","disambiguation","same author"],"dependencies":[],"exceptions":["If only one work by the author appears in the notes, a shorter form may be acceptable by policy."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_38.IBID.IMMEDIATE_PRECEDENT","title":"Use ibid only for the immediately preceding citation","source_refs":["CMOS18 §13.38 p793 (scan p815)"],"category":"citations","severity":"warn","applies_to":"all","rule_text":"Use ibid only when the note refers to exactly the same source as the immediately preceding note and no other source intervenes.","rationale":"Ibid becomes ambiguous when notes are reordered or separated.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","ibid"],"keywords":["ibid","immediate precedent"],"dependencies":[],"exceptions":["If a house style mandates ibid, keep notes stable and avoid renumbering."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_39.IBID.LOCATOR_REQUIRED","title":"Add locators when ibid refers to a different passage","source_refs":["CMOS18 §13.39 p793 (scan p815)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When ibid refers to a different page, section, or passage than the immediately preceding note, add the new locator to keep the reference precise.","rationale":"Locators preserve traceability even when ibid is used.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","ibid","locators"],"keywords":["ibid","locator","page number"],"dependencies":[],"exceptions":["If the locator is identical to the preceding note, ibid alone may be allowed by policy."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_40.SHORT_FORM.AVOID_OP_CIT","title":"Avoid op. cit. and loc. cit. in favor of short forms","source_refs":["CMOS18 §13.40 p793 (scan p815)"],"category":"citations","severity":"warn","applies_to":"all","rule_text":"Avoid op. cit. and loc. cit. in modern Chicago-style notes; use short forms or cross-references that remain unambiguous.","rationale":"Latin backreferences are easy to misread and fragile under reflow.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","short_form"],"keywords":["op. cit.","loc. cit.","short form"],"dependencies":[],"exceptions":["If a legacy style requires these forms, document the policy and enforce it consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_45.NOTES.CITATION_FIRST","title":"Place the source citation first when notes include commentary","source_refs":["CMOS18 §13.45 p796 (scan p818)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a note mixes a source citation with commentary, present the citation first and separate commentary clearly.","rationale":"Readers should find the source quickly before additional discussion.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","notes"],"keywords":["commentary notes","citation order"],"dependencies":[],"exceptions":["If commentary must precede the citation for context, keep the citation visually distinct."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_47.NOTES.SYSTEMS.DONT_MIX","title":"Do not mix footnotes and endnotes for the same note type","source_refs":["CMOS18 §13.47 p796 (scan p818)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Do not mix footnotes and endnotes for the same kind of note; if both systems are used, label each and keep numbering distinct.","rationale":"Mixed systems confuse readers and complicate navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","notes","endnotes","footnotes"],"keywords":["footnotes","endnotes","numbering"],"dependencies":[],"exceptions":["Critical editions may use separate note streams if clearly labeled."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_48.ENDNOTES.GROUP_BY_CHAPTER","title":"Group endnotes by chapter or section when applicable","source_refs":["CMOS18 §13.48 p797 (scan p819)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When endnotes correspond to chapters or sections, group them under clear chapter or section headings.","rationale":"Grouping helps readers match notes to the correct portion of the text.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","endnotes"],"keywords":["endnotes","chapter notes","grouping"],"dependencies":[],"exceptions":["Short works may use a single endnote list without subheadings."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_52.ENDNOTES.NAVIGATION_CUES","title":"Provide navigation cues for endnotes in long works","source_refs":["CMOS18 §13.52 p800 (scan p822)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"In long works with endnotes, add navigation cues such as chapter numbers, section headings, or note ranges so readers can locate notes efficiently.","rationale":"Navigation cues reduce paging friction in endnote-heavy documents.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","endnotes","navigation"],"keywords":["endnotes","navigation","chapter numbering"],"dependencies":[],"exceptions":["If the format provides interactive note links, headings may be simplified."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_54.AUTHOR_DATE.NOTES.COMMENTARY_ONLY","title":"Keep author-date citations in text and reserve notes for commentary","source_refs":["CMOS18 §13.54 p801 (scan p823)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When author-date citations are used, keep source citations in the text and reference list, and reserve notes for substantive commentary only.","rationale":"Separating citations from commentary keeps the author-date system clear.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date","notes"],"keywords":["author-date","notes","commentary"],"dependencies":[],"exceptions":["If a project requires source notes in addition to author-date citations, document the hybrid policy explicitly."],"status":"active"}

View file

@ -0,0 +1,12 @@
{"id":"CMOS.CITATIONS.S13_56.NOTES.DUAL_STREAMS.DISTINCT_LABELS","title":"If two note streams are used, keep them clearly distinct","source_refs":["CMOS18 §13.56 p803 (scan p825)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"If a work uses two different note streams (for example, source notes versus explanatory notes), label each stream clearly and keep numbering distinct so readers can tell which system a note belongs to.","rationale":"Multiple note streams are easy to confuse and can break traceability when notes are renumbered or reformatted.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","notes"],"keywords":["dual notes","note streams","numbering"],"dependencies":[],"exceptions":["If the deliverable mandates a dual-stream apparatus (e.g., critical editions), enforce strong labeling and distinct numbering styles."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_57.NOTES.SEPARATE_SOURCE_VS_COMMENTARY","title":"Separate source notes from discursive commentary when both appear","source_refs":["CMOS18 §13.57 p803 (scan p825)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When notes include both source citations and discursive commentary, keep citation information visually and structurally separate from commentary so the source is easy to locate.","rationale":"Mixed notes slow review and increase the chance that source details are missed.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","notes"],"keywords":["discursive notes","source notes","commentary"],"dependencies":[],"exceptions":["If commentary must precede the source for context, keep the citation clearly demarcated (e.g., after a separator)."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_59.NOTES.MULTI_EDITIONS.CITE_VERSION_USED","title":"When sources have multiple editions or printings, cite the version used","source_refs":["CMOS18 §13.59 p807 (scan p829)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a cited work exists in multiple editions, translations, or printings, cite the version actually consulted and include enough detail to distinguish it; add original-publication details only when the project requires it.","rationale":"Edition ambiguity makes locators and quotations hard to verify.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","notes","editions"],"keywords":["edition","version consulted","reprint"],"dependencies":[],"exceptions":["If a policy requires always citing both original and consulted edition, document that policy and apply it consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_61.BIBLIOGRAPHY.SCOPE.LABEL_CLEARLY","title":"Label bibliography scope (works cited vs selected) explicitly","source_refs":["CMOS18 §13.61 p807 (scan p829)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Label the bibliography/reference list to reflect its scope (e.g., works cited only versus a selected bibliography) and apply the same inclusion rule throughout the document.","rationale":"Clear scope prevents reviewers from assuming missing entries are errors (or vice versa).","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["bibliography scope","works cited","selected bibliography"],"dependencies":[],"exceptions":["Some publishers dictate the label regardless of scope; follow the publisher requirement and document any deviations."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_62.BIBLIOGRAPHY.ENTRY_COMPLETENESS.MORE_THAN_SHORT_FORM","title":"Bibliography entries should be complete enough to retrieve sources","source_refs":["CMOS18 §13.62 p808 (scan p830)"],"category":"citations","severity":"must","applies_to":"all","rule_text":"Ensure bibliography entries include enough publication detail to retrieve the source (author, full title, publication facts, and identifiers/URLs when relevant), not merely the shortened information used in subsequent notes.","rationale":"Bibliography entries are the primary lookup surface for verification.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["bibliography entry","retrieval","publication details"],"dependencies":[],"exceptions":["In constrained formats (one-page memos), a shortened bibliography may be allowed if policy explicitly permits it."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_63.BIBLIOGRAPHY.CONSISTENT_ELEMENT_ORDER","title":"Use a consistent element order within bibliography entries","source_refs":["CMOS18 §13.63 p808 (scan p830)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Within a bibliography, keep the ordering and punctuation of elements consistent for the same source type (e.g., books, chapters, articles), and avoid mixing incompatible entry templates.","rationale":"Inconsistent entry structure causes audit churn and can hide missing fields.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["consistency","entry template","bibliography"],"dependencies":[],"exceptions":["If the bibliography intentionally mixes multiple governing standards (rare), separate them into labeled subsections."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_64.BIBLIOGRAPHY.SUBSECTIONS.CLEAR_HEADINGS","title":"When bibliography entries are subdivided, use clear headings and ordering","source_refs":["CMOS18 §13.64 p809 (scan p831)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"If the bibliography is subdivided (for example, primary vs secondary sources), use clear headings and apply a consistent ordering rule within each subsection.","rationale":"Subsections can improve readability, but only when rules are clear and consistent.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["bibliography subsections","headings","ordering"],"dependencies":[],"exceptions":["Short bibliographies may omit subsections entirely; keep a single ordered list."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_66.BIBLIOGRAPHY.INCLUDE_ONLY_PER_SCOPE","title":"Include bibliography entries according to the declared scope","source_refs":["CMOS18 §13.66 p810 (scan p832)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Include works in the bibliography according to the declared scope (e.g., cited-only versus selected); do not mix inclusion criteria without an explicit note.","rationale":"Mixed criteria makes it unclear whether omissions or additions are intentional.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["inclusion criteria","scope","bibliography"],"dependencies":[],"exceptions":["If a publisher requires including additional background reading, label that section separately."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_67.BIBLIOGRAPHY.ANNOTATIONS.CONSISTENT_AND_DISTINCT","title":"If using annotated bibliography entries, keep annotations consistent and distinct","source_refs":["CMOS18 §13.67 p812 (scan p834)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"If bibliography entries include annotations, keep the annotation style consistent (length, voice, placement) and visually distinct from the citation itself.","rationale":"Annotations are helpful only when they do not obscure the citation data needed for retrieval.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","annotations"],"keywords":["annotated bibliography","annotations","format"],"dependencies":[],"exceptions":["If only a few entries are annotated for special reasons, label them as notes rather than mixing styles silently."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_68.BIBLIOGRAPHY.ENTRY_TYPES.NOT_MIXED","title":"Avoid mixing incompatible bibliography entry types for the same source","source_refs":["CMOS18 §13.68 p812 (scan p834)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For a given source type, avoid mixing incompatible entry forms (for example, sometimes treating a source as a whole book and elsewhere as a chapter) unless the difference is intentional and justified.","rationale":"Inconsistent entry typing makes it hard to reconcile citations against sources.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["entry types","source type","consistency"],"dependencies":[],"exceptions":["If a source is cited both as a whole work and as a specific contribution, ensure both entry forms are correct and distinguishable."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_71.BIBLIOGRAPHY.ALPHABETIZATION.PREFIXES_POLICY","title":"Apply a consistent policy for alphabetizing surnames with prefixes/particles","source_refs":["CMOS18 §13.71 p817 (scan p839)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When alphabetizing bibliography entries, apply a consistent policy for surnames with prefixes or particles (e.g., de, van) and document the choice when ambiguity exists.","rationale":"Prefix handling can change ordering and frustrate lookup if applied inconsistently.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","sorting"],"keywords":["alphabetize","prefixes","particles"],"dependencies":[],"exceptions":["If the corpus has an authoritative catalog record for name sorting, follow that record consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_72.BIBLIOGRAPHY.SORTING.DIACRITICS_AND_TRANSLITERATION","title":"Sort names with diacritics/transliteration consistently","source_refs":["CMOS18 §13.72 p817 (scan p839)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When sorting bibliography entries, treat diacritics and transliteration consistently according to the chosen system; avoid mixing competing transliterations for the same name.","rationale":"Inconsistent transliteration creates duplicate or misordered entries and complicates verification.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","sorting"],"keywords":["diacritics","transliteration","sorting"],"dependencies":[],"exceptions":["If the project uses author-preferred spellings that conflict with a single system, document the policy and keep a cross-reference list."],"status":"active"}

View file

@ -0,0 +1,8 @@
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.AUTHOR_LIST.LENGTH.POLICY","title":"Apply a consistent policy for listing many authors in bibliography entries","source_refs":["CMOS18 §13.77 p820 (scan p842)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When works have many authors, apply a consistent policy for how many names to list before abbreviating (e.g., using an abbreviation like “et al.”) and use the same policy across the bibliography.","rationale":"A consistent author-list policy improves scanability and prevents arbitrary truncation that can hide attribution.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["many authors","et al.","author list"],"dependencies":[],"exceptions":["If a publisher specifies an author-list limit, follow that requirement even if it differs from house defaults."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.CORPORATE_AUTHORS.USE_AS_AUTHOR","title":"Treat organizations as authors when they are credited as such","source_refs":["CMOS18 §13.80 p822 (scan p844)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a work is credited to an organization or group, treat that entity as the author in the bibliography and alphabetize consistently by the chosen form of the name.","rationale":"Corporate authorship is part of the retrieval identity and should not be obscured.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["corporate author","organization","alphabetize"],"dependencies":[],"exceptions":["If the source has both an individual and a corporate author and the style requires one to lead, document the policy and apply it consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.NO_AUTHOR.EDITOR_AS_LEAD_WHEN_APPROPRIATE","title":"For works without authors, use editors/translators as lead only when the work is primarily identified that way","source_refs":["CMOS18 §13.83 p824 (scan p846)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For works without an author, use the title to lead by default; use an editor, translator, or compiler as the lead element only when the work is primarily identified by that persons role and the policy allows it.","rationale":"Lead-element choices affect how entries are sorted and found.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["no author","editor","translator"],"dependencies":[],"exceptions":["If a catalog record or publisher standard dictates the lead element, follow it consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.AUTHOR_NAME.SUFFIXES.INCLUDE","title":"Include name suffixes (Jr., III) consistently when they are part of the authors published name","source_refs":["CMOS18 §13.85 p825 (scan p847)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When an authors name includes a suffix or generational marker, include it consistently across entries when it appears in the published form or authoritative metadata.","rationale":"Suffixes can distinguish different individuals with the same name and prevent misattribution.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["suffix","Jr.","name disambiguation"],"dependencies":[],"exceptions":["If the corpus standardizes names without suffixes, document that policy and ensure disambiguation still works."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.AUTHOR_NAME.PARTICLES.CONSISTENT_FORMAT","title":"Format name particles and compounds consistently","source_refs":["CMOS18 §13.86 p825 (scan p847)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Format name particles and compound surnames consistently within the bibliography (capitalization, spacing, and whether the particle is treated as part of the sorting key) according to the chosen policy.","rationale":"Inconsistent particle handling breaks ordering and fragments an authors works across the list.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["particles","compound surnames","sorting"],"dependencies":[],"exceptions":["If an author has a clear preferred form, follow it and document deviations needed for sorting."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.CONTRIBUTOR_ROLES.LABEL_CLEARLY","title":"Label contributor roles (editor, translator, compiler) clearly and consistently","source_refs":["CMOS18 §13.87 p826 (scan p848)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When contributors other than the author are listed, label their roles clearly (editor, translator, compiler, etc.) and use consistent abbreviations and placement across entries.","rationale":"Role clarity prevents confusion about authorship and improves retrieval.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["editor","translator","roles"],"dependencies":[],"exceptions":["If the bibliography is constrained to a shortened form, include roles only when they materially affect identification."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.MULTIPLE_CONTRIBUTORS.POLICY_CONSISTENT","title":"When multiple contributor roles apply, follow a consistent ordering policy","source_refs":["CMOS18 §13.88 p826 (scan p848)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"If an entry includes multiple contributor roles (e.g., author plus editor, translator, or introducer), follow a consistent ordering and punctuation policy so entries remain comparable.","rationale":"Inconsistent contributor ordering makes similar entries hard to scan and compare.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["multiple roles","ordering","consistency"],"dependencies":[],"exceptions":["If different source types require different templates, keep templates consistent within each type."],"status":"active"}
{"id":"CMOS.CITATIONS.BIBLIOGRAPHY.GROUP_AUTHORS.SUBUNITS.CONSISTENT","title":"Handle group authors with subunits consistently","source_refs":["CMOS18 §13.89 p826 (scan p848)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a group author includes subunits (e.g., department, committee), use a consistent form and hierarchy so entries sort predictably and remain retrievable.","rationale":"Group-name variation can create duplicate entries and hide related works.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["group author","subunits","sorting"],"dependencies":[],"exceptions":["If an authoritative publication record specifies a canonical organizational name, follow that form."],"status":"active"}

View file

@ -0,0 +1,14 @@
{"id":"CMOS.CITATIONS.S13_92.BIBLIOGRAPHY.BOOKS.CORE_ELEMENTS","title":"Book bibliography entries should include core publication elements","source_refs":["CMOS18 §13.92 p827 (scan p849)"],"category":"citations","severity":"must","applies_to":"all","rule_text":"For books cited in a bibliography, include the core elements needed for retrieval: author/editor, full title, publication place/publisher/date (as applicable), and an identifier when useful.","rationale":"Complete book entries make sources findable and verifiable.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["books","bibliography entry","publication facts"],"dependencies":[],"exceptions":["For archival or unpublished works, substitute the most stable locating information available."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_93.BIBLIOGRAPHY.EDITED_VOLUMES.ROLE_MARKING","title":"Edited-volume bibliography entries should clearly mark contributor roles","source_refs":["CMOS18 §13.93 p828 (scan p850)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a bibliography entry involves editors, translators, or compilers, make the role explicit and use consistent wording/abbreviations across entries of the same type.","rationale":"Role clarity prevents misattribution and improves matching against source metadata.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["editors","translators","roles"],"dependencies":[],"exceptions":["If the bibliography is intentionally minimized, include roles only when they materially affect identification."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_95.BIBLIOGRAPHY.CHAPTERS.IN_EDITED_COLLECTIONS","title":"Chapters in edited collections should cite both chapter and book details","source_refs":["CMOS18 §13.95 p828 (scan p850)"],"category":"citations","severity":"must","applies_to":"all","rule_text":"For a chapter or contribution within an edited collection, include chapter author/title plus the edited books details (editor, book title, publication facts) and a locator such as page range when available.","rationale":"Readers must be able to locate the chapter within the larger work.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["chapter","edited collection","page range"],"dependencies":[],"exceptions":["If the contribution is the entire work (e.g., a single-author monograph), treat it as a book entry instead."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_96.BIBLIOGRAPHY.JOURNAL_ARTICLES.VOLUME_ISSUE_PAGES","title":"Journal article entries should include volume/issue and pages when available","source_refs":["CMOS18 §13.96 p829 (scan p851)"],"category":"citations","severity":"must","applies_to":"all","rule_text":"For journal articles, include journal title, publication year, volume/issue (as applicable), and page range or article identifier; include a DOI when available.","rationale":"Periodical metadata is necessary to retrieve and verify specific articles.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["journal article","volume","DOI"],"dependencies":[],"exceptions":["If the journal uses article numbers instead of pagination, cite the article number and identifier."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_97.BIBLIOGRAPHY.NEWSPAPER_MAGAZINE.DATES","title":"News and magazine entries should include a specific date","source_refs":["CMOS18 §13.97 p829 (scan p851)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For newspapers, magazines, and similar periodicals, include the specific publication date (and edition information when needed) so the item can be located reliably.","rationale":"Many periodicals reset pagination and titles across issues; date is the primary locator.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["newspaper","magazine","date"],"dependencies":[],"exceptions":["If a stable URL or archive identifier is used instead of a print issue locator, include that identifier and ensure it is durable."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_98.BIBLIOGRAPHY.THESES_DISSERTATIONS.INSTITUTION","title":"Theses and dissertations should cite the granting institution and format","source_refs":["CMOS18 §13.98 p830 (scan p852)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For theses or dissertations, include author, title, degree type, granting institution, year, and a stable access path or repository identifier when available.","rationale":"Academic works can be hard to retrieve without institution and degree context.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["thesis","dissertation","institution"],"dependencies":[],"exceptions":["If the work is published later as a book or article, cite the published version when that is the one used."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_100.BIBLIOGRAPHY.ONLINE.SOURCE_STABILITY","title":"Online bibliography entries should emphasize stability (identifier, archive, or permalink)","source_refs":["CMOS18 §13.100 p831 (scan p853)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For online sources, prefer stable identifiers (DOI, repository ID) or a durable permalink/archive; include an access date when required by policy or when content is likely to change.","rationale":"Online citations rot quickly without stability cues.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","online_sources"],"keywords":["online sources","permalink","access date"],"dependencies":[],"exceptions":["If the source is a stable, versioned archive, an access date may be omitted if the version identifier is captured."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_101.BIBLIOGRAPHY.EBOOKS.EDITION_AND_FORMAT","title":"E-books should record edition/version and a stable access path when relevant","source_refs":["CMOS18 §13.101 p832 (scan p854)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When citing an e-book, capture edition/version details that affect content and include a stable access path or identifier when applicable; avoid retailer-specific ephemeral URLs for publication.","rationale":"E-book editions can differ materially from print, and retailer links often expire.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","online_sources"],"keywords":["e-book","edition","stability"],"dependencies":[],"exceptions":["If the e-book is accessed through a library platform with a stable record, cite the stable record rather than a session link."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_102.BIBLIOGRAPHY.AUDIOVISUAL.CREDITS","title":"Audio/visual sources should cite the credited creators and release context","source_refs":["CMOS18 §13.102 p833 (scan p855)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For audio/visual sources (film, video, audio), cite the credited creators needed to identify the work (creator/producer/director as relevant), the title, release year, and a stable platform/edition identifier when applicable.","rationale":"A/V works can share titles; creator and release context disambiguate.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography"],"keywords":["film","video","audio","credits"],"dependencies":[],"exceptions":["If citing a specific recording of a work, include the performer/label/recording date as applicable."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_103.BIBLIOGRAPHY.SOCIAL_MEDIA.ARCHIVE","title":"Social media citations should capture enough context to remain verifiable","source_refs":["CMOS18 §13.103 p835 (scan p857)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For social media or short-lived posts, capture author/account, platform, date/time, and a stable link or archived snapshot when feasible; avoid relying on feeds or search-result URLs.","rationale":"Ephemeral posts disappear or change; verification requires preserved context.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","online_sources"],"keywords":["social media","archive","snapshot"],"dependencies":[],"exceptions":["If archiving is not allowed, record the best available metadata and document the limitation."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_104.BIBLIOGRAPHY.PUBLIC_DOCUMENTS.IDENTIFIERS","title":"Public documents should include issuing body and document identifiers","source_refs":["CMOS18 §13.104 p835 (scan p857)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For public documents (standards, regulations, official reports), include the issuing body, document title, date, and any official identifier or number needed for retrieval.","rationale":"Official documents are often found via identifiers rather than titles alone.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","public_documents"],"keywords":["public documents","issuing body","identifier"],"dependencies":[],"exceptions":["If a governing citation standard applies (e.g., legal citation), follow it and treat Chicago pointers as contextual."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_105.BIBLIOGRAPHY.REPORTS.ISSUING_BODY_AND_VERSION","title":"Reports should cite the issuing organization and version context","source_refs":["CMOS18 §13.105 p835 (scan p857)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For reports (whitepapers, technical reports), cite the issuing organization, report title, publication date, and version/edition information when relevant; include a stable URL or identifier for access.","rationale":"Reports are frequently revised; version context prevents mismatches.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","online_sources"],"keywords":["reports","version","issuing body"],"dependencies":[],"exceptions":["If only a draft exists, label it clearly as a draft and record access details."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_106.BIBLIOGRAPHY.DATASETS.VERSION_AND_PROVENANCE","title":"Datasets should record version/provenance and a durable identifier","source_refs":["CMOS18 §13.106 p836 (scan p858)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When citing datasets, include creator/issuing body, dataset title, version or release date, and a durable identifier or repository record; include access date when required by policy.","rationale":"Dataset contents change over time; version and provenance are essential for reproducibility.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","online_sources"],"keywords":["dataset","version","repository"],"dependencies":[],"exceptions":["If the dataset is derived from a larger corpus, cite both the derived dataset and the upstream corpus as appropriate."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_108.BIBLIOGRAPHY.PLATFORMS.PERMALINKS_PREFERRED","title":"Prefer permalinks over transient platform URLs in bibliography entries","source_refs":["CMOS18 §13.108 p836 (scan p858)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a platform offers a permalink or canonical record for an item, prefer that over transient URLs (session links, search URLs) and keep the link format consistent across entries.","rationale":"Stable links reduce breakage during review and future verification.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","bibliography","online_sources"],"keywords":["permalink","canonical URL","stability"],"dependencies":[],"exceptions":["If only a transient URL exists, document the limitation and include an access date if policy requires it."],"status":"active"}

View file

@ -0,0 +1,11 @@
{"id":"CMOS.CITATIONS.S13_111.AUTHOR_DATE.REFERENCE_LIST.REQUIRED","title":"Author-date citations require a matching reference list","source_refs":["CMOS18 §13.111 p837 (scan p859)"],"category":"citations","severity":"must","applies_to":"all","rule_text":"When using author-date citations, provide a reference list (or equivalent) that includes full entries for all sources cited in the text.","rationale":"Without the reference list, author-date citations cannot be resolved for verification.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["author-date","reference list","resolution"],"dependencies":[],"exceptions":["Short formats may omit the list only if the deliverable explicitly allows it and the omission is documented."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.SAME_AUTHOR_SAME_YEAR.SUFFIXES","title":"Disambiguate same-author same-year works with letter suffixes","source_refs":["CMOS18 §13.114 p839 (scan p861)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When an author has multiple works in the same year, disambiguate using a consistent letter suffix (e.g., 2020a, 2020b) and keep the suffix consistent between in-text citations and the reference list.","rationale":"Year collisions are common in author-date and must be resolved deterministically.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["same year","suffix letters","disambiguation"],"dependencies":[],"exceptions":["If the corpus uses explicit short titles instead of letters for disambiguation, document and apply that policy consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.NO_AUTHOR.TITLE_KEY","title":"For author-date works without an author, use a stable title key consistently","source_refs":["CMOS18 §13.115 p839 (scan p861)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"If a work lacks an author, use a stable title-based key in the author position for author-date citations and ensure the same key leads the reference list entry.","rationale":"A consistent key is required to match citations to the reference list.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["no author","title key","reference list"],"dependencies":[],"exceptions":["If the work is best identified by an issuing body, treat the issuing body as the author consistently instead of a title key."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.NO_DATE.POLICY","title":"For undated works, apply a consistent no-date policy","source_refs":["CMOS18 §13.116 p840 (scan p862)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a source has no publication date, apply a consistent no-date policy (e.g., “n.d.” or an approximate date) and keep it consistent across in-text citations and the reference list.","rationale":"Inconsistent no-date handling breaks matching and sorting.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["no date","n.d.","policy"],"dependencies":[],"exceptions":["If the source has a clear revision or access date that stands in for publication date by policy, document the rule."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.IN_TEXT.MULTI_AUTHORS.POLICY","title":"Use a consistent policy for multi-author author-date citations","source_refs":["CMOS18 §13.121 p843 (scan p865)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For multi-author works in author-date citations, apply a consistent policy for how names are shown (full list versus abbreviated forms) and ensure the in-text form still resolves unambiguously to the reference list entry.","rationale":"Inconsistent author rendering increases ambiguity and review friction.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["multiple authors","et al.","author-date"],"dependencies":[],"exceptions":["If the publisher mandates a specific abbreviation threshold, follow that requirement."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.IN_TEXT.CORPORATE_AUTHORS.SHORT_FORM","title":"Corporate-author citations should use a stable short form when needed","source_refs":["CMOS18 §13.122 p843 (scan p865)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When citing corporate authors in text, use a stable short form only if it remains unambiguous, and ensure the reference list entry makes the full organizational name clear.","rationale":"Corporate names can be long; shortening without a stable mapping breaks retrieval.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["corporate author","short form","reference list"],"dependencies":[],"exceptions":["If a formal acronym is widely established for the organization, the acronym may be used if defined clearly in the work."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.REFERENCE_LIST.ENTRY_TEMPLATES.CONSISTENT","title":"Reference list entries should use consistent templates by source type","source_refs":["CMOS18 §13.123 p843 (scan p865)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Within the reference list, use consistent entry templates for each source type (books, articles, reports, online sources) and avoid mixing incompatible element orders for the same type.","rationale":"Template consistency makes missing or incorrect fields easier to spot.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["reference list","templates","consistency"],"dependencies":[],"exceptions":["If multiple governing standards are intentionally used, separate them into labeled subsections."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.IN_TEXT.MULTI_CITATIONS.ORDER_POLICY","title":"When multiple author-date citations appear together, use a consistent ordering policy","source_refs":["CMOS18 §13.125 p845 (scan p867)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When multiple author-date citations are grouped (e.g., in one parenthetical), apply a consistent ordering rule (alphabetical, chronological, or by relevance) and use consistent separators.","rationale":"Ordering consistency reduces ambiguity and aids scanning.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["multiple citations","ordering","parenthetical"],"dependencies":[],"exceptions":["If a style guide mandates chronological ordering in a specific discipline, follow that disciplines convention."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.REFERENCE_LIST.SORTING_STABLE","title":"Sort reference list entries consistently and keep sorting keys stable","source_refs":["CMOS18 §13.126 p845 (scan p867)"],"category":"citations","severity":"must","applies_to":"all","rule_text":"Sort the reference list consistently (typically by author key, then year, then title) and keep sorting keys stable so entries are predictable and easy to locate.","rationale":"Stable sorting is essential for verification workflows and reviewer speed.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["sorting","reference list","alphabetical"],"dependencies":[],"exceptions":["If a publisher requires a different sorting order, follow it and document the deviation from house defaults."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.REFERENCE_LIST.SAME_AUTHOR.ORDER_POLICY","title":"Order multiple reference list entries for the same author consistently","source_refs":["CMOS18 §13.127 p845 (scan p867)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When the reference list contains multiple works by the same author, order them consistently (e.g., by year, then title) and ensure any disambiguation scheme matches the in-text citations.","rationale":"Same-author ordering interacts with suffix letters and lookup behavior.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["same author","ordering","reference list"],"dependencies":[],"exceptions":["Chronological ordering may be preferred in some corpora; pick one policy and apply it consistently."],"status":"active"}
{"id":"CMOS.CITATIONS.AUTHOR_DATE.REFERENCE_LIST.REPEATED_NAMES.POLICY","title":"Apply a consistent policy for repeated author names in author-date reference lists","source_refs":["CMOS18 §13.128 p845 (scan p867)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"In author-date reference lists, apply a consistent policy for how repeated author names are shown (repeated in full versus substituted) and ensure the choice does not reduce clarity or sortability.","rationale":"Repeated-name conventions can confuse readers if applied inconsistently or inappropriately for author-date.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["repeated names","policy","author-date"],"dependencies":[],"exceptions":["If the publisher forbids name substitution in author-date reference lists, keep full names on every entry."],"status":"active"}

View file

@ -0,0 +1,6 @@
{"id":"CMOS.CITATIONS.S13_90.TITLE_PUNCTUATION.CHANGES.POLICY_LIMITED","title":"Limit and document punctuation changes in cited titles","source_refs":["CMOS18 §13.90 p827 (scan p849)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"In citations, preserve the titles original punctuation and wording as given in the source. If a punctuation change is necessary for house style or consistency, apply a single documented policy and keep it consistent across the work.","rationale":"Undocumented title edits create ambiguity and make sources harder to verify.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true"],"keywords":["title","punctuation","normalization","policy"],"dependencies":[],"exceptions":["Minor normalization is acceptable only if it does not change meaning and is applied consistently; when in doubt, keep the original and note the exception."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_91.TITLE_SUBTITLE.SEPARATOR.COLON","title":"Use a colon to separate titles and subtitles in citations","source_refs":["CMOS18 §13.91 p827 (scan p849)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a work has a title and subtitle, separate them with a colon in the citation, even if the source distinguishes them by typography or line breaks instead of punctuation.","rationale":"A consistent separator makes citations easier to parse and compare.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true"],"keywords":["title","subtitle","colon"],"dependencies":[],"exceptions":["If the sources title page uses a different separator that is essential to the titles meaning, preserve the original punctuation and document the choice."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_94.TITLES.TRAILING_PHRASE.PLACEMENT","title":"Treat generic trailing phrases as part of the subtitle in citations","source_refs":["CMOS18 §13.94 p828 (scan p850)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"When a book title ends with a generic trailing phrase (for example, a phrase indicating additional works of the same kind), format the main title as the title proper and treat the trailing phrase as part of the subtitle in the citation, using standard subtitle punctuation.","rationale":"Consistent title/subtitle structure improves readability and avoids accidental title edits.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true"],"keywords":["title","subtitle","trailing phrase"],"dependencies":[],"exceptions":["If the title pages punctuation is distinctive and must be preserved verbatim, follow the source and document the exception policy."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_99.LONG_TITLES.TRUNCATION.AVOID","title":"Avoid truncating long titles in citations; if truncated, do it transparently","source_refs":["CMOS18 §13.99 p831 (scan p853)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"Do not truncate long titles in citations unless a constrained format requires it. If truncation is unavoidable, ensure the shortened form is clearly indicated (for example with an ellipsis) and does not imply the omitted words were absent in the original.","rationale":"Title truncation can change meaning and complicate source matching.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true"],"keywords":["titles","ellipsis","truncation"],"dependencies":[],"exceptions":["If an external style guide mandates a specific truncation scheme, apply it consistently and document it in the deliverables citation policy."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_107.AUTHOR_DATE.REFERENCE_LIST.MULTI_AUTHOR.ORDERING","title":"Keep author ordering consistent for multi-author works in author-date reference lists","source_refs":["CMOS18 §13.107 p836 (scan p858)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For multi-author works in an author-date reference list, preserve the author order from the source and apply a consistent name-ordering scheme (e.g., invert only the first author for sorting) across all entries.","rationale":"Consistent ordering prevents mismatches between in-text citations and reference list entries.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["author-date","reference list","multiple authors"],"dependencies":[],"exceptions":["If a house style limits the displayed author list (e.g., uses et al.), apply the same limit consistently and ensure entries remain uniquely identifiable."],"status":"active"}
{"id":"CMOS.CITATIONS.S13_110.AUTHOR_DATE.JOURNAL_ARTICLES.CORE_FIELDS","title":"Include journal identifiers consistently in author-date reference list entries","source_refs":["CMOS18 §13.110 p837 (scan p859)"],"category":"citations","severity":"should","applies_to":"all","rule_text":"For journal articles in an author-date reference list, include enough journal identifiers to locate the work reliably (year plus journal title, and the journals volume/issue and page or article identifiers as applicable).","rationale":"Journal articles often require multiple identifiers for unambiguous retrieval.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","author_date"],"keywords":["journal articles","volume","issue","page"],"dependencies":[],"exceptions":["If a journal uses article numbers instead of page ranges, use the journals scheme consistently and do not invent pages."],"status":"active"}

View file

@ -0,0 +1,24 @@
{"id":"HOUSE.CODE.BLOCKS.LONG_LINES.AVOID","title":"Avoid very long code lines in published docs","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"md","rule_text":"Avoid very long code lines that will wrap awkwardly or overflow in PDF; prefer formatting or line breaks that preserve meaning.","rationale":"Overflowing code harms readability and can break layout.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn when code lines exceed a conservative length threshold; suggest wrapping or restructuring.","tags":["code","overflow"],"keywords":["code line length","overflow"],"dependencies":[],"exceptions":["Some identifiers/URLs in code may be inherently long; consider formatting guidance rather than strict wrapping."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.TABS.AVOID","title":"Avoid tabs in code blocks for publication","source_refs":["HOUSE §CODE.BLOCKS p1","HOUSE §CODE.TYPOGRAPHY p2"],"category":"code","severity":"should","applies_to":"md","rule_text":"Avoid tab characters in code blocks for publication; prefer spaces to ensure consistent rendering across environments.","rationale":"Tabs render inconsistently and can break alignment.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn when a code block contains tab characters; suggest converting to spaces if safe.","tags":["code","whitespace"],"keywords":["tabs","indentation"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.USE_FOR_MULTILINE","title":"Use code blocks for multi-line examples","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use fenced code blocks for multi-line code examples and preserve exact whitespace.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["code blocks","fences"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.CAPTIONS.EXPLAIN_SNIPPET","title":"Explain what a snippet demonstrates","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Introduce code blocks with a sentence that explains what the snippet demonstrates.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["examples","explanation"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.COMMENTS.MINIMIZE_NOISE","title":"Avoid noisy commentary inside code","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid excessive commentary inside code blocks; keep explanations in prose around the code.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["comments","readability"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.DIFFS.UNIFIED_FORMAT","title":"Use unified diffs for patches","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When including diffs, prefer unified diff format and ensure it is syntactically valid.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["diff","unified"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.ERRORS.SHOW_FAILURES","title":"Show failure modes when helpful","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When documenting commands, include failure modes or common errors when it improves operational safety.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["errors","docs"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.FENCES.CLOSE_PROPERLY","title":"Close code fences properly","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Ensure fenced code blocks are properly closed; avoid accidental fence nesting.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["fences","markdown"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.FENCES.LANGUAGE_INFO.SUGGEST","title":"Specify a language for fenced code blocks when useful","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"md","rule_text":"When using fenced code blocks, specify a language identifier when it improves readability and tooling (syntax highlight, copy/paste cues).","rationale":"Language tags improve comprehension and reduce ambiguity.","enforcement":"lint","autofix":"suggest","autofix_notes":"Warn on fenced code blocks with no info string; suggest adding a language when known.","tags":["code","fences"],"keywords":["code fences","language"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.INLINE.USE_FOR_IDENTIFIERS","title":"Use inline code for identifiers","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use inline code formatting for identifiers, filenames, commands, and small code tokens.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["inline code","identifiers"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.LANGUAGE.CONSISTENT_FENCES","title":"Use consistent fence style","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use a consistent fence style (``` vs ~~~) across the document.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["code fences","consistency"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.LANGUAGE.NOTATION.CONSISTENT","title":"Keep notation consistent","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Keep code notation consistent (quotes, indentation, naming) within a document.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["notation","consistency"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.LINE_ENDINGS.NORMALIZE","title":"Normalize line endings in code","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid mixing CRLF/LF line endings in code examples; normalize for readability.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["line endings","consistency"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.MONO.FONT.PREFERRED","title":"Render code in monospaced fonts","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Render inline and block code in monospaced fonts for legibility.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["monospace","fonts"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.OUTPUT.DISTINGUISH_FROM_INPUT","title":"Distinguish input vs output","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When showing command-line sessions, clearly distinguish input commands from output.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["cli","examples"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.OUTPUT.TRUNCATION.LABELED","title":"Label truncated output","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When output is truncated for brevity, label the truncation so readers know it is incomplete.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["truncation","output"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.PLACEHOLDERS.CLEAR","title":"Use clear placeholders","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use clear placeholders (e.g., <TOKEN>) rather than realistic-looking secrets in examples.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["placeholders","security"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.REFERENCES.VERSION_PIN","title":"Pin versions in install commands","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When providing installation commands, pin versions when reproducibility matters.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["versions","reproducibility"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.SECURITY.REDACT_SECRETS","title":"Redact secrets from code examples","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not publish secrets (tokens, keys, credentials) in code examples; use placeholders.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["secrets","redaction"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.SHELL.PROMPTS.CONSISTENT","title":"Use consistent prompt conventions","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"If shell prompts are included, use a consistent prompt convention and avoid copying destructive commands without context.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["shell","prompts"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.TABLES.AVOID_FOR_CODE","title":"Avoid tables for code","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid using tables to display code; code blocks preserve formatting better.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["tables","code"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.TYPED_VALUES.DISTINGUISH","title":"Distinguish user input from placeholders","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"In examples, distinguish typed values from placeholders so readers do not paste placeholders verbatim.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["placeholders","docs"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.URLS.IN_CODE.AVOID_WRAPPING","title":"Avoid wrapping URLs in code blocks","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid manual line breaks inside URLs shown in code blocks; prefer a single line or a shortened, labeled form.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["urls","code"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.CODE.WRAPPING.NO_SOFT_HYPHENS","title":"Do not insert soft hyphens into code","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not insert soft hyphens or discretionary breaks into code; keep code literal.","rationale":"Code examples must be readable and reproducible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["soft hyphen","code"],"dependencies":[],"exceptions":[],"status":"active"}

View file

@ -0,0 +1,20 @@
{"id":"HOUSE.CODE.BLOCKS.SPLIT_BY_LANGUAGE","title":"Do not mix languages in a single code block","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"If multiple languages or formats appear in an example, split them into separate code blocks with clear labels.","rationale":"Mixed-language blocks reduce readability and tooling support.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["code blocks","language","separation"],"dependencies":[],"exceptions":["Small inline fragments may remain together if the distinction is obvious."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.ELISION.MARKED","title":"Mark omitted lines in code examples","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When lines are omitted from a code example, mark the omission explicitly (for example, with a comment or ellipsis marker).","rationale":"Unmarked gaps make examples ambiguous and hard to reproduce.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["elision","examples","omissions"],"dependencies":[],"exceptions":["Very short snippets that are complete as shown do not need elision markers."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.NO_PERSONAL_PATHS","title":"Avoid personal paths and usernames in code","source_refs":["HOUSE §CODE.SECURITY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid personal paths, usernames, or machine-specific values in examples; use neutral placeholders instead.","rationale":"Personalized paths reduce portability and may leak information.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","security"],"keywords":["paths","usernames","placeholders"],"dependencies":[],"exceptions":["If a real path is required for clarity, label it as an example path."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.PLATFORM.NOTED","title":"Note platform or shell when commands are platform-specific","source_refs":["HOUSE §CODE.SHELL p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"If a command or snippet is platform-specific, state the OS or shell explicitly near the example.","rationale":"Platform clarity prevents misuse and reduces support issues.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","shell"],"keywords":["platform","shell","commands"],"dependencies":[],"exceptions":["When a document is explicitly scoped to one platform, a single global note may suffice."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.PRECONDITIONS.STATED","title":"State prerequisites for runnable code","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When code requires prerequisites (versions, tools, environment variables), state them before the snippet or in a short setup section.","rationale":"Unstated prerequisites cause reproducibility failures.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["prerequisites","versions","environment"],"dependencies":[],"exceptions":["Trivial examples may omit prerequisites if the context makes them obvious."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.TESTED_OR_MARKED","title":"Mark untested code as pseudo-code","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"If a snippet has not been tested or is illustrative only, label it explicitly as pseudo-code or illustrative.","rationale":"Readers need to know whether code is copy-pasteable.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["pseudo-code","tested","examples"],"dependencies":[],"exceptions":["If a document is clearly a conceptual overview, a single global note may suffice."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.DETERMINISTIC_OUTPUT","title":"Prefer deterministic outputs in examples","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Example outputs should be deterministic; avoid nondeterministic ordering, random values, or timestamps unless they are labeled as sample output.","rationale":"Deterministic examples are easier to verify and trust.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["deterministic","output","examples"],"dependencies":[],"exceptions":["If nondeterminism is the subject, explain the variability and show a representative sample."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.CONFIG.VALID","title":"Configuration examples must be syntactically valid","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Configuration snippets (JSON, YAML, TOML, etc.) should be syntactically valid as shown.","rationale":"Invalid config examples cause immediate runtime errors.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","config"],"keywords":["config","json","yaml"],"dependencies":[],"exceptions":["If a snippet is partial by design, label it as a fragment."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.NO_LINE_NUMBERS","title":"Avoid inline line numbers inside code blocks","source_refs":["HOUSE §CODE.TYPOGRAPHY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid embedding manual line numbers inside code blocks unless they are required for discussion or diff context.","rationale":"Inline numbers reduce copy-paste quality and add noise.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","typography"],"keywords":["line numbers","code blocks"],"dependencies":[],"exceptions":["If a line-by-line walkthrough is required, keep numbering consistent and clearly separated."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.NO_SMART_QUOTES","title":"Avoid smart quotes and typographic substitutions in code","source_refs":["HOUSE §CODE.TYPOGRAPHY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not use smart quotes, em dashes, or other typographic substitutions inside code examples; keep code literal.","rationale":"Typographic substitutions can break code when copied.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","typography"],"keywords":["smart quotes","typography","copy paste"],"dependencies":[],"exceptions":["Explanatory prose outside code blocks may use typographic punctuation."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.INDENTATION.CONSISTENT","title":"Use consistent indentation within a code block","source_refs":["HOUSE §CODE.TYPOGRAPHY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use a consistent indentation width and style within each code block; avoid mixed indentation levels that obscure structure.","rationale":"Consistent indentation improves readability and prevents misinterpretation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","whitespace"],"keywords":["indentation","whitespace","style"],"dependencies":[],"exceptions":["Some formats (e.g., Makefiles) require specific indentation rules; note them if used."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.TRAILING_WHITESPACE.AVOID","title":"Avoid trailing whitespace in code blocks","source_refs":["HOUSE §CODE.TYPOGRAPHY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Avoid trailing spaces in code blocks; trailing whitespace can be significant in some formats and looks unedited.","rationale":"Trailing whitespace can change meaning or cause diffs.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","whitespace"],"keywords":["trailing whitespace","code"],"dependencies":[],"exceptions":["If trailing whitespace is meaningful, annotate it explicitly."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.COMMANDS.PROMPT_FREE_COPY","title":"Provide prompt-free command lines when prompts are shown","source_refs":["HOUSE §CODE.SHELL p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"If shell prompts are included in examples, provide a prompt-free version or clearly indicate which parts are user input.","rationale":"Prompt-free commands are easier to copy and less error-prone.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","shell"],"keywords":["shell prompts","copy paste"],"dependencies":[],"exceptions":["If the prompt conveys necessary context (e.g., root vs user), label it clearly."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.ERROR_OUTPUT.LABELED","title":"Label error output distinctly","source_refs":["HOUSE §CODE.SHELL p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"When showing error output, label it clearly as error or stderr so readers can distinguish it from normal output.","rationale":"Clear labeling reduces confusion and misdiagnosis.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","shell"],"keywords":["stderr","errors","output"],"dependencies":[],"exceptions":["Short examples may prefix error lines with a clear marker instead of a label."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.LINE_BREAKS.SEMANTIC_SAFE","title":"Avoid line breaks that change code meaning","source_refs":["HOUSE §CODE.BLOCKS p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not insert manual line breaks inside a token or statement when it changes semantics; use line continuation syntax if needed.","rationale":"Meaning-changing line breaks produce broken examples.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["line breaks","semantics","continuation"],"dependencies":[],"exceptions":["If a line break is required by formatting, add an explicit continuation marker for the language."],"status":"active"}
{"id":"HOUSE.CODE.BLOCKS.DATA.SYNTHETIC_FOR_SENSITIVE","title":"Use synthetic data for sensitive examples","source_refs":["HOUSE §CODE.SECURITY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use synthetic or anonymized data in code examples when real data could expose sensitive information.","rationale":"Protects privacy and reduces security risk.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","security"],"keywords":["synthetic data","privacy"],"dependencies":[],"exceptions":["If real data must be shown for auditability, document the approval and scrub identifiers."],"status":"active"}
{"id":"HOUSE.CODE.DIFFS.FILE_HEADERS.PRESENT","title":"Include file headers in unified diffs","source_refs":["HOUSE §CODE.DIFFS p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Unified diffs should include file headers (---/+++ lines) so context is explicit.","rationale":"File headers make patches unambiguous.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","diff"],"keywords":["diffs","file headers"],"dependencies":[],"exceptions":["Inline diffs used only to highlight a single line may omit headers if the file is named nearby."],"status":"active"}
{"id":"HOUSE.CODE.DIFFS.CONTEXT_LINES.PRESENT","title":"Provide context lines in diffs","source_refs":["HOUSE §CODE.DIFFS p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Include sufficient context lines in diffs to understand where changes apply.","rationale":"Context reduces patch ambiguity and misapplication.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","diff"],"keywords":["diffs","context"],"dependencies":[],"exceptions":["Very small patches may use minimal context if the file/section is clearly identified."],"status":"active"}
{"id":"HOUSE.CODE.SHELL.DESTRUCTIVE.WARN","title":"Warn before destructive commands","source_refs":["HOUSE §CODE.SHELL p2"],"category":"code","severity":"must","applies_to":"all","rule_text":"If a command is destructive or irreversible, warn explicitly and provide safer alternatives or confirmation steps.","rationale":"Destructive commands can cause data loss if copied blindly.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","shell"],"keywords":["destructive commands","warnings","safety"],"dependencies":[],"exceptions":["If the entire document is a controlled runbook, ensure warnings are still explicit."],"status":"active"}
{"id":"HOUSE.CODE.TYPOGRAPHY.UNICODE.MINIMIZE","title":"Use non-ASCII characters in code only when required","source_refs":["HOUSE §CODE.TYPOGRAPHY p2"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use non-ASCII characters in code examples only when required by the domain; otherwise prefer ASCII-safe representations.","rationale":"ASCII-safe code is more portable across tools and fonts.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","typography"],"keywords":["unicode","ascii","portability"],"dependencies":[],"exceptions":["If a system requires Unicode identifiers, call that requirement out explicitly."],"status":"active"}

View file

@ -0,0 +1,4 @@
{"id":"HOUSE.CODE.EXAMPLES.FILE_PATH.LABEL","title":"Label snippets with filenames or paths","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When a snippet belongs to a specific file, label it with the filename or path so readers know where it applies.","rationale":"File context improves reproducibility.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["filename","path","context"],"dependencies":[],"exceptions":["Single-file documents may omit labels if the context is unambiguous."],"status":"active"}
{"id":"HOUSE.CODE.EXAMPLES.MULTI_FILE.SEPARATE","title":"Separate multi-file examples into distinct blocks","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"For multi-file examples, use separate code blocks for each file and label them clearly.","rationale":"Separation reduces confusion and copy errors.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["multi-file","code blocks"],"dependencies":[],"exceptions":["Very small multi-file snippets may be combined if clearly annotated."],"status":"active"}
{"id":"HOUSE.CODE.EXAMPLES.ENV_VARS.DOCUMENT","title":"Document required environment variables","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"Document required environment variables and expected defaults near the example that depends on them.","rationale":"Hidden environment dependencies break reproducibility.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["environment variables","defaults"],"dependencies":[],"exceptions":["If environment variables are defined in a shared setup section, reference it explicitly."],"status":"active"}
{"id":"HOUSE.CODE.EXAMPLES.ORDERED_STEPS","title":"Present multi-step sequences in order","source_refs":["HOUSE §CODE.EXAMPLES p1"],"category":"code","severity":"should","applies_to":"all","rule_text":"When a command sequence must be executed in order, label steps or separate them clearly to preserve the sequence.","rationale":"Ordered steps prevent misuse.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code"],"keywords":["steps","sequence"],"dependencies":[],"exceptions":["Single-step commands do not require step labels."],"status":"active"}

View file

@ -0,0 +1,6 @@
{"id":"BRING.CODE.MONO_RAGGED_RIGHT","title":"Set monospaced code ragged-right","source_refs":["BRING §2.1.3 p27"],"category":"code","severity":"should","applies_to":"all","rule_text":"Set monospaced or typewriter-style code ragged-right rather than fully justified.","rationale":"Monospaced text looks uneven when forced into full justification.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","ragged_right"],"keywords":["monospaced","ragged right","code blocks"],"dependencies":[],"exceptions":["If a code listing must be justified for a specific style guide, document the exception."],"status":"active"}
{"id":"BRING.CODE.RAG.NO_MIN_LINE","title":"Avoid minimum line-length constraints in ragged code","source_refs":["BRING §2.1.3 p27"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not enforce a minimum line length when setting ragged code; allow natural variation in line endings.","rationale":"Forced minimums create artificial ripples in the rag.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","ragged_right"],"keywords":["rag","line length","code"],"dependencies":[],"exceptions":["Extremely narrow measures may require a minimum to prevent excessive short lines."],"status":"active"}
{"id":"BRING.CODE.RAG.NO_AUTO_HYPHENATION","title":"Disable automatic hyphenation in code blocks","source_refs":["BRING §2.1.3 p27"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not allow automatic hyphenation in code blocks; break only at explicit hyphens or by manual intervention.","rationale":"Hyphenation changes literal code and confuses copy/paste.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","hyphenation"],"keywords":["code","hyphenation","ragged"],"dependencies":[],"exceptions":["If a code font lacks required glyphs, replace the font rather than hyphenating."],"status":"active"}
{"id":"BRING.CODE.RAG.FIXED_WORD_SPACES","title":"Use fixed word spaces in ragged code","source_refs":["BRING §2.1.3 p27"],"category":"code","severity":"should","applies_to":"all","rule_text":"Use fixed word spaces for monospaced code and avoid stretching or shrinking spaces to refine the rag.","rationale":"Variable spacing breaks code alignment and readability.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","spacing"],"keywords":["fixed spaces","code alignment"],"dependencies":[],"exceptions":["If a renderer forces proportional spaces, switch to a true monospaced font."],"status":"active"}
{"id":"BRING.CODE.RAG.NO_LETTERSPACING","title":"Avoid letterspacing in code blocks","source_refs":["BRING §2.1.3 p27"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not apply letterspacing or tracking adjustments to monospaced code blocks.","rationale":"Letterspacing disrupts code alignment and scanning.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","tracking"],"keywords":["letterspacing","tracking","code"],"dependencies":[],"exceptions":["If a font renders too tightly, use a different mono font rather than tracking."],"status":"active"}
{"id":"BRING.CODE.RAG.AVOID_FAKE_JUSTIFY","title":"Avoid typewriter-style justification","source_refs":["BRING §2.1.3 p27"],"category":"code","severity":"should","applies_to":"all","rule_text":"Do not justify monospaced code to imitate typeset text; keep it true to typewriter-style spacing.","rationale":"Justified mono code looks forced and reduces legibility.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","code","justification"],"keywords":["justification","monospaced","code"],"dependencies":[],"exceptions":["None."],"status":"active"}

View file

@ -0,0 +1,53 @@
{"id":"HOUSE.EDITORIAL.PLACEHOLDERS.NO_TODO_FIXME","title":"Remove TODO/FIXME markers before publishing","source_refs":["HOUSE §EDITORIAL.PLACEHOLDERS p1"],"category":"editorial","severity":"must","applies_to":"md","rule_text":"Do not ship documents with TODO or FIXME markers in prose; resolve or remove them before publication.","rationale":"Draft markers signal incomplete work.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","placeholders"],"keywords":["TODO","FIXME","draft"],"dependencies":[],"exceptions":["Allowed inside fenced code examples when the marker is part of the example."],"status":"active"}
{"id":"HOUSE.EDITORIAL.PLACEHOLDERS.NO_TBD_TKTK","title":"Remove TBD/TKTK placeholders before publishing","source_refs":["HOUSE §EDITORIAL.PLACEHOLDERS p1"],"category":"editorial","severity":"must","applies_to":"md","rule_text":"Do not ship documents with TBD or TKTK placeholders; replace with concrete content or remove.","rationale":"Placeholders undermine credibility.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","placeholders"],"keywords":["TBD","TKTK","placeholder"],"dependencies":[],"exceptions":["Allowed inside fenced code examples when the marker is part of the example."],"status":"active"}
{"id":"HOUSE.EDITORIAL.PLACEHOLDERS.NO_LOREM_IPSUM","title":"Avoid lorem ipsum placeholder text","source_refs":["HOUSE §EDITORIAL.PLACEHOLDERS p1"],"category":"editorial","severity":"should","applies_to":"md","rule_text":"Avoid lorem ipsum (or similar filler text) in documents intended for review or publication.","rationale":"Filler text hides missing content.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","placeholders"],"keywords":["lorem ipsum","filler","placeholder"],"dependencies":[],"exceptions":["If discussing placeholder text explicitly, label the section clearly."],"status":"active"}
{"id":"HOUSE.EDITORIAL.PLACEHOLDERS.NO_REVIEW_NOTES_INLINE","title":"Do not leave reviewer notes inline in the final output","source_refs":["HOUSE §EDITORIAL.PLACEHOLDERS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Remove inline reviewer notes (e.g., questions to self, review-only callouts) from the published output; move decisions into the text or a change log.","rationale":"Inline notes confuse readers and leak process.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","placeholders"],"keywords":["review notes","comments","draft"],"dependencies":[],"exceptions":["Internal drafts may keep reviewer notes; do not publish them externally."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.H1_TITLE.PRESENT","title":"Include a single H1 title","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"md","rule_text":"Include an H1 title for the document so exports have a clear, stable title.","rationale":"A title improves navigation and traceability.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","structure"],"keywords":["title","H1","heading"],"dependencies":[],"exceptions":["Very short memos may use a first-line title format if agreed by the profile."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.H1_TITLE.SINGLE","title":"Avoid multiple H1 titles","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"md","rule_text":"Use only one H1 title per document; use H2+ for sections.","rationale":"Multiple top-level titles confuse structure.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","structure"],"keywords":["multiple H1","title","structure"],"dependencies":[],"exceptions":["Collections may use a wrapper page; keep the exported unit to one title."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.H1_TITLE.EARLY","title":"Place the title near the top","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"md","rule_text":"Place the H1 title at the start of the document or immediately after a brief metadata block.","rationale":"Early titles improve scanability.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","structure"],"keywords":["title placement","frontmatter","H1"],"dependencies":[],"exceptions":["Cover pages may precede the title when the profile supports it."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.SUMMARY.EARLY","title":"Provide an early summary for long documents","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"For long or decision-bearing documents, include a short summary near the start (what, why, decisions, next steps).","rationale":"Summaries reduce review time.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["summary","executive summary","decisions"],"dependencies":[],"exceptions":["Short notes may skip a summary if the first section is already concise."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.SCOPE.STATED","title":"State scope and non-goals","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"State the scope and (when helpful) explicit non-goals so readers know what is included and excluded.","rationale":"Clear scope prevents misinterpretation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["scope","non-goals","assumptions"],"dependencies":[],"exceptions":["Some narrative documents may embed scope implicitly; ensure it is still clear."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.AUDIENCE.STATED","title":"Make the intended audience explicit","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Make the intended audience explicit (operators, reviewers, executives, developers) and write to that audiences constraints.","rationale":"Audience clarity improves tone and depth.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["audience","tone","assumptions"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.DECISIONS.EXPLICIT","title":"Write decisions explicitly","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When a document contains decisions, write them explicitly (what was decided, by whom, when, and why) rather than implying them.","rationale":"Explicit decisions reduce operational ambiguity.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["decisions","accountability","rationale"],"dependencies":[],"exceptions":["Exploratory notes may mark decisions as pending."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.ACTION_ITEMS.EXPLICIT","title":"List action items with owners and dates","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When assigning work, list action items with an owner and a target date (or an explicit no date rationale).","rationale":"Action items without owners/dates are often dropped.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["action items","owners","deadlines"],"dependencies":[],"exceptions":["If no owner exists yet, label it explicitly as unassigned."],"status":"active"}
{"id":"HOUSE.EDITORIAL.HEADINGS.NO_TRAILING_PUNCTUATION","title":"Avoid trailing punctuation in headings","source_refs":["HOUSE §EDITORIAL.HEADINGS p1"],"category":"editorial","severity":"should","applies_to":"md","rule_text":"Avoid ending headings with punctuation (especially periods and colons) unless the heading is intentionally a question.","rationale":"Trailing punctuation adds visual noise.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","headings"],"keywords":["headings","punctuation","titles"],"dependencies":[],"exceptions":["Headings that are questions may end with a question mark."],"status":"active"}
{"id":"HOUSE.EDITORIAL.HEADINGS.AVOID_ALL_CAPS","title":"Avoid ALL CAPS headings in prose documents","source_refs":["HOUSE §EDITORIAL.HEADINGS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid ALL CAPS headings in prose documents; use normal capitalization for readability.","rationale":"All caps reduces readability.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","headings"],"keywords":["all caps","headings","readability"],"dependencies":[],"exceptions":["Short labels in UI-like docs may use caps when consistent with the domain."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.AVOID_SINGLE_ITEM","title":"Avoid single-item lists","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"warn","applies_to":"md","rule_text":"Avoid single-item lists; convert to a sentence or add the missing parallel items.","rationale":"Single-item lists often signal incomplete structure.","enforcement":"lint","autofix":"none","autofix_notes":"","tags":["editorial","lists"],"keywords":["single-item list","lists","structure"],"dependencies":[],"exceptions":["A single bullet can be acceptable for emphasis when intentional."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.PARALLEL_STRUCTURE","title":"Use parallel structure in list items","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Write list items in parallel grammatical form (e.g., all verb phrases or all noun phrases).","rationale":"Parallelism improves scanability.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","lists"],"keywords":["parallel structure","lists","scanability"],"dependencies":[],"exceptions":["If parallelism is impossible, split the list into smaller lists by type."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.ORDERED_ONLY_WHEN_ORDERED","title":"Use ordered lists only when order matters","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Use ordered lists only when sequence is meaningful (steps, priority); otherwise use unordered lists.","rationale":"Correct list types improve comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","lists"],"keywords":["ordered lists","steps","priority"],"dependencies":[],"exceptions":["Numbered lists may be required by standards; follow the governing standard."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.PUNCTUATION.CONSISTENT","title":"Keep list punctuation consistent","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Within a list, keep punctuation consistent (either all fragments without periods or all full sentences with periods).","rationale":"Consistency reduces editorial noise.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","lists"],"keywords":["list punctuation","periods","consistency"],"dependencies":[],"exceptions":["Lists mixing fragments and sentences should usually be rewritten."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.AVOID_DEEP_NESTING","title":"Avoid overly deep list nesting","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid deep list nesting; if nesting goes beyond two levels, consider restructuring into sections or tables.","rationale":"Deep nesting is hard to follow in PDF.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","lists"],"keywords":["nested lists","structure","readability"],"dependencies":[],"exceptions":["Legal or standards text may require deep nesting; keep indentation consistent."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.ONE_IDEA_PER_PARAGRAPH","title":"Keep paragraphs focused on one idea","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Keep paragraphs focused on a single idea; split long paragraphs when they mix multiple topics.","rationale":"Focused paragraphs improve comprehension.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["paragraphs","focus","structure"],"dependencies":[],"exceptions":["Narrative writing may use long paragraphs intentionally; ensure clarity."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.AVOID_AMBIGUOUS_PRONOUNS","title":"Avoid ambiguous pronouns","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid ambiguous pronouns (it, this, that, they) when the referent could be unclear; repeat the noun or rewrite.","rationale":"Ambiguity causes misreading.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["pronouns","ambiguity","clarity"],"dependencies":[],"exceptions":["Short sentences with an obvious referent may be fine."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.DEFINE_JARGON_ON_FIRST_USE","title":"Define jargon and uncommon terms on first use","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Define jargon and uncommon terms on first use, or link to a glossary/definition section.","rationale":"Definitions lower the cost of entry for readers.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["jargon","definitions","glossary"],"dependencies":[],"exceptions":["Widely-known terms for the declared audience may not need definition."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.AVOID_METACOMMENTARY","title":"Avoid metacommentary like 'as mentioned above'","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid metacommentary (e.g., 'as mentioned above'); use explicit references (section titles, links) or rewrite to be self-contained.","rationale":"Metacommentary breaks when documents are rearranged.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["metacommentary","above/below","self-contained"],"dependencies":[],"exceptions":["If unavoidable, use stable anchors or section identifiers."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.EDIT_FOR_BREVITY","title":"Edit for brevity without losing meaning","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Prefer concise phrasing; remove redundant sentences and filler words while preserving meaning and necessary nuance.","rationale":"Brevity improves review speed.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["brevity","redundancy","editing"],"dependencies":[],"exceptions":["Legal and compliance text may require explicit repetition; follow requirements."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.AVOID_WEASEL_WORDS","title":"Avoid weasel words and ungrounded certainty","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid weasel words (e.g., 'clearly', 'obviously') and ungrounded certainty; provide evidence, quantify, or soften appropriately.","rationale":"Unsupported claims reduce trust.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["weasel words","certainty","evidence"],"dependencies":[],"exceptions":["When stating a proven fact, cite the proof or standard."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.AVOID_DOUBLE_NEGATIVES","title":"Avoid double negatives in instructions","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid double negatives in instructions and requirements; rewrite to a direct positive requirement when possible.","rationale":"Double negatives cause errors.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["double negatives","requirements","instructions"],"dependencies":[],"exceptions":["Quoted requirements may keep original wording; consider annotating with a clearer paraphrase."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.EXAMPLES_WHEN_COMPLEX","title":"Use examples for complex procedures","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When procedures are complex or error-prone, include a small example (input/output, command, or sample data) to reduce ambiguity.","rationale":"Examples reduce misinterpretation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["examples","procedures","clarity"],"dependencies":[],"exceptions":["If examples risk leaking secrets, use synthetic placeholders."],"status":"active"}
{"id":"HOUSE.EDITORIAL.TONE.PROFESSIONAL_AND_RESPECTFUL","title":"Keep tone professional and respectful","source_refs":["HOUSE §EDITORIAL.TONE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Keep tone professional and respectful; avoid insults, sarcasm, or adversarial phrasing in publishable documents.","rationale":"Tone affects trust and adoption.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","tone"],"keywords":["tone","professional","respect"],"dependencies":[],"exceptions":["Direct incident reports may use firm language; keep it factual."],"status":"active"}
{"id":"HOUSE.EDITORIAL.TONE.INCLUSIVE_LANGUAGE","title":"Use inclusive language","source_refs":["HOUSE §EDITORIAL.TONE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Use inclusive language where feasible; avoid unnecessary gendering and avoid terms widely recognized as derogatory.","rationale":"Inclusive writing broadens accessibility.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","tone"],"keywords":["inclusive language","accessibility","audience"],"dependencies":[],"exceptions":["Quoted historical material may retain original wording; annotate if needed."],"status":"active"}
{"id":"HOUSE.EDITORIAL.TONE.AVOID_EXCESSIVE_EMPHASIS","title":"Avoid excessive emphasis styling","source_refs":["HOUSE §EDITORIAL.TONE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid excessive emphasis (all caps, repeated exclamation points, excessive bolding); rely on structure and evidence instead.","rationale":"Over-emphasis reads as unprofessional.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","tone"],"keywords":["emphasis","all caps","exclamation"],"dependencies":[],"exceptions":["Short warnings may use strong emphasis when safety-critical."],"status":"active"}
{"id":"HOUSE.EDITORIAL.TONE.CALIBRATE_CERTAINTY","title":"Calibrate certainty to evidence","source_refs":["HOUSE §EDITORIAL.TONE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Calibrate certainty to evidence: use must/will only for guarantees, and use may/typically when describing tendencies.","rationale":"Precision prevents overpromising.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","tone"],"keywords":["certainty","guarantees","precision"],"dependencies":[],"exceptions":["Normative specifications may use MUST/SHALL as defined by the standard."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLAIMS.SUPPORT_WITH_SOURCES","title":"Support factual claims with sources or evidence","source_refs":["HOUSE §EDITORIAL.CLAIMS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Support factual or quantitative claims with citations, data, or a reproducible method; avoid unsupported assertions.","rationale":"Evidence increases trust and auditability.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","claims"],"keywords":["claims","evidence","citations"],"dependencies":[],"exceptions":["Widely-known facts may omit citations, but be conservative in formal outputs."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLAIMS.DISTINGUISH_FACT_OPINION","title":"Distinguish facts from opinions and proposals","source_refs":["HOUSE §EDITORIAL.CLAIMS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Distinguish factual reporting from opinion or proposals; label recommendations and assumptions explicitly.","rationale":"Clear framing avoids misreading.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","claims"],"keywords":["facts","opinions","recommendations"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLAIMS.QUANTIFY_WHEN_POSSIBLE","title":"Quantify when it matters","source_refs":["HOUSE §EDITORIAL.CLAIMS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When describing performance, risk, or scale, quantify (numbers, ranges) when possible and state the measurement conditions.","rationale":"Quantification prevents vague conclusions.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","claims"],"keywords":["quantify","metrics","ranges"],"dependencies":[],"exceptions":["If quantification is impossible, say why and what proxy was used."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLAIMS.AVOID_ABSOLUTES","title":"Avoid absolute claims unless you can prove them","source_refs":["HOUSE §EDITORIAL.CLAIMS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid absolute claims (always, never, impossible) unless you can prove them or you are stating a defined invariant.","rationale":"Absolutes are easy to falsify.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","claims"],"keywords":["absolute claims","always","never"],"dependencies":[],"exceptions":["Security policies may use absolutes as requirements when enforced."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLAIMS.BASELINE_FOR_COMPARISONS","title":"Define the baseline for comparisons","source_refs":["HOUSE §EDITORIAL.CLAIMS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When comparing (faster, cheaper, safer), define the baseline and what is being compared; avoid better without context.","rationale":"Comparisons require context to be meaningful.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","claims"],"keywords":["baseline","comparisons","context"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.EDITORIAL.CONSISTENCY.TERMINOLOGY.STABLE","title":"Use stable terminology for the same concept","source_refs":["HOUSE §EDITORIAL.CONSISTENCY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Use the same term for the same concept throughout; avoid switching between synonyms unless you are deliberately distinguishing concepts.","rationale":"Terminology drift confuses readers.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","consistency"],"keywords":["terminology","consistency","definitions"],"dependencies":[],"exceptions":["If renaming is necessary, note the equivalence explicitly."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CONSISTENCY.CAPITALIZATION.STABLE","title":"Keep capitalization consistent for defined terms","source_refs":["HOUSE §EDITORIAL.CONSISTENCY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Keep capitalization consistent for defined terms, product names, and headings; do not alternate between forms without intent.","rationale":"Inconsistent casing looks unedited.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","consistency"],"keywords":["capitalization","defined terms","consistency"],"dependencies":[],"exceptions":["Quoted brand styling may preserve original casing; note it."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CONSISTENCY.SPELLING_VARIANT.CHOOSE_ONE","title":"Choose one spelling variant (US/UK) per document","source_refs":["HOUSE §EDITORIAL.CONSISTENCY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Choose one spelling variant (US/UK) per document unless the audience or quoted material requires mixing; keep it consistent.","rationale":"Mixed spelling distracts reviewers.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","consistency"],"keywords":["spelling","US/UK","locale"],"dependencies":[],"exceptions":["Proper names preserve their original spelling."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CONSISTENCY.TIMEZONE.EXPLICIT","title":"Make time zones explicit for operational times","source_refs":["HOUSE §EDITORIAL.CONSISTENCY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"For operational times (maintenance windows, incidents), specify a time zone or use UTC; avoid ambiguous local times.","rationale":"Ambiguous times cause outages.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","consistency"],"keywords":["time zone","UTC","timestamps"],"dependencies":[],"exceptions":["Purely local events may use local time if the locale is explicit."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CONSISTENCY.NAMES.SAME_FORM","title":"Use a consistent form for names and identifiers","source_refs":["HOUSE §EDITORIAL.CONSISTENCY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Use a consistent form for names and identifiers (people, systems, projects); avoid switching between nicknames and formal names without explanation.","rationale":"Name drift complicates attribution and search.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","consistency"],"keywords":["names","identifiers","consistency"],"dependencies":[],"exceptions":["If multiple aliases exist, list them once and choose a primary form."],"status":"active"}
{"id":"HOUSE.EDITORIAL.REVIEW.SPELLCHECK_AND_READTHROUGH","title":"Run a final spellcheck and read-through","source_refs":["HOUSE §EDITORIAL.REVIEW p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Before publishing, run a spellcheck and do a final read-through for missing words, repeated words, and obvious grammar issues.","rationale":"Basic errors reduce trust.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","review"],"keywords":["spellcheck","proofread","copyedit"],"dependencies":[],"exceptions":["Time-critical incident updates may publish quickly; follow up with a corrected version."],"status":"active"}
{"id":"HOUSE.EDITORIAL.REVIEW.FACT_CHECK","title":"Fact-check names, numbers, and dates","source_refs":["HOUSE §EDITORIAL.REVIEW p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Fact-check names, numbers, and dates against authoritative sources; correct typos that change meaning (IDs, ports, versions).","rationale":"Small factual errors can be costly.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","review"],"keywords":["fact-check","numbers","dates"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"HOUSE.EDITORIAL.REVIEW.SENSITIVE_INFO.NO_SECRETS","title":"Remove secrets and sensitive data","source_refs":["HOUSE §EDITORIAL.OPSEC p1"],"category":"editorial","severity":"must","applies_to":"all","rule_text":"Do not publish secrets or sensitive data (tokens, private keys, passwords, internal-only hostnames) in outputs intended for sharing.","rationale":"Leaks create security incidents.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","opsec"],"keywords":["secrets","tokens","private keys"],"dependencies":[],"exceptions":["Red-team/internal documents may include secrets only in controlled systems; never publish externally."],"status":"active"}
{"id":"HOUSE.EDITORIAL.REVIEW.LINKS.VERIFY","title":"Verify outbound links","source_refs":["HOUSE §EDITORIAL.REVIEW p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Verify outbound links (correct target, stable URL, no tracking params) and prefer durable references where available.","rationale":"Broken links degrade trust.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","review"],"keywords":["links","verification","durability"],"dependencies":[],"exceptions":["Some links may be internal-only; label them clearly as such."],"status":"active"}

View file

@ -0,0 +1,18 @@
{"id":"HOUSE.EDITORIAL.STRUCTURE.METADATA.OWNER_DATE","title":"Include owner and last-updated metadata","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"For operational or decision documents, include owner/author and last-updated date near the top.","rationale":"Metadata improves accountability and reduces stale guidance.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["metadata","owner","date"],"dependencies":[],"exceptions":["If the hosting system provides authoritative metadata, a separate section may be unnecessary."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.CHANGELOG.LIVING_DOCS","title":"Maintain a changelog for living documents","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"For documents that evolve over time, maintain a brief changelog or revision history so readers can see what changed.","rationale":"Revision context helps reviewers and operators track changes.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["changelog","revision history"],"dependencies":[],"exceptions":["If readers rely on version control history and it is easily accessible, a changelog may be redundant."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.ASSUMPTIONS.EXPLICIT","title":"State assumptions explicitly","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"State key assumptions explicitly, especially when they affect recommendations or conclusions.","rationale":"Hidden assumptions lead to incorrect decisions.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["assumptions","scope"],"dependencies":[],"exceptions":["If assumptions are obvious and trivial, keep them inline rather than as a dedicated section."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.RISKS.MITIGATIONS","title":"List risks and mitigations for proposals","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When proposing changes or plans, list major risks and proposed mitigations.","rationale":"Risk visibility improves decision quality.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["risks","mitigations","plans"],"dependencies":[],"exceptions":["Purely descriptive reports may omit a risk section if no actions are proposed."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.REFERENCES.WHEN_CITED","title":"Provide a references section when citing sources","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"If the document cites external sources, provide a short references section or consistent citation list.","rationale":"A references section improves verification and reuse.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["references","citations"],"dependencies":[],"exceptions":["Short memos may use inline citations if they are complete and consistent."],"status":"active"}
{"id":"HOUSE.EDITORIAL.STRUCTURE.GLOSSARY.WHEN_DENSE","title":"Add a glossary when terminology is dense","source_refs":["HOUSE §EDITORIAL.STRUCTURE p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"If a document uses many specialized terms or abbreviations, add a short glossary or definitions section.","rationale":"A glossary reduces reader friction.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","structure"],"keywords":["glossary","definitions"],"dependencies":[],"exceptions":["If each term is defined inline and used only briefly, a glossary may be unnecessary."],"status":"active"}
{"id":"HOUSE.EDITORIAL.HEADINGS.CASE.CONSISTENT","title":"Keep heading capitalization consistent","source_refs":["HOUSE §EDITORIAL.HEADINGS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Use a consistent heading capitalization style (sentence case or title case) within the document.","rationale":"Inconsistent casing looks unedited and reduces scanability.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","headings"],"keywords":["heading case","consistency"],"dependencies":[],"exceptions":["Proper nouns and official names should keep their original casing."],"status":"active"}
{"id":"HOUSE.EDITORIAL.HEADINGS.LENGTH.CONCISE","title":"Keep headings concise","source_refs":["HOUSE §EDITORIAL.HEADINGS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Keep headings concise; long headings should be shortened or turned into a short heading plus a summary sentence.","rationale":"Concise headings improve navigation and visual rhythm.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","headings"],"keywords":["headings","concise"],"dependencies":[],"exceptions":["Regulatory or legal headings may need to remain long; consider a short label in addition."],"status":"active"}
{"id":"HOUSE.EDITORIAL.HEADINGS.NO_DUPLICATE","title":"Avoid duplicate heading text","source_refs":["HOUSE §EDITORIAL.HEADINGS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid repeating the exact same heading text at the same level; add qualifiers to distinguish sections.","rationale":"Duplicate headings confuse readers and anchors.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","headings"],"keywords":["duplicate headings","anchors"],"dependencies":[],"exceptions":["If duplicate labels are required by a standard, add disambiguating prefixes or numbering."],"status":"active"}
{"id":"HOUSE.EDITORIAL.HEADINGS.AVOID_GENERIC","title":"Avoid generic headings without context","source_refs":["HOUSE §EDITORIAL.HEADINGS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Avoid headings like Misc or Other without descriptive qualifiers; name the section by its content.","rationale":"Generic headings reduce discoverability and scan value.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","headings"],"keywords":["generic headings","structure"],"dependencies":[],"exceptions":["Appendices may use a generic label if the appendix is clearly scoped."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.TASKS.CHECKLIST","title":"Use checklists for actionable task lists","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When listing actionable tasks, use a checklist format so completion status is clear.","rationale":"Checklists reduce missed actions and improve review clarity.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","lists"],"keywords":["checklists","tasks"],"dependencies":[],"exceptions":["If tasks are already tracked elsewhere, an ordered list may be sufficient with a reference."],"status":"active"}
{"id":"HOUSE.EDITORIAL.LISTS.ITEMS.ACTIONABLE","title":"Start action items with verbs","source_refs":["HOUSE §EDITORIAL.LISTS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Write action items as verb-led phrases (e.g., Update, Verify, Deploy) to make the action explicit.","rationale":"Verb-led items are easier to scan and execute.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","lists"],"keywords":["action items","verbs"],"dependencies":[],"exceptions":["If a task is already captured as a noun phrase in an external system, keep it but add a verb in parentheses."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.ACTIVE_VOICE_INSTRUCTIONS","title":"Prefer active voice in instructions","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Prefer active voice when giving instructions or requirements; specify the actor to reduce ambiguity.","rationale":"Active voice makes ownership and action clear.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["active voice","instructions"],"dependencies":[],"exceptions":["Passive voice is acceptable when the actor is unknown or irrelevant."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLARITY.DEFINE_METRICS","title":"Define metrics and measurement context","source_refs":["HOUSE §EDITORIAL.CLARITY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Define metrics, units, and measurement context before using them in conclusions or claims.","rationale":"Undefined metrics can be misinterpreted or misapplied.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","clarity"],"keywords":["metrics","units","measurement"],"dependencies":[],"exceptions":["Well-known metrics in a narrow domain may need only a brief reminder."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CLAIMS.SCOPE_TIMEBOUND","title":"Scope claims by time and context","source_refs":["HOUSE §EDITORIAL.CLAIMS p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"When making performance or risk claims, state the time frame and context so the claim is not read as universal.","rationale":"Scoped claims reduce overgeneralization.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","claims"],"keywords":["claims","scope","time"],"dependencies":[],"exceptions":["Definitions or invariant requirements may be stated without a time qualifier."],"status":"active"}
{"id":"HOUSE.EDITORIAL.CONSISTENCY.DATE_FORMAT.SINGLE","title":"Use one date format consistently","source_refs":["HOUSE §EDITORIAL.CONSISTENCY p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Use a single date format throughout the document (prefer an unambiguous form such as YYYY-MM-DD) unless quoting sources.","rationale":"Mixed date formats cause confusion across locales.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","consistency"],"keywords":["dates","format","consistency"],"dependencies":[],"exceptions":["Quoted material may retain original date formats if clearly attributed."],"status":"active"}
{"id":"HOUSE.EDITORIAL.REVIEW.CROSS_REFERENCES.VERIFY","title":"Verify cross-references and captions","source_refs":["HOUSE §EDITORIAL.REVIEW p1"],"category":"editorial","severity":"should","applies_to":"all","rule_text":"Verify references to figures, tables, and sections so labels and targets match the content.","rationale":"Broken cross-references undermine trust and navigation.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","review"],"keywords":["cross-references","figures","tables"],"dependencies":[],"exceptions":["Short documents without cross-references may skip this step."],"status":"active"}
{"id":"HOUSE.EDITORIAL.OPSEC.REMOVE_PII","title":"Remove personal data from publishable outputs","source_refs":["HOUSE §EDITORIAL.OPSEC p1"],"category":"editorial","severity":"must","applies_to":"all","rule_text":"Remove personal data (emails, phone numbers, addresses) from publishable outputs unless explicit consent and context are documented.","rationale":"Personal data exposure is a privacy and compliance risk.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","editorial","opsec"],"keywords":["PII","privacy","redaction"],"dependencies":[],"exceptions":["Internal-only documents may include PII if access is restricted and logged."],"status":"active"}

View file

@ -0,0 +1,22 @@
{"id":"CMOS.FIGURES.ACCESSIBILITY.ALT_TEXT","title":"Provide alternative text where possible","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Provide alternative text or a textual summary for figures when the audience includes screen-reader users.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["alt text","accessibility"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.ASPECT_RATIO.PRESERVE","title":"Preserve aspect ratio","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Do not stretch or distort figures; preserve aspect ratios when scaling.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["aspect ratio","scaling"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.CAPTION.LENGTH.REASONABLE","title":"Keep captions concise","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Keep captions concise; if extensive explanation is needed, move detail into the body text.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["captions","concise"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.CAPTION.PLACEMENT.CONSISTENT","title":"Keep caption placement consistent","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Keep caption placement consistent (above or below) based on the chosen style and profile.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["caption placement","layout"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.CAPTION.PUNCTUATION.CONSISTENT","title":"Use consistent caption punctuation","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Keep caption punctuation, capitalization, and end punctuation consistent across figures.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["captions","punctuation"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.CAPTIONS.PRESENT","title":"Provide captions for figures","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Provide a caption for each figure that explains what the reader should take from it; keep caption style consistent.","rationale":"Captions make figures interpretable without guesswork.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures","captions"],"keywords":["captions","figures"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.COLOR.NOT_SOLE_SIGNAL","title":"Do not rely on color alone","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Do not rely on color alone to convey meaning in figures; use labels, patterns, or annotations.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["color","accessibility"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.CONTRAST.SUFFICIENT","title":"Use sufficient contrast","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Use sufficient contrast in figures so content remains readable in grayscale and for low-vision readers.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["contrast","accessibility"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.CREDIT.SOURCE_WHEN_REQUIRED","title":"Credit sources when required","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Credit the source of third-party figures when required, and record permissions/licensing.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["credits","permissions"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.FILENAME.STABLE","title":"Use stable filenames for figure assets","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Use stable figure filenames and paths to support deterministic builds and avoid broken links.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["filenames","assets"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.FORMAT.VECTOR_WHEN_POSSIBLE","title":"Prefer vector formats for diagrams","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Prefer vector formats for diagrams and charts when possible to avoid raster blur in PDF output.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["vector","svg","pdf"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.LEGENDS.EXPLAIN_SYMBOLS","title":"Explain symbols and legend items","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"If a figure uses symbols, colors, or abbreviations, include a legend or explain them in the caption.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["legend","symbols"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.MARGINS.AVOID_CLIPPING","title":"Avoid clipping at page margins","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Ensure figures do not clip into margins or bleed areas unless the profile explicitly supports bleed.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["margins","clipping"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.NUMBERING.SEQUENTIAL","title":"Number figures sequentially","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Number figures sequentially within the chosen scope (document-wide or per chapter) and do not reuse numbers.","rationale":"Consistent numbering supports cross-references.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures","numbering"],"keywords":["figures","numbering","captions"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.NUMBERING.WITHIN_CHAPTERS","title":"If numbering by chapter, keep prefixes consistent","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"If figure numbering is per chapter (e.g., Figure 3.2), keep the prefixing scheme consistent and reflect it in cross-references.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["chapter numbering","figures"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.PLACEMENT.NEAR_MENTION","title":"Place figures near first mention","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Place figures as close as practical to the text that discusses them, subject to layout constraints.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["placement","layout"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.REFERENCES.IN_TEXT","title":"Refer to figures from the text","source_refs":["CMOS18 §3.1 p120"],"category":"figures","severity":"should","applies_to":"all","rule_text":"When figures carry meaning, refer to them from the text (e.g., “see Figure 2”) so readers know when to consult them.","rationale":"Cross-references prevent orphaned visuals.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures","cross_reference"],"keywords":["cross reference","Figure 1"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.RESOLUTION.RASTER_SUFFICIENT","title":"Use sufficient resolution for raster images","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Use raster images at sufficient resolution for the target medium; avoid upscaled low-res images.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["resolution","images"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.SCALE.LEGIBLE","title":"Ensure figure text is legible","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Ensure any text inside figures remains legible at the target page size; avoid tiny labels that disappear when printed.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["legibility","scale"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.SENSITIVE.DATA.REDACT","title":"Redact sensitive data in figures","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Before publication, ensure figures do not expose secrets, internal hostnames, or personal data; redact as required.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["redaction","privacy"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.TABLE_VS_FIGURE.CHOOSE","title":"Choose table vs figure appropriately","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"Use tables for precise lookup and figures for patterns/trends; do not duplicate the same information unnecessarily.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["tables","figures"],"dependencies":[],"exceptions":[],"status":"active"}
{"id":"CMOS.FIGURES.UNITS.LABEL_AXES","title":"Label axes and units","source_refs":["CMOS18 §3.1 p120","CMOS18 §3.2 p122"],"category":"figures","severity":"should","applies_to":"all","rule_text":"For charts, label axes and units clearly and consistently.","rationale":"Figures should be interpretable, reproducible, and accessible.","enforcement":"manual","autofix":"none","autofix_notes":"","tags":["manual_checklist=true","figures"],"keywords":["axes","units"],"dependencies":[],"exceptions":[],"status":"active"}

View file

@ -0,0 +1,28 @@
{"id": "CMOS.FIGURES.CAPTION.PREFIX.CONSISTENT", "title": "Use a consistent figure label", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Use a consistent label format for figures (e.g., Figure, Fig.) and apply it throughout.", "rationale": "Consistent labels aid cross-references.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["figure label", "prefix"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.CAPTION.NUMBER.MATCH_LABEL", "title": "Match caption numbers to figure labels", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Ensure the caption number matches the figure label used in text references.", "rationale": "Mismatched numbering confuses readers.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures", "numbering"], "keywords": ["captions", "numbering"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.CAPTION.ALIGNMENT.CONSISTENT", "title": "Align captions consistently", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Keep caption alignment consistent (left, centered, or full width) across figures.", "rationale": "Consistent alignment improves scanning.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["caption alignment", "layout"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.CAPTION.FONT.CONSISTENT", "title": "Keep caption typography consistent", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Use consistent caption typography (size, weight, and style) for all figures.", "rationale": "Typography consistency improves professionalism.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["caption typography", "consistency"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.CAPTION.CREDITS.INLINE_OR_NOTE", "title": "Place credits consistently", "source_refs": ["CMOS18 \u00a713.109 p836 (scan p858)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "If figure credits are required, place them consistently (in the caption or a note) using one scheme.", "rationale": "Consistent credits simplify review.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures", "credits"], "keywords": ["credits", "permissions"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.PLACEMENT.TOP_OR_BOTTOM.CONSISTENT", "title": "Use consistent figure placement", "source_refs": ["CMOS18 \u00a73.8 p15 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Place figures consistently within the layout (e.g., top or bottom of a page/column) to avoid visual jitter.", "rationale": "Consistent placement improves rhythm.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["placement", "layout"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.PLACEMENT.AVOID_SPLIT", "title": "Avoid splitting figures across pages", "source_refs": ["CMOS18 \u00a73.38 p39 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Avoid splitting a single figure across pages unless it is designed as a multi-page figure.", "rationale": "Split figures are hard to interpret.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["page breaks", "splitting"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.SIZE.MATCH_READABILITY", "title": "Size figures for readability", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Size figures so labels and details remain readable at the target output size.", "rationale": "Readable figures preserve meaning.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["size", "readability"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.LABELS.FONT.CONSISTENT", "title": "Use consistent label typography", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Use consistent font family and size for labels within figures.", "rationale": "Consistent labels improve clarity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["labels", "typography"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.LABELS.AVOID_OVERLAP", "title": "Avoid overlapping labels", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Avoid label overlaps or collisions within figures; adjust layout if needed.", "rationale": "Overlaps reduce legibility.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["labels", "overlap"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.ANNOTATIONS.CONSISTENT_STYLE", "title": "Keep annotation styles consistent", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Use a consistent style for callouts, arrows, and annotation boxes within a document.", "rationale": "Consistent annotations improve comprehension.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["annotations", "callouts"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.AXES.UNITS.CONSISTENT", "title": "Use consistent axis units", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "When charts use axes, keep unit conventions consistent across related figures.", "rationale": "Consistency aids comparison.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["axes", "units"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.CALL_OUTS.AVOID_OVERLAP", "title": "Place callouts without obscuring data", "source_refs": ["CMOS18 \u00a73.38 p39 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Position callouts and annotations so they do not obscure data points or labels.", "rationale": "Obscured data undermines trust.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["callouts", "data"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.COLOR.PALETTE.CONSISTENT", "title": "Use a consistent color palette", "source_refs": ["CMOS18 \u00a73.3 p11 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Use a consistent color palette across related figures unless a change is meaningful.", "rationale": "Palette consistency helps comparison.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["color", "palette"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.LINE_WEIGHTS.CONSISTENT", "title": "Keep line weights consistent", "source_refs": ["CMOS18 \u00a73.3 p11 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Keep line weights and stroke styles consistent across figures for similar elements.", "rationale": "Consistent strokes improve clarity.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["line weights", "strokes"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.SYMBOLS.CONSISTENT", "title": "Use consistent symbols", "source_refs": ["CMOS18 \u00a73.3 p11 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Use consistent symbols and iconography across related figures.", "rationale": "Consistency reduces cognitive load.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["symbols", "icons"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.CROP.AVOID_LOSS", "title": "Avoid cropping that loses meaning", "source_refs": ["CMOS18 \u00a73.38 p39 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Avoid cropping figures in a way that removes important context or labels.", "rationale": "Cropping can distort meaning.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["cropping", "context"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.BLEED.ONLY_WHEN_ENABLED", "title": "Use bleed only when supported", "source_refs": ["CMOS18 \u00a73.38 p39 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Use bleed or full-bleed figures only when the output profile and printer support it.", "rationale": "Unsupported bleed can cause clipping.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["bleed", "printing"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.ORIENTATION.CONSISTENT", "title": "Keep orientation consistent", "source_refs": ["CMOS18 \u00a73.38 p39 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "pdf", "rule_text": "Keep figure orientation consistent (portrait vs landscape) within a section unless a change is necessary.", "rationale": "Consistent orientation improves rhythm.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["orientation", "layout"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.SOURCE.DATA.CITED", "title": "Cite data sources for figures", "source_refs": ["CMOS18 \u00a715.12 p29 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Cite the data source or dataset when a figure summarizes or transforms external data.", "rationale": "Citations support verification.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures", "citations"], "keywords": ["data source", "citation"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.PERMISSIONS.DOCUMENTED", "title": "Document permissions for reused figures", "source_refs": ["CMOS18 \u00a713.109 p836 (scan p858)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Document permissions or licenses for any reused figures and keep records accessible.", "rationale": "Permissions protect against infringement.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures", "permissions"], "keywords": ["permissions", "licenses"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.LIST_OF_FIGURES.WHEN_NEEDED", "title": "Provide a list of figures when numerous", "source_refs": ["CMOS18 \u00a73.34 p33 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Provide a list of figures when a document contains many figures to improve navigation.", "rationale": "Lists improve navigation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["list of figures", "navigation"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.LIST_ENTRIES.MATCH_CAPTIONS", "title": "Match list-of-figures entries to captions", "source_refs": ["CMOS18 \u00a73.34 p33 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Ensure list-of-figures entries match the figure captions or short titles used in the document.", "rationale": "Matching entries prevents confusion.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["list of figures", "captions"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.KEY.READABLE", "title": "Keep legends and keys readable", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Ensure figure legends or keys are large enough to read at output size.", "rationale": "Readable keys preserve meaning.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["legend", "keys"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.EMBEDDED_TEXT.MINIMAL", "title": "Avoid excessive text inside figures", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Avoid packing long paragraphs into figures; move narrative text into the body.", "rationale": "Dense text in figures reduces readability.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["embedded text", "readability"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.SCALING.UNIFORM", "title": "Scale related figures uniformly", "source_refs": ["CMOS18 \u00a73.5 p64 (scan p1123)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "When comparing related figures, keep scaling consistent so visual comparisons are accurate.", "rationale": "Uniform scaling prevents misinterpretation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["scaling", "comparisons"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.MULTIPART.PANEL_LABELS", "title": "Label multipart figure panels", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Label multipart figure panels (A, B, C) clearly and reference them consistently.", "rationale": "Panel labels aid navigation.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["panel labels", "multipart"], "dependencies": [], "exceptions": [], "status": "active"}
{"id": "CMOS.FIGURES.PANEL_ORDER.LOGICAL", "title": "Order multipart panels logically", "source_refs": ["CMOS18 \u00a73.12 p24 (scan p1122)"], "category": "figures", "severity": "should", "applies_to": "all", "rule_text": "Order multipart panels logically (left-to-right, top-to-bottom) and reflect the order in references.", "rationale": "Logical order reduces confusion.", "enforcement": "manual", "autofix": "none", "autofix_notes": "", "tags": ["manual_checklist=true", "figures"], "keywords": ["panel order", "multipart"], "dependencies": [], "exceptions": [], "status": "active"}

Some files were not shown because too many files have changed in this diff Show more