Set up citations in one repository
Your pages and the code they describe live in one repository. This page wires
manni cite into it once, so that a bare manni cite check covers the right
pages and finds the right sources. That is the whole of the setup for a single
repository. There are two more pages beside this one for the repositories that
need more.
Get started teaches the loop, meaning pin, check, read the finding, fix, re-pin. This page is the repository around that loop.
Every transcript below is real output from the built tool.
What you configure, and what you do not
Section titled “What you configure, and what you do not”| Thing | Where it comes from |
|---|---|
| Which pages are checked | A collection in manni.config.yaml, read by every manni tool. |
Where source.file resolves from | The git root, unless you say otherwise. One repository rarely says otherwise. |
| Where an entry is written | The page’s frontmatter, unless a collection declares a sidecar manifest. |
| Which findings fail the build | The default severities, unless the team moves one. |
-
Declare the pages as a collection.
collections:is a top-level key of the family’s one config file, not acite:key. Every tool reads it, so the pages you validate metadata on are the pages you check citations on:manni.config.yaml collections:- name: docs-pagespaths: ["docs/**/*.md"]exclude: ["docs/drafts/**"]pathsandexcludeare globs, relative to the config file. With this in place,manni cite checkwith no arguments covers every declared collection, and--collection docs-pagesnarrows a run to one of them. Named paths on the command line beat both.Every key of a collection is in the metadata tool’s configuration reference. The
cite:keys, all seven of them, are in the configuration reference for this tool. -
Leave the root alone. A
source.fileis a path relative to one root, settled once per run. In a single repository that root is the git root above your working directory, which is what you want, so there is nothing to set.cd docs && manni cite checkreaches the same sources as a run from the top.You find out when the root is wrong, because the source end reads
missingrather than resolving to the wrong file:✗ docs/limits.md✗ fetch-timeout :16 current lib/limits.ts:2 missingRun manni cite remove --only fetch-timeout, then manni cite add against the file's new path.manni:cite source-missing: The path names no tracked file, or an encrypted source cannot be decrypted.Guide: https://hawkeyexl.github.io/manni/cite/fix/#source-missing1 file checked, 0 passed, 1 failed, 1 findingWhere git is available, sources resolve through tracked files only, from
git ls-files, under a realpath containment check. So a file you have not committed ismissingtoo. Without git, a directory walk stands in, and an uncommitted file resolves. Where sources resolve from has the full order, and--rootis how a second checkout is reached. -
Mint the first citation.
addtakes the page with its lines, then the source with its lines.--dry-runprints the diff and writes nothing:Terminal window manni cite add docs/limits.md:6 lib/limits.ts:2 --id fetch-timeout --dry-run--- docs/limits.md+++ docs/limits.md@@ -2,2 +2,12 @@title: Limits+citations:+ - id: fetch-timeout+ claim:+ lines: 3+ integrity: sha256-921b21cccab21a4577f224ec4171aa56a3414bb3a5a4704ab8b6f314c46aa094+ source:+ file: lib/limits.ts+ lines: 2+ integrity: sha256-78af1d3321f9cbb177a7e4c958e39be56fd14cb93c1e441778bc4232e0fe4b1f+ commit-sha: 9265563d8ea84a13fea0001b7e531c119f47d070---Drop
--dry-runto write it. The report names both pins and the line each end sits on:docs/limits.md: added fetch-timeout to frontmatter (claim at line 16, sha256-921b21cc…; source lib/limits.ts:2 "export const FETCH_TIMEOUT_MS = 10_000;", sha256-78af1d33…, 9265563)You typed line 6 and the report says line 16, because the entry pushed the sentence down by ten lines. The entry itself stored
lines: 3, which counts the page body rather than the file, so editing the frontmatter never moves a claim. Body lines and file lines states the rule once. -
Run the first check. With the collection declared, no arguments are needed:
Terminal window manni cite check✓ docs/limits.md✓ fetch-timeout :16 current lib/limits.ts:2 current1 file checked, 1 passed, 0 failed, 0 findingsBoth ends read in file lines, whatever lines the entry stored.
-qhides the clean files once the corpus is larger than a screen. Read a result decodes the row, and Fix a failing check decodes every status it can carry. -
Commit the page and the config, then gate it.
manni cite checkis something CI runs on every push, next to the metadata gate. Run it in CI has the workflow, the output formats and the exit-code contract. It also has the baseline, which lets an existing backlog ramp in rather than block the first pull request.
When nothing is declared and nothing is named
Section titled “When nothing is declared and nothing is named”A run with no positional paths and no config is an operational error, exit
2, rather than a silently empty pass:
manni cite check --no-configmanni: No files to check. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml.That is the metadata tool’s shared input
model, which check and
update both follow. add is the exception, because it takes one page and
one source rather than a set.
Choose an anchor
Section titled “Choose an anchor”An entry anchors its sentence in one of two ways. Claim lines name the sentence by its body lines. A marker is a comment in the body that names the entry. Either way the entry itself stays in frontmatter or a sidecar. The choice is per entry, so one page can use both.
Neither anchor always wins. They differ in what a prose edit costs:
| When the prose changes | Claim lines | A marker |
|---|---|---|
| Text above the sentence is added or cut | claim-moved, a notice. manni cite update rewrites the lines. | Nothing to do. The marker moves with its sentence. |
| The sentence is reworded | claim-changed. update --accept re-pins the text at the recorded line. | claim-changed. update --accept re-pins what the marker anchors. |
| The sentence is reworded and moved | claim-changed, and the recorded line holds other text. cite add it again. | claim-changed. update --accept re-pins it. |
| Two branches edit prose near the sentence | The body holds no citation, so the merge sees only prose. | The marker line sits among the edits, so the merge can conflict on it. |
A marker also adds a line to the page source for every citation. On a page many people edit at once, those lines are where merges collide. Claim lines leave the body untouched. In a sidecar, they leave the frontmatter untouched too.
So markers suit a page whose sentences move and get reworded. Claim lines
suit a page many people edit at once, with manni cite update after each
merge. Anchoring has the full
rule.
Where entries are written
Section titled “Where entries are written”By default an entry goes into the page’s own frontmatter, and nothing in the body repeats it. Two things change that, and each has a page of its own.