@hawkeyexl/manni 2.3.6 → 2.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/meta/core/reencrypt.ts","../src/cite/index.ts","../src/cite/types.ts","../src/cite/errors.ts","../src/cite/core/severity.ts","../src/cite/core/range.ts","../src/cite/core/hash.ts","../src/cite/core/spell.ts","../src/cite/core/sources.ts","../src/shared/code-regions.ts","../src/cite/core/statements.ts","../src/cite/core/claims.ts","../src/cite/core/git.ts","../src/cite/core/classify.ts","../src/cite/core/page.ts","../src/cite/schema/citations.json","../src/cite/core/sidecar.ts","../src/cite/core/manifest.ts","../src/cite/core/write.ts","../src/cite/core/adapt.ts","../src/cite/core/check-page.ts","../src/cite/core/mint.ts","../src/cite/core/config.ts","../src/shared/severity.ts","../src/cite/commands/check.ts","../src/cite/commands/add.ts","../src/cite/commands/update.ts","../src/cite/core/reencrypt.ts","../src/cite/reporters/pretty.ts","../src/cite/reporters/json.ts","../src/cite/reporters/github.ts","../src/key/errors.ts","../src/key/commands/rotate.ts","../src/key/core/config.ts","../src/key/commands/set.ts"],"sourcesContent":["/**\n * Re-encrypt a page's metadata under a new key: meta's half of `manni key\n * rotate` (proposal 0045).\n *\n * Values are found by their ciphertext, not through schema marks. Every\n * string at any depth of the metadata that has the ciphertext shape is a\n * candidate, and the authentication tag decides whether it is ours: no schema\n * is resolved, so a mark from a `-s` schema or an unreachable remote cannot\n * hide a value from rotation. `citations` is left alone; cite owns it, and\n * re-encrypts its own sources with their pins.\n *\n * Pure: no IO. The caller reads the page and writes `content` back.\n */\nimport { extname } from \"node:path\";\nimport { decryptValue, encryptValue, isEncryptedValue } from \"../../shared/encryption.js\";\nimport { errorMessage } from \"../../shared/errors.js\";\nimport { escapePointerSegment } from \"../extractors/pointer.js\";\nimport { extractorByName, extractorForExtension, supportedExtensions } from \"../extractors/index.js\";\nimport { DocmetaError, type MetadataExtractor, type MetadataPatch } from \"../types.js\";\nimport { META_CONTEXT, withValueAt } from \"./encrypted.js\";\n\n/** One value re-encrypted: where, and the ciphertext before and after. */\nexport interface ReencryptedValue {\n pointer: string;\n from: string;\n to: string;\n}\n\nexport interface ReencryptMetadataResult {\n /** The page with every rewritten value; the input itself when nothing was. */\n content: string;\n rewritten: ReencryptedValue[];\n /** Values that could not be re-encrypted, and why. */\n skipped: { pointer: string; message: string }[];\n}\n\nexport interface ReencryptDataResult {\n /** The metadata with every rewritten value; the input itself when nothing was. */\n data: Record<string, unknown>;\n rewritten: ReencryptedValue[];\n /** Values that could not be re-encrypted, and why. */\n skipped: { pointer: string; message: string }[];\n /** The top-level keys whose value changed, in document order. */\n keys: string[];\n}\n\n/** The subtree cite owns. */\nconst CITATIONS_KEY = \"citations\";\n\nconst NOT_OURS = \"does not decrypt under the current key\";\nconst READ_ONLY = \"this format cannot be written\";\n\n/**\n * Re-encrypt every encrypted value in one page's metadata from `fromKey` to\n * `toKey`.\n *\n * - A value that decrypts under `fromKey` is rewritten under `toKey`.\n * - One that already decrypts under `toKey` is done: an interrupted rotation\n * can be run again. It is neither rewritten nor skipped.\n * - One that decrypts under neither is skipped.\n *\n * The format is `page.format` (an extractor name) when given, else the\n * file's extension. A nested value rewrites its top-level key; everything\n * else in the page is kept. A format that cannot be written lists every value\n * it would have rewritten as skipped, and returns the content unchanged.\n */\nexport function reencryptMetadata(\n page: { file: string; content: string; format?: string },\n opts: { fromKey: string; toKey: string },\n): ReencryptMetadataResult {\n const extractor =\n page.format !== undefined\n ? extractorByName(page.format)\n : extractorForExtension(extname(page.file));\n if (!extractor) {\n throw new DocmetaError(\n page.format !== undefined\n ? `Unknown format \"${page.format}\" for \"${page.file}\".`\n : `Unsupported file type \"${extname(page.file)}\" for \"${page.file}\". Supported: ${supportedExtensions().join(\", \")}.`,\n );\n }\n return reencryptWith(extractor, page, opts);\n}\n\ninterface Found {\n pointer: string;\n top: string;\n token: string;\n}\n\n/** Every ciphertext in `data`, in document order, outside `citations`. */\nfunction tokensIn(data: Record<string, unknown>): Found[] {\n const found: Found[] = [];\n const walk = (node: unknown, pointer: string, top: string): void => {\n if (isEncryptedValue(node)) {\n found.push({ pointer, top, token: node });\n return;\n }\n if (Array.isArray(node)) {\n (node as unknown[]).forEach((item, i) => {\n walk(item, `${pointer}/${String(i)}`, top);\n });\n return;\n }\n if (typeof node === \"object\" && node !== null && !(node instanceof Date)) {\n for (const [k, v] of Object.entries(node)) {\n walk(v, `${pointer}/${escapePointerSegment(k)}`, top);\n }\n }\n };\n for (const [key, value] of Object.entries(data)) {\n if (key === CITATIONS_KEY) continue;\n walk(value, `/${escapePointerSegment(key)}`, key);\n }\n return found;\n}\n\n/**\n * Re-encrypt every ciphertext in one metadata object, `citations` aside.\n *\n * The rule `reencryptMetadata` runs on a page, on the data alone: a value\n * that decrypts under `fromKey` is rewritten under `toKey`, one already under\n * `toKey` is done, and one under neither is skipped. `manni key rotate` calls\n * it a second time for the values an external-metadata manifest supplies,\n * which live in the manifest rather than in any page.\n *\n * `writable` says whether the caller can write what it plans. `false` lists\n * every value it would have rewritten as skipped instead, in document order\n * beside the ones that could not be read, and rewrites nothing.\n */\nexport function reencryptData(\n data: Record<string, unknown>,\n opts: { fromKey: string; toKey: string; writable?: boolean },\n): ReencryptDataResult {\n const writable = opts.writable ?? true;\n const rewritten: ReencryptedValue[] = [];\n const skipped: { pointer: string; message: string }[] = [];\n const found = tokensIn(data);\n for (const { pointer, token } of found) {\n const opened = decryptValue(token, opts.fromKey, META_CONTEXT);\n if (opened.ok) {\n if (!writable) {\n skipped.push({ pointer, message: READ_ONLY });\n continue;\n }\n rewritten.push({\n pointer,\n from: token,\n to: encryptValue(opened.value, opts.toKey, META_CONTEXT),\n });\n continue;\n }\n if (decryptValue(token, opts.toKey, META_CONTEXT).ok) continue;\n skipped.push({ pointer, message: NOT_OURS });\n }\n if (rewritten.length === 0) return { data, rewritten, skipped, keys: [] };\n\n let next: Record<string, unknown> = data;\n for (const r of rewritten) next = withValueAt(next, r.pointer, r.to);\n const done = new Set(rewritten.map((r) => r.pointer));\n const keys = [...new Set(found.filter((f) => done.has(f.pointer)).map((f) => f.top))];\n return { data: next, rewritten, skipped, keys };\n}\n\n/** `reencryptMetadata` with the extractor chosen. Exported for tests. */\nexport function reencryptWith(\n extractor: MetadataExtractor,\n page: { file: string; content: string },\n opts: { fromKey: string; toKey: string },\n): ReencryptMetadataResult {\n const read = (content: string): Record<string, unknown> => {\n try {\n return extractor.extract(content, page.file).data;\n } catch (err) {\n if (err instanceof DocmetaError) throw err;\n throw new DocmetaError(`${page.file}: ${errorMessage(err)}`);\n }\n };\n const data = read(page.content);\n const apply = extractor.apply;\n const plan = reencryptData(data, { ...opts, writable: apply !== undefined });\n const { rewritten, skipped } = plan;\n if (rewritten.length === 0 || apply === undefined) {\n return { content: page.content, rewritten: [], skipped };\n }\n\n // One patch entry per top-level key: the whole value, with its tokens\n // replaced, because a writer sets top-level keys and nothing deeper.\n const patch: MetadataPatch = {};\n for (const top of plan.keys) patch[top] = plan.data[top];\n const content = apply(page.content, patch, { filePath: page.file });\n\n // A writer that cannot keep a value is worse than a refused rotation: the\n // old ciphertext would be gone and the new one nowhere.\n const reread = tokensIn(read(content));\n for (const r of rewritten) {\n if (!reread.some((f) => f.pointer === r.pointer && f.token === r.to)) {\n throw new DocmetaError(\n `${page.file}: the ${extractor.name} writer did not keep ${r.pointer}; nothing was re-encrypted.`,\n );\n }\n }\n return { content, rewritten, skipped };\n}\n","/**\n * The citation tool's programmatic API, exported from the package as the\n * `cite` namespace: `import { cite } from \"@hawkeyexl/manni\"`.\n */\nexport * from \"./types.js\";\nexport { CiteError } from \"./errors.js\";\nexport { DEFAULT_SEVERITY, RULE_ID_PREFIX, isCiteRule, resolveSeverity, ruleId } from \"./core/severity.js\";\nexport {\n FILE_PATTERN,\n SRC_PATTERN,\n formatSrc,\n lineSpec,\n parseLines,\n parseSrc,\n rangeLines,\n sourceRange,\n spellLines,\n spellSource,\n} from \"./core/range.js\";\nexport { hashLines, hashRange, isKeyedPin, normalizeText, sliceLines, splitLines } from \"./core/hash.js\";\nexport { shortCommit, shortPin, shortSrc } from \"./core/spell.js\";\nexport { buildSourceIndex, readSource } from \"./core/sources.js\";\nexport type { BuildIndexOptions, ReadSourceResult } from \"./core/sources.js\";\nexport {\n anchoredLines,\n detectEol,\n fenceSpanAt,\n fencedBlockAfter,\n fencedBlockAt,\n fencedBlocks,\n formatStatement,\n insideFence,\n lineAt,\n offsetOfLine,\n paragraphAfter,\n parseStatements,\n statementForms,\n} from \"./core/statements.js\";\nexport type { StatementForm } from \"./core/statements.js\";\nexport {\n blockMatches,\n claimEnd,\n claimLine,\n markerUnit,\n normalizeWhitespace,\n pinOfLines,\n toBodyLines,\n toFileLines,\n unitAt,\n} from \"./core/claims.js\";\nexport type { ClaimUnit } from \"./core/claims.js\";\nexport { GIT_UNAVAILABLE_COMMIT, GIT_UNAVAILABLE_HISTORY, gitClient, noGit } from \"./core/git.js\";\nexport { MAX_RANGE_LINES, MOVE_BUDGET_BYTES, MOVE_WINDOW_LINES, classifyCitation, findWindows, historyOf } from \"./core/classify.js\";\nexport type { ClassifyOptions, FindWindowsOptions, History } from \"./core/classify.js\";\nexport {\n MARKER_JSON,\n MAX_MARKERS_PER_PAGE,\n bodyLineOf,\n ownedMessage,\n pickExtractor,\n readPage,\n validateEntry,\n} from \"./core/page.js\";\nexport {\n CITATIONS_KEY,\n duplicateJoinRefusal,\n loadCitationSidecars,\n orphanRefusal,\n sidecarsFor,\n twoManifestsRefusal,\n urlManifestRefusal,\n} from \"./core/sidecar.js\";\nexport type {\n CitationManifest,\n CitationSidecars,\n LoadSidecarOptions,\n PageSidecar,\n} from \"./core/sidecar.js\";\nexport { ManifestSet, itemLine, splice } from \"./core/manifest.js\";\nexport type { HeldManifest } from \"./core/manifest.js\";\nexport type { ReadPageOptions } from \"./core/page.js\";\nexport { checkCitations } from \"./core/check-page.js\";\nexport { claimMessageFor, errorSite, findingsFor, messageFor, toValidationResult } from \"./core/adapt.js\";\nexport { appendFrontmatterCitation, entryObject, insertStatementBefore, spliceEntryField, unifiedDiff } from \"./core/write.js\";\nexport type { EntryPath } from \"./core/write.js\";\nexport { mintCitation } from \"./core/mint.js\";\nexport { CITE_SECTION, DEFAULT_CITE_BASELINE_PATH, loadCiteConfig, parseCiteConfig, readCiteConfigFile, resolveCiteRun } from \"./core/config.js\";\nexport type { CiteRunOptions } from \"./core/config.js\";\n\nexport { runCheck } from \"./commands/check.js\";\nexport { runAdd } from \"./commands/add.js\";\nexport { runUpdate } from \"./commands/update.js\";\nexport { reencryptCitationEntries, reencryptCitations } from \"./core/reencrypt.js\";\nexport type { ReencryptEntriesResult, ReencryptOptions } from \"./core/reencrypt.js\";\nexport { renderCheckPretty, renderUpdatePretty, rewriteLine } from \"./reporters/pretty.js\";\nexport type { PrettyOptions } from \"./reporters/pretty.js\";\nexport { renderCheckJson, renderUpdateJson } from \"./reporters/json.js\";\nexport { renderCheckGithub } from \"./reporters/github.js\";\n","/**\n * The citation tool's types. Proposal 0044 is the record, and stress test 25\n * the shape: an entry has two ends, `claim` and `source`, each a line range\n * and a hash, and a check classifies both with one set of rules.\n *\n * Vocabulary: a page's `citations` live in its frontmatter, or in a manifest\n * a collection declares (handed in through `CheckPageOptions.citations`). A\n * body marker, `cite <id>` in the format's comment syntax, is the other way\n * to anchor an entry's claim.\n */\nimport type { ValidationResult } from \"../meta/index.js\";\nimport type { CollectionConfig } from \"../shared/collections.js\";\nimport type { ConfigFile } from \"../shared/config-file.js\";\nimport type { KeySource } from \"../shared/encryption-key.js\";\nimport type { LineSpec, PageLines } from \"../shared/pin.js\";\nimport type { Confirm } from \"../shared/prompt.js\";\nimport type { Severity } from \"../shared/severity.js\";\n\n/** A parsed `<src>` or `source`: a path or `~` ciphertext, and an optional line range. */\nexport interface SourceRange {\n /** Repo-root-relative posix path, or the `~` ciphertext when `encrypted`. */\n path: string;\n /** `true` when `path` is an encrypted source (`~` and 82+ base64url characters) rather than a path. */\n encrypted: boolean;\n /** 1-based, inclusive. Both absent for a whole-file citation. */\n start?: number;\n end?: number;\n}\n\n// The line shapes are the shared pin engine's, re-exported so cite's imports and its namespace keep them.\nexport type { LineSpec, PageLines };\n\n/** The page text a citation supports. */\nexport interface CitationClaim {\n /** Body lines: counted from the first line after the frontmatter. Absent when a marker anchors the entry. */\n lines?: LineSpec;\n /** `sha256-<64 hex>` over the claimed lines, always plain. */\n integrity: string;\n}\n\n/** The lines a claim rests on. */\nexport interface CitationSource {\n /** Root-relative posix path, or `~` and the path encrypted with the family key. */\n file: string;\n /** File lines. Absent pins the whole file. */\n lines?: LineSpec;\n /** `sha256-<64 hex>`, or `hmac-sha256-<64 hex>` exactly when `file` is encrypted. */\n integrity: string;\n /** The git commit hash the pin was taken at: 7 to 64 lowercase hex. */\n \"commit-sha\"?: string;\n}\n\n/** One entry of `citations`, as the schema (`manni:citations:1.0.0-proposal.4`) spells it. */\nexport interface Citation {\n id?: string;\n claim?: CitationClaim;\n source: CitationSource;\n quote?: boolean;\n}\n\n/** Where an entry is kept: the page's frontmatter, or a manifest a collection declares. */\nexport type OriginKind = \"frontmatter\" | \"manifest\";\n\n/** Where an entry sits. */\nexport interface CitationOrigin {\n kind: OriginKind;\n /** The file the entry sits in: the page for frontmatter, the manifest otherwise. */\n file: string;\n /** Line of the entry in that file. */\n line?: number;\n /** Index in the page's `citations` list. */\n index: number;\n}\n\n/**\n * One entry handed to `checkCitations` from outside the page, already merged\n * from a manifest. `entry` is the raw value and is validated as a frontmatter\n * entry is; its index is its position in the list.\n */\nexport interface CitationInput {\n entry: unknown;\n origin: { kind: OriginKind; file: string; line?: number };\n}\n\n/** How a citation's claim is anchored: by its lines, by a body marker, or not at all. */\nexport type CitationAnchor = \"claim\" | \"marker\" | null;\n\nexport type SourceStatus =\n | \"current\"\n | \"moved\"\n | \"moved-ambiguous\"\n | \"changed\"\n | \"missing\"\n | \"never-true\"\n | \"skipped\";\n\nexport type ClaimStatus = \"current\" | \"moved\" | \"moved-ambiguous\" | \"changed\" | \"skipped\";\n\n/**\n * Why a source could not be read: not a tracked file under the root, an\n * encrypted source with no key to decrypt it, one that does not decrypt under\n * the key there is, or a tracked file that could not be read.\n */\nexport type MissingReason = \"untracked\" | \"no-key\" | \"undecryptable\" | \"unreadable\";\n\n/**\n * Every rule a finding can carry, stated once. The union and the default\n * severity table are derived from this array so the three cannot disagree.\n */\nexport const CITE_RULES = [\n \"source-moved\",\n \"source-moved-ambiguous\",\n \"source-changed\",\n \"source-never-true\",\n \"source-missing\",\n \"claim-moved\",\n \"claim-moved-ambiguous\",\n \"claim-changed\",\n \"marker-orphan\",\n \"marker-invalid\",\n \"marker-repeated\",\n \"anchor-invalid\",\n \"entry-invalid\",\n \"quote-drift\",\n] as const;\nexport type CiteRule = (typeof CITE_RULES)[number];\n\n/**\n * A rule's level: the family scale (`src/shared/severity.ts`) plus `off`,\n * which drops the rule's findings altogether.\n */\nexport type CiteSeverity = Severity | \"off\";\n\n/** The claim end of a classified citation. Line specs are `\"L\"` or `\"L1-L2\"`. */\nexport interface ClaimEnd {\n /** The entry's body lines. Absent when a marker anchors the claim. */\n lines?: string;\n /** Where the claim is judged, in file lines: the recorded lines, or what the marker anchors. */\n fileLines?: string;\n status: ClaimStatus;\n /** For `moved`: the new body lines. */\n newLines?: string;\n /** For `moved-ambiguous`: every candidate, in body lines. */\n candidates?: string[];\n /** For `moved`: the new file lines. Pretty-only. */\n newFileLines?: string;\n /** For `moved-ambiguous`: every candidate, in file lines. Pretty-only. */\n candidateFileLines?: string[];\n /** For `changed`: the page lines at the claim now, for `--show-diff`. Pretty-only. */\n text?: string[];\n}\n\n/** The source end of a classified citation. */\nexport interface SourceEnd {\n /** `file` and `lines` as the entry spells them: `path`, `path:L`, `path:L1-L2`, the ciphertext for `path`. */\n src: string;\n status: SourceStatus;\n /**\n * The path an encrypted source decrypted to. Never printed except by the\n * pretty reporter under `--reveal`; never serialized to a machine format.\n */\n resolvedPath?: string;\n /** For `missing`: why the source could not be read. Composes the message, which never names a path. */\n missingReason?: MissingReason;\n /** For `moved`: the new file lines. */\n newLines?: string;\n /** For `moved`: the new `src`, spelled as the entry spells sources. */\n newSrc?: string;\n /** For `moved-ambiguous`: every candidate `src`. */\n candidates?: string[];\n /** The commit the pin was taken at. */\n commitSha?: string;\n /** For `changed` with a commit: whether git could show that commit. */\n historyAvailable?: boolean;\n /** Subjects of commits touching the path since the commit. Pretty-only. */\n commitsSince?: string[];\n /** Unified diff of the path since the commit. Pretty-only, `--show-diff`. */\n diff?: string;\n /** The move search hit its byte budget before covering the file. */\n truncatedSearch?: boolean;\n}\n\n/** One classified citation: both ends, and how it is anchored. */\nexport interface CitationResult {\n citation: Citation;\n origin: CitationOrigin;\n anchor: CitationAnchor;\n /** File line of the marker that names the entry, when one does. */\n markerLine?: number;\n /**\n * File line the citation anchors to now: the claim's first line, or the\n * first line of the text a marker anchors. Where its findings sit.\n */\n anchorLine?: number;\n /** `null` for an entry with no `claim`: a bare pin, or a marker with no drift check. */\n claim: ClaimEnd | null;\n source: SourceEnd;\n}\n\nexport interface CitationFinding {\n rule: CiteRule;\n /** `manni:cite/<rule>`. */\n ruleId: string;\n /** On the family scale: an `error` fails the file; a `warning` or a `notice` is reported and never does. */\n severity: Severity;\n message: string;\n /** Line the finding anchors to: in the page, or in `file` when that is set. */\n line?: number;\n /** The manifest, when the finding sits there rather than on the page. */\n file?: string;\n id?: string;\n /** The source, spelled as the entry spells it. */\n src?: string;\n newSrc?: string;\n /** Index in the page's `citations` for a finding about one entry. */\n index?: number;\n}\n\nexport interface PageCitationReport {\n file: string;\n format: string;\n citations: CitationResult[];\n findings: CitationFinding[];\n /** Run-level advice, said once per run by the caller: shallow clone, root fallback. */\n notices: string[];\n}\n\n/** What `showFile` answers: the bytes, or why it could not. */\nexport type ShownFile = { text: string } | { missing: \"commit\" | \"path\" };\n\n/**\n * A thin git client over `execFile(\"git\", …)`, memoized per call shape so a\n * page with a thousand citations against one path runs one `git show`.\n */\nexport interface GitClient {\n available(): Promise<boolean>;\n head(): Promise<string | null>;\n /** Tracked files, posix, relative to the root. */\n lsFiles(): Promise<string[]>;\n showFile(commit: string, path: string): Promise<ShownFile>;\n subjectsSince(commit: string, path: string): Promise<string[]>;\n diffSince(commit: string, path: string): Promise<string>;\n}\n\n/**\n * The files a source may resolve to. Built from `git ls-files` when git is\n * available, else from a walk that follows no symlinks. Every entry is\n * realpath-contained in the root.\n */\nexport interface SourceIndex {\n files(): readonly string[];\n /** Whether `path` is a tracked file under the root. An encrypted source is decrypted first, then asked here. */\n has(path: string): boolean;\n}\n\nexport interface CheckPageOptions {\n /** Absolute directory source paths resolve from. */\n root: string;\n /** Default true. False: page-side rules only; every source status is `skipped`. Claim ends are still judged. */\n checkSources?: boolean;\n /**\n * The encryption key: decrypts encrypted sources and keys their pins.\n * Absent, an encrypted citation is `missing` (no key to decrypt it).\n */\n key?: string;\n severity?: Partial<Record<CiteRule, CiteSeverity>>;\n /**\n * The git client the source index and history are read through. Defaults\n * to one over the root, which is used whenever git is on PATH and the root\n * is inside a work tree. A caller that wants no git at all passes `noGit()`.\n */\n gitClient?: GitClient;\n sourceIndex?: SourceIndex;\n /**\n * The page's citations as merged from a manifest, each with where it sits.\n * Given, the page's own frontmatter `citations` is not read. Without it, a\n * grader calling `checkCitations` on a sidecar page would find no citations.\n */\n citations?: readonly CitationInput[];\n /**\n * The manifest that owns this page's `citations`, when one does. A page\n * that carries its own anyway is `entry-invalid`, in meta's `external:owned`\n * words.\n */\n owned?: { file: string; collection: string };\n}\n\nexport interface MintOptions {\n root: string;\n /** `path`, `path:L`, `path:L1-L2`, or an encrypted `~file` with the same line forms. */\n src: string;\n id?: string;\n /** The claim pin, already taken over the page lines. */\n claim?: CitationClaim;\n quote?: boolean;\n /** A commit to record; `false` records none; absent records HEAD when git has one. */\n commitSha?: string | false;\n /**\n * Write `file` encrypted and pin the lines with the keyed pin; needs `key`.\n * A source that is already encrypted stays encrypted either way.\n */\n encrypt?: boolean;\n /** The encryption key: encrypts, decrypts an encrypted source, and keys its pin. */\n key?: string;\n gitClient?: GitClient;\n sourceIndex?: SourceIndex;\n}\n\n/** One marker found in a page body: `cite <id>` in the format's comment syntax. */\nexport interface InlineStatement {\n /** File line of the marker. */\n line: number;\n /** File line of the anchored text: the rest of the marker's line, else the paragraph or block that follows. */\n anchorLine?: number;\n payload: { kind: \"ref\"; id: string } | { kind: \"bad\"; reason: string; json?: boolean };\n /** The marker text between the delimiters, trimmed. */\n raw: string;\n /** Character offsets of the whole marker in the file, for rewriting. */\n start: number;\n end: number;\n}\n\n/** A validated citation with where it sits and the marker that names it, before classification. */\nexport interface PageCitation {\n citation: Citation;\n origin: CitationOrigin;\n /** The first marker naming the entry's id. */\n marker?: InlineStatement;\n}\n\n/** What `readPage` returns: the entries, the markers, and page-side findings. */\nexport interface PageCitations {\n file: string;\n format: string;\n content: string;\n /** Offset where the body starts (just past the closing fence, or 0). */\n bodyOffset: number;\n /** File line of body line 1: the first line after the frontmatter, or 1. */\n bodyLine: number;\n citations: PageCitation[];\n statements: InlineStatement[];\n findings: CitationFinding[];\n}\n\nexport interface CheckOptions {\n /** Positional inputs; empty means the configured collections' `paths:` (0041). */\n inputs: string[];\n /**\n * `--collection <name>`, repeatable: the collections this run covers. Empty\n * or absent means every declared one; see `selectCollections`.\n */\n collection?: string[];\n exts?: string[];\n /** `--exclude`, appended to the selected collections' `exclude:` when the run reads from them. */\n exclude?: string[];\n as?: string;\n configPath?: string;\n noConfig?: boolean;\n cwd?: string;\n stdinContent?: string;\n allowEmpty?: boolean;\n respectGitignore?: boolean;\n onNotice?: (message: string) => void;\n onConfigLoaded?: (info: { path: string; dir: string }) => void;\n baseline?: string | boolean;\n writeBaseline?: string | boolean;\n /** `--no-check-sources` (false): page-side rules only. Absent leaves `checkSources:` in charge. */\n checkSources?: boolean;\n /**\n * `--show-diff`: the report will want diffs and commit subjects. The check\n * is the same either way; the run only says, once, when git is not there\n * to give them.\n */\n showDiff?: boolean;\n root?: string;\n /**\n * The git client every page is checked through. Defaults to one over the\n * root, used whenever git is on PATH and the root is inside a work tree; a\n * test hands in a fake.\n */\n gitClient?: GitClient;\n /** Defaults to `process.env`; read for `MANNI_ENCRYPTION_KEY`. A test hands in its own. */\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface CheckRun {\n results: ValidationResult[];\n summary: import(\"../meta/index.js\").RunSummary;\n frame: import(\"../meta/index.js\").FingerprintContext;\n pages: PageCitationReport[];\n warnings: number;\n notices: number;\n}\n\n\nexport interface AddOptions {\n page: string;\n /** The claim's lines as an editor numbers them (`page:L`, `page:L1-L2`). Absent: a bare pin. */\n pageLines?: PageLines;\n src: string;\n id?: string;\n /** Write a marker above the page lines instead of claim lines, and pin the text it anchors. Needs `pageLines` and `id`. */\n marker?: boolean;\n /** The page lines are a fenced block that reproduces the source. Needs `pageLines`. */\n quote?: boolean;\n /**\n * `--encrypt`: write `file` encrypted, with a keyed pin, even when no key is\n * available yet, in which case `confirm` is asked whether to generate one.\n * An available key encrypts every add without it, so `false` and absent\n * are the same.\n */\n encrypt?: boolean;\n /** `false` records no `commit-sha`. */\n commitSha?: boolean;\n dryRun?: boolean;\n as?: string;\n configPath?: string;\n noConfig?: boolean;\n cwd?: string;\n stdinContent?: string;\n root?: string;\n /**\n * The git client HEAD and the source index are read through. Defaults to\n * one over the root; a test hands in a fake.\n */\n gitClient?: GitClient;\n /** Defaults to `process.env`; read for `MANNI_ENCRYPTION_KEY`. A test hands in its own. */\n env?: NodeJS.ProcessEnv;\n onNotice?: (message: string) => void;\n onConfigLoaded?: (info: { path: string; dir: string }) => void;\n /**\n * Asked when `encrypt` needs a key and there is none; the CLI passes\n * `terminalConfirm()`. Absent, the add refuses instead of asking.\n */\n confirm?: Confirm;\n}\n\n/** The manifest half of a write: what it says now, and whether it was saved. */\nexport interface ManifestWrite {\n /** The manifest as the run reports it. */\n file: string;\n /** 1-based line the written entry now sits on. */\n line: number;\n /** The whole manifest, rewritten. */\n content: string;\n diff: string;\n written: boolean;\n}\n\nexport interface AddResult {\n file: string;\n citation: Citation;\n /**\n * Where the entry was written: the page's frontmatter, or the manifest the\n * page's collection declares. The config decides, not a flag.\n */\n placed: \"frontmatter\" | \"manifest\";\n /** The manifest the entry went to, under `placed: \"manifest\"`. */\n manifest?: ManifestWrite;\n /** File lines of the claim after the write: the claim lines, or the text the marker anchors. */\n claimLines?: PageLines;\n /** File line of the marker written above the claim, under `marker`. */\n markerLine?: number;\n /** The rewritten page. */\n content: string;\n diff: string;\n written: boolean;\n}\n\nexport interface UpdateOptions extends Omit<CheckOptions, \"baseline\" | \"writeBaseline\"> {\n accept?: boolean;\n only?: string[];\n dryRun?: boolean;\n}\n\n/** One end `update` rewrote. */\nexport interface UpdateRewrite {\n id?: string;\n /** Index in the page's `citations`. */\n index: number;\n /** File line of the entry. */\n line?: number;\n end: \"claim\" | \"source\";\n reason: \"moved\" | \"accepted\";\n /** The status that was repaired. */\n status: \"moved\" | \"changed\" | \"never-true\";\n /**\n * Before and after. A moved claim: its file lines. A moved source: its\n * `src`. An accepted end: its pin.\n */\n from: string;\n to: string;\n /** An accepted claim: its first file line. */\n at?: number;\n /** An accepted claim a marker anchors: the marker's file line. Pretty-only. */\n markerLine?: number;\n /** An accepted claim: the text now pinned, whitespace collapsed. */\n text?: string;\n /** An accepted source: its `src`. */\n src?: string;\n /** An accepted source: the commit recorded in the entry, when it records one. */\n commitSha?: string;\n}\n\nexport interface UpdatePage {\n file: string;\n rewritten: UpdateRewrite[];\n skipped: CitationFinding[];\n diff: string;\n written: boolean;\n /** The rewritten page, for the stdin input only: it has no file to be written to. */\n content?: string;\n}\n\n/** One manifest a run rewrote: what changed in it, and whether it was saved. */\nexport interface ManifestChange {\n /** The manifest as the run reports it. */\n file: string;\n diff: string;\n written: boolean;\n}\n\nexport interface UpdateRun {\n pages: UpdatePage[];\n rewritten: number;\n skipped: number;\n /** The manifests this run rewrote, each written once however many pages it holds. */\n manifests?: ManifestChange[];\n exitCode: 0 | 1;\n}\n\n/** One citation `reencryptCitations` rewrote: where it sits, and its source before and after. */\nexport interface ReencryptedCitation {\n id?: string;\n /** Index in `citations`. */\n index?: number;\n /** File line of the entry. */\n line?: number;\n /** `file` and its line suffix, under the old key and under the new. */\n from: string;\n to: string;\n}\n\n/** What `reencryptCitations` did to one page. */\nexport interface ReencryptCitationsResult {\n /** The page with every re-encrypted citation rewritten; the input itself when none was. */\n content: string;\n rewritten: ReencryptedCitation[];\n /** Citations that could not be re-encrypted, and why. A message never names a path. */\n skipped: { id?: string; index?: number; line?: number; message: string }[];\n}\n\n/**\n * Config under `cite:` in manni.config.yaml, camelCase as `meta:` is. The\n * document set is not here: proposal 0041 moved `paths` and `exclude` to the\n * family-level `collections:` list, which every tool reads. Neither is the\n * encryption key, the top-level `encryptionKey:` every tool reads (0045).\n */\nexport interface CiteConfig {\n allowEmpty?: boolean;\n respectGitignore?: boolean;\n root?: string;\n baseline?: string;\n checkSources?: boolean;\n severity?: Partial<Record<CiteRule, CiteSeverity>>;\n}\n\nexport interface LoadedCiteConfig {\n config: CiteConfig;\n path: string;\n dir: string;\n /** The file as the user would name it, for messages. */\n source: string;\n /** The family file's top-level `collections:`, parsed by the shared layer (0041). */\n collections: CollectionConfig[];\n}\n\n/** What every command core resolves before touching a file. */\nexport interface CiteRun {\n config: CiteConfig | null;\n /** The positional inputs, or the selected collections' `paths:` in declaration order. */\n inputs: string[];\n /** Directory the inputs resolve from: cwd for positional inputs, the config directory for collections. */\n base: string;\n /**\n * The collections this run covers: every declared one, or the ones\n * `--collection` named. `[]` when no config governs the run.\n */\n collections: CollectionConfig[];\n /** Whether `inputs` came from the collections rather than the command line. */\n fromCollections: boolean;\n configDir?: string;\n configPath?: string;\n /** The config file as the user would name it, for messages. */\n configSource?: string;\n /** Absolute root source paths resolve from. */\n root: string;\n /**\n * The family encryption key (proposal 0045): `MANNI_ENCRYPTION_KEY`, else\n * the config's top-level `encryptionKey:`. Absent when neither is set.\n */\n key?: string;\n /** Where `key` came from. The environment wins over the config. */\n keySource: KeySource;\n /**\n * The config file that governs the run, as discovery found it. A write\n * that needs a key (`add --encrypt` with none) puts one there.\n */\n configFile?: ConfigFile;\n}\n","import { ToolError } from \"../shared/errors.js\";\nimport { LineRangeError } from \"../shared/pin.js\";\n\n/** An operational or usage error in the citation tool: exit 2. */\nexport class CiteError extends ToolError {\n constructor(message: string) {\n super(message);\n this.name = \"CiteError\";\n }\n}\n\n/**\n * Run a shared pin-engine call under cite's error contract: a\n * `LineRangeError` comes back as a `CiteError` with the same message, which is\n * what cite's callers (and library users of the `cite` namespace) match on.\n */\nexport function asCiteError<T>(call: () => T): T {\n try {\n return call();\n } catch (error) {\n if (error instanceof LineRangeError) throw new CiteError(error.message);\n throw error;\n }\n}\n","/**\n * Which rules fail a run, which only warn, and which are notices.\n *\n * Warnings and notices never affect the exit code (docevals' rule).\n * `source-moved` is a warning because `cite update` fixes it mechanically,\n * and a PR job that failed on it would make the ratchet noisy. `claim-moved`\n * is a notice: the text is found verbatim, so nothing drifted.\n * `claim-changed` is a warning, since it fires on any edit to a pinned\n * paragraph, a typo fix beside the cited sentence included. A repository that\n * wants either hard sets `severity: { claim-changed: error }`.\n */\nimport { CITE_RULES, type CiteRule, type CiteSeverity } from \"../types.js\";\n\nexport const DEFAULT_SEVERITY: Readonly<Record<CiteRule, CiteSeverity>> = {\n \"source-moved\": \"warning\",\n \"source-moved-ambiguous\": \"error\",\n \"source-changed\": \"error\",\n \"source-never-true\": \"error\",\n \"source-missing\": \"error\",\n \"claim-moved\": \"notice\",\n \"claim-moved-ambiguous\": \"warning\",\n \"claim-changed\": \"warning\",\n \"marker-orphan\": \"error\",\n \"marker-invalid\": \"error\",\n \"marker-repeated\": \"warning\",\n \"anchor-invalid\": \"error\",\n \"entry-invalid\": \"error\",\n \"quote-drift\": \"error\",\n};\n\nexport const RULE_ID_PREFIX = \"manni:cite\";\n\n/** `manni:cite/<rule>`: the SARIF rule id and the JUnit failure type. */\nexport function ruleId(rule: CiteRule): string {\n return `${RULE_ID_PREFIX}/${rule}`;\n}\n\nexport function isCiteRule(value: string): value is CiteRule {\n return (CITE_RULES as readonly string[]).includes(value);\n}\n\n/** The effective severity table: defaults with the config's overrides. */\nexport function resolveSeverity(\n overrides?: Partial<Record<CiteRule, CiteSeverity>>,\n): Record<CiteRule, CiteSeverity> {\n return { ...DEFAULT_SEVERITY, ...(overrides ?? {}) };\n}\n","/**\n * Source and line grammar.\n *\n * An entry's `source.file` is a path or an encrypted source (`~` and at least\n * 82 base64url characters, proposal 0045), and its `lines` an integer or\n * `\"L1-L2\"`. `FILE_PATTERN` is the schema's `$defs.fileRef.pattern`, spelled\n * once here and once in `schema/citations.json`; `test/cite/range.test.ts`\n * pins the two equal.\n *\n * The command line spells a source as one string, `path`, `path:L` or\n * `path:L1-L2` (`SRC_PATTERN`), and reports spell it that way too.\n */\nimport { isEncryptedValue } from \"../../shared/encryption.js\";\nimport { MAX_RANGE_LINES, lineSpec, parseLines } from \"../../shared/pin.js\";\nimport { CiteError } from \"../errors.js\";\nimport type { CitationSource, LineSpec, PageLines, SourceRange } from \"../types.js\";\n\n// The line grammar is the shared pin engine's; this path keeps cite's imports working.\nexport { lineSpec, parseLines, spellLines } from \"../../shared/pin.js\";\n\n/** The schema's `$defs.fileRef.pattern`, as a RegExp. */\nexport const FILE_PATTERN =\n /^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\\.\\.?(?:\\/|$))[^/\\\\:\\r\\n\\t]+)(?:\\/(?:(?!\\.\\.?(?:\\/|$))[^/\\\\:\\r\\n\\t]+))*)$/;\n\n/** A source on the command line: a `file`, then an optional `:L` or `:L1-L2`. */\nexport const SRC_PATTERN =\n /^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\\.\\.?(?:\\/|:|$))[^/\\\\:\\r\\n\\t]+)(?:\\/(?:(?!\\.\\.?(?:\\/|:|$))[^/\\\\:\\r\\n\\t]+))*)(?::[1-9][0-9]*(?:-[1-9][0-9]*)?)?$/;\n\n/**\n * Parse a command-line source. Throws `CiteError` on bad grammar or an end\n * line before the start. A one-line `path:L` comes back with `end` equal to\n * `start`, so a range's width is always `end - start + 1`.\n */\nexport function parseSrc(src: string): SourceRange {\n if (!SRC_PATTERN.test(src)) {\n throw new CiteError(\n `Invalid src \"${src}\": expected path, path:L, path:L1-L2, or an encrypted source (~ and at least 82 base64url characters) with the same line forms; ` +\n \"the path is repo-root-relative, posix, and free of . and .. segments.\",\n );\n }\n // The grammar keeps `:` out of every path segment and out of the base64url\n // alphabet, so the first one starts the line suffix.\n const colon = src.indexOf(\":\");\n const path = colon === -1 ? src : src.slice(0, colon);\n const range: SourceRange = { path, encrypted: isEncryptedValue(path) };\n if (colon === -1) return range;\n const [startText, endText] = src.slice(colon + 1).split(\"-\");\n const start = Number(startText);\n const end = endText === undefined ? start : Number(endText);\n if (end < start) {\n throw new CiteError(`Invalid range \"${src}\": end line ${end} is before start line ${start}.`);\n }\n range.start = start;\n range.end = end;\n return range;\n}\n\n/**\n * How a range too wide to cite is refused: `spans N lines, more than 5000`.\n * Undefined for a range of at most `MAX_RANGE_LINES` lines.\n */\nexport function tooWide(lines: PageLines): string | undefined {\n const width = lines.end - lines.start + 1;\n return width > MAX_RANGE_LINES\n ? `spans ${String(width)} lines, more than ${String(MAX_RANGE_LINES)}`\n : undefined;\n}\n\n/** The canonical spelling: `path:L` for one line, `path:L1-L2` otherwise. */\nexport function formatSrc(range: SourceRange): string {\n const { path, start, end } = range;\n if (start === undefined) return path;\n if (end === undefined || end === start) return `${path}:${start}`;\n return `${path}:${start}-${end}`;\n}\n\n/** An entry's source as a range. Its lines must already be valid (see `parseLines`). */\nexport function sourceRange(source: CitationSource): SourceRange {\n const range: SourceRange = { path: source.file, encrypted: isEncryptedValue(source.file) };\n if (source.lines === undefined) return range;\n const lines = parseLines(source.lines);\n if (lines !== undefined) {\n range.start = lines.start;\n range.end = lines.end;\n }\n return range;\n}\n\n/** An entry's source spelled as one string, `path:L1-L2`, the way the command line takes it. */\nexport function spellSource(source: CitationSource): string {\n return formatSrc(sourceRange(source));\n}\n\n/** A range's lines as an entry writes them; undefined for a whole file. */\nexport function rangeLines(range: SourceRange): LineSpec | undefined {\n if (range.start === undefined) return undefined;\n return lineSpec({ start: range.start, end: range.end ?? range.start });\n}\n","/**\n * The hashing rule, as cite uses it. The engine is `src/shared/pin.ts`, shared\n * with meta; this module keeps cite's import path and its error contract: a\n * range past the end of the text throws `CiteError`.\n */\nimport {\n hashRange as sharedHashRange,\n sliceLines as sharedSliceLines,\n type LineRange,\n} from \"../../shared/pin.js\";\nimport { asCiteError } from \"../errors.js\";\n\nexport { hashLines, isKeyedPin, normalizeText, splitLines } from \"../../shared/pin.js\";\n\n/**\n * The cited lines joined by LF. Throws `CiteError` when the range runs past\n * the end of the text (`<path> has N lines; line M is out of range`).\n */\nexport function sliceLines(lines: readonly string[], range?: LineRange, label?: string): string {\n return asCiteError(() => sharedSliceLines(lines, range, label));\n}\n\n/** The pin of the cited lines: plain, or the keyed pin under `key` when one is given. Throws `CiteError` past the end. */\nexport function hashRange(text: string, range?: LineRange, key?: string): string {\n return asCiteError(() => sharedHashRange(text, range, key));\n}\n","/**\n * How a citation reads on a terminal. A pin is sixty-four hex digits and a\n * ciphertext is longer still, so both are abbreviated for a person, and every\n * report and every `add` line abbreviates them the same way.\n */\n\n/** `sha256-78af1d33…`, `hmac-sha256-5e0c1a2b…`: the prefix and eight hex digits. */\nexport function shortPin(integrity: string): string {\n const m = /^((?:hmac-)?sha256-)([0-9a-f]{8})/i.exec(integrity);\n const prefix = m?.[1];\n const digits = m?.[2];\n if (prefix === undefined || digits === undefined) return integrity;\n return `${prefix}${digits}…`;\n}\n\n/** The seven characters a person reads a commit by. */\nexport function shortCommit(commit: string): string {\n return commit.slice(0, 7);\n}\n\n/**\n * `~AQx7…:2`: an encrypted source, abbreviated, with its line suffix kept. A\n * plain path is spelled in full, because that is what a reader has to find.\n */\nexport function shortSrc(src: string): string {\n if (!src.startsWith(\"~\")) return src;\n const colon = src.indexOf(\":\");\n const token = colon === -1 ? src : src.slice(0, colon);\n const lines = colon === -1 ? \"\" : src.slice(colon);\n return token.length <= 5 ? src : `${token.slice(0, 5)}…${lines}`;\n}\n","/**\n * Where a `src` may resolve to, and how an encrypted source is written and\n * read.\n *\n * Sources resolve through tracked files only (`git ls-files -z`) when git is\n * available, else through a walk that follows no symlinks. Every candidate is\n * realpath-contained in the root, so a committed symlink or a `..` cannot reach\n * outside it. A page is untrusted input to the CI job that checks it.\n *\n * An encrypted source is the path encrypted with the family key in the\n * `cite-src` context (proposal 0045). Reading one decrypts it to the path and\n * then asks the index exactly as a plain path is asked, so a ciphertext is\n * never a way around the tracked-file rule.\n */\nimport fg from \"fast-glob\";\nimport { lstat, readFile, realpath } from \"node:fs/promises\";\nimport { join, sep } from \"node:path\";\nimport { decryptValue, encryptValue } from \"../../shared/encryption.js\";\nimport { CiteError } from \"../errors.js\";\nimport type { GitClient, MissingReason, SourceIndex, SourceRange } from \"../types.js\";\nimport { SRC_PATTERN } from \"./range.js\";\n\n/** The one context cite encrypts in, bound as associated data. */\nconst CONTEXT = \"cite-src\";\n\n/** `path` encrypted under `key`: `~` and at least 82 base64url characters. */\nexport function encryptSourcePath(path: string, key: string): string {\n return encryptValue(path, key, CONTEXT);\n}\n\n/**\n * The path an encrypted source holds, or `undefined` when it does not decrypt\n * under `key` in the `cite-src` context, or holds anything but a path a plain\n * `src` could spell. A ciphertext is trusted no further than the page's own\n * paths are.\n */\nexport function decryptSourcePath(token: string, key: string): string | undefined {\n const opened = decryptValue(token, key, CONTEXT);\n if (!opened.ok || typeof opened.value !== \"string\") return undefined;\n const path = opened.value;\n // A bare plain path: no line suffix, and no ciphertext inside a ciphertext.\n if (path.includes(\":\") || path.startsWith(\"~\") || !SRC_PATTERN.test(path)) return undefined;\n return path;\n}\n\nexport interface BuildIndexOptions {\n /** `git ls-files` when this client reports git available; a walk when it does not, or with no client. */\n gitClient?: GitClient;\n}\n\n/** `true` when `real` is `realRoot` itself or lies below it. */\nfunction isUnder(real: string, realRoot: string): boolean {\n return real === realRoot || real.startsWith(realRoot.endsWith(sep) ? realRoot : realRoot + sep);\n}\n\n/**\n * The candidate's posix relative path if it is a regular file whose real\n * location lies under the real root; `undefined` to drop it. A symlink is\n * dropped by `lstat` before it is ever followed; a path that walks out, or a\n * file reached through a symlinked directory, is dropped by the realpath check.\n */\nasync function admit(root: string, realRoot: string, rel: string): Promise<string | undefined> {\n const abs = join(root, rel);\n try {\n const info = await lstat(abs);\n if (!info.isFile()) return undefined;\n const real = await realpath(abs);\n return isUnder(real, realRoot) ? rel : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function candidates(root: string, opts: BuildIndexOptions | undefined): Promise<string[]> {\n const client = opts?.gitClient;\n if (client !== undefined && (await client.available())) {\n return client.lsFiles();\n }\n return fg(\"**/*\", {\n cwd: root,\n onlyFiles: true,\n dot: true,\n followSymbolicLinks: false,\n ignore: [\"**/.git/**\", \"**/node_modules/**\"],\n });\n}\n\nexport async function buildSourceIndex(root: string, opts?: BuildIndexOptions): Promise<SourceIndex> {\n const realRoot = await realpath(root);\n const admitted = await Promise.all(\n (await candidates(root, opts)).map((rel) => admit(root, realRoot, rel)),\n );\n const files = Object.freeze(\n [...new Set(admitted.filter((rel): rel is string => rel !== undefined))].sort(),\n );\n const byPath = new Set(files);\n return {\n files: () => files,\n has: (path) => byPath.has(path),\n };\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\n/**\n * The source index for a run, with a root that is not there refused as a\n * `CiteError`. Every verb that reads sources builds its index here, so the\n * refusal reads the same on each.\n */\nexport async function sourceIndexFor(root: string, client: GitClient): Promise<SourceIndex> {\n try {\n return await buildSourceIndex(root, { gitClient: client });\n } catch (error) {\n if (isEnoent(error)) throw new CiteError(`Root directory not found: ${root}.`);\n throw error;\n }\n}\n\nexport type ReadSourceResult =\n | { kind: \"ok\"; resolvedPath: string; text: string }\n | { kind: \"missing\"; reason: MissingReason };\n\n/**\n * Read the file a range names. An encrypted source is decrypted under `key`\n * first: with no key it is `no-key`, under another key `undecryptable`. Never\n * reads a path the index does not hold.\n */\nexport async function readSource(\n root: string,\n index: SourceIndex,\n range: SourceRange,\n key?: string,\n): Promise<ReadSourceResult> {\n let resolvedPath: string;\n if (range.encrypted) {\n if (key === undefined) return { kind: \"missing\", reason: \"no-key\" };\n const path = decryptSourcePath(range.path, key);\n if (path === undefined) return { kind: \"missing\", reason: \"undecryptable\" };\n resolvedPath = path;\n } else {\n resolvedPath = range.path;\n }\n if (!index.has(resolvedPath)) return { kind: \"missing\", reason: \"untracked\" };\n try {\n const text = await readFile(join(root, resolvedPath), \"utf8\");\n return { kind: \"ok\", resolvedPath, text };\n } catch {\n return { kind: \"missing\", reason: \"unreadable\" };\n }\n}\n","/**\n * The stretches of a text that are code, so a scanner can skip them: a page\n * that documents a syntax is not an instance of it. cite skips code when it\n * looks for markers, and term's body readers skip it when they look for\n * glossary entries.\n *\n * - A fenced block: ``` or ~~~ in markdown and mdx, indented or not, since a\n * fence keeps its meaning inside a list item; `----` at column 0 in\n * asciidoc. It is closed by the same character, at least as many of it, and\n * nothing else on the line. An unclosed fence runs to the end, as a renderer\n * reads it.\n * - A backtick span, in markdown, mdx, asciidoc and rst: a run of backticks\n * closed by a run of the same length on the same line. A run with no closer\n * is literal text.\n *\n * html and xml have neither; a `<pre>` is not code here.\n */\n\n/** A stretch of code, as `[start, end)` offsets of the text it was found in. */\nexport interface CodeRegion {\n start: number;\n end: number;\n}\n\nexport interface CodeRegionOptions {\n /** Include backtick spans. Default `true`; `false` returns fenced blocks only. */\n spans?: boolean;\n}\n\nconst SKIP_MARKDOWN_FENCE = /^[ \\t]*(`{3,}|~{3,})/;\nconst SKIP_ASCIIDOC_FENCE = /^(-{4,})/;\n/** Formats where a backtick span is inline code. */\nconst SPAN_FORMATS = new Set([\"markdown\", \"mdx\", \"asciidoc\", \"rst\"]);\nconst BACKTICK = 96;\n\n/** The fence-opener pattern for a format, or undefined when it has no fences. */\nfunction fenceFor(format: string): RegExp | undefined {\n switch (format) {\n case \"markdown\":\n case \"mdx\":\n return SKIP_MARKDOWN_FENCE;\n case \"asciidoc\":\n return SKIP_ASCIIDOC_FENCE;\n default:\n return undefined;\n }\n}\n\n/** Length of the run of backticks starting at `i` in `text` (0 when none). */\nfunction backtickRun(text: string, i: number): number {\n let n = 0;\n while (text.charCodeAt(i + n) === BACKTICK) n++;\n return n;\n}\n\n/** The backtick spans on one line, appended to `out` as offsets of the whole text. */\nfunction spanRegions(line: string, lineStart: number, out: CodeRegion[]): void {\n let i = 0;\n while (i < line.length) {\n const n = backtickRun(line, i);\n if (n === 0) {\n i++;\n continue;\n }\n let j = i + n;\n let closer = -1;\n while (j < line.length) {\n const m = backtickRun(line, j);\n if (m === 0) {\n j++;\n continue;\n }\n if (m === n) {\n closer = j;\n break;\n }\n j += m;\n }\n if (closer === -1) {\n i += n;\n continue;\n }\n out.push({ start: lineStart + i, end: lineStart + closer + n });\n i = closer + n;\n }\n}\n\n/**\n * Whether a line closes the fence `open`. A longer run does not close a\n * shorter one's block, which is how a ```` block carries a ``` block inside it.\n */\nfunction closesFence(line: string, open: { char: string; length: number }): boolean {\n const trimmed = line.trim();\n let n = 0;\n while (trimmed.charAt(n) === open.char) n++;\n return n >= open.length && n === trimmed.length;\n}\n\n/**\n * Every fenced block and backtick span in `text`, in order, for a format that\n * has them. A closed fence's region ends at its closing line's terminator; an\n * unclosed one ends at the end of the text. Spans are not looked for inside a\n * fence.\n */\nexport function codeRegions(\n text: string,\n format: string,\n options: CodeRegionOptions = {},\n): CodeRegion[] {\n const fence = fenceFor(format);\n const spans = options.spans !== false && SPAN_FORMATS.has(format);\n const out: CodeRegion[] = [];\n if (fence === undefined && !spans) return out;\n let open: { char: string; length: number; start: number } | undefined;\n let pos = 0;\n while (pos < text.length) {\n const nl = text.indexOf(\"\\n\", pos);\n const end = nl === -1 ? text.length : nl;\n const raw = text.slice(pos, end);\n const line = raw.endsWith(\"\\r\") ? raw.slice(0, -1) : raw;\n if (open !== undefined) {\n if (closesFence(line, open)) {\n out.push({ start: open.start, end });\n open = undefined;\n }\n } else {\n const opener = fence?.exec(line)?.[1];\n if (opener !== undefined) {\n open = { char: opener.charAt(0), length: opener.length, start: pos };\n } else if (spans) {\n spanRegions(line, pos, out);\n }\n }\n pos = end + 1;\n }\n if (open !== undefined) out.push({ start: open.start, end: text.length });\n return out;\n}\n\n/** The end of the region `offset` falls in, or undefined when it falls in none. */\nexport function codeEndAt(regions: readonly CodeRegion[], offset: number): number | undefined {\n return regions.find((r) => offset >= r.start && offset < r.end)?.end;\n}\n","/**\n * Markers: `cite <id>` inside the format's comment syntax.\n *\n * | Format | Forms |\n * |---------------|--------------------------------------------------------------|\n * | markdown, mdx | `<!-- cite … -->`, `{/* cite … *\\/}`, `[comment]: # (cite …)` |\n * | html, xml | `<!-- cite … -->` |\n * | asciidoc | `// (cite …)` |\n * | rst | `.. (cite …)` |\n *\n * A marker carries an id and nothing else (`cite true` names id `true`). A\n * payload starting with `{` was the inline entry of proposal 0044's first\n * draft; it is `marker-invalid` now, because an entry lives in frontmatter or\n * a manifest and a source is never written into the body. The scanner uses\n * `indexOf` for the delimiters, never a regex over the whole page, and is\n * handed the body only, so a `cite` inside frontmatter is never matched.\n *\n * It does not read code. An opener inside a fenced block or a backtick span,\n * as `src/shared/code-regions.ts` finds them, is skipped, so a page that\n * documents the syntax carries no statements.\n *\n * Every form parses in both markdown and mdx. The first form is what\n * `formatStatement` writes: the html comment for markdown, the jsx comment\n * for mdx, which rejects an html comment.\n */\nimport type { InlineStatement } from \"../types.js\";\nimport { codeEndAt, codeRegions } from \"../../shared/code-regions.js\";\nimport { CiteError } from \"../errors.js\";\n\nexport interface StatementForm {\n open: string;\n close: string;\n}\n\nconst HTML_COMMENT: StatementForm = { open: \"<!--\", close: \"-->\" };\nconst JSX_COMMENT: StatementForm = { open: \"{/*\", close: \"*/}\" };\nconst LINK_REFERENCE: StatementForm = { open: \"[comment]: # (\", close: \")\" };\nconst MARKDOWN_FORMS: readonly StatementForm[] = [HTML_COMMENT, JSX_COMMENT, LINK_REFERENCE];\nconst MDX_FORMS: readonly StatementForm[] = [JSX_COMMENT, HTML_COMMENT, LINK_REFERENCE];\nconst COMMENT_FORMS: readonly StatementForm[] = [{ open: \"<!--\", close: \"-->\" }];\nconst ASCIIDOC_FORMS: readonly StatementForm[] = [{ open: \"// (\", close: \")\" }];\nconst RST_FORMS: readonly StatementForm[] = [{ open: \".. (\", close: \")\" }];\n\nconst ID = /^[a-z0-9][a-z0-9-]*$/;\n\n/**\n * A fence opener in any format. `paragraphAfter` and the claim search\n * (`claims.ts`) have no format parameter, so they treat every family's opener\n * as a fence; the per-format locators below are what `quote` anchoring uses.\n * A markdown fence keeps its meaning when indented, as inside a list item, so\n * it is read there too, matching the code skip in `src/shared/code-regions.ts`; the\n * asciidoc `----` stays at column 0.\n */\nexport const ANY_FENCE = /^(?:[ \\t]*(?:`{3,}|~{3,})|-{4,})/;\nconst MARKDOWN_FENCE = /^(`{3,}|~{3,})/;\nconst ASCIIDOC_FENCE = /^(-{4,})/;\n/** The forms per extractor name. Unknown formats have none. */\nexport function statementForms(format: string): readonly StatementForm[] {\n switch (format) {\n case \"markdown\":\n return MARKDOWN_FORMS;\n case \"mdx\":\n return MDX_FORMS;\n case \"html\":\n case \"xml\":\n return COMMENT_FORMS;\n case \"asciidoc\":\n return ASCIIDOC_FORMS;\n case \"rst\":\n return RST_FORMS;\n default:\n return [];\n }\n}\n\n/** The fence-opener pattern for a format, or undefined when it has no locator. */\nfunction fenceFor(format: string): RegExp | undefined {\n switch (format) {\n case \"markdown\":\n case \"mdx\":\n return MARKDOWN_FENCE;\n case \"asciidoc\":\n return ASCIIDOC_FENCE;\n default:\n return undefined;\n }\n}\n\n/** Offset of the terminator of the line containing `pos` (or the text length). */\nfunction lineEnd(content: string, pos: number): number {\n const nl = content.indexOf(\"\\n\", pos);\n return nl === -1 ? content.length : nl;\n}\n\n/** The text of the line `[pos, end)`, without a trailing CR. */\nfunction lineText(content: string, pos: number, end: number): string {\n const text = content.slice(pos, end);\n return text.endsWith(\"\\r\") ? text.slice(0, -1) : text;\n}\n\n/** `end` pulled back over a CR so a CRLF terminator is excluded whole. */\nfunction beforeCr(content: string, end: number): number {\n return end > 0 && content.charCodeAt(end - 1) === 13 ? end - 1 : end;\n}\n\n/**\n * Where a forward scan of whole lines starts from `offset`: the next line when\n * `offset` sits inside one (the rest of a statement's own line), the line\n * itself when `offset` is already at its start.\n */\nfunction nextLineStart(content: string, offset: number): number {\n if (offset === 0 || content.charCodeAt(offset - 1) === 10) return offset;\n return lineEnd(content, offset) + 1;\n}\n\nfunction payloadOf(payload: string): InlineStatement[\"payload\"] {\n if (payload === \"\") return { kind: \"bad\", reason: \"empty payload\" };\n // An entry lives in frontmatter or a manifest; the body carries a name.\n if (payload.startsWith(\"{\")) return { kind: \"bad\", reason: \"a JSON payload\", json: true };\n if (ID.test(payload)) return { kind: \"ref\", id: payload };\n return { kind: \"bad\", reason: \"payload is not an id\" };\n}\n\n/** Whether the text between a form's delimiters is a cite statement. */\nfunction isCite(inner: string): boolean {\n return inner === \"cite\" || (inner.startsWith(\"cite\") && /\\s/.test(inner.charAt(4)));\n}\n\n/**\n * Whether a line holds one marker and nothing else, in any of the format's\n * forms. Such a line is never text a marker anchors: markers stacked above a\n * paragraph all anchor the paragraph, and none of them is part of its pin.\n */\nexport function isMarkerLine(line: string, format: string): boolean {\n const text = line.trim();\n return statementForms(format).some((form) => {\n if (text.length < form.open.length + form.close.length) return false;\n if (!text.startsWith(form.open)) return false;\n // The first close is the last thing on the line, so there is one marker.\n const closeAt = text.indexOf(form.close, form.open.length);\n if (closeAt !== text.length - form.close.length) return false;\n return isCite(text.slice(form.open.length, closeAt).trim());\n });\n}\n\n/** Scan a body for statements. `from` maps body offsets/lines to file offsets/lines. */\nexport function parseStatements(\n body: string,\n format: string,\n from: { offset: number; line: number } = { offset: 0, line: 1 },\n): InlineStatement[] {\n const out: InlineStatement[] = [];\n const fileLine = (bodyOffset: number): number =>\n from.line + lineAt(body, bodyOffset) - 1;\n const code = codeRegions(body, format);\n\n for (const form of statementForms(format)) {\n let cursor = 0;\n for (;;) {\n const at = body.indexOf(form.open, cursor);\n if (at === -1) break;\n const codeEnd = codeEndAt(code, at);\n if (codeEnd !== undefined) {\n cursor = codeEnd;\n continue;\n }\n const closeAt = body.indexOf(form.close, at + form.open.length);\n if (closeAt === -1) break;\n const end = closeAt + form.close.length;\n cursor = end;\n const inner = body.slice(at + form.open.length, closeAt).trim();\n if (!isCite(inner)) continue;\n const payload = inner.slice(4).trim();\n\n // Anchor: the rest of the close delimiter's line when it carries text,\n // else the paragraph or fenced block that follows.\n const unit = anchoredLines(body, end, format);\n const anchorLine = unit === undefined ? undefined : from.line + unit.start - 1;\n\n const statement: InlineStatement = {\n line: fileLine(at),\n payload: payloadOf(payload),\n raw: inner,\n start: from.offset + at,\n end: from.offset + end,\n };\n if (anchorLine !== undefined) statement.anchorLine = anchorLine;\n out.push(statement);\n }\n }\n return out.sort((a, b) => a.start - b.start);\n}\n\n/** `\"\\r\\n\"` when the text's first line break is CRLF, else `\"\\n\"`. */\nexport function detectEol(text: string): \"\\n\" | \"\\r\\n\" {\n const nl = text.indexOf(\"\\n\");\n return nl > 0 && text.charCodeAt(nl - 1) === 13 ? \"\\r\\n\" : \"\\n\";\n}\n\n/**\n * The paragraph starting at or after `offset` (skipping blank lines), as\n * `{ start, end, line }` file offsets and the file line it starts on. A fence\n * opener ends the search with no paragraph. Given a `format`, a marker-only\n * line is skipped like a blank one before the paragraph, and ends it after.\n */\nexport function paragraphAfter(\n content: string,\n offset: number,\n format?: string,\n): { start: number; end: number; line: number } | undefined {\n const marker = (text: string): boolean => format !== undefined && isMarkerLine(text, format);\n let pos = offset;\n // The rest of the line `offset` sits in counts when it carries text; when\n // it is blank the paragraph can only start on a later line.\n const firstEnd = lineEnd(content, pos);\n if (lineText(content, pos, firstEnd).trim() === \"\") pos = firstEnd + 1;\n\n while (pos < content.length) {\n const end = lineEnd(content, pos);\n const text = lineText(content, pos, end);\n if (text.trim() === \"\" || marker(text)) {\n pos = end + 1;\n continue;\n }\n if (ANY_FENCE.test(text)) return undefined;\n const start = pos;\n let last = end;\n let cursor = end + 1;\n while (cursor < content.length) {\n const e = lineEnd(content, cursor);\n const t = lineText(content, cursor, e);\n if (t.trim() === \"\" || ANY_FENCE.test(t) || marker(t)) break;\n last = e;\n cursor = e + 1;\n }\n return { start, end: beforeCr(content, last), line: lineAt(content, start) };\n }\n return undefined;\n}\n\ninterface FencedBlock {\n start: number;\n end: number;\n line: number;\n text: string;\n}\n\n/**\n * The next fenced block whose opener matches `fence`, scanning whole lines\n * from `offset`, plus the offset just past its closing fence line so a caller\n * can continue.\n */\nfunction scanFence(\n content: string,\n offset: number,\n fence: RegExp,\n): (FencedBlock & { next: number }) | undefined {\n let pos = nextLineStart(content, offset);\n while (pos < content.length) {\n const end = lineEnd(content, pos);\n const text = lineText(content, pos, end);\n const opener = fence.exec(text)?.[1];\n if (opener === undefined) {\n pos = end + 1;\n continue;\n }\n const line = lineAt(content, pos);\n const start = Math.min(end + 1, content.length);\n let cursor = start;\n while (cursor < content.length) {\n const e = lineEnd(content, cursor);\n if (lineText(content, cursor, e).startsWith(opener)) {\n return {\n start,\n end: cursor,\n line,\n text: content.slice(start, cursor),\n next: e + 1,\n };\n }\n cursor = e + 1;\n }\n return undefined;\n }\n return undefined;\n}\n\n/**\n * The fenced code block starting at or after `offset` (``` or ~~~; asciidoc\n * `----`), as file offsets of its content lines and the file line of the\n * opening fence. `undefined` for formats with no locator (html, xml, rst).\n */\nexport function fencedBlockAfter(\n content: string,\n offset: number,\n format: string,\n): { start: number; end: number; line: number; text: string } | undefined {\n const fence = fenceFor(format);\n if (!fence) return undefined;\n const block = scanFence(content, offset, fence);\n if (!block) return undefined;\n const { start, end, line, text } = block;\n return { start, end, line, text };\n}\n\n/**\n * The fenced block at `offset` in any fence family, for callers that have no\n * format at hand (the claim search). Undefined when the line at `offset` is\n * not an opener.\n */\nexport function fencedBlockAt(\n content: string,\n offset: number,\n): { start: number; end: number; line: number; text: string } | undefined {\n const pos = nextLineStart(content, offset);\n if (!ANY_FENCE.test(lineText(content, pos, lineEnd(content, pos)))) {\n return undefined;\n }\n const block =\n scanFence(content, pos, MARKDOWN_FENCE) ?? scanFence(content, pos, ASCIIDOC_FENCE);\n if (!block || block.line !== lineAt(content, pos)) return undefined;\n const { start, end, line, text } = block;\n return { start, end, line, text };\n}\n\n/** Every fenced block in the body, for `--quote` without `--claim`. */\nexport function fencedBlocks(\n content: string,\n bodyOffset: number,\n format: string,\n): { start: number; end: number; line: number; text: string }[] {\n const fence = fenceFor(format);\n if (!fence) return [];\n const out: FencedBlock[] = [];\n let pos = bodyOffset;\n for (;;) {\n const block = scanFence(content, pos, fence);\n if (!block) return out;\n const { start, end, line, text } = block;\n out.push({ start, end, line, text });\n pos = block.next;\n }\n}\n\n/** The form `formatStatement` writes for a format, or a refusal naming the format. */\nfunction writtenForm(format: string): StatementForm {\n const form = statementForms(format)[0];\n if (!form) {\n throw new CiteError(`No marker syntax for format \"${format}\".`);\n }\n return form;\n}\n\n/** Render a marker in the format's first form, e.g. `<!-- cite fetch-timeout -->`. */\nexport function formatStatement(format: string, payload: { kind: \"ref\"; id: string }): string {\n const form = writtenForm(format);\n // `[comment]: # (`, `// (` and `.. (` hug their parentheses; the comment\n // forms take a space inside each delimiter.\n const pad = form.open.endsWith(\"(\") ? \"\" : \" \";\n return `${form.open}${pad}cite ${payload.id}${pad}${form.close}`;\n}\n\n/**\n * The first line at or after `offset` that is neither blank nor a marker on\n * its own, as a 1-based line of `text`.\n */\nfunction nextTextLine(text: string, offset: number, format: string): number | undefined {\n let pos = nextLineStart(text, offset);\n while (pos < text.length) {\n const end = lineEnd(text, pos);\n const line = lineText(text, pos, end);\n if (line.trim() !== \"\" && !isMarkerLine(line, format)) return lineAt(text, pos);\n pos = end + 1;\n }\n return undefined;\n}\n\n/**\n * The fenced block opening on `line`, as the lines it spans, fences included.\n * Undefined when that line is not an opener the format knows, or the block is\n * never closed.\n */\nexport function fenceSpanAt(\n text: string,\n line: number,\n format: string,\n): { start: number; end: number } | undefined {\n const fence = fenceFor(format);\n if (!fence) return undefined;\n const block = scanFence(text, offsetOfLine(text, line), fence);\n if (!block || block.line !== line) return undefined;\n return { start: line, end: lineAt(text, block.end) };\n}\n\n/** Whether `line` sits inside a fenced block rather than opening one. */\nexport function insideFence(\n text: string,\n bodyOffset: number,\n line: number,\n format: string,\n): boolean {\n return fencedBlocks(text, bodyOffset, format).some(\n (block) => line > block.line && line <= lineAt(text, block.end),\n );\n}\n\n/**\n * The paragraph or fenced block that holds `line`, as the lines it spans,\n * fences included: what a marker written above it anchors. A paragraph runs\n * up to a blank line, a fence, a marker-only line or the body's start, and\n * down as `paragraphAfter` reads it. Undefined for a blank line, a marker-only\n * line, or a line nothing can anchor.\n */\nexport function unitHolding(\n text: string,\n line: number,\n format: string,\n body: { offset: number; line: number },\n): { start: number; end: number; kind: \"paragraph\" | \"block\" } | undefined {\n const textOf = (n: number): string => lineText(text, offsetOfLine(text, n), lineEnd(text, offsetOfLine(text, n)));\n const own = textOf(line);\n if (own.trim() === \"\" || isMarkerLine(own, format)) return undefined;\n const block = fencedBlocks(text, body.offset, format).find(\n (b) => line >= b.line && line <= lineAt(text, b.end),\n );\n if (block !== undefined) {\n return { start: block.line, end: lineAt(text, block.end), kind: \"block\" };\n }\n if (ANY_FENCE.test(own)) return undefined;\n let start = line;\n while (start - 1 >= body.line) {\n const above = textOf(start - 1);\n if (above.trim() === \"\" || ANY_FENCE.test(above) || isMarkerLine(above, format)) break;\n start--;\n }\n const paragraph = paragraphAfter(text, offsetOfLine(text, start), format);\n if (paragraph?.line !== start) return undefined;\n return { start, end: lineAt(text, paragraph.end), kind: \"paragraph\" };\n}\n\n/** A markdown list item's opening line: its indentation, its bullet or number, and the gap after. */\nconst LIST_ITEM = /^([ \\t]*)([-*+]|\\d{1,9}[.)])([ \\t]+|$)/;\n/** A thematic break, which a list item's pattern would otherwise read as `* * *`. */\nconst THEMATIC_BREAK = /^[ \\t]*([-*_])(?:[ \\t]*\\1){2,}[ \\t]*$/;\n\n/** The text of 1-based line `n` of `text`. */\nfunction textOfLine(text: string, n: number): string {\n const pos = offsetOfLine(text, n);\n return lineText(text, pos, lineEnd(text, pos));\n}\n\n/** The leading spaces and tabs of a line. */\nfunction indentOf(line: string): string {\n return /^[ \\t]*/.exec(line)?.[0] ?? \"\";\n}\n\n/** The column a run of spaces and tabs reaches, with tab stops every 4 columns. */\nfunction columnOf(indent: string): number {\n let column = 0;\n for (const ch of indent) column = ch === \"\\t\" ? column + 4 - (column % 4) : column + 1;\n return column;\n}\n\n/** The list item a markdown line opens, or undefined. */\nfunction listItemOf(line: string): { lead: string; bullet: string; gap: string } | undefined {\n if (THEMATIC_BREAK.test(line)) return undefined;\n const match = LIST_ITEM.exec(line);\n if (match === null) return undefined;\n const [, lead = \"\", bullet = \"\", gap = \"\"] = match;\n return { lead, bullet, gap };\n}\n\n/**\n * Whether the list item on `line` follows an earlier item of its list: the\n * nearest text above it, past blank and marker-only lines, is indented deeper\n * than the item, or sits in a paragraph holding an item at the same column.\n */\nfunction continuesList(\n text: string,\n line: number,\n format: string,\n bodyLine: number,\n column: number,\n): boolean {\n let n = line - 1;\n while (n >= bodyLine) {\n const above = textOfLine(text, n);\n if (above.trim() !== \"\" && !isMarkerLine(above, format)) break;\n n--;\n }\n if (n < bodyLine) return false;\n if (columnOf(indentOf(textOfLine(text, n))) > column) return true;\n for (; n >= bodyLine; n--) {\n const above = textOfLine(text, n);\n if (above.trim() === \"\" || ANY_FENCE.test(above) || isMarkerLine(above, format)) break;\n const item = listItemOf(above);\n if (item !== undefined && columnOf(item.lead) === column) return true;\n }\n return false;\n}\n\n/**\n * The indentation a marker written above `line` carries, so it stays in the\n * container the line is in. A paragraph's own leading spaces and tabs, copied\n * as they are. Above a markdown list item that follows an earlier item, the\n * column of the item's text, which keeps the marker inside the list: at the\n * item's own column it would end the list. asciidoc never indents one, since\n * a comment there starts at column 0.\n */\nexport function markerIndent(\n text: string,\n line: number,\n format: string,\n bodyLine: number,\n): string {\n if (format === \"asciidoc\") return \"\";\n const own = textOfLine(text, line);\n const indent = indentOf(own);\n if (format !== \"markdown\" && format !== \"mdx\") return indent;\n const item = listItemOf(own);\n if (item === undefined || !continuesList(text, line, format, bodyLine, columnOf(item.lead))) {\n return indent;\n }\n // A gap of five spaces or more is one space and indented code, so the text starts after one.\n const gap = item.gap === \"\" || columnOf(item.gap) > 4 ? \" \" : item.gap;\n return item.lead + \" \".repeat(item.bullet.length) + gap;\n}\n\n/**\n * The lines a marker anchors, as 1-based lines of `text`: the rest of its own\n * line when that carries text, else the paragraph or fenced block that\n * follows. Marker-only lines below it are skipped, so markers stacked above\n * one paragraph all anchor it, and none is part of the pin. With `quote`, the\n * next fenced block after it, wherever that is. Undefined when nothing\n * follows to anchor.\n */\nexport function anchoredLines(\n text: string,\n after: number,\n format: string,\n quote = false,\n): { start: number; end: number } | undefined {\n if (quote) {\n const block = fencedBlockAfter(text, after, format);\n return block === undefined ? undefined : { start: block.line, end: lineAt(text, block.end) };\n }\n const restEnd = lineEnd(text, after);\n if (text.slice(after, restEnd).trim() !== \"\") {\n const line = lineAt(text, after);\n return { start: line, end: line };\n }\n const paragraph = paragraphAfter(text, after, format);\n if (paragraph !== undefined) {\n return { start: paragraph.line, end: lineAt(text, paragraph.end) };\n }\n // A fence where a paragraph would be: the block is what the marker anchors.\n const line = nextTextLine(text, after, format);\n return line === undefined ? undefined : fenceSpanAt(text, line, format);\n}\n\n/** 1-based file line of a file offset, counting CRLF once. */\nexport function lineAt(content: string, offset: number): number {\n const stop = Math.min(offset, content.length);\n let line = 1;\n for (let i = 0; i < stop; i++) {\n if (content.charCodeAt(i) === 10) line++;\n }\n return line;\n}\n\n/** File offset of the first character of a 1-based line (the length when past the end). */\nexport function offsetOfLine(content: string, line: number): number {\n let pos = 0;\n for (let n = 1; n < line; n++) {\n const nl = content.indexOf(\"\\n\", pos);\n if (nl === -1) return content.length;\n pos = nl + 1;\n }\n return pos;\n}\n","/**\n * The claim end: the page text a citation supports, classified by the same\n * machinery as the source end and against the page as it is now.\n *\n * The claim's lines are body-relative, so editing the frontmatter never moves\n * them; every line a person reads is a file line, translated here. The pin\n * holds at the recorded lines: `current`. The same text is found verbatim\n * elsewhere in the body: `moved`, once, or `moved-ambiguous`. Nowhere:\n * `changed`, the sentence was edited. A marker-anchored claim pins what the\n * marker anchors, so it never moves; it is `current` or `changed`.\n */\nimport type {\n ClaimEnd,\n PageCitation,\n PageCitations,\n PageLines,\n} from \"../types.js\";\nimport { findWindows, parseLines, pinOfLines, spellLines, toFileLines } from \"../../shared/pin.js\";\nimport {\n anchoredLines,\n fenceSpanAt,\n insideFence,\n lineAt,\n offsetOfLine,\n paragraphAfter,\n} from \"./statements.js\";\n\n// The line translation and the claim pin are the shared pin engine's; this path keeps cite's imports working.\nexport { pinOfLines, toBodyLines, toFileLines } from \"../../shared/pin.js\";\n\nexport function normalizeWhitespace(text: string): string {\n return text.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * The hashing rule's normalization for a whole quoted block: one BOM, CRLF →\n * LF, and one trailing LF dropped. It differs from the shared `normalizeText`\n * only in that last step, because a quote is compared as one joined block\n * rather than split into lines first.\n */\nfunction normalizeBlock(text: string): string {\n let out = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n out = out.replace(/\\r\\n/g, \"\\n\");\n return out.endsWith(\"\\n\") ? out.slice(0, -1) : out;\n}\n\n/** `true` when the block's normalized text equals the cited lines under the hashing rule. */\nexport function blockMatches(blockText: string, citedJoined: string): boolean {\n return normalizeBlock(blockText) === normalizeBlock(citedJoined);\n}\n\n/** The page lines a range covers, as far as the page reaches. */\nfunction textAt(lines: readonly string[], range: PageLines): string[] {\n return lines.slice(range.start - 1, Math.min(range.end, lines.length));\n}\n\n/** The first file line of a classified claim: where its findings sit. */\nexport function claimLine(claim: ClaimEnd): number | undefined {\n const at = claim.fileLines === undefined ? undefined : parseLines(claim.fileLines);\n return at?.start;\n}\n\n/** Where the claim is now: the moved-to lines when it moved, else the recorded ones. */\nexport function claimLineNow(claim: ClaimEnd): number | undefined {\n const spec = claim.newFileLines ?? claim.candidateFileLines?.[0] ?? claim.fileLines;\n const at = spec === undefined ? undefined : parseLines(spec);\n return at?.start;\n}\n\n/** The file lines the claim occupies now, for the quote check. */\nexport function claimLinesNow(claim: ClaimEnd): PageLines | undefined {\n const spec = claim.newFileLines ?? claim.candidateFileLines?.[0] ?? claim.fileLines;\n return spec === undefined ? undefined : parseLines(spec);\n}\n\n/**\n * Classify one entry's claim end against the page. `lines` is the page under\n * the hashing rule (`splitLines`). `null` for an entry with no `claim`: a\n * bare pin, or a marker with no drift check on its sentence.\n */\nexport function claimEnd(\n page: PageCitations,\n entry: PageCitation,\n lines: readonly string[],\n): ClaimEnd | null {\n const { citation, marker } = entry;\n const claim = citation.claim;\n if (claim === undefined) return null;\n const quote = citation.quote === true;\n const body = page.bodyLine;\n\n if (claim.lines !== undefined) {\n const recorded = parseLines(claim.lines);\n // An unreadable range is `entry-invalid`, and that entry is never classified.\n if (recorded === undefined) return { status: \"skipped\" };\n const file = toFileLines(recorded, body);\n const end: ClaimEnd = {\n lines: spellLines(recorded),\n fileLines: spellLines(file),\n status: \"changed\",\n };\n // Lines and a marker both: `anchor-invalid`, and neither anchor is judged.\n if (marker !== undefined) return { ...end, status: \"skipped\" };\n if (pinOfLines(lines, file) === claim.integrity) return { ...end, status: \"current\" };\n\n const width = recorded.end - recorded.start + 1;\n const found = findWindows(lines.slice(body - 1), width, claim.integrity, undefined, {\n around: recorded.start,\n });\n const spans = found.starts.map((start) => ({ start, end: start + width - 1 }));\n const [only] = spans;\n if (spans.length === 1 && only !== undefined) {\n return {\n ...end,\n status: \"moved\",\n newLines: spellLines(only),\n newFileLines: spellLines(toFileLines(only, body)),\n };\n }\n if (spans.length > 1) {\n return {\n ...end,\n status: \"moved-ambiguous\",\n candidates: spans.map(spellLines),\n candidateFileLines: spans.map((span) => spellLines(toFileLines(span, body))),\n };\n }\n return { ...end, text: textAt(lines, file) };\n }\n\n if (marker !== undefined) {\n // The marker moves with its text, so a marker-anchored claim never moves.\n const unit = anchoredLines(page.content, marker.end, page.format, quote);\n if (unit === undefined) return { status: \"changed\" };\n const end: ClaimEnd = { fileLines: spellLines(unit), status: \"changed\" };\n if (pinOfLines(lines, unit) === claim.integrity) return { ...end, status: \"current\" };\n return { ...end, text: textAt(lines, unit) };\n }\n\n // A claim pin with neither lines nor a marker anchors nothing at all.\n return { status: \"changed\" };\n}\n\n/** What `update --accept` re-pins over: the paragraph or fenced block at a line. */\nexport interface ClaimUnit {\n lines: PageLines;\n kind: \"paragraph\" | \"block\";\n text: string[];\n}\n\n/**\n * The paragraph or fenced block at a file line. Undefined when the line is\n * blank, outside the body, or inside a fenced block rather than opening one:\n * those are the claims `update --accept` skips.\n *\n * A paragraph runs from this line to its end, not from the paragraph's own\n * first line. The line asked about is the claim's first line, and re-pinning\n * has to leave that where it is, so a claim that started mid-paragraph keeps\n * starting there.\n */\nexport function unitAt(\n page: PageCitations,\n line: number,\n lines: readonly string[],\n): ClaimUnit | undefined {\n if (line < page.bodyLine || line > lines.length) return undefined;\n if ((lines[line - 1] ?? \"\").trim() === \"\") return undefined;\n const block = fenceSpanAt(page.content, line, page.format);\n if (block !== undefined) {\n return { lines: block, kind: \"block\", text: lines.slice(block.start - 1, block.end) };\n }\n if (insideFence(page.content, page.bodyOffset, line, page.format)) return undefined;\n const paragraph = paragraphAfter(page.content, offsetOfLine(page.content, line));\n if (paragraph === undefined || paragraph.line !== line) return undefined;\n const span: PageLines = { start: line, end: lineAt(page.content, paragraph.end) };\n return { lines: span, kind: \"paragraph\", text: lines.slice(span.start - 1, span.end) };\n}\n\n/** The lines a marker anchors now, for `update --accept` on a marker-anchored claim. */\nexport function markerUnit(\n page: PageCitations,\n entry: PageCitation,\n lines: readonly string[],\n): ClaimUnit | undefined {\n const { marker, citation } = entry;\n if (marker === undefined) return undefined;\n const span = anchoredLines(page.content, marker.end, page.format, citation.quote === true);\n if (span === undefined || span.end > lines.length) return undefined;\n return {\n lines: span,\n kind: citation.quote === true ? \"block\" : \"paragraph\",\n text: lines.slice(span.start - 1, span.end),\n };\n}\n","/**\n * A thin git client. Every call is `execFile(\"git\", args, { cwd: root,\n * windowsHide: true, maxBuffer: 32 MiB })` with `-c core.quotepath=false`,\n * `--end-of-options` before a commit, `--` before a path, and `<commit>:./<path>`\n * for `show` so the path resolves against the root, not the repository top.\n * Results are memoized per (call, commit, path). The commit is validated\n * against the schema's hex pattern by the caller before it reaches here.\n */\nimport { execFile } from \"node:child_process\";\nimport { CiteError } from \"../errors.js\";\nimport type { GitClient, ShownFile } from \"../types.js\";\n\nconst MAX_BUFFER = 32 * 1024 * 1024;\n\n/** Stderr shapes `git show` uses for a revision it does not have. */\nconst NO_COMMIT = /invalid object name|bad revision|unknown revision|bad object/i;\n/**\n * Stderr shapes for a path absent from the tree at a revision. Git uses these\n * for an unknown *full-length* commit too (`path 'x' does not exist in\n * '<40 hex>'`; only an abbreviated unknown commit says \"invalid object name\"),\n * so a path-shaped failure is trusted only once `rev-parse --verify` has said\n * the commit exists. A shallow clone must degrade to \"history unavailable\",\n * never to \"never true\".\n */\nconst NO_PATH = /does not exist in|exists on disk, but not in|path .* does not exist/i;\n\ntype Outcome =\n | { ok: true; stdout: string }\n /** `code` is git's exit status; absent when git could not be run at all. */\n | { ok: false; stderr: string; message: string; code?: number };\n\nfunction run(root: string, args: readonly string[]): Promise<Outcome> {\n return new Promise((resolve) => {\n execFile(\n \"git\",\n [\"-c\", \"core.quotepath=false\", ...args],\n { cwd: root, windowsHide: true, maxBuffer: MAX_BUFFER, encoding: \"utf8\" },\n (error, stdout, stderr) => {\n if (error) {\n const failure: Outcome = { ok: false, stderr, message: error.message };\n if (typeof error.code === \"number\") failure.code = error.code;\n resolve(failure);\n } else resolve({ ok: true, stdout });\n },\n );\n });\n}\n\n/** `git` at `root`, as a client; see the module comment for the call shapes. */\nexport function gitClient(root: string): GitClient {\n const memo = new Map<string, Promise<unknown>>();\n const once = <T>(key: string, compute: () => Promise<T>): Promise<T> => {\n const held = memo.get(key);\n if (held !== undefined) return held as Promise<T>;\n const made = compute();\n memo.set(key, made);\n return made;\n };\n\n const available = (): Promise<boolean> =>\n once(\"available\", async () => (await run(root, [\"rev-parse\", \"--show-toplevel\"])).ok);\n\n const failed = (verb: string, outcome: Extract<Outcome, { ok: false }>): CiteError =>\n new CiteError(`git ${verb} failed: ${outcome.stderr.trim() || outcome.message}`);\n\n /**\n * Whether the repository has the commit. `--verify --quiet` exits 1 for an\n * object it does not have, and that alone is \"no\": any other failure is\n * git itself failing, and reading it as \"no\" would turn a broken checkout\n * into shallow-clone advice.\n */\n const hasCommit = (commit: string): Promise<boolean> =>\n once(`has\\0${commit}`, async () => {\n const out = await run(root, [\"rev-parse\", \"--verify\", \"--quiet\", \"--end-of-options\", `${commit}^{commit}`]);\n if (out.ok) return true;\n if (out.code === 1) return false;\n throw failed(\"rev-parse\", out);\n });\n\n return {\n available,\n\n head: () =>\n once(\"head\", async () => {\n if (!(await available())) return null;\n const out = await run(root, [\"rev-parse\", \"HEAD\"]);\n return out.ok ? out.stdout.trim() : null;\n }),\n\n lsFiles: () =>\n once(\"ls-files\", async () => {\n if (!(await available())) return [];\n const out = await run(root, [\"ls-files\", \"-z\"]);\n if (!out.ok) throw failed(\"ls-files\", out);\n return out.stdout.split(\"\\0\").filter((entry) => entry !== \"\");\n }),\n\n showFile: (commit, path) =>\n once(`show\\0${commit}\\0${path}`, async (): Promise<ShownFile> => {\n const out = await run(root, [\"show\", \"--end-of-options\", `${commit}:./${path}`]);\n if (out.ok) return { text: out.stdout };\n if (NO_COMMIT.test(out.stderr)) return { missing: \"commit\" };\n if (NO_PATH.test(out.stderr)) {\n return (await hasCommit(commit)) ? { missing: \"path\" } : { missing: \"commit\" };\n }\n throw failed(\"show\", out);\n }),\n\n subjectsSince: (commit, path) =>\n once(`log\\0${commit}\\0${path}`, async () => {\n const out = await run(root, [\"log\", \"--format=%s\", \"--end-of-options\", `${commit}..HEAD`, \"--\", path]);\n if (!out.ok) throw failed(\"log\", out);\n return out.stdout.split(/\\r?\\n/).filter((line) => line !== \"\");\n }),\n\n diffSince: (commit, path) =>\n once(`diff\\0${commit}\\0${path}`, async () => {\n const out = await run(root, [\"diff\", \"--end-of-options\", commit, \"--\", path]);\n if (!out.ok) throw failed(\"diff\", out);\n return out.stdout;\n }),\n };\n}\n\n/**\n * What a run says, once, when git is not there and the run wanted it: a\n * citation carries a commit, or `--show-diff` asked for diffs, so history\n * would have been read. Said through `onNotice`; never a finding.\n */\nexport const GIT_UNAVAILABLE_HISTORY =\n \"git is not available here, so citations are checked without history: no never-true, no diffs, no commit subjects.\";\n\n/** What `add` and `update --accept` say, once, when a commit would have been recorded and git is not there. */\nexport const GIT_UNAVAILABLE_COMMIT = \"git is not available here, so the citation records no commit.\";\n\n/**\n * A client that answers \"no git\": `available()` false, everything else empty.\n * What a caller passes as `gitClient` to run without git where git is there.\n */\nexport function noGit(): GitClient {\n return {\n available: () => Promise.resolve(false),\n head: () => Promise.resolve(null),\n lsFiles: () => Promise.resolve([]),\n showFile: () => Promise.resolve({ missing: \"commit\" }),\n subjectsSince: () => Promise.resolve([]),\n diffSince: () => Promise.resolve(\"\"),\n };\n}\n","/**\n * Source-side classification of one citation.\n *\n * current: the range hashes to the pin. moved / moved-ambiguous: a window of\n * the same length hashes equal elsewhere (once / more than once); whole-file\n * citations never move. changed: none equal; with a commit and history,\n * the diff and commit subjects are attached (pretty-only). never-true: no\n * window of the range's length anywhere in the file at the commit hashes to\n * the pin, or the path is absent there. The recorded lines are tried first;\n * the rest of the file is searched because `update` rewrites `src` for a move\n * without touching `commit`, so the lines a pin was minted from may sit\n * elsewhere in the file as it was then. A window that matches there is the\n * original for the move search below. missing: the source cannot be read.\n *\n * Move search: with the original text (git could show the commit), candidate\n * offsets are where the first line matches, compared lexically, hashed only on\n * a full match. Without it, a ±2000-line window around the original position\n * first, then the rest of the file under a 64 MiB hashing budget; past the\n * budget the result is `changed` with `truncatedSearch`.\n *\n * Order, as the ladder has it: the move search runs whenever the pin does not\n * hold, and history decides only what a non-match is called. So a pin that\n * never held at its commit but whose bytes sit elsewhere in the file is\n * `moved`, not `never-true`; the search sees the file as it is.\n */\nimport type { GitClient, PageCitation, SourceEnd, SourceIndex, SourceRange } from \"../types.js\";\nimport { findWindows, type FindWindowsOptions } from \"../../shared/pin.js\";\nimport { hashLines, sliceLines, splitLines } from \"./hash.js\";\nimport { formatSrc, lineSpec, sourceRange, spellSource } from \"./range.js\";\nimport { readSource } from \"./sources.js\";\n\n// The move search is the shared pin engine's; this path keeps cite's imports working.\nexport { MAX_RANGE_LINES, MOVE_BUDGET_BYTES, MOVE_WINDOW_LINES, findWindows } from \"../../shared/pin.js\";\nexport type { FindWindowsOptions } from \"../../shared/pin.js\";\n\nexport interface ClassifyOptions {\n root: string;\n index: SourceIndex;\n /** History is read through it when it reports git available, and never otherwise. */\n git: GitClient;\n /** The encryption key: decrypts an encrypted source and keys its pin. */\n key?: string;\n /** Hashing budget for the blind move search, in bytes. Default `MOVE_BUDGET_BYTES`. */\n budget?: number;\n}\n\n/**\n * What git could say about the pin at the recorded commit. `unknown` is a\n * file at the commit too large to search under the budget with the pin found\n * nowhere in the part that was: neither true nor never true. `original`\n * carries the cited lines as they were then, which `reencryptCitations` re-keys\n * from when the pin no longer holds today.\n */\nexport type History =\n | { kind: \"none\" }\n | { kind: \"unavailable\" }\n | { kind: \"never-true\" }\n | { kind: \"unknown\" }\n | { kind: \"original\"; lines: string[] };\n\nexport async function historyOf(\n git: GitClient,\n commit: string,\n path: string,\n range: SourceRange,\n pin: string,\n key: string | undefined,\n budget: number | undefined,\n): Promise<History> {\n const shown = await git.showFile(commit, path);\n if (\"missing\" in shown) {\n return shown.missing === \"commit\" ? { kind: \"unavailable\" } : { kind: \"never-true\" };\n }\n const then = splitLines(shown.text);\n let joined: string | undefined;\n try {\n joined = sliceLines(then, range);\n } catch {\n // The range ran past the end of the file as it was at the commit.\n joined = undefined;\n }\n if (joined !== undefined && hashLines(joined, key) === pin) {\n return { kind: \"original\", lines: joined.split(\"\\n\") };\n }\n\n // Not at the recorded lines. `update` rewrites `src` for a move and keeps\n // `commit`, so the lines the pin was minted from may sit elsewhere in the\n // file as it was then. Only a pin found nowhere there never held. A\n // whole-file pin has nowhere else to be.\n if (range.start === undefined) return { kind: \"never-true\" };\n const length = (range.end ?? range.start) - range.start + 1;\n const search: FindWindowsOptions = { around: range.start };\n if (budget !== undefined) search.budget = budget;\n const found = findWindows(then, length, pin, key, search);\n const [first] = found.starts;\n if (first !== undefined) {\n return { kind: \"original\", lines: then.slice(first - 1, first - 1 + length) };\n }\n return found.truncated ? { kind: \"unknown\" } : { kind: \"never-true\" };\n}\n\nexport async function classifyCitation(\n entry: PageCitation,\n opts: ClassifyOptions,\n): Promise<SourceEnd> {\n const { citation } = entry;\n const range = sourceRange(citation.source);\n const commit = citation.source[\"commit-sha\"];\n const result: SourceEnd = { src: spellSource(citation.source), status: \"missing\" };\n if (commit !== undefined) result.commitSha = commit;\n\n const source = await readSource(opts.root, opts.index, range, opts.key);\n if (source.kind === \"missing\") {\n result.missingReason = source.reason;\n return result;\n }\n result.resolvedPath = source.resolvedPath;\n\n // Only an encrypted source carries a keyed pin, and reading one needed the key.\n const key = range.encrypted ? opts.key : undefined;\n const pin = citation.source.integrity;\n const lines = splitLines(source.text);\n\n let here: string | undefined;\n try {\n here = hashLines(sliceLines(lines, range), key);\n } catch {\n // The range runs past the end of the file: nothing to compare, so it is\n // `changed`, and the search below has no window of that length to find.\n here = undefined;\n }\n if (here === pin) {\n result.status = \"current\";\n return result;\n }\n\n let history: History = { kind: \"none\" };\n if (commit !== undefined && (await opts.git.available())) {\n history = await historyOf(opts.git, commit, source.resolvedPath, range, pin, key, opts.budget);\n }\n\n // A whole-file pin has nowhere to move to.\n if (range.start !== undefined) {\n const start = range.start;\n const end = range.end ?? start;\n const search: FindWindowsOptions = { around: start };\n if (history.kind === \"original\") search.original = history.lines;\n if (opts.budget !== undefined) search.budget = opts.budget;\n const found = findWindows(lines, end - start + 1, pin, key, search);\n if (found.truncated) result.truncatedSearch = true;\n const spell = (at: number): string =>\n formatSrc({ ...range, start: at, end: at + (end - start) });\n const [only] = found.starts;\n if (found.starts.length === 1 && only !== undefined) {\n result.status = \"moved\";\n result.newSrc = spell(only);\n result.newLines = String(lineSpec({ start: only, end: only + (end - start) }));\n return result;\n }\n if (found.starts.length > 1) {\n result.status = \"moved-ambiguous\";\n result.candidates = found.starts.map(spell);\n return result;\n }\n }\n\n if (history.kind === \"never-true\") {\n result.status = \"never-true\";\n return result;\n }\n result.status = \"changed\";\n if (history.kind === \"unavailable\") result.historyAvailable = false;\n if (history.kind === \"unknown\") result.truncatedSearch = true;\n if (history.kind === \"original\" && commit !== undefined) {\n result.historyAvailable = true;\n result.commitsSince = await opts.git.subjectsSince(commit, source.resolvedPath);\n result.diff = await opts.git.diffSince(commit, source.resolvedPath);\n }\n return result;\n}\n","/**\n * Read a page's citations and its markers.\n *\n * Entries come from the frontmatter (via meta's extractor for the format), or\n * from `CheckPageOptions.citations` when a manifest owns them; either way each\n * one is validated against the bundled draft schema and carries where it sits.\n * Markers are `cite <id>` comments in the body, resolved to the entries they\n * name, so each citation knows what anchors it.\n *\n * The findings made here are the ones that need no source: `entry-invalid`,\n * `marker-invalid`, `marker-orphan`, `marker-repeated` and `anchor-invalid`.\n */\nimport { extname } from \"node:path\";\nimport * as Ajv2020Ns from \"ajv/dist/2020.js\";\nimport type { ValidateFunction } from \"ajv/dist/2020.js\";\nimport citationsSchema from \"../schema/citations.json\" with { type: \"json\" };\nimport {\n extractorForExtension,\n locateFrontmatter,\n supportedExtensions,\n type MetadataExtractor,\n} from \"../../meta/index.js\";\nimport { extractorByName, hasFrontmatterFence } from \"../../meta/internal.js\";\nimport { isEncryptedValue } from \"../../shared/encryption.js\";\nimport { CiteError } from \"../errors.js\";\nimport type {\n Citation,\n CitationFinding,\n CitationInput,\n CitationOrigin,\n CiteRule,\n PageCitation,\n PageCitations,\n} from \"../types.js\";\nimport { isKeyedPin } from \"./hash.js\";\nimport { parseLines, spellSource, tooWide } from \"./range.js\";\nimport { DEFAULT_SEVERITY, ruleId } from \"./severity.js\";\nimport { lineAt, parseStatements } from \"./statements.js\";\n\nexport const MAX_MARKERS_PER_PAGE = 500;\n\n/** Formats whose leading fenced block is frontmatter meta would read. */\nconst ELEMENT_BACKED = new Set([\"html\", \"xml\"]);\n/** Formats whose only metadata channel is a fenced block. */\nconst FENCE_ONLY = new Set([\"markdown\", \"mdx\"]);\n\n/** What a marker with a JSON payload is told, since an entry never lives in the body. */\nexport const MARKER_JSON =\n \"A marker names an entry by id. Write the entry in frontmatter or the sidecar.\";\n\nexport interface ReadPageOptions {\n /** Extractor name; derived from the file's extension when absent. */\n format?: string;\n /**\n * The page's citations as a manifest owns them, already merged. Given, the\n * page's own frontmatter `citations` is not read.\n */\n citations?: readonly CitationInput[];\n /**\n * The manifest that owns this page's `citations`, when one does. A page\n * that also carries its own is `entry-invalid`: neither channel wins, and\n * the discarded value would be exactly the one nobody checked.\n */\n owned?: { file: string; collection: string };\n}\n\n/** Meta's `external:owned` sentence, said by `cite check` under `entry-invalid`. */\nexport function ownedMessage(owner: { file: string; collection: string }): string {\n return `\"citations\" is owned by manifest ${owner.file} (collection ${owner.collection}); remove it from the document`;\n}\n\n// ajv is CommonJS with a default export; under NodeNext the constructor lives\n// on `.default`, as src/meta/core/validator.ts notes.\ntype AjvCtor = typeof import(\"ajv/dist/2020.js\").default;\nconst Ajv2020 = Ajv2020Ns.default as unknown as AjvCtor;\n\nlet entryValidator: ValidateFunction | undefined;\n\nfunction compileEntryValidator(): ValidateFunction {\n if (entryValidator) return entryValidator;\n const ajv = new Ajv2020({ allErrors: false, strict: false });\n ajv.addSchema(citationsSchema);\n entryValidator = ajv.compile({\n $ref: `${citationsSchema.$id}#/$defs/citationEntry`,\n });\n return entryValidator;\n}\n\n/** Ajv validation of one entry object against `$defs.citationEntry`; the first error text, or undefined. */\nexport function validateEntry(entry: unknown): string | undefined {\n const validate = compileEntryValidator();\n if (validate(entry)) return undefined;\n const first = validate.errors?.[0];\n if (!first) return \"invalid entry\";\n return `${first.instancePath} ${first.message ?? \"is invalid\"}`.trim();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Copy a validated entry into the `Citation` shape, field by field. */\nfunction toCitation(entry: Record<string, unknown>): Citation {\n const source = isRecord(entry.source) ? entry.source : {};\n const citation: Citation = {\n source: {\n file: String(source.file),\n integrity: String(source.integrity),\n },\n };\n if (typeof source.lines === \"number\" || typeof source.lines === \"string\") {\n citation.source.lines = source.lines;\n }\n if (typeof source[\"commit-sha\"] === \"string\") {\n citation.source[\"commit-sha\"] = source[\"commit-sha\"];\n }\n if (typeof entry.id === \"string\") citation.id = entry.id;\n if (isRecord(entry.claim)) {\n const claim = entry.claim;\n citation.claim = { integrity: String(claim.integrity) };\n if (typeof claim.lines === \"number\" || typeof claim.lines === \"string\") {\n citation.claim.lines = claim.lines;\n }\n }\n if (typeof entry.quote === \"boolean\") citation.quote = entry.quote;\n return citation;\n}\n\ntype FindingExtra = Pick<CitationFinding, \"line\" | \"id\" | \"src\" | \"index\" | \"file\">;\n\nfunction finding(rule: CiteRule, message: string, extra: FindingExtra): CitationFinding {\n const level = DEFAULT_SEVERITY[rule];\n const out: CitationFinding = {\n rule,\n ruleId: ruleId(rule),\n // The caller re-applies the configured severity table; no page-side rule\n // defaults to `off`, so there is nothing to collapse.\n severity: level === \"off\" ? \"error\" : level,\n message,\n };\n if (extra.line !== undefined) out.line = extra.line;\n if (extra.file !== undefined) out.file = extra.file;\n if (extra.id !== undefined) out.id = extra.id;\n if (extra.src !== undefined) out.src = extra.src;\n if (extra.index !== undefined) out.index = extra.index;\n return out;\n}\n\n/** `<id>: <text>`, or the text alone for an entry with no id. */\nfunction named(id: string | undefined, text: string): string {\n return id === undefined ? text : `${id}: ${text}`;\n}\n\n/** The `id`/`src` a finding carries for an entry that may not have validated. */\nfunction subjectOf(entry: unknown): Pick<FindingExtra, \"id\" | \"src\"> {\n const out: Pick<FindingExtra, \"id\" | \"src\"> = {};\n if (!isRecord(entry)) return out;\n if (typeof entry.id === \"string\") out.id = entry.id;\n if (isRecord(entry.source) && typeof entry.source.file === \"string\") out.src = entry.source.file;\n return out;\n}\n\nexport function pickExtractor(file: string, format: string | undefined): MetadataExtractor {\n if (format !== undefined) {\n const forced = extractorByName(format);\n if (forced === undefined) {\n throw new CiteError(\n `Unknown format \"${format}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n return forced;\n }\n const extension = extname(file);\n const byExt = extractorForExtension(extension);\n if (!byExt) {\n throw new CiteError(\n `Unsupported file type \"${extension}\" for \"${file}\". Supported: ${supportedExtensions().join(\", \")}. Use --as to override.`,\n );\n }\n return byExt;\n}\n\nfunction byLine(a: CitationFinding, b: CitationFinding): number {\n return (a.line ?? Number.MAX_SAFE_INTEGER) - (b.line ?? Number.MAX_SAFE_INTEGER);\n}\n\n/** File line of body line 1: the first line after the frontmatter, or 1. */\nexport function bodyLineOf(content: string, bodyOffset: number): number {\n if (bodyOffset <= 0) return 1;\n const line = lineAt(content, bodyOffset);\n // A page that ends at the closing fence with no newline leaves the body\n // starting on the line after the one the offset sits at the end of.\n return content.charCodeAt(bodyOffset - 1) === 10 ? line : line + 1;\n}\n\nexport function readPage(\n file: string,\n content: string,\n opts?: ReadPageOptions,\n): PageCitations {\n const extractor = pickExtractor(file, opts?.format);\n const format = extractor.name;\n // An opening fence with no close is not a block, so the extractor reads no\n // metadata and every entry the page carries would silently vanish. rst and\n // asciidoc read a stray fence as body on purpose, ahead of their native\n // headers; the fence-only formats have no such reading.\n if (FENCE_ONLY.has(format) && hasFrontmatterFence(content) && locateFrontmatter(content) === null) {\n throw new CiteError(\n `${file}: Unterminated front matter fence: the opening fence has no matching close, so the page's citations cannot be read. Add a closing fence.`,\n );\n }\n const extracted = extractor.extract(content, file);\n const data = extracted.data;\n const bodyOffset = ELEMENT_BACKED.has(format)\n ? 0\n : (locateFrontmatter(content)?.closeEnd ?? 0);\n const bodyLine = bodyLineOf(content, bodyOffset);\n\n const findings: CitationFinding[] = [];\n const citations: PageCitation[] = [];\n /** Entries by id, for marker resolution. */\n const byId = new Map<string, PageCitation>();\n /** Every id seen, for uniqueness. */\n const ids = new Set<string>();\n /** The first marker naming an entry, by entry. */\n const markedAt = new Map<PageCitation, number>();\n\n // The page root reserves the whole `citation-` prefix, so a typo fails\n // loudly rather than passing as a key of somebody else's.\n for (const key of Object.keys(data)) {\n if (!key.startsWith(\"citation-\")) continue;\n findings.push(\n finding(\n \"entry-invalid\",\n `\"${key}\" is not a citations key; the page root reserves the citation- prefix`,\n { line: extracted.lineFor(`/${key}`) },\n ),\n );\n }\n\n const injected = opts?.citations;\n const rawCitations = data.citations;\n // The page carries a key a manifest owns (0020 across files). The page's\n // own entries are still read and checked, so the report shows what the\n // page would publish; the finding says the manifest is the one authority.\n if (opts?.owned !== undefined && rawCitations !== undefined) {\n findings.push(\n finding(\"entry-invalid\", ownedMessage(opts.owned), {\n line: extracted.lineFor(\"/citations\"),\n }),\n );\n }\n if (injected === undefined && rawCitations !== undefined && !Array.isArray(rawCitations)) {\n findings.push(\n finding(\"entry-invalid\", \"citations must be an array of entries\", {\n line: extracted.lineFor(\"/citations\"),\n }),\n );\n }\n const inputs: CitationInput[] =\n injected !== undefined\n ? [...injected]\n : (Array.isArray(rawCitations) ? (rawCitations as unknown[]) : []).map((entry, index) => {\n const origin: CitationInput[\"origin\"] = { kind: \"frontmatter\", file };\n const line = extracted.lineFor(`/citations/${String(index)}`);\n if (line !== undefined) origin.line = line;\n return { entry, origin };\n });\n\n inputs.forEach((input, index) => {\n const origin: CitationOrigin = { ...input.origin, index };\n /** Where a finding about the entry itself sits: the entry's own line, in its own file. */\n const where: FindingExtra = { index };\n if (origin.line !== undefined) where.line = origin.line;\n if (origin.kind === \"manifest\") where.file = origin.file;\n\n const entry = input.entry;\n const error = validateEntry(entry);\n if (error !== undefined || !isRecord(entry)) {\n findings.push(finding(\"entry-invalid\", error ?? \"must be object\", { ...where, ...subjectOf(entry) }));\n return;\n }\n const citation = toCitation(entry);\n const subject: FindingExtra = { ...where, src: spellSource(citation.source) };\n if (citation.id !== undefined) subject.id = citation.id;\n\n // A range that ends before it starts: the schema cannot compare two\n // numbers, so the rule is kept here.\n const bad = ([\"claim\", \"source\"] as const).find((end) => {\n const lines = end === \"claim\" ? citation.claim?.lines : citation.source.lines;\n return lines !== undefined && parseLines(lines) === undefined;\n });\n if (bad !== undefined) {\n const lines = bad === \"claim\" ? citation.claim?.lines : citation.source.lines;\n findings.push(\n finding(\n \"entry-invalid\",\n named(citation.id, `${bad}.lines \"${String(lines)}\" ends before it starts`),\n subject,\n ),\n );\n return;\n }\n\n // A range wider than the cap is refused at either end (proposal 0044).\n const wide = ([\"claim\", \"source\"] as const)\n .map((end) => {\n const lines = end === \"claim\" ? citation.claim?.lines : citation.source.lines;\n const parsed = lines === undefined ? undefined : parseLines(lines);\n const reason = parsed === undefined ? undefined : tooWide(parsed);\n return reason === undefined ? undefined : `${end}.lines \"${String(lines)}\" ${reason}`;\n })\n .find((message) => message !== undefined);\n if (wide !== undefined) {\n findings.push(finding(\"entry-invalid\", named(citation.id, wide), subject));\n return;\n }\n\n // The pin's prefix says how it was taken, and only an encrypted source\n // carries a keyed one.\n const encrypted = isEncryptedValue(citation.source.file);\n if (encrypted !== isKeyedPin(citation.source.integrity)) {\n findings.push(\n finding(\n \"entry-invalid\",\n named(\n citation.id,\n encrypted\n ? \"an encrypted source is pinned with hmac-sha256-, not sha256-.\"\n : \"a plain source is pinned with sha256-, not hmac-sha256-.\",\n ),\n subject,\n ),\n );\n return;\n }\n\n const page: PageCitation = { citation, origin };\n citations.push(page);\n if (citation.id !== undefined) {\n if (ids.has(citation.id)) {\n findings.push(finding(\"entry-invalid\", `duplicate id \"${citation.id}\"`, subject));\n } else {\n ids.add(citation.id);\n byId.set(citation.id, page);\n }\n }\n });\n\n // Markers.\n const body = content.slice(bodyOffset);\n const statements = parseStatements(body, format, {\n offset: bodyOffset,\n line: bodyLine,\n });\n if (statements.length > MAX_MARKERS_PER_PAGE) {\n findings.push(\n finding(\n \"marker-invalid\",\n `more than ${String(MAX_MARKERS_PER_PAGE)} markers on one page (${String(statements.length)}); the rest are not read`,\n { line: statements[MAX_MARKERS_PER_PAGE]?.line },\n ),\n );\n }\n\n for (const statement of statements.slice(0, MAX_MARKERS_PER_PAGE)) {\n const { payload } = statement;\n if (payload.kind === \"bad\") {\n findings.push(\n finding(\n \"marker-invalid\",\n payload.json === true ? MARKER_JSON : `invalid marker: ${payload.reason}`,\n { line: statement.line },\n ),\n );\n continue;\n }\n const target = byId.get(payload.id);\n if (target === undefined) {\n findings.push(\n finding(\"marker-orphan\", `no entry has id \"${payload.id}\"`, {\n line: statement.line,\n id: payload.id,\n }),\n );\n continue;\n }\n const first = markedAt.get(target);\n if (first !== undefined) {\n findings.push(\n finding(\n \"marker-repeated\",\n `${payload.id} is named by markers at lines ${String(first)} and ${String(statement.line)}; the first anchors it.`,\n {\n line: statement.line,\n id: payload.id,\n index: target.origin.index,\n src: spellSource(target.citation.source),\n },\n ),\n );\n continue;\n }\n markedAt.set(target, statement.line);\n target.marker = statement;\n }\n\n // Anchors: exactly one way in, and a quote needs one of them.\n for (const entry of citations) {\n const { citation, origin, marker } = entry;\n const subject: FindingExtra = { index: origin.index, src: spellSource(citation.source) };\n if (citation.id !== undefined) subject.id = citation.id;\n if (origin.line !== undefined) subject.line = origin.line;\n if (origin.kind === \"manifest\") subject.file = origin.file;\n\n if (citation.claim?.lines !== undefined && marker !== undefined) {\n // A marker names an id, so an entry with both always has one. The\n // finding sits on the marker, which is the half a reader can see.\n const onPage: FindingExtra = { index: origin.index, line: marker.line, src: subject.src };\n if (citation.id !== undefined) onPage.id = citation.id;\n findings.push(\n finding(\n \"anchor-invalid\",\n `${citation.id ?? \"the entry\"} has claim lines and a marker. Keep one.`,\n onPage,\n ),\n );\n continue;\n }\n if (citation.quote === true && citation.claim?.lines === undefined && marker === undefined) {\n findings.push(\n finding(\"anchor-invalid\", named(citation.id, \"quote needs a claim or a marker.\"), subject),\n );\n }\n }\n\n return {\n file,\n format,\n content,\n bodyOffset,\n bodyLine,\n citations,\n statements,\n findings: findings.sort(byLine),\n };\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"manni:citations:1.0.0-proposal.4\",\n \"title\": \"manni citations vocabulary (1.0.0-proposal.4)\",\n \"description\": \"What do this page's claims rest on? For each claim, the page lines that make it, the source lines it was written from, and a hash of each. A manni common vocabulary: any drift check can implement it, and other schemas may compose on top of it. A pin is a record of the past, not a copy of the present. It says what the lines were when the sentence was written. The check compares that record with the files as they are now. Recompute it on every run and there is nothing to compare against. `source-of-truth` (manni:stewardship) names the file a page answers to; a citation names the lines a sentence answers to. The page root stays open so sibling tools' keys pass untouched. The `citation-` prefix is reserved, so an unrecognized `citation-*` key is rejected and a typo fails loudly.\",\n \"type\": \"object\",\n \"additionalProperties\": true,\n \"properties\": {\n \"citations\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": \"#/$defs/citationEntry\"\n },\n \"description\": \"The page's citations, one entry per claim or pin. An empty list is not a declaration; a page with no citations omits the key. Ids are unique within a page, and two entries claiming one id is an error. JSON Schema cannot say that over a list whose members may omit the id. So it is a requirement on implementations, stated here so every tool agrees.\",\n \"x-manni-location\": \"external\"\n }\n },\n \"patternProperties\": {\n \"^citation-\": false\n },\n \"$defs\": {\n \"citationEntry\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"source\"\n ],\n \"description\": \"One citation: the page text it supports, the source lines it rests on, and how the two are anchored. Both ends share one shape, a line range and a hash.\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9-]*$\",\n \"description\": \"A kebab-case name for this citation, unique within the page. A body marker names an entry by it, and findings are reported under it. Optional for an entry anchored by its claim lines or pinned bare. Required when a marker names the entry.\"\n },\n \"claim\": {\n \"$ref\": \"#/$defs/claim\"\n },\n \"source\": {\n \"$ref\": \"#/$defs/source\"\n },\n \"quote\": {\n \"type\": \"boolean\",\n \"default\": false,\n \"description\": \"The claim is a fenced block that reproduces the source lines. The pinned claim covers the whole block, fences included. An implementer compares the lines inside the fences with the source under the pin's rule. So a quoted snippet that drifts from its source is a finding even while the pin still holds. Under a marker, the block is the next fence after the marker. Default false.\"\n }\n }\n },\n \"claim\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"integrity\"\n ],\n \"description\": \"The page text the citation supports, pinned by lines and a hash. Absent, the entry is a bare pin, or a marker with no drift check on its sentence. Without `lines`, the text pinned is what a body marker naming this entry anchors.\",\n \"properties\": {\n \"lines\": {\n \"$ref\": \"#/$defs/lines\",\n \"description\": \"Lines of the page body. The body starts on the first line after the closing frontmatter fence, or on line 1 with no frontmatter. So editing the frontmatter never moves a claim. Required unless a marker names the entry, and never inside the frontmatter.\"\n },\n \"integrity\": {\n \"type\": \"string\",\n \"pattern\": \"^sha256-[0-9a-f]{64}$\",\n \"description\": \"`sha256-` and sixty-four lowercase hex digits over the claimed lines, under the rule `source.integrity` states. Always plain, never keyed: the page is public, so there is nothing to hide. With a marker, the lines hashed are the ones the marker anchors.\"\n }\n }\n },\n \"source\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"file\",\n \"integrity\"\n ],\n \"description\": \"The lines the claim rests on: a file, an optional line range, a pin, and the commit the pin was taken at.\",\n \"properties\": {\n \"file\": {\n \"$ref\": \"#/$defs/fileRef\"\n },\n \"lines\": {\n \"$ref\": \"#/$defs/lines\",\n \"description\": \"File lines. Absent, the whole file is pinned. The lines stay readable even when `file` is encrypted.\"\n },\n \"integrity\": {\n \"type\": \"string\",\n \"pattern\": \"^(?:sha256|hmac-sha256)-[0-9a-f]{64}$\",\n \"description\": \"The pin: an algorithm prefix and sixty-four lowercase hex digits over the cited lines under one rule. Decode as UTF-8 and drop one leading byte-order mark. Turn CRLF into LF, split on LF, and discard the empty element a trailing LF leaves. Take lines L1 to L2 inclusive, or every line for a whole file. Join with LF and no trailing LF, and keep trailing whitespace. A plain `file` is pinned `sha256-` over that text. An encrypted `file` is pinned `hmac-sha256-`: the HMAC-SHA256 of that text under a key derived from the encryption key. So a public page carries no verifier a reader could run against a guessed private line. The prefix follows `file`, and any other pairing is an invalid entry.\"\n },\n \"commit-sha\": {\n \"type\": \"string\",\n \"pattern\": \"^[0-9a-f]{7,64}$\",\n \"description\": \"The git commit hash the source pin was taken at, as lowercase hex. Seven digits is what git abbreviates to; sixty-four covers a SHA-256 repository. A tool writes the full hash, because an abbreviation that is unique today need not be next year. Without it, a check can still say the lines changed. With it, the check can say since when, and whether the pin was ever true.\"\n }\n }\n },\n \"lines\": {\n \"oneOf\": [\n {\n \"type\": \"integer\",\n \"minimum\": 1\n },\n {\n \"type\": \"string\",\n \"pattern\": \"^[1-9][0-9]*-[1-9][0-9]*$\"\n }\n ],\n \"description\": \"A line range, 1-based and inclusive: an integer for one line, or `\\\"L1-L2\\\"` for several. `L1 <= L2` is a rule on implementations, since a pattern cannot compare two numbers. There is no line 0 to cite.\"\n },\n \"fileRef\": {\n \"type\": \"string\",\n \"pattern\": \"^(?:~[A-Za-z0-9_-]{82,}|(?!~)(?:(?!\\\\.\\\\.?(?:/|$))[^/\\\\\\\\:\\\\r\\\\n\\\\t]+)(?:/(?:(?!\\\\.\\\\.?(?:/|$))[^/\\\\\\\\:\\\\r\\\\n\\\\t]+))*)$\",\n \"description\": \"The file: a path relative to the repository root, posix-separated, and free of `.` and `..` segments. Segments may hold spaces and dots but not `/`, `\\\\`, `:` or a line break. So a URL, a drive letter, a Windows path and an absolute path all fail here. In place of the path, `~` and at least 82 base64url characters is the path encrypted with the family key. Proposal 0045 states the construction. Only a checkout with the key and the files can decrypt the path and read the lines. So a public docs repo can cite a private code repo without publishing its paths. The value carries no encryption mark, because the citation tool encrypts it, and a plain path stays valid.\"\n }\n }\n}\n","/**\n * Citations kept outside the page, in an external-metadata manifest a\n * collection declares (proposal 0037, and 0044's \"the sidecar is external\n * metadata\"). No `cite:` key turns this on: a collection whose\n * `externalMetadata:` owns `citations` keeps its pages' entries there.\n *\n * Reading is meta's merge, not a second loader. `loadCitationSidecars` loads\n * every manifest that owns `citations`, and `forPage` merges one page through\n * `mergeExternalMetadata`, so the join rules, the ownership rules and the\n * per-item lines are the ones `meta validate` already applies.\n *\n * Three things are cite's own, because cite *writes* manifests where meta\n * only reads them:\n *\n * - **Membership is decided by every declared collection**, not by the ones\n * `--collection` or the positional paths selected. A page named by path is\n * still a member of the collection that contains it, and its citations are\n * still in that collection's manifest; a run that read frontmatter instead\n * would report every entry as missing and then write a second copy.\n * - **A URL manifest may not own `citations`** (exit 2). cite writes them,\n * and a URL is not somewhere to write; it would also put a private\n * `source.file` in public CI output.\n * - **A page whose collections own `citations` twice is refused** (exit 2),\n * even before either manifest has an entry for it: a writer has to know\n * which file to write to, and picking one would be the tiebreak 0020\n * refuses.\n *\n * `--no-config` never reaches here: with no config there are no collections,\n * so a page's citations are its frontmatter's.\n */\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport {\n classifyRef,\n externalMetadataJoin,\n loadExternalMetadata,\n memberOf,\n mergeExternalMetadata,\n orphanEntries,\n orphanError,\n orphanJoins,\n PATH_JOIN,\n type CollectionConfig,\n type ExternalMetadataConfig,\n type ExternalMetadataEntry,\n type ExternalMetadataIndex,\n type ExternalMetadataJoin,\n type ExtractedMetadata,\n} from \"../../meta/index.js\";\nimport { CiteError } from \"../errors.js\";\nimport type { CitationInput, CiteRun } from \"../types.js\";\nimport { pickExtractor } from \"./page.js\";\n\n/** The one key cite keeps in a manifest. */\nexport const CITATIONS_KEY = \"citations\";\n\nconst toPosix = (path: string): string => path.split(sep).join(\"/\");\n\n/** How a run spells a manifest: relative to its base, posix, like every file label. */\nfunction reportedPath(abs: string, base: string): string {\n const rel = relative(base, abs);\n return rel === \"\" ? \".\" : toPosix(rel);\n}\n\n/** A manifest that owns `citations` for one collection. */\nexport interface CitationManifest {\n /** The collection that declares it. */\n collection: string;\n /** Absolute path of the manifest file. */\n path: string;\n /** The manifest as the run reports it. */\n file: string;\n /** `path`, or the page field the manifest joins on. */\n join: string;\n}\n\n/** Where one page's citations are kept, and what the manifest already holds. */\nexport interface PageSidecar {\n /** The manifest that owns this page's citations, when one does. */\n owner?: CitationManifest;\n /**\n * The key under which this page is written in the manifest: its path\n * relative to the config directory, or its value of the join field.\n * Undefined when the manifest joins on a field the page does not carry, so\n * a writer refuses rather than inventing a key.\n */\n entry?: string;\n /** The manifest's entries for this page, when it supplies any. */\n citations?: CitationInput[];\n /** Field-joined entries this page matched, for the duplicate-join check. */\n joins: readonly ExternalMetadataJoin[];\n}\n\nexport interface CitationSidecars {\n /** The manifests that own `citations`, by collection. */\n manifests: readonly CitationManifest[];\n /** Directory manifest paths and manifest keys resolve from. */\n configDir: string;\n /** Directory the run's file labels are relative to. */\n base: string;\n forPage(label: string, content: string, format?: string): PageSidecar;\n /**\n * Manifest entries naming a page this run did not load, under meta's own\n * corpus invariant. `covered` names the collections a `--collection` run\n * narrowed to, or `undefined` for a whole-corpus run.\n */\n orphans(loaded: readonly string[], covered?: readonly string[]): ExternalMetadataEntry[];\n /** Field entries no loaded page matched, same invariant. */\n orphanJoins(\n matched: ReadonlyMap<string, ReadonlySet<string>>,\n covered?: readonly string[],\n ): ExternalMetadataEntry[];\n}\n\nexport interface LoadSidecarOptions {\n /** Every collection the config declares, not only the ones the run selected. */\n collections: readonly CollectionConfig[];\n /** The config file's directory. */\n configDir: string;\n /** Directory the run's file labels are relative to. */\n base: string;\n /** The config file as the user would name it, for the URL refusal. */\n configSource: string;\n /** The family encryption key, for a join field a page holds encrypted. */\n key?: string;\n /** The tool's error class; `CiteError` unless a sibling command says otherwise. */\n toError?: (message: string) => Error;\n}\n\n/** `collection <name>: citations cannot come from a URL manifest, because cite writes them.` */\nexport function urlManifestRefusal(source: string, collection: string): string {\n return `${source}: collection ${collection}: ${CITATIONS_KEY} cannot come from a URL manifest, because cite writes them.`;\n}\n\n/** `<page> is in collections a and b, and both keep citations in a manifest.` */\nexport function twoManifestsRefusal(label: string, a: string, b: string): string {\n return `${label} is in collections ${a} and ${b}, and both keep citations in a manifest.`;\n}\n\n/** Does any declared collection keep `citations` in a manifest? */\nfunction ownsCitations(manifest: ExternalMetadataConfig): boolean {\n return manifest.keys.includes(CITATIONS_KEY);\n}\n\n/**\n * Load every manifest that owns `citations`, or `null` when none does — which\n * is every setup that keeps its citations in frontmatter, and costs nothing.\n *\n * Only the citations-owning manifests are loaded. A sibling manifest of the\n * same collection, supplying meta's own keys from a URL, is none of cite's\n * business and is never fetched here.\n */\nexport async function loadCitationSidecars(\n opts: LoadSidecarOptions,\n): Promise<CitationSidecars | null> {\n const toError = opts.toError ?? ((message: string): Error => new CiteError(message));\n const manifests: CitationManifest[] = [];\n const scoped: CollectionConfig[] = [];\n for (const collection of opts.collections) {\n const owning = collection.externalMetadata.filter(ownsCitations);\n if (owning.length === 0) continue;\n for (const manifest of owning) {\n if (classifyRef(manifest.file).kind === \"url\") {\n throw toError(urlManifestRefusal(opts.configSource, collection.name));\n }\n const path = isAbsolute(manifest.file)\n ? manifest.file\n : resolve(opts.configDir, manifest.file);\n manifests.push({\n collection: collection.name,\n path,\n file: reportedPath(path, opts.base),\n join: externalMetadataJoin(manifest),\n });\n }\n scoped.push({ ...collection, externalMetadata: owning });\n }\n if (manifests.length === 0) return null;\n\n const index = await loadExternalMetadata(scoped, {\n configDir: opts.configDir,\n base: opts.base,\n });\n if (index === null) return null;\n return sidecars(index, manifests, scoped, opts);\n}\n\nfunction sidecars(\n index: ExternalMetadataIndex,\n manifests: readonly CitationManifest[],\n collections: readonly CollectionConfig[],\n opts: LoadSidecarOptions,\n): CitationSidecars {\n const toError = opts.toError ?? ((message: string): Error => new CiteError(message));\n const { configDir, base } = opts;\n\n const forPage = (label: string, content: string, format?: string): PageSidecar => {\n const members = memberOf(collections, configDir, base, label);\n if (members.length === 0) return { joins: [] };\n\n // The owning manifest is the page's, decided before anything is read:\n // two of them is a refusal even when only one has an entry today.\n const mine = manifests.filter((m) => members.includes(m.collection));\n const [owner, second] = mine;\n if (owner === undefined) return { joins: [] };\n if (second !== undefined) {\n throw toError(twoManifestsRefusal(label, owner.collection, second.collection));\n }\n\n const extractor = pickExtractor(label, format);\n const extracted: ExtractedMetadata = extractor.extract(content, label);\n const merged = mergeExternalMetadata(label, extracted, index, members, base, {\n encryptionKey: () => opts.key,\n });\n\n const out: PageSidecar = { owner, joins: merged.joins };\n if (owner.join === PATH_JOIN) {\n out.entry = toPosix(relative(configDir, resolve(base, label)));\n } else {\n const value = merged.joins.find((j) => j.field === owner.join)?.value;\n // No match: the page's own value of the join field still keys it, so a\n // first `add` can write an entry a later run will match.\n const raw = value ?? extracted.data[owner.join];\n if (typeof raw === \"string\" && raw !== \"\") out.entry = raw;\n else if (typeof raw === \"number\" || typeof raw === \"boolean\") out.entry = String(raw);\n }\n\n // The manifest supplied the key exactly when `locate` answers for it;\n // a page carrying its own `citations:` keeps them (the collision is a\n // finding, not a tiebreak), and `locate` then answers `undefined`.\n const where = merged.locate(`/${CITATIONS_KEY}`);\n if (where !== undefined) {\n const supplied: unknown = merged.extracted.data[CITATIONS_KEY];\n const list: unknown[] = Array.isArray(supplied) ? (supplied as unknown[]) : [supplied];\n out.citations = list.map((entry, i) => {\n const at = merged.locate(`/${CITATIONS_KEY}/${String(i)}`);\n const line = (Array.isArray(supplied) ? at?.line : undefined) ?? where.line;\n return {\n entry,\n origin: {\n kind: \"manifest\" as const,\n file: where.file,\n ...(line === undefined ? {} : { line }),\n },\n };\n });\n }\n return out;\n };\n\n return {\n manifests,\n configDir,\n base,\n forPage,\n orphans: (loaded, covered) => orphanEntries(index, loaded, base, covered),\n orphanJoins: (matched, covered) => orphanJoins(index, matched, covered),\n };\n}\n\n/** The refusal a whole-corpus run raises for a manifest entry naming nothing. */\nexport function orphanRefusal(\n orphans: readonly ExternalMetadataEntry[],\n toError: (message: string) => Error = (m) => new CiteError(m),\n): Error {\n return toError(orphanError(orphans).message);\n}\n\n/**\n * Two pages carrying one `join:` value: the manifest cannot tell them apart,\n * and cite would write one page's entry over the other's. Meta files this as\n * a finding on each document; here it is the run's problem, because the run\n * writes.\n */\nexport function duplicateJoinRefusal(\n field: string,\n value: string,\n file: string,\n labels: readonly string[],\n): string {\n return `${String(labels.length)} pages carry ${field} \"${value}\"; ${file} cannot tell them apart (${labels.join(\", \")}).`;\n}\n\n/**\n * Load the sidecars a resolved run governs; `null` with no config, or no\n * citations manifest. `base` overrides the run's when a command labels its\n * pages from somewhere else — `add` takes one page from the command line and\n * labels it from the working directory, whatever the collections would.\n */\nexport function sidecarsFor(\n run: CiteRun,\n over: { base?: string; toError?: (message: string) => Error } = {},\n): Promise<CitationSidecars | null> {\n const declared = run.configFile?.collections ?? [];\n if (run.configDir === undefined || declared.length === 0) return Promise.resolve(null);\n return loadCitationSidecars({\n // Every declared collection, whatever `--collection` or the paths chose.\n collections: declared,\n configDir: run.configDir,\n base: over.base ?? run.base,\n configSource: run.configSource ?? run.configPath ?? \"the config\",\n ...(run.key === undefined ? {} : { key: run.key }),\n ...(over.toError === undefined ? {} : { toError: over.toError }),\n });\n}\n","/**\n * Writing a page's `citations` into the manifest that owns them.\n *\n * The splice itself is meta's (`spliceManifestValue` on the family-internal\n * barrel): one owned value of one entry is replaced, every other byte of the\n * file survives by construction, and the result is read back before it is\n * returned. This module is the part cite owns — holding each manifest's text\n * for the length of a run so it is written once, and finding the line a\n * written entry now sits on, which is what `add` reports and what a finding\n * about an entry points at.\n *\n * Nothing here touches the disk: a caller reads the manifests it needs and\n * writes them when the whole run has succeeded, the way `key rotate` writes\n * pages only once every one of them could be re-encrypted.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { posix } from \"node:path\";\nimport { LineCounter, isMap, isNode, isScalar, isSeq, parseDocument } from \"yaml\";\nimport { DocmetaError } from \"../../meta/index.js\";\nimport { spliceManifestValue } from \"../../meta/internal.js\";\nimport { CiteError } from \"../errors.js\";\nimport { unifiedDiff } from \"./write.js\";\nimport { CITATIONS_KEY, type CitationManifest } from \"./sidecar.js\";\n\n/** One manifest held for the length of a run: its text before, and now. */\nexport interface HeldManifest {\n /** Absolute path, the write target. */\n path: string;\n /** The manifest as the run reports it. */\n file: string;\n /** The bytes as they were read. */\n before: string;\n /** The bytes as the run has rewritten them. */\n text: string;\n}\n\n/** Every manifest one run writes, read once and spliced in memory. */\nexport class ManifestSet {\n private readonly held = new Map<string, HeldManifest>();\n\n /** Read a manifest, or hand back the copy this run has already rewritten. */\n async hold(manifest: CitationManifest): Promise<HeldManifest> {\n const already = this.held.get(manifest.path);\n if (already !== undefined) return already;\n let before: string;\n try {\n before = await readFile(manifest.path, \"utf8\");\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new CiteError(`Manifest ${manifest.file} could not be read: ${reason}`);\n }\n const fresh: HeldManifest = { path: manifest.path, file: manifest.file, before, text: before };\n this.held.set(manifest.path, fresh);\n return fresh;\n }\n\n /**\n * Write one page's whole `citations` list into its entry, and answer where\n * the entry at `index` now sits. The manifest is not saved: `changed()`\n * lists what the run would write.\n */\n async write(\n manifest: CitationManifest,\n entry: string,\n citations: readonly unknown[],\n index: number,\n ): Promise<{ file: string; line: number }> {\n const held = await this.hold(manifest);\n const spliced = splice(held.text, {\n entry,\n key: CITATIONS_KEY,\n value: [...citations],\n join: manifest.join,\n file: manifest.file,\n });\n held.text = spliced.text;\n return { file: manifest.file, line: itemLine(spliced.text, entry, index, manifest.join) ?? spliced.line };\n }\n\n /** The manifests this run rewrote, with the diff of each. */\n changed(): { path: string; file: string; before: string; text: string; diff: string }[] {\n return [...this.held.values()]\n .filter((m) => m.text !== m.before)\n .map((m) => ({ ...m, diff: unifiedDiff(m.file, m.before, m.text) }));\n }\n}\n\n/** `spliceManifestValue`, with meta's refusal reported as this tool's. */\nexport function splice(\n text: string,\n options: Parameters<typeof spliceManifestValue>[1],\n): { text: string; line: number } {\n try {\n return spliceManifestValue(text, options);\n } catch (error) {\n if (error instanceof DocmetaError) throw new CiteError(error.message);\n throw error;\n }\n}\n\n/**\n * The 1-based line of one item of an entry's `citations`, in a manifest that\n * may not have been written yet. The loader answers this for a manifest on\n * disk; a freshly spliced one has to be read where it stands, so `add` can\n * say where the entry it just wrote went.\n */\nexport function itemLine(\n text: string,\n entry: string,\n index: number,\n join: string,\n): number | undefined {\n const lc = new LineCounter();\n const doc = parseDocument(text, { lineCounter: lc, uniqueKeys: false });\n if (doc.errors.length > 0) return undefined;\n const root = doc.contents;\n if (!isMap(root)) return undefined;\n const same = (key: unknown): boolean => {\n const spelled = isScalar(key) ? String(key.value) : String(key);\n return join === \"path\" ? posix.normalize(spelled) === posix.normalize(entry) : spelled === entry;\n };\n const pair = root.items.find((p) => same(p.key));\n const value = pair?.value;\n if (!isMap(value)) return undefined;\n const kv = value.items.find(\n (p) => (isScalar(p.key) ? String(p.key.value) : String(p.key)) === CITATIONS_KEY,\n );\n const list = kv?.value;\n if (!isSeq(list)) return undefined;\n const item: unknown = list.items[index];\n const range = isNode(item) ? item.range : undefined;\n return range ? lc.linePos(range[0]).line : undefined;\n}\n","/**\n * Every way the tool rewrites a page. Frontmatter appends go through meta's\n * `applyFrontmatter` (comments and key order preserved). A repair splices one\n * scalar textually at `lineFor(\"/citations/N/source/lines\")` and the like, so\n * nothing else in the block is touched. Markers are inserted by offset with\n * the page's own EOL. Files are written with `writeFileAtomic`.\n */\nimport { DocmetaError, locateFrontmatter, type MetadataExtractor } from \"../../meta/index.js\";\nimport { extractorByName } from \"../../meta/internal.js\";\nimport { CiteError } from \"../errors.js\";\nimport type { Citation, LineSpec } from \"../types.js\";\nimport { splitLines } from \"./hash.js\";\nimport { detectEol, lineAt, offsetOfLine } from \"./statements.js\";\n\nfunction extractorFor(format: string): MetadataExtractor {\n const extractor = extractorByName(format);\n if (!extractor) throw new CiteError(`Unknown format \"${format}\".`);\n return extractor;\n}\n\n/**\n * Whether the format reads a leading fenced block as its frontmatter. Asked\n * of the extractor itself rather than kept as a list of names here, so a\n * format added to meta's registry answers for itself. An element-backed\n * format (html, xml) sees the probe as body text and says no.\n */\nfunction readsFencedFrontmatter(extractor: MetadataExtractor, label: string): boolean {\n return extractor.extract(\"---\\nprobe: 1\\n---\\n\", label).fenced === true;\n}\n\n/** Append one entry to `citations` (creating the key), via the format's extractor. */\nexport function appendFrontmatterCitation(\n content: string,\n format: string,\n citation: Citation,\n filePath?: string,\n): string {\n const label = filePath ?? \"the page\";\n const extractor = extractorFor(format);\n // Element-backed metadata (html, xml) has `apply` too, but it is not\n // frontmatter. Whether this *page* can take a block is `apply`'s call:\n // markdown creates one, asciidoc and rst refuse when none exists.\n if (!extractor.apply || !readsFencedFrontmatter(extractor, label)) {\n throw new CiteError(\n `${label} has no frontmatter to write to; keep its citations in a manifest instead.`,\n );\n }\n const extracted = extractor.extract(content, label);\n if (locateFrontmatter(content)?.flavor === \"toml\") {\n throw new CiteError(\n `${label} has TOML frontmatter; manni cannot add a citations table without re-emitting the whole block, which would drop its comments. Add the entry by hand.`,\n );\n }\n\n const raw: unknown = extracted.data.citations ?? [];\n if (!Array.isArray(raw)) {\n throw new CiteError(`${label}: \\`citations\\` is not a list; edit it by hand.`);\n }\n // `isArray` narrows `unknown` to `any[]`; name the element type before it spreads.\n const existing: unknown[] = raw;\n const entry = entryObject(citation);\n try {\n return extractor.apply(content, { citations: [...existing, entry] });\n } catch (e) {\n if (e instanceof DocmetaError) throw new CiteError(`${label}: ${e.message}`);\n throw e;\n }\n}\n\n/**\n * The entry as a plain object, in the order a reader scans it, with every\n * absent optional left out rather than written as `null`.\n */\nexport function entryObject(citation: Citation): Record<string, unknown> {\n const source: Record<string, unknown> = { file: citation.source.file };\n if (citation.source.lines !== undefined) source.lines = citation.source.lines;\n source.integrity = citation.source.integrity;\n if (citation.source[\"commit-sha\"] !== undefined) {\n source[\"commit-sha\"] = citation.source[\"commit-sha\"];\n }\n const entry: Record<string, unknown> = {};\n if (citation.id !== undefined) entry.id = citation.id;\n if (citation.claim !== undefined) {\n const claim: Record<string, unknown> = {};\n if (citation.claim.lines !== undefined) claim.lines = citation.claim.lines;\n claim.integrity = citation.claim.integrity;\n entry.claim = claim;\n }\n entry.source = source;\n if (citation.quote !== undefined) entry.quote = citation.quote;\n return entry;\n}\n\n/** Plain YAML scalars that would read back as something other than the string. */\nfunction needsYamlQuotes(value: string): boolean {\n return (\n value === \"\" ||\n /^[\\s!&*?|>'\"%@`{}[\\],#]/.test(value) ||\n /^-(\\s|$)/.test(value) ||\n /:\\s|\\s#|:$|\\s$/.test(value) ||\n /^(?:true|false|null|~|yes|no|on|off|[-+]?(?:\\d[\\d_]*\\.?\\d*|\\.\\d+)(?:e[-+]?\\d+)?)$/i.test(value)\n );\n}\n\n/** `\"…\"` with the escapes YAML and JSON share. */\nconst doubleQuote = (value: string): string => JSON.stringify(value);\nconst singleQuote = (value: string): string => `'${value.replace(/'/g, \"''\")}'`;\n\n/**\n * Split a `key: value` line into its lead (` - src: `), the scalar, and what\n * trails it (a comment, a JSON comma). Undefined when the line does not carry\n * `field`.\n */\nfunction splitScalarLine(\n line: string,\n field: string,\n): { lead: string; scalar: string; trail: string } | undefined {\n const keyed = new RegExp(`^(\\\\s*(?:-\\\\s+)?\"?${field}\"?\\\\s*:\\\\s*)(.*)$`).exec(line);\n const lead = keyed?.[1];\n const rest = keyed?.[2];\n if (lead === undefined || rest === undefined) return undefined;\n const quote = rest.charAt(0);\n let end: number;\n if (quote === '\"' || quote === \"'\") {\n end = -1;\n for (let i = 1; i < rest.length; i++) {\n const ch = rest.charAt(i);\n if (quote === '\"' && ch === \"\\\\\") {\n i++;\n } else if (ch === quote) {\n if (quote === \"'\" && rest.charAt(i + 1) === \"'\") {\n i++;\n continue;\n }\n end = i + 1;\n break;\n }\n }\n if (end < 0) return undefined;\n } else {\n const comment = /\\s#/.exec(rest);\n end = comment ? comment.index : rest.length;\n while (end > 0 && /\\s/.test(rest.charAt(end - 1))) end--;\n }\n return { lead, scalar: rest.slice(0, end), trail: rest.slice(end) };\n}\n\n/** One scalar of an entry a repair may rewrite: a file, an end's lines, its pin, or the commit. */\nexport type EntryPath = readonly [\n end: \"claim\" | \"source\",\n field: \"file\" | \"lines\" | \"integrity\" | \"commit-sha\",\n];\n\n/** Replace the scalar on one line of entry N, e.g. `source.lines` after a move. */\nexport function spliceEntryField(\n content: string,\n format: string,\n index: number,\n path: EntryPath,\n value: LineSpec,\n): string {\n const [which, field] = path;\n const refuse = (): CiteError =>\n new CiteError(\n `Cannot rewrite citations[${String(index)}].${which}.${field} in ${format} frontmatter; edit it by hand.`,\n );\n const extractor = extractorFor(format);\n const pointer = `/citations/${String(index)}/${which}/${field}`;\n // `lineFor` walks up to the nearest recorded ancestor when the exact\n // pointer is unknown (TOML records top-level keys only), so the line it\n // names is checked for the field before anything is touched.\n const line = extractor.extract(content, \"page\").lineFor(pointer);\n if (line === undefined) throw refuse();\n const start = offsetOfLine(content, line);\n const nl = content.indexOf(\"\\n\", start);\n let end = nl === -1 ? content.length : nl;\n if (end > start && content.charAt(end - 1) === \"\\r\") end--;\n const parts = splitScalarLine(content.slice(start, end), field);\n if (!parts) throw refuse();\n\n const quote = parts.scalar.charAt(0);\n // A number is written plain whatever the old value's quoting was, so that\n // a range that became one line reads back as the integer it now is.\n const spelled =\n typeof value === \"number\" ? String(value)\n : quote === '\"' ? doubleQuote(value)\n : quote === \"'\" ? singleQuote(value)\n : needsYamlQuotes(value) ? doubleQuote(value)\n : value;\n const out = content.slice(0, start) + parts.lead + spelled + parts.trail + content.slice(end);\n\n // Read it back: a splice that lands anywhere but on that one value is a\n // refusal, not a damaged page.\n const check: unknown = extractor.extract(out, \"page\").data.citations;\n const entry: unknown = Array.isArray(check) ? check[index] : undefined;\n const block = isRecord(entry) ? entry[which] : undefined;\n const readBack = isRecord(block) ? block[field] : undefined;\n if (readBack !== value) throw refuse();\n return out;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Insert a statement line before the line containing `offset`, with the page's EOL. */\nexport function insertStatementBefore(\n content: string,\n offset: number,\n statement: string,\n): string {\n const start = offsetOfLine(content, lineAt(content, offset));\n return content.slice(0, start) + statement + detectEol(content) + content.slice(start);\n}\n\ntype Edit = { op: \" \" | \"-\" | \"+\"; text: string };\n\n/**\n * A unified diff of two texts, `---`/`+++` headers with the same label. Lines\n * are the hashing rule's (`splitLines`): a BOM is never part of a line, so a\n * page that carries one diffs the same as one that does not.\n */\nexport function unifiedDiff(label: string, before: string, after: string): string {\n const a = splitLines(before);\n const b = splitLines(after);\n // Shared prefix and suffix leave the LCS table to the lines that differ.\n let head = 0;\n while (head < a.length && head < b.length && a[head] === b[head]) head++;\n let tail = 0;\n while (tail < a.length - head && tail < b.length - head && a[a.length - 1 - tail] === b[b.length - 1 - tail]) tail++;\n const x = a.slice(head, a.length - tail);\n const y = b.slice(head, b.length - tail);\n if (x.length === 0 && y.length === 0) return \"\";\n\n const width = y.length + 1;\n const lcs = new Uint32Array((x.length + 1) * width);\n for (let i = x.length - 1; i >= 0; i--) {\n for (let j = y.length - 1; j >= 0; j--) {\n lcs[i * width + j] =\n x[i] === y[j]\n ? (lcs[(i + 1) * width + j + 1] ?? 0) + 1\n : Math.max(lcs[(i + 1) * width + j] ?? 0, lcs[i * width + j + 1] ?? 0);\n }\n }\n const edits: Edit[] = a.slice(0, head).map((text) => ({ op: \" \", text }));\n let i = 0;\n let j = 0;\n while (i < x.length || j < y.length) {\n const xi = x[i];\n const yj = y[j];\n if (xi !== undefined && yj !== undefined && xi === yj) {\n edits.push({ op: \" \", text: xi });\n i++;\n j++;\n } else if (xi !== undefined && (yj === undefined || (lcs[(i + 1) * width + j] ?? 0) >= (lcs[i * width + j + 1] ?? 0))) {\n // Deletions before insertions on a tie, as unified diffs read.\n edits.push({ op: \"-\", text: xi });\n i++;\n } else if (yj !== undefined) {\n edits.push({ op: \"+\", text: yj });\n j++;\n }\n }\n edits.push(...a.slice(a.length - tail).map((text) => ({ op: \" \" as const, text })));\n\n // Hunks: each change with one line of context; hunks whose context touches merge.\n const CONTEXT = 1;\n const out = [`--- ${label}`, `+++ ${label}`];\n let pos = 0;\n while (pos < edits.length) {\n if (edits[pos]?.op === \" \") {\n pos++;\n continue;\n }\n const from = Math.max(0, pos - CONTEXT);\n let to = pos;\n for (let k = pos; k < edits.length; k++) {\n if (edits[k]?.op !== \" \") to = k;\n else if (k - to > CONTEXT * 2) break;\n }\n to = Math.min(edits.length - 1, to + CONTEXT);\n let oldStart = 1;\n let newStart = 1;\n for (let k = 0; k < from; k++) {\n const op = edits[k]?.op;\n if (op !== \"+\") oldStart++;\n if (op !== \"-\") newStart++;\n }\n const slice = edits.slice(from, to + 1);\n const oldCount = slice.filter((e) => e.op !== \"+\").length;\n const newCount = slice.filter((e) => e.op !== \"-\").length;\n out.push(\n `@@ -${oldCount === 0 ? oldStart - 1 : oldStart},${oldCount} +${newCount === 0 ? newStart - 1 : newStart},${newCount} @@`,\n ...slice.map((e) => e.op + e.text),\n );\n pos = to + 1;\n }\n return out.join(\"\\n\") + \"\\n\";\n}\n","/**\n * Findings, their messages, and the bridge to meta's `ValidationResult`, so\n * the github/sarif/junit reporters and the baseline ratchet work unchanged.\n *\n * A claim or marker finding sits on the page line a reviewer reads. A finding\n * about the entry itself, `entry-invalid` or a bare pin whose source changed,\n * sits on the entry's own line, in the manifest when one owns it.\n *\n * FieldError: schema \"manni:cite\" (matches BUILTIN_ID, so canonicalSchemaRef\n * leaves it alone), keyword = rule, instancePath \"/citations/N\", subject =\n * id ?? source.integrity, never the claim's pin, so accepting a claim does\n * not reopen baselined findings. `ok` is true iff no error-severity finding.\n *\n * Every message spells the source as the entry spelled it. `resolvedPath`,\n * `commitsSince` and `diff` never enter a message: they are pretty-only\n * fields, shown under `--reveal` and `--show-diff`.\n */\nimport { isAbsolute } from \"node:path\";\nimport { isErrorSeverity, type FieldError, type ValidationResult } from \"../../meta/index.js\";\nimport type {\n CitationFinding,\n CitationResult,\n CiteRule,\n CiteSeverity,\n ClaimEnd,\n PageCitationReport,\n SourceEnd,\n SourceStatus,\n} from \"../types.js\";\nimport { claimLine } from \"./claims.js\";\nimport { parseSrc } from \"./range.js\";\nimport { RULE_ID_PREFIX, ruleId } from \"./severity.js\";\n\n/** The seven characters a person reads a commit by. */\nfunction short(commit: string): string {\n return commit.slice(0, 7);\n}\n\nfunction plural(n: number, noun: string): string {\n return `${String(n)} ${noun}${n === 1 ? \"\" : \"s\"}`;\n}\n\n/** `11 and 30`, `11, 20 and 30`: a list as a sentence reads it. */\nfunction listOf(values: readonly string[]): string {\n if (values.length <= 1) return values.join(\"\");\n return `${values.slice(0, -1).join(\", \")} and ${values[values.length - 1] ?? \"\"}`;\n}\n\n/** Whether the entry spelled this source encrypted. */\nfunction citesEncrypted(src: string): boolean {\n try {\n return parseSrc(src).encrypted;\n } catch {\n return false;\n }\n}\n\n/**\n * Why an encrypted source is missing, in words that never name the path. A\n * plain path names its own file, so the bare status says the rest.\n */\nfunction missingMessage(source: SourceEnd): string {\n if (!citesEncrypted(source.src)) return \"missing\";\n switch (source.missingReason) {\n case \"no-key\":\n return \"missing (no encryption key is available to decrypt it)\";\n case \"undecryptable\":\n return \"missing (does not decrypt under the current key)\";\n case \"untracked\":\n return \"missing (no tracked file matches; wrong --root?)\";\n case \"unreadable\":\n case undefined:\n return \"missing\";\n }\n}\n\n/** The one place a source end's message is composed, per status. */\nexport function messageFor(source: SourceEnd): string {\n switch (source.status) {\n case \"current\":\n return \"current\";\n case \"skipped\":\n return \"skipped\";\n case \"moved\":\n return `moved -> ${source.newSrc ?? \"?\"}`;\n case \"moved-ambiguous\": {\n const candidates = source.candidates ?? [];\n return `moved, ${plural(candidates.length, \"candidate\")} (${candidates.join(\", \")}); widen the range`;\n }\n case \"changed\": {\n if (source.commitSha === undefined) return \"changed\";\n const at = short(source.commitSha);\n if (source.historyAvailable === false) {\n return `changed (history unavailable: commit ${at} not found; fetch-depth: 0)`;\n }\n if (source.commitsSince === undefined) return `changed since ${at}`;\n return `changed since ${at}, ${plural(source.commitsSince.length, \"commit\")}`;\n }\n case \"never-true\":\n return source.commitSha === undefined\n ? \"never true: the pin does not match at the recorded commit\"\n : `never true: the pin does not match at ${short(source.commitSha)}`;\n case \"missing\":\n return missingMessage(source);\n }\n}\n\n/** `<id>: <text>`, or the text alone for an entry with no id. */\nfunction named(id: string | undefined, text: string): string {\n return id === undefined ? text : `${id}: ${text}`;\n}\n\n/** `line 9`, or `lines 9-10` when the claim covers several. */\nfunction at(spec: string): string {\n return spec.includes(\"-\") ? `lines ${spec}` : `line ${spec}`;\n}\n\n/** The one place a claim end's message is composed, per status. */\nexport function claimMessageFor(result: CitationResult): string {\n const claim = result.claim;\n const id = result.citation.id;\n if (claim === null) return \"\";\n // A marker-anchored claim has no lines of its own; it is judged where the\n // marker's text sits, and that is what the message names.\n const where =\n claim.fileLines ??\n (result.markerLine === undefined ? undefined : String(result.markerLine));\n switch (claim.status) {\n case \"moved\":\n return named(\n id,\n `the claim moved from ${at(where ?? \"?\")} to ${at(claim.newFileLines ?? \"?\")}.`,\n );\n case \"moved-ambiguous\":\n return named(\n id,\n `the claim at ${at(where ?? \"?\")} now appears at lines ${listOf(claim.candidateFileLines ?? [])}.`,\n );\n case \"changed\":\n return where === undefined\n ? named(id, \"the claim has no lines and no marker names the entry, so its pin anchors nothing.\")\n : named(id, `the claim at ${at(where)} has changed since it was pinned.`);\n case \"current\":\n case \"skipped\":\n return \"\";\n }\n}\n\n/** The rule a source status reports under, or undefined for one that is not a finding. */\nfunction sourceRuleOf(status: SourceStatus): CiteRule | undefined {\n if (status === \"skipped\" || status === \"current\") return undefined;\n return `source-${status}`;\n}\n\n/** The rule a claim status reports under, or undefined. */\nfunction claimRuleOf(claim: ClaimEnd): CiteRule | undefined {\n const status = claim.status;\n if (status === \"skipped\" || status === \"current\") return undefined;\n return `claim-${status}`;\n}\n\n/** Where a finding about a whole entry sits: its own line, in its own file. */\nfunction entrySite(result: CitationResult): Pick<CitationFinding, \"line\" | \"file\"> {\n const site: Pick<CitationFinding, \"line\" | \"file\"> = {};\n if (result.origin.line !== undefined) site.line = result.origin.line;\n if (result.origin.kind === \"manifest\") site.file = result.origin.file;\n return site;\n}\n\n/** Where a finding about an anchored citation sits: the page line it anchors to. */\nfunction anchorSite(result: CitationResult): Pick<CitationFinding, \"line\" | \"file\"> {\n if (result.anchorLine !== undefined) return { line: result.anchorLine };\n return entrySite(result);\n}\n\n/** Findings for classified citations under a severity table; `off` rules produce none. */\nexport function findingsFor(\n results: readonly CitationResult[],\n severity: Readonly<Record<CiteRule, CiteSeverity>>,\n): CitationFinding[] {\n const out: CitationFinding[] = [];\n const push = (\n result: CitationResult,\n rule: CiteRule,\n message: string,\n site: Pick<CitationFinding, \"line\" | \"file\">,\n extra?: Pick<CitationFinding, \"newSrc\">,\n ): void => {\n const level = severity[rule];\n if (level === \"off\") return;\n const finding: CitationFinding = {\n rule,\n ruleId: ruleId(rule),\n severity: level,\n message,\n src: result.source.src,\n index: result.origin.index,\n };\n if (site.line !== undefined) finding.line = site.line;\n if (site.file !== undefined) finding.file = site.file;\n if (result.citation.id !== undefined) finding.id = result.citation.id;\n if (extra?.newSrc !== undefined) finding.newSrc = extra.newSrc;\n out.push(finding);\n };\n\n for (const result of results) {\n const claim = result.claim;\n if (claim !== null) {\n const rule = claimRuleOf(claim);\n // A claim pin that anchors nothing has no page line to sit on.\n if (rule !== undefined) {\n const site =\n claimLine(claim) === undefined && result.markerLine === undefined\n ? entrySite(result)\n : { line: claimLine(claim) ?? result.markerLine };\n push(result, rule, claimMessageFor(result), site);\n }\n }\n const rule = sourceRuleOf(result.source.status);\n if (rule === undefined) continue;\n const extra =\n result.source.newSrc === undefined ? undefined : { newSrc: result.source.newSrc };\n push(result, rule, messageFor(result.source), anchorSite(result), extra);\n }\n return out;\n}\n\n/**\n * The pin of the citation a finding is about, for the fingerprint subject of\n * an entry with no id. Always the source's: accepting a changed claim must\n * not reopen a baselined finding.\n */\nfunction integrityFor(\n finding: CitationFinding,\n results: readonly CitationResult[],\n): string | undefined {\n if (finding.index === undefined) return undefined;\n return results.find((r) => r.origin.index === finding.index)?.citation.source.integrity;\n}\n\n/**\n * Where a finding is located once it becomes a `FieldError`: the page, or\n * the manifest the entry sits in.\n *\n * A manifest outside the repository has no location any reporter can use —\n * SARIF drops a uri that rebases to `../…`, and a GitHub annotation on one\n * lands nowhere — so the finding falls back to the page, and its line goes\n * with the file it belonged to. Inside the tree, both travel, and `file`\n * is what every reporter reads to annotate the manifest instead.\n */\nexport function errorSite(\n finding: CitationFinding,\n): Pick<CitationFinding, \"line\" | \"file\"> {\n if (finding.file === undefined) {\n return finding.line === undefined ? {} : { line: finding.line };\n }\n if (finding.file.startsWith(\"../\") || isAbsolute(finding.file)) return {};\n return {\n file: finding.file,\n ...(finding.line === undefined ? {} : { line: finding.line }),\n };\n}\n\nexport function toValidationResult(report: PageCitationReport): ValidationResult {\n const errors: FieldError[] = report.findings.map((finding) => {\n const error: FieldError = {\n schema: RULE_ID_PREFIX,\n instancePath: finding.index === undefined ? \"\" : `/citations/${String(finding.index)}`,\n message: finding.message,\n keyword: finding.rule,\n severity: finding.severity,\n };\n const subject = finding.id ?? integrityFor(finding, report.citations);\n if (subject !== undefined) error.subject = subject;\n const site = errorSite(finding);\n if (site.file !== undefined) error.file = site.file;\n if (site.line !== undefined) error.line = site.line;\n return error;\n });\n return {\n file: report.file,\n format: report.format,\n ok: !errors.some(isErrorSeverity),\n schemas: [RULE_ID_PREFIX],\n errors,\n };\n}\n","/**\n * `checkCitations`: the programmatic core a docevals `tool:cite` grader calls\n * for one page. Reads the entries and markers, classifies both ends of each\n * citation, applies the severity table, and returns findings whose messages\n * spell sources exactly as the entry spelled them.\n *\n * The claim end is page-side, so it is judged even under `--no-check-sources`,\n * which a public docs checkout runs. The source end needs the files.\n *\n * `quote: true` is settled here. The claim must still be a fenced block\n * (`anchor-invalid`), and the block is faithful when it reproduces the cited\n * lines as pinned (which survives a move and a missing source) or as they are\n * now (a block someone refreshed ahead of a re-mint). Neither: `quote-drift`.\n */\nimport type {\n CheckPageOptions,\n CitationFinding,\n CitationResult,\n CiteRule,\n CiteSeverity,\n ClaimEnd,\n PageCitation,\n PageCitationReport,\n PageCitations,\n PageLines,\n SourceEnd,\n SourceIndex,\n} from \"../types.js\";\nimport { findingsFor } from \"./adapt.js\";\nimport { classifyCitation, MOVE_BUDGET_BYTES } from \"./classify.js\";\nimport { blockMatches, claimEnd, claimLineNow, claimLinesNow } from \"./claims.js\";\nimport { GIT_UNAVAILABLE_HISTORY, gitClient } from \"./git.js\";\nimport { hashLines, sliceLines, splitLines } from \"./hash.js\";\nimport { readPage } from \"./page.js\";\nimport { parseSrc, sourceRange, spellSource } from \"./range.js\";\nimport { buildSourceIndex, readSource } from \"./sources.js\";\nimport { resolveSeverity, ruleId } from \"./severity.js\";\nimport { anchoredLines, fenceSpanAt } from \"./statements.js\";\n\nfunction byLine(a: CitationFinding, b: CitationFinding): number {\n return (a.line ?? Number.MAX_SAFE_INTEGER) - (b.line ?? Number.MAX_SAFE_INTEGER);\n}\n\n/** A page-side finding under the configured table: dropped when `off`, else re-levelled. */\nfunction relevel(\n finding: CitationFinding,\n severity: Readonly<Record<CiteRule, CiteSeverity>>,\n): CitationFinding | undefined {\n const level = severity[finding.rule];\n if (level === \"off\") return undefined;\n return { ...finding, severity: level };\n}\n\ninterface QuoteInput {\n page: PageCitations;\n lines: string[];\n root: string;\n index: Parameters<typeof readSource>[1];\n key?: string;\n checkSources: boolean;\n}\n\n/** The cited lines as they are now, or undefined when they cannot be read. */\nasync function citedNow(\n input: QuoteInput,\n source: SourceEnd,\n entry: PageCitation,\n): Promise<string | undefined> {\n const range = sourceRange(entry.citation.source);\n const read = await readSource(input.root, input.index, range, input.key);\n if (read.kind === \"missing\") return undefined;\n // After a move the bytes live at the new range; compare against those.\n const at = source.status === \"moved\" && source.newSrc !== undefined ? parseSrc(source.newSrc) : range;\n try {\n return sliceLines(splitLines(read.text), at);\n } catch {\n return undefined;\n }\n}\n\n/** Whether a block reproduces the citation, as pinned or as the source is now. */\nfunction faithful(\n blockText: string,\n pin: string,\n key: string | undefined,\n now: string | undefined,\n): boolean {\n return hashLines(splitLines(blockText).join(\"\\n\"), key) === pin || (now !== undefined && blockMatches(blockText, now));\n}\n\n/** The lines inside a block's fences, joined as the hashing rule joins them. */\nfunction insideOf(lines: readonly string[], block: PageLines): string {\n return lines.slice(block.start, block.end - 1).join(\"\\n\");\n}\n\n/**\n * The quote check for one entry: where its block is, whether that is still a\n * fenced block, and whether it still reproduces the source. Findings here are\n * `anchor-invalid` (page-side) and `quote-drift` (needs the source).\n */\nasync function quoteFindings(\n input: QuoteInput,\n entry: PageCitation,\n result: CitationResult,\n): Promise<{ rule: CiteRule; message: string; line?: number }[]> {\n const { citation } = entry;\n if (citation.quote !== true || result.anchor === null) return [];\n const id = citation.id;\n const named = (text: string): string => (id === undefined ? text : `${id}: ${text}`);\n const { page } = input;\n\n let block: PageLines | undefined;\n if (result.anchor === \"marker\" && entry.marker !== undefined) {\n block = anchoredLines(page.content, entry.marker.end, page.format, true);\n if (block === undefined) {\n return [\n {\n rule: \"quote-drift\",\n message: \"quote: true, but no fenced block follows the marker\",\n ...(result.markerLine === undefined ? {} : { line: result.markerLine }),\n },\n ];\n }\n } else {\n const at = result.claim === null ? undefined : claimLinesNow(result.claim);\n if (at === undefined) return [];\n const span = fenceSpanAt(page.content, at.start, page.format);\n if (span === undefined || span.end !== at.end) {\n return [\n {\n rule: \"anchor-invalid\",\n message: named(\n `the quote's claim lines ${at.start === at.end ? String(at.start) : `${String(at.start)}-${String(at.end)}`} are no longer a fenced block.`,\n ),\n line: at.start,\n },\n ];\n }\n block = span;\n }\n\n if (!input.checkSources || result.source.status === \"missing\") return [];\n const key = sourceRange(citation.source).encrypted ? input.key : undefined;\n const now = await citedNow(input, result.source, entry);\n const inside = insideOf(input.lines, block);\n if (faithful(inside, citation.source.integrity, key, now)) return [];\n return [\n {\n rule: \"quote-drift\",\n message: \"quote: true, but the fenced block does not reproduce the cited lines\",\n line: block.start,\n },\n ];\n}\n\n/** How a citation is anchored, and the page line it anchors to. */\nfunction anchorOf(\n entry: PageCitation,\n claim: ClaimEnd | null,\n page: PageCitations,\n): Pick<CitationResult, \"anchor\" | \"markerLine\" | \"anchorLine\"> {\n const { citation, marker } = entry;\n const hasLines = citation.claim?.lines !== undefined;\n const out: Pick<CitationResult, \"anchor\" | \"markerLine\" | \"anchorLine\"> = { anchor: null };\n if (marker !== undefined) out.markerLine = marker.line;\n // Lines and a marker both is `anchor-invalid`: neither anchor is trusted.\n if (hasLines && marker !== undefined) return out;\n if (hasLines) {\n out.anchor = \"claim\";\n const at = claim === null ? undefined : claimLineNow(claim);\n if (at !== undefined) out.anchorLine = at;\n return out;\n }\n if (marker !== undefined) {\n out.anchor = \"marker\";\n const unit = anchoredLines(page.content, marker.end, page.format, citation.quote === true);\n out.anchorLine = unit?.start ?? marker.line;\n }\n return out;\n}\n\nexport async function checkCitations(\n page: { file: string; content: string; format?: string },\n opts: CheckPageOptions,\n): Promise<PageCitationReport> {\n const readOptions: Parameters<typeof readPage>[2] = {};\n if (page.format !== undefined) readOptions.format = page.format;\n if (opts.citations !== undefined) readOptions.citations = opts.citations;\n if (opts.owned !== undefined) readOptions.owned = opts.owned;\n const read = readPage(page.file, page.content, readOptions);\n const severity = resolveSeverity(opts.severity);\n const client = opts.gitClient ?? gitClient(opts.root);\n const checkSources = opts.checkSources !== false;\n const lines = splitLines(read.content);\n\n const results: CitationResult[] = [];\n const findings: CitationFinding[] = [];\n const notices: string[] = [];\n for (const finding of read.findings) {\n const kept = relevel(finding, severity);\n if (kept !== undefined) findings.push(kept);\n }\n\n const index = checkSources\n ? (opts.sourceIndex ?? (await buildSourceIndex(opts.root, { gitClient: client })))\n : undefined;\n const classifyOpts =\n index === undefined\n ? undefined\n : ({ root: opts.root, index, git: client, ...(opts.key === undefined ? {} : { key: opts.key }) } satisfies Parameters<\n typeof classifyCitation\n >[1]);\n\n // A quote is judged page-side even with the sources off, so this stands\n // whether or not there is an index; `quoteFindings` reads a source only\n // when `checkSources` says it may.\n const quoteInput: QuoteInput = {\n page: read,\n lines,\n root: opts.root,\n index: index ?? emptyIndex,\n checkSources,\n ...(opts.key === undefined ? {} : { key: opts.key }),\n };\n\n for (const entry of read.citations) {\n const claim = claimEnd(read, entry, lines);\n const source: SourceEnd =\n classifyOpts === undefined\n ? skippedSource(entry)\n : await classifyCitation(entry, classifyOpts);\n const result: CitationResult = {\n citation: entry.citation,\n origin: entry.origin,\n ...anchorOf(entry, claim, read),\n claim,\n source,\n };\n results.push(result);\n\n for (const found of await quoteFindings(quoteInput, entry, result)) {\n const level = severity[found.rule];\n if (level === \"off\") continue;\n const finding: CitationFinding = {\n rule: found.rule,\n ruleId: ruleId(found.rule),\n severity: level,\n message: found.message,\n src: source.src,\n index: entry.origin.index,\n };\n if (found.line !== undefined) finding.line = found.line;\n if (entry.citation.id !== undefined) finding.id = entry.citation.id;\n findings.push(finding);\n }\n }\n\n findings.push(...findingsFor(results, severity));\n\n // History is read for a citation with a commit, so a page that holds one\n // and has no git to read it through says why its verdicts are plainer.\n // With the sources off nothing is classified, and git is never asked.\n const wantsHistory =\n checkSources &&\n read.citations.some(({ citation }) => citation.source[\"commit-sha\"] !== undefined);\n if (wantsHistory && !(await client.available())) notices.push(GIT_UNAVAILABLE_HISTORY);\n\n const unavailable = results.find((r) => r.source.historyAvailable === false);\n if (unavailable?.source.commitSha !== undefined) {\n notices.push(\n `commit ${unavailable.source.commitSha.slice(0, 7)} not found in history; use fetch-depth: 0 to enable never-true and diffs`,\n );\n }\n if (results.some((r) => r.source.truncatedSearch === true)) {\n notices.push(\n `a move search hit its ${String(MOVE_BUDGET_BYTES / (1024 * 1024))} MiB budget before covering the file; a citation may read changed rather than moved`,\n );\n }\n\n return {\n file: read.file,\n format: read.format,\n citations: results,\n findings: findings.sort(byLine),\n notices,\n };\n}\n\n/** With `--no-check-sources` no file is read, so every source end is `skipped`. */\nfunction skippedSource(entry: PageCitation): SourceEnd {\n const { source } = entry.citation;\n const out: SourceEnd = { src: spellSource(source), status: \"skipped\" };\n if (source[\"commit-sha\"] !== undefined) out.commitSha = source[\"commit-sha\"];\n return out;\n}\n\n/** Stands in where a quote is judged page-side only; nothing is ever read from it. */\nconst emptyIndex: SourceIndex = { files: () => [], has: () => false };\n","/**\n * Mint a citation's source end: read the range through the source index, hash\n * it under the rule (the keyed pin when the source is encrypted), record HEAD\n * unless told not to. Refuses (CiteError) a source the index does not hold, an\n * encrypted source the key cannot open, a range wider than\n * `MAX_RANGE_LINES`, or a range past EOF. No refusal names\n * the path an encrypted source holds.\n *\n * The claim end is minted by the caller, over the page lines it was given,\n * and passed in whole.\n */\nimport { ENCRYPTION_KEY_ENV } from \"../../shared/encryption-key.js\";\nimport { CiteError } from \"../errors.js\";\nimport type { Citation, CitationSource, MintOptions, MissingReason } from \"../types.js\";\nimport { hashLines, sliceLines, splitLines } from \"./hash.js\";\nimport { parseSrc, rangeLines, tooWide } from \"./range.js\";\nimport { buildSourceIndex, encryptSourcePath, readSource } from \"./sources.js\";\n\n/** The schema's `commit-sha` pattern: seven to sixty-four lowercase hex digits. */\nconst COMMIT_PATTERN = /^[0-9a-f]{7,64}$/;\n\nasync function commitFor(opts: MintOptions): Promise<string | undefined> {\n if (opts.commitSha === false) return undefined;\n if (typeof opts.commitSha === \"string\") {\n if (!COMMIT_PATTERN.test(opts.commitSha)) {\n throw new CiteError(\n `Invalid commit-sha \"${opts.commitSha}\": expected 7 to 64 lowercase hex digits.`,\n );\n }\n return opts.commitSha;\n }\n const client = opts.gitClient;\n if (client === undefined || !(await client.available())) return undefined;\n return (await client.head()) ?? undefined;\n}\n\n/**\n * The refusal for a source that could not be read, naming it as the caller\n * spelled it: an encrypted source stays a ciphertext even on stderr.\n */\nfunction refusalFor(reason: MissingReason, path: string, encrypted: boolean): CiteError {\n switch (reason) {\n case \"untracked\":\n return new CiteError(\n encrypted\n ? `No tracked file matches ${path} (wrong --root?).`\n : `Source not found: ${path} is not a tracked file under the root.`,\n );\n case \"no-key\":\n return new CiteError(`${path} is encrypted, and no encryption key is available to decrypt it.`);\n case \"undecryptable\":\n return new CiteError(`${path} does not decrypt under the current key.`);\n case \"unreadable\":\n return new CiteError(`Source not readable: ${path} could not be read.`);\n }\n}\n\nexport async function mintCitation(opts: MintOptions): Promise<Citation> {\n const range = parseSrc(opts.src);\n const wide =\n range.start === undefined || range.end === undefined\n ? undefined\n : tooWide({ start: range.start, end: range.end });\n if (wide !== undefined) throw new CiteError(`Invalid range \"${opts.src}\": it ${wide}.`);\n const { key } = opts;\n // A source that is already encrypted stays encrypted whatever `encrypt`\n // says: the check side keys every pin whose file is encrypted, so a plain\n // pin under a ciphertext would never hold.\n const encrypt = opts.encrypt === true || range.encrypted;\n if (encrypt && !range.encrypted && key === undefined) {\n throw new CiteError(\n `${opts.src} must be encrypted, and no encryption key is available. Run \\`manni key set\\`, or set ${ENCRYPTION_KEY_ENV}.`,\n );\n }\n const index = opts.sourceIndex ?? (await buildSourceIndex(opts.root, { gitClient: opts.gitClient }));\n\n const read = await readSource(opts.root, index, range, key);\n if (read.kind === \"missing\") throw refusalFor(read.reason, range.path, range.encrypted);\n\n // The out-of-range error names the source as the caller spelled it, never a\n // decrypted path.\n const joined = sliceLines(splitLines(read.text), range, range.path);\n // Set whenever `encrypt` is: refused above for a plain source, and an\n // encrypted one could not have been read without it.\n const pinKey = encrypt ? key : undefined;\n const file =\n pinKey !== undefined && !range.encrypted ? encryptSourcePath(read.resolvedPath, pinKey) : range.path;\n const lines = rangeLines(range);\n const commitSha = await commitFor(opts);\n\n const source: CitationSource = { file, integrity: hashLines(joined, pinKey) };\n // Field order is the order a reader scans a source in: which file, which\n // lines, what they hashed to, and when that was taken.\n const ordered: CitationSource = {\n file: source.file,\n ...(lines === undefined ? {} : { lines }),\n integrity: source.integrity,\n ...(commitSha === undefined ? {} : { \"commit-sha\": commitSha }),\n };\n // And an entry reads: what it is called, what it says, what it rests on.\n return {\n ...(opts.id === undefined ? {} : { id: opts.id }),\n ...(opts.claim === undefined ? {} : { claim: opts.claim }),\n source: ordered,\n ...(opts.quote === undefined ? {} : { quote: opts.quote }),\n };\n}\n","/**\n * The `cite:` section of manni.config.yaml, and the run resolution every\n * command shares (meta's rule: positional inputs resolve from cwd, a\n * collection's `paths` from the config directory; `root` and `baseline` are\n * config-dir relative). The document set itself is not a `cite:` key:\n * proposal 0041 put it in the family-level `collections:` list, which the\n * shared loader parses and `resolveCiteRun` selects from. Unknown keys, rules\n * or levels are errors that name the supported keys and never echo a value.\n * Root resolution: `--root` (cwd-relative) > `cite.root` > git root > cwd,\n * with a notice on the last fallback. The encryption key is the family's, not\n * a `cite:` key: `MANNI_ENCRYPTION_KEY` > the top-level `encryptionKey:` >\n * none, resolved in src/shared/encryption-key.ts (proposal 0045).\n */\nimport { resolve } from \"node:path\";\nimport { selectCollections } from \"../../shared/collections.js\";\nimport {\n findConfigFile,\n readConfigFile,\n type ConfigFile,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { resolveEncryptionKey } from \"../../shared/encryption-key.js\";\nimport { findGitRoot } from \"../../shared/git-root.js\";\nimport { SEVERITIES } from \"../../shared/severity.js\";\nimport { CiteError } from \"../errors.js\";\nimport {\n CITE_RULES,\n type CiteConfig,\n type CiteRule,\n type CiteRun,\n type CiteSeverity,\n type LoadedCiteConfig,\n} from \"../types.js\";\nimport { isCiteRule } from \"./severity.js\";\n\nexport const CITE_SECTION = \"cite\";\n\nexport const DEFAULT_CITE_BASELINE_PATH = \".manni-cite-baseline.json\";\n\n/** The keys `cite:` accepts, in the order the reference table lists them. */\nconst CONFIG_KEYS: readonly (keyof CiteConfig)[] = [\n \"allowEmpty\",\n \"respectGitignore\",\n \"root\",\n \"baseline\",\n \"checkSources\",\n \"severity\",\n];\n\n/**\n * The key the family encryption key replaced (proposal 0045). It keyed cite's\n * own hashed tokens; values are now encrypted under one key every tool reads,\n * so the old key is refused by name rather than called a typo. The message\n * never quotes the value, which was a secret.\n */\nconst SALT_KEY = \"salt\";\nconst saltRefusal = (source: string): string =>\n `${source}: \"salt\" is no longer a cite key. Values are encrypted with a family key: a top-level encryptionKey:, or MANNI_ENCRYPTION_KEY. Run \\`manni key set\\`.`;\n\n/**\n * The levels a rule takes: the family scale, most severe first, then `off`.\n * Built from `SEVERITIES`, so a level the family adds is a level cite takes.\n */\nconst SEVERITY_LEVELS: readonly CiteSeverity[] = [...[...SEVERITIES].reverse(), \"off\"];\n\nfunction isLevel(value: unknown): value is CiteSeverity {\n return typeof value === \"string\" && (SEVERITY_LEVELS as readonly string[]).includes(value);\n}\n\n/**\n * Where the metadata tool's configuration reference documents `collections:`.\n * The literal meta's `config.ts` carries, repeated because that module is\n * meta's own and sibling tools import only its public and family barrels.\n */\nconst CONFIG_REF = \"https://hawkeyexl.github.io/manni/meta/reference/configuration/\";\n\n/**\n * The two keys proposal 0041 moved out of `cite:` and up to the family level.\n * Refused rather than aliased, as meta refuses them: an alias would be a\n * second place to declare a document set that is meant to be declared once.\n */\nconst MOVED_KEYS: readonly string[] = [\"paths\", \"exclude\"];\n\n/**\n * Refuse a moved key before the unknown-key check, which would otherwise call\n * `paths` a typo. Same sentence as meta's, with the section renamed.\n */\nfunction assertNoMovedKeys(raw: Record<string, unknown>, source: string): void {\n for (const key of MOVED_KEYS) {\n if (Object.hasOwn(raw, key)) {\n throw new CiteError(\n `${source}: \"${key}\" is no longer a cite key. Document sets are declared once for every tool, under a top-level collections: list. See ${CONFIG_REF}#collections`,\n );\n }\n }\n}\n\nconst CONFIG_FILE: ConfigFileOptions = {\n section: CITE_SECTION,\n // The citation tool never had a file of its own before the family file.\n legacyNames: [],\n toError: (message) => new CiteError(message),\n};\n\n/**\n * A key the parser does not know is a typo, not a no-op. Dropping it in\n * silence would let `allowEmtpy: true` read as configured and be nothing.\n * `where` is the mapping as the user spells it: `cite` or `cite.severity`.\n */\nfunction rejectUnknownKeys(\n obj: Record<string, unknown>,\n allowed: readonly string[],\n where: string,\n source: string,\n): void {\n for (const key of Object.keys(obj)) {\n if (!allowed.includes(key)) {\n throw new CiteError(\n `Unknown key \"${key}\" under ${where}: in ${source}. Supported keys: ${allowed.join(\", \")}.`,\n );\n }\n }\n}\n\n/**\n * Every type error names the key and the type it wanted, and nothing else.\n * A value can be a secret pasted under the wrong key, and a message that\n * quoted it would put it in a CI log; the same shape for every key keeps that\n * a rule rather than a special case.\n */\nfunction wrongType(key: string, expected: string, source: string): CiteError {\n return new CiteError(`cite.${key} in ${source} must be ${expected}.`);\n}\n\nfunction asBoolean(value: unknown, key: string, source: string): boolean {\n if (typeof value !== \"boolean\") throw wrongType(key, \"a boolean\", source);\n return value;\n}\n\nfunction asString(value: unknown, key: string, source: string): string {\n if (typeof value !== \"string\") throw wrongType(key, \"a string\", source);\n return value;\n}\n\nfunction isMapping(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parseSeverity(\n value: unknown,\n source: string,\n): Partial<Record<CiteRule, CiteSeverity>> {\n if (!isMapping(value)) throw wrongType(\"severity\", \"a mapping\", source);\n rejectUnknownKeys(value, CITE_RULES, \"cite.severity\", source);\n const severity: Partial<Record<CiteRule, CiteSeverity>> = {};\n for (const [rule, level] of Object.entries(value)) {\n // `rejectUnknownKeys` already settled this; the guard is for the type.\n if (!isCiteRule(rule)) continue;\n if (!isLevel(level)) {\n // A level is not a secret, so a string one is quoted back: `eror` reads\n // as the typo it is. Anything else is described by type only.\n const got = typeof level === \"string\" ? `, not \"${level}\"` : \"\";\n throw new CiteError(\n `cite.severity.${rule} in ${source} must be one of ${SEVERITY_LEVELS.join(\", \")}${got}.`,\n );\n }\n severity[rule] = level;\n }\n return severity;\n}\n\n/**\n * Validate the `cite:` slice of a family file. `raw` is what the loader cut\n * out: `null` for an empty section, which is the same as no keys at all.\n * `source` is the file as the user would name it, for the messages.\n */\nexport function parseCiteConfig(raw: unknown, source: string): CiteConfig {\n if (raw == null) return {};\n if (!isMapping(raw)) {\n throw new CiteError(`cite: in ${source} must be a mapping.`);\n }\n assertNoMovedKeys(raw, source);\n // Before the unknown-key check, which would call it a typo.\n if (Object.hasOwn(raw, SALT_KEY)) throw new CiteError(saltRefusal(source));\n rejectUnknownKeys(raw, CONFIG_KEYS, \"cite\", source);\n const config: CiteConfig = {};\n if (raw.allowEmpty !== undefined)\n config.allowEmpty = asBoolean(raw.allowEmpty, \"allowEmpty\", source);\n if (raw.respectGitignore !== undefined)\n config.respectGitignore = asBoolean(raw.respectGitignore, \"respectGitignore\", source);\n if (raw.root !== undefined) config.root = asString(raw.root, \"root\", source);\n if (raw.baseline !== undefined)\n config.baseline = asString(raw.baseline, \"baseline\", source);\n if (raw.checkSources !== undefined)\n config.checkSources = asBoolean(raw.checkSources, \"checkSources\", source);\n\n if (raw.severity !== undefined) config.severity = parseSeverity(raw.severity, source);\n return config;\n}\n\n/**\n * The family file itself, found as `loadCiteConfig` finds it but before its\n * `cite:` slice is parsed: the text, the section shape and the family keys\n * (`collections:`, `encryptionKey:`), for a caller that needs more than the\n * values, such as a write that puts a key there. `null` when discovery finds\n * nothing.\n */\nexport function readCiteConfigFile(\n explicitPath: string | undefined,\n cwd: string,\n): Promise<ConfigFile | null> {\n return explicitPath\n ? readConfigFile(explicitPath, cwd, CONFIG_FILE)\n : findConfigFile(cwd, CONFIG_FILE);\n}\n\n/**\n * Load the config from an explicit path (an error if missing) or by\n * discovery: cwd and each ancestor up to the nearest `.git` boundary, reading\n * `manni.config.yaml` at its `cite:` key. A family file with neither `cite:`\n * nor `collections:` belongs to a sibling tool and discovery keeps looking;\n * one with `collections:` alone is this tool's config with no options of its\n * own (0041). See src/shared/config-file.ts for the rules. `null` when\n * discovery finds nothing.\n */\nexport async function loadCiteConfig(\n explicitPath?: string,\n cwd: string = process.cwd(),\n): Promise<LoadedCiteConfig | null> {\n const file = await readCiteConfigFile(explicitPath, cwd);\n return file === null ? null : toLoaded(file);\n}\n\n/** A discovered file's `cite:` slice, parsed, with where it came from. */\nfunction toLoaded(file: ConfigFile): LoadedCiteConfig {\n return {\n config: parseCiteConfig(file.value, file.source),\n path: file.path,\n dir: file.dir,\n source: file.source,\n collections: file.collections,\n };\n}\n\nexport interface CiteRunOptions {\n cwd: string;\n /** `-c/--config`. */\n configPath?: string;\n /** `--no-config`: skip discovery and run on the built-in defaults. */\n noConfig?: boolean;\n /** Positional inputs; empty means fall back to the selected collections' `paths:`. */\n inputs: string[];\n /**\n * `--collection <name>`, repeatable: the collections this run covers. Empty\n * or absent means every declared one, the same thing, because commander's\n * collector hands `[]` over when the flag was never typed.\n */\n collection?: string[];\n /** `--root`, cwd-relative. */\n root?: string;\n onConfigLoaded?: (info: { path: string; dir: string }) => void;\n /** Told once when the root fell back to cwd. */\n onNotice?: (message: string) => void;\n /** Defaults to `process.env`; a test hands in its own. */\n env?: NodeJS.ProcessEnv;\n}\n\n/** The stdin token, repeated so this module does not depend on the file loader above it. */\nconst STDIN = \"-\";\n\n/**\n * Settle what every command core needs before it touches a file: which\n * config governs the run, what to resolve and from where, the root `src:`\n * paths resolve against, and the encryption key.\n */\nexport async function resolveCiteRun(opts: CiteRunOptions): Promise<CiteRun> {\n const cwd = resolve(opts.cwd);\n const env = opts.env ?? process.env;\n\n // `--collection` names something only a config can define, and selects a\n // set the operator did not type, so it composes with neither positional\n // paths nor `--no-config`. The same two sentences meta and a11y use.\n // Stdin is one more input rather than a path, so it rides beside the flag.\n const wanted = opts.collection ?? [];\n if (wanted.length > 0 && opts.inputs.some((input) => input !== STDIN)) {\n throw new CiteError(\n \"--collection selects a configured collection; it cannot be combined with paths.\",\n );\n }\n\n // `--no-config` wins over an explicit path, as in meta: the CLI cannot\n // supply both, but the cores are public API. It drops the collections with\n // the section: the file the run was told to ignore is where both live.\n const file = opts.noConfig ? null : await readCiteConfigFile(opts.configPath, cwd);\n const loaded = file === null ? null : toLoaded(file);\n if (wanted.length > 0 && loaded === null) {\n throw new CiteError(\"--collection needs a config file to select from.\");\n }\n if (loaded) opts.onConfigLoaded?.({ path: loaded.path, dir: loaded.dir });\n const config = loaded ? loaded.config : null;\n\n // Selected whatever the inputs are: a typed file is still a member of the\n // collections that contain it. An unknown name is the shared helper's error.\n const collections = loaded\n ? selectCollections(loaded.collections, wanted, loaded.source, (message) => new CiteError(message))\n : [];\n\n // One base per run: positional paths are typed from a shell and stay\n // cwd-relative; a collection's `paths:` was written next to the config and\n // resolves there.\n const fromCollections = opts.inputs.length === 0;\n const inputs = fromCollections ? collections.flatMap((c) => c.paths) : opts.inputs;\n const base = fromCollections && inputs.length > 0 && loaded ? loaded.dir : cwd;\n\n let root: string;\n if (opts.root !== undefined) {\n root = resolve(cwd, opts.root);\n } else if (loaded && config?.root !== undefined) {\n root = resolve(loaded.dir, config.root);\n } else {\n const gitRoot = findGitRoot(cwd);\n if (gitRoot !== null) {\n root = gitRoot;\n } else {\n root = cwd;\n opts.onNotice?.(`No git root found; resolving src: paths from ${cwd}`);\n }\n }\n\n // The family key, from the environment or the file's top level. A\n // malformed one is refused here, before any page is read.\n const { key, source: keySource } = resolveEncryptionKey({\n env,\n file,\n toError: (message) => new CiteError(message),\n });\n\n return {\n config,\n inputs,\n base,\n collections,\n fromCollections,\n ...(loaded ? { configDir: loaded.dir, configPath: loaded.path, configSource: loaded.source } : {}),\n root,\n key,\n keySource,\n ...(file === null ? {} : { configFile: file }),\n };\n}\n","/**\n * The one severity scale every manni tool speaks. Least to most severe.\n *\n * Three values, chosen to match the sinks every tool writes to and the\n * linters that sit beside it. GitHub annotations are `error`, `warning` and\n * `notice`; so are ESLint's and Vale's levels, and pa11y's. A flag or config\n * key that two domains both have carries the same name and the same values,\n * and this is where the values for `severity` are defined once.\n *\n * A domain whose source speaks another scale maps onto this one and keeps\n * the source's value in a field of its own, so nothing is lost for lookup.\n * a11y is the first case: axe reports four impacts, the analyzer folds them\n * onto these three, and each finding still carries axe's word as `impact`.\n */\nexport const SEVERITIES = [\"notice\", \"warning\", \"error\"] as const;\nexport type Severity = (typeof SEVERITIES)[number];\n\n/** The list the way a usage message spells it: `notice | warning | error`. */\nexport const SEVERITY_LIST: string = SEVERITIES.join(\" | \");\n\nexport function isSeverity(value: string): value is Severity {\n return (SEVERITIES as readonly string[]).includes(value);\n}\n\n/** `true` when `severity` is at or above `min`. */\nexport function meetsSeverity(severity: Severity, min: Severity): boolean {\n return SEVERITIES.indexOf(severity) >= SEVERITIES.indexOf(min);\n}\n","/**\n * `manni cite check`: resolve targets, check every page, settle the baseline.\n *\n * The run shape is meta's `validate`: `resolveCiteRun` → `resolveTargetSet` /\n * `assertNonEmpty` → one `checkCitations` per page → `settleBaseline`. One git\n * client and one source index are built for the run and handed to every page,\n * so a thousand pages against one root cost one `git ls-files`. `prepareRun`\n * is the shared front half; `update` runs the same one.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport {\n isErrorSeverity,\n supportedExtensions,\n type FieldError,\n type FingerprintContext,\n type MetadataExtractor,\n type RunSummary,\n} from \"../../meta/index.js\";\nimport {\n assertNonEmpty,\n extractorByName,\n gitignoreOptions,\n resolveBaselineRequest,\n resolveTargetSet,\n settleBaseline,\n STDIN_LABEL,\n STDIN_TOKEN,\n} from \"../../meta/internal.js\";\nimport { toValidationResult } from \"../core/adapt.js\";\nimport { checkCitations } from \"../core/check-page.js\";\nimport { DEFAULT_CITE_BASELINE_PATH, resolveCiteRun } from \"../core/config.js\";\nimport { GIT_UNAVAILABLE_HISTORY, gitClient } from \"../core/git.js\";\nimport {\n duplicateJoinRefusal,\n orphanRefusal,\n sidecarsFor,\n type CitationSidecars,\n type PageSidecar,\n} from \"../core/sidecar.js\";\nimport { sourceIndexFor } from \"../core/sources.js\";\nimport { CiteError } from \"../errors.js\";\nimport type {\n CheckOptions,\n CheckPageOptions,\n CheckRun,\n CiteRun,\n GitClient,\n PageCitationReport,\n} from \"../types.js\";\n\n/** What `check` and `update` settle before touching a page. */\nexport interface PreparedRun {\n cwd: string;\n run: CiteRun;\n /** Files to process, posix and relative to `run.base`. */\n files: string[];\n gitignoreSkipped: number;\n usingStdin: boolean;\n /** The `--as` extractor, validated. */\n forced?: MetadataExtractor;\n /** What every `checkCitations` call in the run shares: root, key, table, client, index. */\n pageOptions: CheckPageOptions;\n /** The git client every page shares, the one in `pageOptions`. */\n git: GitClient;\n /** The manifests that own `citations`, or `null` when none does. */\n sidecars: CitationSidecars | null;\n /**\n * What this page's manifest supplies, and the options that carry it. One\n * call per page, so a page named by path still finds its sidecar.\n */\n setupFor: (label: string, content: string) => PageSetup;\n /** Whether a flag reshaped the input set, which turns the corpus checks off. */\n scopedByFlags: boolean;\n /** The collections a `--collection` run narrowed to; `undefined` for a whole corpus. */\n covered?: string[];\n}\n\n/** One page's manifest entries, and the check options that carry them. */\nexport interface PageSetup {\n options: CheckPageOptions;\n /** Absent when no manifest owns this page's citations. */\n sidecar?: PageSidecar;\n}\n\n/**\n * The join values pages carried, for the duplicate-join refusal and the\n * orphan check that follows the per-page loop.\n */\nexport interface JoinHits {\n record: (page: PageSidecar, label: string) => void;\n /** Field -> the values loaded pages carried. */\n matched: Map<string, Set<string>>;\n}\n\nexport function joinHits(): JoinHits {\n const matched = new Map<string, Set<string>>();\n const seen = new Map<string, { file: string; labels: string[] }>();\n return {\n matched,\n record(page, label) {\n for (const join of page.joins) {\n const values = matched.get(join.field) ?? new Set<string>();\n values.add(join.value);\n matched.set(join.field, values);\n const id = `${join.field}\\u0000${join.value}`;\n const hit = seen.get(id) ?? { file: join.file, labels: [] };\n if (!hit.labels.includes(label)) hit.labels.push(label);\n seen.set(id, hit);\n // Two pages behind one entry: the manifest cannot tell them apart,\n // and a write would land on whichever the run reached last.\n if (hit.labels.length > 1) {\n throw new CiteError(\n duplicateJoinRefusal(join.field, join.value, join.file, hit.labels),\n );\n }\n }\n },\n };\n}\n\n/**\n * The front half of a run: which config governs it, which files it covers,\n * and the clients every page shares. `action` is the past-tense verb the\n * empty-set error uses (\"checked\"), `verb` the imperative one (\"check\").\n */\nexport async function prepareRun(\n opts: CheckOptions,\n action: string,\n verb: string,\n requireSources = false,\n): Promise<PreparedRun> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const run = await resolveCiteRun({\n cwd,\n configPath: opts.configPath,\n noConfig: opts.noConfig,\n inputs: opts.inputs,\n collection: opts.collection,\n root: opts.root,\n onConfigLoaded: opts.onConfigLoaded,\n onNotice: opts.onNotice,\n env: opts.env,\n });\n const { config, inputs, base } = run;\n\n const checkSources = opts.checkSources ?? config?.checkSources ?? true;\n if (requireSources && !checkSources) {\n throw new CiteError(`${verb} needs the sources: drop --no-check-sources (or \\`checkSources: false\\`).`);\n }\n if (inputs.length === 0) {\n throw new CiteError(\n `No files to ${verb}. Pass paths/globs, or declare a collection under \\`collections:\\` in manni.config.yaml.`,\n );\n }\n\n const usingStdin = inputs.includes(STDIN_TOKEN);\n const forced = opts.as === undefined ? undefined : extractorByName(opts.as);\n if (opts.as !== undefined && forced === undefined) {\n throw new CiteError(\n `Unknown format \"${opts.as}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n if (usingStdin && forced === undefined) {\n throw new CiteError(\"Reading from stdin (`-`) requires --as <format> to choose an extractor.\");\n }\n\n const exts = opts.exts ?? forced?.extensions;\n const fileInputs = inputs.filter((input) => input !== STDIN_TOKEN);\n const allowEmpty = opts.allowEmpty ?? config?.allowEmpty;\n // A collection's `exclude:` shapes the collection, so it applies when the\n // inputs came from the collections and never to a path the operator typed.\n // `--exclude` filters either way; the union is deduplicated, first spelling wins.\n const exclude = [\n ...new Set([\n ...(opts.exclude ?? []),\n ...(run.fromCollections ? run.collections.flatMap((c) => c.exclude) : []),\n ]),\n ];\n const { files, gitignoreSkipped } = await resolveTargetSet({\n inputs: fileInputs,\n exts,\n exclude,\n cwd: base,\n allowEmpty,\n ...gitignoreOptions({\n flag: opts.respectGitignore,\n configured: config?.respectGitignore,\n onNotice: opts.onNotice,\n }),\n });\n assertNonEmpty({ files, inputs: fileInputs, usingStdin, allowEmpty, exclude, exts, gitignoreSkipped, action });\n\n // Git is used whenever it is there: on PATH, with the root inside a work\n // tree. Where it is not, the index is a walk and history is off, and a page\n // whose citations wanted history says so (see `checkCitations`).\n const git = opts.gitClient ?? gitClient(run.root);\n const pageOptions: CheckPageOptions = {\n root: run.root,\n checkSources,\n key: run.key,\n severity: config?.severity,\n gitClient: git,\n };\n if (checkSources) pageOptions.sourceIndex = await sourceIndexFor(run.root, git);\n\n // The sidecar manifests, read once per run. Membership is every declared\n // collection's, whatever this run selected, so a page given by path still\n // finds the manifest that owns its citations.\n const sidecars = await sidecarsFor(run);\n const setupFor = (label: string, content: string): PageSetup => {\n const page = sidecars?.forPage(label, content, forced?.name);\n if (page?.owner === undefined) return { options: pageOptions };\n return {\n sidecar: page,\n options: {\n ...pageOptions,\n owned: { file: page.owner.file, collection: page.owner.collection },\n ...(page.citations === undefined ? {} : { citations: page.citations }),\n },\n };\n };\n\n // The corpus invariant meta's orphan checks use: any CLI reshaping of the\n // input set means the operator chose to look at part of the corpus, and an\n // entry for the rest is expected rather than orphaned. `--collection` is\n // not such a reshaping; it makes each named collection a corpus of its own.\n const scopedByFlags =\n // The inputs the operator typed, not the collection globs they resolved\n // to: a corpus run has none of the first and all of the second.\n opts.inputs.length > 0 ||\n usingStdin ||\n opts.as !== undefined ||\n opts.exts !== undefined ||\n (opts.exclude !== undefined && opts.exclude.length > 0) ||\n opts.respectGitignore !== undefined;\n const covered = (opts.collection?.length ?? 0) > 0 ? run.collections.map((c) => c.name) : undefined;\n\n return {\n cwd,\n run,\n files,\n gitignoreSkipped,\n usingStdin,\n forced,\n pageOptions,\n git,\n sidecars,\n setupFor,\n scopedByFlags,\n ...(covered === undefined ? {} : { covered }),\n };\n}\n\n/**\n * The manifest entries a corpus run found nothing for. A run the CLI\n * narrowed checks nothing: it never claimed to cover the corpus.\n */\nexport function assertNoOrphans(prepared: PreparedRun): void {\n const { sidecars } = prepared;\n if (sidecars === null || prepared.scopedByFlags) return;\n const orphans = sidecars.orphans(prepared.files, prepared.covered);\n if (orphans.length > 0) throw orphanRefusal(orphans);\n}\n\n/** The same invariant, for field-joined entries no loaded page matched. */\nexport function assertNoOrphanJoins(prepared: PreparedRun, hits: JoinHits): void {\n const { sidecars } = prepared;\n if (sidecars === null || prepared.scopedByFlags) return;\n const orphans = sidecars.orphanJoins(hits.matched, prepared.covered);\n if (orphans.length > 0) throw orphanRefusal(orphans);\n}\n\n/** Read a resolved target, as the run labelled it. */\nexport function readTarget(run: CiteRun, file: string): Promise<string> {\n return readFile(resolve(run.base, file), \"utf8\");\n}\n\n/**\n * Run-level notices are said once per run, however many pages raised them.\n * `also` is what the run has to say beyond its pages: said after them, and\n * not again when a page already said it.\n */\nexport function sayNotices(\n pages: readonly PageCitationReport[],\n onNotice: CheckOptions[\"onNotice\"],\n also: readonly string[] = [],\n): void {\n const said = new Set<string>();\n for (const notice of [...pages.flatMap((page) => page.notices), ...also]) {\n if (said.has(notice)) continue;\n said.add(notice);\n onNotice?.(notice);\n }\n}\n\nexport async function runCheck(opts: CheckOptions): Promise<CheckRun> {\n const prepared = await prepareRun(opts, \"checked\", \"check\");\n const { cwd, run, files, gitignoreSkipped, usingStdin, forced, pageOptions, git } = prepared;\n assertNoOrphans(prepared);\n const hits = joinHits();\n\n const pages: PageCitationReport[] = [];\n const checkOne = async (label: string, content: string): Promise<void> => {\n const setup = prepared.setupFor(label, content);\n if (setup.sidecar !== undefined) hits.record(setup.sidecar, label);\n pages.push(await checkCitations({ file: label, content, format: forced?.name }, setup.options));\n };\n if (usingStdin) await checkOne(STDIN_LABEL, opts.stdinContent ?? \"\");\n for (const file of files) await checkOne(file, await readTarget(run, file));\n assertNoOrphanJoins(prepared, hits);\n // `--show-diff` wants history whatever the pages carry. With the sources\n // off nothing is classified, so nothing wants git.\n const wantsDiff = opts.showDiff === true && pageOptions.checkSources !== false && !(await git.available());\n sayNotices(pages, opts.onNotice, wantsDiff ? [GIT_UNAVAILABLE_HISTORY] : []);\n\n const results = pages.map(toValidationResult);\n // Fingerprints must not depend on where the command was run from, so they\n // are measured from the config's directory when one governs the run.\n const frame: FingerprintContext = { cwd, base: run.configDir ?? cwd, runBase: run.base };\n const request = resolveBaselineRequest(opts, run.config?.baseline, run.configDir, cwd, {\n current: DEFAULT_CITE_BASELINE_PATH,\n });\n // The ratchet's own not-found error names `meta validate`; this tool's\n // baseline is recorded by its own command, so the advice has to say so.\n if (request !== null && !request.write && !existsSync(request.absPath)) {\n throw new CiteError(\n `Baseline \"${request.label}\" not found. Record one with \\`manni cite check --write-baseline\\`, or drop --baseline.`,\n );\n }\n const { results: reported, baseline } = await settleBaseline(results, request, frame);\n\n const failed = reported.filter((r) => !r.ok).length;\n const count = (keep: (e: FieldError) => boolean): number =>\n reported.reduce((n, r) => n + r.errors.filter(keep).length, 0);\n const warnings = count((e) => e.severity === \"warning\");\n const notices = count((e) => e.severity === \"notice\");\n const summary: RunSummary = {\n files: reported.length,\n passed: reported.length - failed,\n failed,\n errors: count(isErrorSeverity),\n // Omitted at zero, as meta's summary has them, so the JSON shape of a\n // clean run is the one every consumer of `meta validate` already reads.\n ...(warnings > 0 ? { warnings } : {}),\n ...(notices > 0 ? { notices } : {}),\n ...(gitignoreSkipped > 0 ? { gitignoreSkipped } : {}),\n ...(baseline ? { baseline } : {}),\n };\n\n return { results: reported, summary, frame, pages, warnings, notices };\n}\n","/**\n * `manni cite add`: mint one citation and write it to a page.\n *\n * The page lines are the claim: `add docs/limits.md:9 lib/limits.ts:2` pins\n * line 9 of the page to line 2 of the source. Lines reach the command as an\n * editor numbers them and are stored body-relative, so editing the\n * frontmatter never moves them. `--marker` writes a `cite <id>` comment above\n * those lines instead, and pins the text it anchors; `--quote` says the lines\n * are a fenced block that reproduces the source. No lines at all is a bare\n * pin: this page rests on these lines, say so when they change.\n *\n * Every refusal is a `CiteError` (exit 2) with the page and the source\n * spelled as the caller spelled them, and nothing is written.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { locateFrontmatter, writeFileAtomic } from \"../../meta/index.js\";\nimport { STDIN_LABEL, STDIN_TOKEN } from \"../../meta/internal.js\";\nimport { ensureEncryptionKey } from \"../../shared/prompt.js\";\nimport { blockMatches, pinOfLines, toBodyLines, toFileLines } from \"../core/claims.js\";\nimport { resolveCiteRun } from \"../core/config.js\";\nimport { GIT_UNAVAILABLE_COMMIT, gitClient } from \"../core/git.js\";\nimport { sliceLines, splitLines } from \"../core/hash.js\";\nimport { mintCitation } from \"../core/mint.js\";\nimport { bodyLineOf, readPage } from \"../core/page.js\";\nimport { lineSpec, parseLines, parseSrc, spellLines, tooWide } from \"../core/range.js\";\nimport { readSource, sourceIndexFor } from \"../core/sources.js\";\nimport { ManifestSet } from \"../core/manifest.js\";\nimport { sidecarsFor, type PageSidecar } from \"../core/sidecar.js\";\nimport {\n anchoredLines,\n fenceSpanAt,\n formatStatement,\n markerIndent,\n offsetOfLine,\n unitHolding,\n} from \"../core/statements.js\";\nimport {\n appendFrontmatterCitation,\n entryObject,\n insertStatementBefore,\n spliceEntryField,\n unifiedDiff,\n} from \"../core/write.js\";\nimport { CiteError } from \"../errors.js\";\nimport type {\n AddOptions,\n AddResult,\n Citation,\n CitationClaim,\n LineSpec,\n PageCitation,\n PageLines,\n SourceIndex,\n} from \"../types.js\";\n\n/** The schema's id grammar, checked before anything is written. */\nconst ID = /^[a-z0-9][a-z0-9-]*$/;\n\nconst toPosix = (path: string): string => path.replace(/\\\\/g, \"/\");\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nasync function readPageFile(path: string, label: string): Promise<string> {\n try {\n return await readFile(path, \"utf8\");\n } catch (error) {\n if (isEnoent(error)) throw new CiteError(`File not found: \"${label}\".`);\n throw error;\n }\n}\n\n/** The cited lines, joined as the hashing rule joins them. */\nasync function citedText(\n root: string,\n index: SourceIndex,\n src: string,\n key: string | undefined,\n): Promise<string> {\n const range = parseSrc(src);\n const source = await readSource(root, index, range, key);\n // Minting already read this range, so a miss here is a race with the disk.\n if (source.kind === \"missing\") {\n throw new CiteError(`Source not readable: ${range.path} could not be read.`);\n }\n return sliceLines(splitLines(source.text), range, range.path);\n}\n\n/** `line 9`, or `lines 9-12` for a range. */\nfunction spellAt(lines: PageLines): string {\n return lines.start === lines.end\n ? `line ${String(lines.start)}`\n : `lines ${String(lines.start)}-${String(lines.end)}`;\n}\n\n/** The new `claim.lines` of each entry a marker pushes down, by where the entry lives. */\ninterface Shifted {\n frontmatter: { index: number; lines: LineSpec }[];\n manifest: Map<number, LineSpec>;\n}\n\n/**\n * The entries whose claim lines start at or below `insertLine`, each moved\n * down one line. An entry whose claim starts above the marker and reaches it\n * would have a line inserted into its pin, so that is a refusal.\n */\nfunction shiftedEntries(\n citations: readonly PageCitation[],\n insertLine: number,\n bodyLine: number,\n label: string,\n): Shifted {\n const out: Shifted = { frontmatter: [], manifest: new Map() };\n for (const { citation, origin } of citations) {\n const spec = citation.claim?.lines;\n const recorded = spec === undefined ? undefined : parseLines(spec);\n if (recorded === undefined) continue;\n const file = toFileLines(recorded, bodyLine);\n if (file.start < insertLine) {\n if (file.end < insertLine) continue;\n const whose =\n citation.id === undefined\n ? `the claim at ${spellAt(file)}`\n : `the claim of ${citation.id} (${spellAt(file)})`;\n throw new CiteError(\n `${label}:${String(insertLine)} is inside ${whose}. A marker there would change its pin.`,\n );\n }\n const moved = lineSpec({ start: recorded.start + 1, end: recorded.end + 1 });\n if (origin.kind === \"manifest\") out.manifest.set(origin.index, moved);\n else out.frontmatter.push({ index: origin.index, lines: moved });\n }\n return out;\n}\n\n/** A copy of a manifest entry with its `claim.lines` replaced. */\nfunction withClaimLines(entry: unknown, lines: LineSpec): unknown {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) return entry;\n const claim: unknown = (entry as Record<string, unknown>).claim;\n if (typeof claim !== \"object\" || claim === null || Array.isArray(claim)) return entry;\n return { ...entry, claim: { ...claim, lines } };\n}\n\nexport async function runAdd(opts: AddOptions): Promise<AddResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const run = await resolveCiteRun({\n cwd,\n configPath: opts.configPath,\n noConfig: opts.noConfig,\n inputs: [],\n root: opts.root,\n onConfigLoaded: opts.onConfigLoaded,\n onNotice: opts.onNotice,\n env: opts.env,\n });\n const { root } = run;\n\n const usingStdin = opts.page === STDIN_TOKEN;\n if (usingStdin && opts.as === undefined) {\n throw new CiteError(\"Reading from stdin (`-`) requires --as <format> to choose an extractor.\");\n }\n // `-` names no file: nothing to resolve, and nothing to write back to.\n const path = usingStdin ? undefined : resolve(cwd, opts.page);\n const label = path === undefined ? STDIN_LABEL : toPosix(relative(cwd, path));\n const content = path === undefined ? (opts.stdinContent ?? \"\") : await readPageFile(path, label);\n\n // The manifests that own `citations`, if any collection declares one. The\n // page is labelled from the working directory here, so membership is\n // measured from there too.\n const sidecars = await sidecarsFor(run, { base: cwd });\n const firstManifest = sidecars?.manifests[0];\n if (usingStdin && firstManifest !== undefined) {\n const keyedBy = firstManifest.join === \"path\" ? \"path\" : firstManifest.join;\n throw new CiteError(\n `A page read from stdin has no path, and its citations live in ${firstManifest.file}, which is keyed by ${keyedBy}.`,\n );\n }\n const sidecar: PageSidecar | undefined = usingStdin\n ? undefined\n : sidecars?.forPage(label, content, opts.as);\n const owner = sidecar?.owner;\n\n const page = readPage(label, content, {\n ...(opts.as === undefined ? {} : { format: opts.as }),\n // The entries already there are the manifest's, so `--id` uniqueness and\n // the marker checks are measured against them and not against a page\n // that carries none.\n ...(sidecar?.citations === undefined ? {} : { citations: sidecar.citations }),\n ...(owner === undefined ? {} : { owned: { file: owner.file, collection: owner.collection } }),\n });\n const { format } = page;\n\n const pageLines = opts.pageLines;\n const marker = opts.marker === true;\n const quote = opts.quote === true;\n const at = pageLines === undefined ? \"\" : `${label}:${spellLines(pageLines)}`;\n\n // Composition first: these need no source and no search.\n if (marker && pageLines === undefined) {\n throw new CiteError(`--marker needs the page lines to anchor: ${label}:L.`);\n }\n if (marker && opts.id === undefined) {\n throw new CiteError(\"--marker needs --id: the marker names the entry.\");\n }\n const wide = pageLines === undefined ? undefined : tooWide(pageLines);\n if (wide !== undefined) throw new CiteError(`Invalid range \"${at}\": it ${wide}.`);\n if (quote && pageLines === undefined) {\n throw new CiteError(`--quote needs the block's lines: ${label}:L1-L2.`);\n }\n if (opts.id !== undefined && !ID.test(opts.id)) {\n throw new CiteError(\n `Invalid id \"${opts.id}\": use lowercase letters, digits and hyphens, starting with a letter or digit.`,\n );\n }\n if (opts.id !== undefined && page.citations.some((c) => c.citation.id === opts.id)) {\n throw new CiteError(`${label} already has an entry ${opts.id}.`);\n }\n if (marker && opts.id !== undefined) {\n const already = page.statements.find(\n (s) => s.payload.kind === \"ref\" && s.payload.id === opts.id,\n );\n if (already !== undefined) {\n throw new CiteError(\n `${label} already has a marker ${opts.id} at line ${String(already.line)}.`,\n );\n }\n }\n\n const lines = splitLines(content);\n if (pageLines !== undefined) {\n if (pageLines.end > lines.length) {\n throw new CiteError(`${at} is past the end of the page (${String(lines.length)} lines).`);\n }\n if (pageLines.start < page.bodyLine) {\n throw new CiteError(`${at} is in the frontmatter. A claim is body text.`);\n }\n if (quote) {\n const span = fenceSpanAt(content, pageLines.start, format);\n if (span === undefined || span.end !== pageLines.end) {\n throw new CiteError(`${at} is not a fenced block, so it cannot be a quote.`);\n }\n }\n }\n\n // Git is used whenever it is there, as on check and update: the index is\n // `git ls-files` and the commit is HEAD. Where it is not, a walk and none.\n const client = opts.gitClient ?? gitClient(root);\n const sourceIndex = await sourceIndexFor(root, client);\n\n // The marker goes in before the claim is pinned, because what it anchors is\n // what the claim pins. Everything below counts lines in `body`, the page\n // with the marker, and the frontmatter append shifts them once at the end.\n let body = content;\n let markerAt: number | undefined;\n let claimSpan: PageLines | undefined;\n let claim: CitationClaim | undefined;\n // Entries whose claim lines sit below a marker move down with the text.\n let shifted: Shifted = { frontmatter: [], manifest: new Map() };\n if (marker && pageLines !== undefined) {\n // The marker goes above the paragraph or block holding the lines, below\n // any markers already stacked there, at its indentation, and the lines\n // must stay inside it.\n const holding = unitHolding(content, pageLines.start, format, {\n offset: page.bodyOffset,\n line: page.bodyLine,\n });\n if (holding === undefined) {\n throw new CiteError(`${at} has no paragraph or block for a marker to anchor.`);\n }\n if (pageLines.end > holding.end) {\n throw new CiteError(\n `${at} runs past the ${holding.kind} at ${spellAt(holding)}. A marker anchors one paragraph.`,\n );\n }\n shifted = shiftedEntries(page.citations, holding.start, page.bodyLine, label);\n const statement =\n markerIndent(content, holding.start, format, page.bodyLine) +\n formatStatement(format, { kind: \"ref\", id: opts.id ?? \"\" });\n const insertAt = offsetOfLine(content, holding.start);\n body = insertStatementBefore(content, insertAt, statement);\n markerAt = holding.start;\n const unit = anchoredLines(body, insertAt + statement.length, format, quote);\n const pin = unit === undefined ? undefined : pinOfLines(splitLines(body), unit);\n if (unit === undefined || pin === undefined) {\n throw new CiteError(`${at} has no paragraph or block for a marker to anchor.`);\n }\n for (const { index, lines: moved } of shifted.frontmatter) {\n body = spliceEntryField(body, format, index, [\"claim\", \"lines\"], moved);\n }\n claimSpan = unit;\n claim = { integrity: pin };\n } else if (pageLines !== undefined) {\n const pin = pinOfLines(lines, pageLines);\n if (pin === undefined) {\n throw new CiteError(`${at} is past the end of the page (${String(lines.length)} lines).`);\n }\n claimSpan = pageLines;\n claim = { lines: lineSpec(toBodyLines(pageLines, page.bodyLine)), integrity: pin };\n }\n\n const mint = (key: string | undefined, encrypt: boolean): Promise<Citation> =>\n mintCitation({\n root,\n src: opts.src,\n ...(opts.id === undefined ? {} : { id: opts.id }),\n ...(claim === undefined ? {} : { claim }),\n ...(quote ? { quote: true } : {}),\n ...(opts.commitSha === false ? { commitSha: false as const } : {}),\n encrypt,\n ...(key === undefined ? {} : { key }),\n gitClient: client,\n sourceIndex,\n });\n\n // Encryption follows the key: an available one encrypts every add, with no\n // flag to remember, and `--encrypt` asks for one when there is none. With a\n // key in hand this mint is the citation written. Without one it is plain,\n // and settles every refusal that needs no key before the question is put,\n // so a refused add never leaves a key behind.\n const needsKey = opts.encrypt === true && run.key === undefined;\n let citation = await mint(run.key, run.key !== undefined);\n\n if (quote && claimSpan !== undefined) {\n // The lines inside the fences are what the source has to match.\n const cited = await citedText(root, sourceIndex, opts.src, run.key);\n const inside = splitLines(body).slice(claimSpan.start, claimSpan.end - 1).join(\"\\n\");\n if (!blockMatches(inside, cited)) {\n throw new CiteError(`The block at ${at} does not reproduce ${opts.src}.`);\n }\n }\n\n if (needsKey) {\n const { key } = await ensureEncryptionKey({\n subject: opts.src,\n cwd,\n file: run.configFile ?? null,\n env: opts.env,\n confirm: opts.confirm,\n notice: (message) => {\n opts.onNotice?.(message);\n },\n toError: (message) => new CiteError(message),\n });\n citation = await mint(key, true);\n }\n\n // Where the entry goes follows the config, not a flag: a collection whose\n // manifest owns `citations` keeps them there, and the page is left alone\n // but for a marker.\n const manifests = new ManifestSet();\n let placed: AddResult[\"manifest\"];\n if (owner !== undefined) {\n if (sidecar?.entry === undefined) {\n throw new CiteError(\n `${label} carries no ${owner.join}: value, so its citations cannot be keyed in ${owner.file}.`,\n );\n }\n const existing = (sidecar.citations ?? []).map((input, index) => {\n const moved = shifted.manifest.get(index);\n return moved === undefined ? input.entry : withClaimLines(input.entry, moved);\n });\n const list = [...existing, entryObject(citation)];\n const at = await manifests.write(owner, sidecar.entry, list, list.length - 1);\n const [changed] = manifests.changed();\n placed = {\n file: at.file,\n line: at.line,\n content: changed?.text ?? \"\",\n diff: changed?.diff ?? \"\",\n written: false,\n };\n }\n\n const after = owner === undefined ? appendFrontmatterCitation(body, format, citation, label) : body;\n // The frontmatter append leaves the body's bytes alone, so every body line\n // moves by exactly what the block grew. The marker sits in the body, so the\n // page it was inserted into already has this page's body line. An entry\n // written to a manifest grows no block, so nothing moves.\n const shift = bodyLineOf(after, locateFrontmatter(after)?.closeEnd ?? 0) - page.bodyLine;\n\n const result: AddResult = {\n file: label,\n citation,\n placed: owner === undefined ? \"frontmatter\" : \"manifest\",\n content: after,\n diff: unifiedDiff(label, content, after),\n written: false,\n ...(placed === undefined ? {} : { manifest: placed }),\n };\n if (markerAt !== undefined) result.markerLine = markerAt + shift;\n if (claimSpan !== undefined) {\n result.claimLines = { start: claimSpan.start + shift, end: claimSpan.end + shift };\n }\n\n // A manifest entry leaves the page byte for byte as it was, unless a\n // marker went into the body; there is then nothing to write.\n result.written = path !== undefined && opts.dryRun !== true && after !== content;\n if (result.written && path !== undefined) await writeFileAtomic(path, after);\n if (result.manifest !== undefined && opts.dryRun !== true) {\n for (const changed of manifests.changed()) await writeFileAtomic(changed.path, changed.text);\n result.manifest.written = true;\n }\n // A commit was wanted (no --no-commit-sha) and git had none to give. Said\n // once the add has succeeded, so a refused add says nothing about git.\n if (opts.commitSha !== false && !(await client.available())) {\n opts.onNotice?.(GIT_UNAVAILABLE_COMMIT);\n }\n return result;\n}\n","/**\n * `manni cite update`: repair what moved; with `--accept`, re-pin what changed.\n *\n * A moved end gets its `lines` spliced where it stands, so comments and\n * quoting are untouched: `claim.lines` for a claim found verbatim elsewhere on\n * the page, `source.lines` for a source found elsewhere in its file. A marker\n * never moves, because it travels with its own text.\n *\n * `--accept` re-pins a changed end. A claim is re-pinned over the paragraph or\n * fenced block now at its first line, and the report prints that text, so the\n * log shows exactly what was accepted; a claim whose line is blank, or now a\n * different kind of block, is skipped, and a sentence that was reworded *and*\n * moved is an `add` again. A source is re-minted at HEAD, with a new\n * `commit-sha` where the entry records one.\n *\n * Every finding the run did not resolve is reported as skipped, and an\n * error-severity one is work left undone: exit 1, as `fill` has it. Writes by\n * default (0025).\n */\nimport { resolve } from \"node:path\";\nimport { writeFileAtomic } from \"../../meta/index.js\";\nimport { STDIN_LABEL } from \"../../meta/internal.js\";\nimport { checkCitations } from \"../core/check-page.js\";\nimport {\n claimLine,\n markerUnit,\n normalizeWhitespace,\n pinOfLines,\n toBodyLines,\n unitAt,\n type ClaimUnit,\n} from \"../core/claims.js\";\nimport { GIT_UNAVAILABLE_COMMIT } from \"../core/git.js\";\nimport { splitLines } from \"../core/hash.js\";\nimport { mintCitation } from \"../core/mint.js\";\nimport { ManifestSet } from \"../core/manifest.js\";\nimport { readPage } from \"../core/page.js\";\nimport { lineSpec, parseLines } from \"../core/range.js\";\nimport { spliceEntryField, unifiedDiff } from \"../core/write.js\";\nimport { CiteError } from \"../errors.js\";\nimport type {\n Citation,\n CitationResult,\n LineSpec,\n ManifestChange,\n PageCitation,\n PageCitationReport,\n PageCitations,\n UpdateOptions,\n UpdatePage,\n UpdateRewrite,\n UpdateRun,\n} from \"../types.js\";\nimport {\n assertNoOrphanJoins,\n assertNoOrphans,\n joinHits,\n prepareRun,\n readTarget,\n sayNotices,\n} from \"./check.js\";\n\ntype Plan =\n | { kind: \"claim-moved\"; result: CitationResult; lines: LineSpec; from: string; to: string }\n | { kind: \"source-moved\"; result: CitationResult; lines: LineSpec; to: string }\n | { kind: \"claim-accepted\"; result: CitationResult; unit: ClaimUnit; pin: string; lines?: LineSpec }\n | { kind: \"source-accepted\"; result: CitationResult; minted: Citation };\n\n/** The rule a plan settles, so its finding is not also reported as skipped. */\nfunction settles(plan: Plan): string {\n switch (plan.kind) {\n case \"claim-moved\":\n return \"claim-moved\";\n case \"source-moved\":\n return \"source-moved\";\n case \"claim-accepted\":\n return \"claim-changed\";\n case \"source-accepted\":\n return plan.result.source.status === \"never-true\" ? \"source-never-true\" : \"source-changed\";\n }\n}\n\nfunction apply(content: string, format: string, plan: Plan): string {\n const index = plan.result.origin.index;\n switch (plan.kind) {\n case \"claim-moved\":\n return spliceEntryField(content, format, index, [\"claim\", \"lines\"], plan.lines);\n case \"source-moved\":\n return spliceEntryField(content, format, index, [\"source\", \"lines\"], plan.lines);\n case \"claim-accepted\": {\n let out = spliceEntryField(content, format, index, [\"claim\", \"integrity\"], plan.pin);\n if (plan.lines !== undefined) {\n out = spliceEntryField(out, format, index, [\"claim\", \"lines\"], plan.lines);\n }\n return out;\n }\n case \"source-accepted\": {\n let out = spliceEntryField(\n content,\n format,\n index,\n [\"source\", \"integrity\"],\n plan.minted.source.integrity,\n );\n const commit = plan.minted.source[\"commit-sha\"];\n // An entry with no `commit-sha:` line of its own keeps none: the splice\n // replaces a scalar, it does not add a key.\n if (commit !== undefined) {\n out = spliceEntryField(out, format, index, [\"source\", \"commit-sha\"], commit);\n }\n return out;\n }\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The same repair, against an entry that lives in a manifest. The page's\n * whole `citations` value is written back at the end of the run, so a repair\n * here is an edit to the parsed entry rather than a splice of one scalar.\n * An entry the writer cannot reach — a list item that is not a mapping —\n * leaves its finding reported.\n */\nfunction applyToEntry(entry: unknown, plan: Plan): boolean {\n if (!isRecord(entry)) return false;\n const end = (name: \"claim\" | \"source\"): Record<string, unknown> | undefined =>\n isRecord(entry[name]) ? entry[name] : undefined;\n switch (plan.kind) {\n case \"claim-moved\": {\n const claim = end(\"claim\");\n if (claim === undefined) return false;\n claim.lines = plan.lines;\n return true;\n }\n case \"source-moved\": {\n const source = end(\"source\");\n if (source === undefined) return false;\n source.lines = plan.lines;\n return true;\n }\n case \"claim-accepted\": {\n const claim = end(\"claim\");\n if (claim === undefined) return false;\n claim.integrity = plan.pin;\n if (plan.lines !== undefined) claim.lines = plan.lines;\n return true;\n }\n case \"source-accepted\": {\n const source = end(\"source\");\n if (source === undefined) return false;\n source.integrity = plan.minted.source.integrity;\n const commit = plan.minted.source[\"commit-sha\"];\n // As on a page: a re-mint records a commit only where the entry\n // already recorded one, so this never adds the key.\n if (commit !== undefined) source[\"commit-sha\"] = commit;\n return true;\n }\n }\n}\n\nfunction rewriteOf(plan: Plan): UpdateRewrite {\n const { citation, origin, source } = plan.result;\n const base: Pick<UpdateRewrite, \"id\" | \"index\" | \"line\"> = { index: origin.index };\n if (citation.id !== undefined) base.id = citation.id;\n if (origin.line !== undefined) base.line = origin.line;\n\n switch (plan.kind) {\n case \"claim-moved\":\n return { ...base, end: \"claim\", reason: \"moved\", status: \"moved\", from: plan.from, to: plan.to };\n case \"source-moved\":\n return {\n ...base,\n end: \"source\",\n reason: \"moved\",\n status: \"moved\",\n from: source.src,\n to: plan.to,\n };\n case \"claim-accepted\": {\n const out: UpdateRewrite = {\n ...base,\n end: \"claim\",\n reason: \"accepted\",\n status: \"changed\",\n from: citation.claim?.integrity ?? \"\",\n to: plan.pin,\n at: plan.unit.lines.start,\n text: normalizeWhitespace(plan.unit.text.join(\"\\n\")),\n };\n // Where the report says the claim is: its marker, when one anchors it.\n if (plan.result.anchor === \"marker\" && plan.result.markerLine !== undefined) {\n out.markerLine = plan.result.markerLine;\n }\n return out;\n }\n case \"source-accepted\": {\n const out: UpdateRewrite = {\n ...base,\n end: \"source\",\n reason: \"accepted\",\n status: source.status === \"never-true\" ? \"never-true\" : \"changed\",\n from: citation.source.integrity,\n to: plan.minted.source.integrity,\n src: source.src,\n };\n const commit = plan.minted.source[\"commit-sha\"];\n if (commit !== undefined) out.commitSha = commit;\n return out;\n }\n }\n}\n\nexport async function runUpdate(opts: UpdateOptions): Promise<UpdateRun> {\n const prepared = await prepareRun(opts, \"updated\", \"update\", true);\n const { run, files, usingStdin, forced, pageOptions, git } = prepared;\n assertNoOrphans(prepared);\n const hits = joinHits();\n // Each manifest is read once and written once, however many of its pages\n // the run repairs.\n const manifests = new ManifestSet();\n const only = opts.only !== undefined && opts.only.length > 0 ? new Set(opts.only) : undefined;\n const accept = opts.accept === true;\n\n /** What this citation needs, in the order the repairs are worth trying. */\n const plansFor = async (\n result: CitationResult,\n entry: PageCitation | undefined,\n page: PageCitations,\n lines: readonly string[],\n ): Promise<Plan[]> => {\n const out: Plan[] = [];\n const claim = result.claim;\n if (claim !== null && claim.status === \"moved\" && claim.newLines !== undefined) {\n const at = parseLines(claim.newLines);\n if (at !== undefined) {\n out.push({\n kind: \"claim-moved\",\n result,\n lines: lineSpec(at),\n from: claim.fileLines ?? \"\",\n to: claim.newFileLines ?? \"\",\n });\n }\n }\n if (result.source.status === \"moved\" && result.source.newLines !== undefined) {\n const at = parseLines(result.source.newLines);\n if (at !== undefined && result.source.newSrc !== undefined) {\n out.push({ kind: \"source-moved\", result, lines: lineSpec(at), to: result.source.newSrc });\n }\n }\n if (!accept) return out;\n\n if (claim !== null && claim.status === \"changed\" && entry !== undefined) {\n // The paragraph or block now at the claim's first line, or what the\n // marker anchors. Anything else is left for a fresh `cite add`.\n const unit =\n result.anchor === \"marker\"\n ? markerUnit(page, entry, lines)\n : ((): ClaimUnit | undefined => {\n const at = claimLine(claim);\n return at === undefined ? undefined : unitAt(page, at, lines);\n })();\n const wantsBlock = entry.citation.quote === true;\n const pin = unit === undefined ? undefined : pinOfLines(lines, unit.lines);\n if (unit !== undefined && pin !== undefined && (!wantsBlock || unit.kind === \"block\")) {\n const plan: Plan = { kind: \"claim-accepted\", result, unit, pin };\n // A paragraph that grew or shrank moves the claim's last line too.\n if (entry.citation.claim?.lines !== undefined) {\n const body = toBodyLines(unit.lines, page.bodyLine);\n const recorded = parseLines(entry.citation.claim.lines);\n if (recorded === undefined || recorded.start !== body.start || recorded.end !== body.end) {\n plan.lines = lineSpec(body);\n }\n }\n out.push(plan);\n }\n }\n if (result.source.status === \"changed\" || result.source.status === \"never-true\") {\n try {\n // The source as the entry spells it: an encrypted one stays encrypted,\n // under the key it decrypted with, and mint keys the pin accordingly.\n // HEAD is recorded only where the entry already records a commit.\n const minted = await mintCitation({\n root: run.root,\n src: result.source.src,\n ...(run.key === undefined ? {} : { key: run.key }),\n ...(result.citation.source[\"commit-sha\"] === undefined\n ? { commitSha: false as const }\n : {}),\n gitClient: git,\n ...(pageOptions.sourceIndex === undefined\n ? {}\n : { sourceIndex: pageOptions.sourceIndex }),\n });\n out.push({ kind: \"source-accepted\", result, minted });\n } catch (error) {\n // A range the file no longer reaches cannot be re-minted; its finding stays reported.\n if (!(error instanceof CiteError)) throw error;\n }\n }\n return out;\n };\n\n const pages: UpdatePage[] = [];\n const updateOne = async (\n label: string,\n content: string,\n path?: string,\n ): Promise<PageCitationReport> => {\n const setup = prepared.setupFor(label, content);\n if (setup.sidecar !== undefined) hits.record(setup.sidecar, label);\n const report = await checkCitations({ file: label, content, format: forced?.name }, setup.options);\n const { format } = report;\n const page = readPage(label, content, {\n ...(forced === undefined ? {} : { format: forced.name }),\n ...(setup.options.citations === undefined ? {} : { citations: setup.options.citations }),\n ...(setup.options.owned === undefined ? {} : { owned: setup.options.owned }),\n });\n const lines = splitLines(content);\n const rewritten: UpdateRewrite[] = [];\n /** `<index>\\0<rule>` of every finding a rewrite settled. */\n const settled = new Set<string>();\n let after = content;\n // The manifest's entries for this page, edited in memory and written\n // back as one value once the page is done.\n const owner = setup.sidecar?.owner;\n const entries: unknown[] | undefined =\n setup.sidecar?.citations === undefined\n ? undefined\n : (JSON.parse(JSON.stringify(setup.sidecar.citations.map((c) => c.entry))) as unknown[]);\n let manifestDirty = false;\n for (const result of report.citations) {\n if (only !== undefined && (result.citation.id === undefined || !only.has(result.citation.id))) {\n continue;\n }\n const entry = page.citations.find((c) => c.origin.index === result.origin.index);\n for (const plan of await plansFor(result, entry, page, lines)) {\n if (result.origin.kind === \"manifest\") {\n if (entries === undefined || !applyToEntry(entries[result.origin.index], plan)) continue;\n manifestDirty = true;\n } else {\n after = apply(after, format, plan);\n }\n rewritten.push(rewriteOf(plan));\n settled.add(`${String(result.origin.index)}\\0${settles(plan)}`);\n }\n }\n if (manifestDirty && owner !== undefined && entries !== undefined) {\n if (setup.sidecar?.entry === undefined) {\n throw new CiteError(\n `${label} carries no ${owner.join}: value, so its citations cannot be keyed in ${owner.file}.`,\n );\n }\n await manifests.write(owner, setup.sidecar.entry, entries, 0);\n }\n const skipped = report.findings.filter(\n (finding) =>\n (only === undefined || (finding.id !== undefined && only.has(finding.id))) &&\n !settled.has(`${String(finding.index ?? -1)}\\0${finding.rule}`),\n );\n const diff = after === content ? \"\" : unifiedDiff(label, content, after);\n const written = after !== content && path !== undefined && opts.dryRun !== true;\n if (written) await writeFileAtomic(path, after);\n const out: UpdatePage = { file: label, rewritten, skipped, diff, written };\n // The stdin page has nowhere to be written; the caller prints it instead.\n if (path === undefined) out.content = after;\n pages.push(out);\n return report;\n };\n\n const reports: PageCitationReport[] = [];\n if (usingStdin) reports.push(await updateOne(STDIN_LABEL, opts.stdinContent ?? \"\"));\n for (const file of files) {\n reports.push(await updateOne(file, await readTarget(run, file), resolve(run.base, file)));\n }\n assertNoOrphanJoins(prepared, hits);\n\n // One write per manifest, after every page that touches it is settled.\n const changedManifests = manifests.changed();\n const rewrittenManifests: ManifestChange[] = [];\n for (const changed of changedManifests) {\n const write = opts.dryRun !== true;\n if (write) await writeFileAtomic(changed.path, changed.text);\n rewrittenManifests.push({ file: changed.file, diff: changed.diff, written: write });\n }\n // A re-mint records HEAD when git has one. Where git is not there the entry\n // is re-pinned without a commit, and the run says so once.\n const reminted = pages.some((page) =>\n page.rewritten.some((r) => r.reason === \"accepted\" && r.end === \"source\"),\n );\n sayNotices(reports, opts.onNotice, reminted && !(await git.available()) ? [GIT_UNAVAILABLE_COMMIT] : []);\n\n const rewritten = pages.reduce((n, page) => n + page.rewritten.length, 0);\n const skipped = pages.reduce((n, page) => n + page.skipped.length, 0);\n const undone = pages.some((page) => page.skipped.some((finding) => finding.severity === \"error\"));\n return {\n pages,\n rewritten,\n skipped,\n ...(rewrittenManifests.length > 0 ? { manifests: rewrittenManifests } : {}),\n exitCode: undone ? 1 : 0,\n };\n}\n","/**\n * `reencryptCitations`: re-encrypt one page's encrypted citations under a new\n * key, for `manni key rotate` (proposal 0045). It reads sources and never\n * writes: the caller gets the rewritten page back, and writes it only once\n * every page in the run could be re-encrypted.\n *\n * A citation counts as done only when its `source.file` decrypts under the\n * new key *and* its pin holds under the new key. Either alone is a half\n * rotation, and a rerun has to finish it rather than declare it done. Meta's\n * walker cannot leave one today, because it skips the whole `citations` key\n * and cite encrypts in its own `cite-src` context; an interrupted run, a hand\n * edit, or a second writer of the same manifest can.\n *\n * The path must be tracked, and the pin must hold under the old key, over the\n * lines as they are today or, with git, as they were at the entry's\n * `commit-sha` (the classifier's history search). Then `file` becomes the\n * path's ciphertext under the new key, its lines kept, and `integrity` the\n * keyed pin under it, so a `changed` citation stays exactly as changed. A pin\n * that holds nowhere is skipped, with `update --accept` named as the repair.\n * No message names a path.\n */\nimport type {\n Citation,\n CitationInput,\n CitationOrigin,\n GitClient,\n ReencryptCitationsResult,\n ReencryptedCitation,\n SourceIndex,\n SourceRange,\n} from \"../types.js\";\nimport { historyOf } from \"./classify.js\";\nimport { gitClient } from \"./git.js\";\nimport { hashLines, sliceLines, splitLines } from \"./hash.js\";\nimport { readPage } from \"./page.js\";\nimport { formatSrc, sourceRange, spellSource } from \"./range.js\";\nimport { buildSourceIndex, decryptSourcePath, encryptSourcePath, readSource } from \"./sources.js\";\nimport { spliceEntryField } from \"./write.js\";\n\nconst UNDECRYPTABLE = \"does not decrypt under the current key\";\nconst MISSING = \"missing (no tracked file matches)\";\nconst CHANGED = \"changed; run `manni cite update --accept` before rotating\";\n\ntype Where = Pick<ReencryptedCitation, \"id\" | \"index\" | \"line\">;\n\n/** The fields a report row carries to name the entry: its id, or where it sits. */\nfunction whereOf(citation: Citation, origin: CitationOrigin): Where {\n const where: Where = { index: origin.index };\n if (citation.id !== undefined) where.id = citation.id;\n if (origin.line !== undefined) where.line = origin.line;\n return where;\n}\n\ninterface Context {\n root: string;\n index: SourceIndex;\n git: GitClient;\n}\n\n/**\n * The lines the pin was taken over, joined: today's when the pin holds there\n * under `key`, else the lines at the entry's commit when git can show them;\n * else why neither.\n */\nasync function pinnedLines(\n ctx: Context,\n citation: Citation,\n range: SourceRange,\n path: string,\n key: string,\n): Promise<{ joined: string } | { skip: string }> {\n const source = await readSource(ctx.root, ctx.index, { ...range, path, encrypted: false });\n if (source.kind === \"missing\") return { skip: MISSING };\n const pin = citation.source.integrity;\n let joined: string | undefined;\n try {\n joined = sliceLines(splitLines(source.text), range);\n } catch {\n // The range runs past the end of the file as it is now.\n joined = undefined;\n }\n if (joined !== undefined && hashLines(joined, key) === pin) return { joined };\n\n const commit = citation.source[\"commit-sha\"];\n if (commit !== undefined && (await ctx.git.available())) {\n const history = await historyOf(ctx.git, commit, path, range, pin, key, undefined);\n if (history.kind === \"original\") return { joined: history.lines.join(\"\\n\") };\n }\n return { skip: CHANGED };\n}\n\n/** What one citation needs: nothing, a new pair of values, or a reason it cannot be done. */\ntype Verdict =\n | { kind: \"done\" }\n | { kind: \"skip\"; message: string }\n | { kind: \"write\"; file: string; integrity: string; to: string };\n\n/** Options every re-encryption takes, whichever channel the entry lives in. */\nexport interface ReencryptOptions {\n root: string;\n fromKey: string;\n toKey: string;\n /** History and the source index are read through it; defaults to one over the root. */\n gitClient?: GitClient;\n sourceIndex?: SourceIndex;\n}\n\n/**\n * One citation's verdict: whether it is already under the new key, what its\n * `source.file` and `source.integrity` become, or why neither. The rule is\n * the same wherever the entry is kept, so the page splicer and the manifest\n * writer both go through here.\n */\nasync function verdictFor(\n ctx: Context,\n citation: Citation,\n opts: Pick<ReencryptOptions, \"fromKey\" | \"toKey\">,\n): Promise<Verdict> {\n const range = sourceRange(citation.source);\n const underNew = decryptSourcePath(range.path, opts.toKey);\n // Done only when both halves are under the new key; a file that is and a\n // pin that is not is the half rotation this finishes.\n if (underNew !== undefined) {\n const held = await pinnedLines(ctx, citation, range, underNew, opts.toKey);\n if (\"joined\" in held) return { kind: \"done\" };\n }\n const path = underNew ?? decryptSourcePath(range.path, opts.fromKey);\n if (path === undefined) return { kind: \"skip\", message: UNDECRYPTABLE };\n const lines = await pinnedLines(ctx, citation, range, path, opts.fromKey);\n if (\"skip\" in lines) return { kind: \"skip\", message: lines.skip };\n const file = underNew === undefined ? encryptSourcePath(path, opts.toKey) : range.path;\n return {\n kind: \"write\",\n file,\n integrity: hashLines(lines.joined, opts.toKey),\n to: formatSrc({ ...range, path: file }),\n };\n}\n\n/** The git client and source index a run shares, built once per page at most. */\nasync function contextFor(opts: ReencryptOptions): Promise<Context> {\n const git = opts.gitClient ?? gitClient(opts.root);\n const index = opts.sourceIndex ?? (await buildSourceIndex(opts.root, { gitClient: git }));\n return { root: opts.root, index, git };\n}\n\nexport async function reencryptCitations(\n page: { file: string; content: string; format?: string },\n opts: ReencryptOptions,\n): Promise<ReencryptCitationsResult> {\n const read = readPage(page.file, page.content, page.format === undefined ? undefined : { format: page.format });\n const result: ReencryptCitationsResult = { content: page.content, rewritten: [], skipped: [] };\n const encrypted = read.citations.filter(({ citation }) => sourceRange(citation.source).encrypted);\n // A page with nothing encrypted costs no index and no git.\n if (encrypted.length === 0) return result;\n\n const ctx = await contextFor(opts);\n let after = page.content;\n for (const { citation, origin } of encrypted) {\n const range = sourceRange(citation.source);\n const where = whereOf(citation, origin);\n const verdict = await verdictFor(ctx, citation, opts);\n if (verdict.kind === \"done\") continue;\n if (verdict.kind === \"skip\") {\n result.skipped.push({ ...where, message: verdict.message });\n continue;\n }\n if (verdict.file !== range.path) {\n after = spliceEntryField(after, read.format, origin.index, [\"source\", \"file\"], verdict.file);\n }\n after = spliceEntryField(\n after,\n read.format,\n origin.index,\n [\"source\", \"integrity\"],\n verdict.integrity,\n );\n result.rewritten.push({ ...where, from: spellSource(citation.source), to: verdict.to });\n }\n result.content = after;\n return result;\n}\n\n/** What `reencryptCitationEntries` did to one page's manifest entries. */\nexport interface ReencryptEntriesResult {\n /** The entries as they should now be written, a copy of what came in. */\n entries: unknown[];\n /** Whether any of them changed. */\n changed: boolean;\n rewritten: ReencryptedCitation[];\n skipped: { id?: string; index?: number; line?: number; message: string }[];\n}\n\n/**\n * The same rotation, for a page whose citations live in a manifest.\n *\n * The entries come from meta's merge, so they are plain values; each one is\n * validated as `readPage` validates a frontmatter entry, and an encrypted\n * source's `file` and `integrity` are rewritten in place. The caller writes\n * the whole list back with one splice, once every page of the run could be\n * re-encrypted.\n */\nexport async function reencryptCitationEntries(\n page: { file: string; content: string; format?: string; citations: readonly CitationInput[] },\n opts: ReencryptOptions,\n): Promise<ReencryptEntriesResult> {\n const entries: unknown[] = JSON.parse(\n JSON.stringify(page.citations.map((input) => input.entry)),\n ) as unknown[];\n const out: ReencryptEntriesResult = { entries, changed: false, rewritten: [], skipped: [] };\n\n const read = readPage(page.file, page.content, {\n ...(page.format === undefined ? {} : { format: page.format }),\n citations: page.citations,\n });\n const encrypted = read.citations.filter(({ citation }) => sourceRange(citation.source).encrypted);\n if (encrypted.length === 0) return out;\n\n const ctx = await contextFor(opts);\n for (const { citation, origin } of encrypted) {\n const where = whereOf(citation, origin);\n const verdict = await verdictFor(ctx, citation, opts);\n if (verdict.kind === \"done\") continue;\n if (verdict.kind === \"skip\") {\n out.skipped.push({ ...where, message: verdict.message });\n continue;\n }\n const entry: unknown = entries[origin.index];\n const source =\n typeof entry === \"object\" && entry !== null && !Array.isArray(entry)\n ? (entry as Record<string, unknown>).source\n : undefined;\n if (typeof source !== \"object\" || source === null || Array.isArray(source)) {\n out.skipped.push({ ...where, message: UNDECRYPTABLE });\n continue;\n }\n const fields = source as Record<string, unknown>;\n fields.file = verdict.file;\n fields.integrity = verdict.integrity;\n out.changed = true;\n out.rewritten.push({ ...where, from: spellSource(citation.source), to: verdict.to });\n }\n return out;\n}\n","/**\n * Pretty output for `check` and `update`.\n *\n * A citation is one row: its name, its claim end, its source end, and, when a\n * manifest owns the entry, where that is. Both ends read in file lines, the\n * only lines a person sees. Marks: ✓ current, ✗ error, ↕ warning, ℹ notice,\n * · skipped or baselined; a file line is ✓, ✗ (an error), ⚠ (a warning, no\n * error) or ℹ (notices only). Diffs, commit subjects and a changed claim's\n * current lines print only under `showDiff`; a decrypted path only under\n * `reveal`. Colour via `shouldColor`; never under `--no-color`/`NO_COLOR`.\n */\nimport type { ValidationResult } from \"../../meta/index.js\";\nimport { palette } from \"../../shared/color.js\";\nimport { errorSite, messageFor } from \"../core/adapt.js\";\nimport { parseSrc } from \"../core/range.js\";\nimport { shortCommit, shortPin, shortSrc } from \"../core/spell.js\";\nimport type {\n CheckRun,\n CitationFinding,\n CitationResult,\n PageCitationReport,\n UpdateRewrite,\n UpdateRun,\n} from \"../types.js\";\n\nexport interface PrettyOptions {\n color: boolean;\n quiet?: boolean;\n showDiff?: boolean;\n reveal?: boolean;\n}\n\n/** Diff lines printed under a `changed` row before the rest is elided. */\nexport const DIFF_LINE_CAP = 60;\n\nconst plural = (n: number, one: string, many = `${one}s`): string =>\n `${String(n)} ${n === 1 ? one : many}`;\n\n/** A finding's mark, by severity: ✗ error, ↕ warning, ℹ notice. */\nfunction severityMark(severity: CitationFinding[\"severity\"], c: ReturnType<typeof palette>): string {\n switch (severity) {\n case \"error\":\n return c.red(\"✗\");\n case \"warning\":\n return c.yellow(\"↕\");\n case \"notice\":\n return c.dim(\"ℹ\");\n }\n}\n\n/** A page's findings, split into the ones the baseline let through and the ones it forgave. */\nexport interface SplitFindings {\n reported: CitationFinding[];\n baselined: CitationFinding[];\n}\n\n/**\n * Which of a page's findings the run actually reported.\n *\n * The baseline works on the adapted `ValidationResult`: a forgiven finding is\n * removed from `errors` and counted in `baselined`, while `pages[].findings`\n * keeps every finding the check produced. So a finding is baselined exactly\n * when no error in the adapted result is left to account for it. Each error\n * is consumed once, so two identical findings need two identical errors.\n */\nexport function splitBaselined(\n page: PageCitationReport,\n result: ValidationResult | undefined,\n): SplitFindings {\n if (result === undefined) return { reported: [...page.findings], baselined: [] };\n const pool = [...result.errors];\n const out: SplitFindings = { reported: [], baselined: [] };\n for (const finding of page.findings) {\n const instancePath =\n finding.index === undefined ? \"\" : `/citations/${String(finding.index)}`;\n // A finding that sits on a manifest carries that file's line, and one\n // whose manifest lies outside the tree carries no line at all.\n const line = errorSite(finding).line;\n const at = pool.findIndex(\n (e) =>\n e.keyword === finding.rule &&\n e.instancePath === instancePath &&\n e.message === finding.message &&\n (e.line ?? null) === (line ?? null),\n );\n if (at === -1) {\n out.baselined.push(finding);\n } else {\n pool.splice(at, 1);\n out.reported.push(finding);\n }\n }\n return out;\n}\n\n/** The adapted result for a page: same position first, then by file label. */\nexport function resultFor(run: CheckRun, index: number): ValidationResult | undefined {\n const page = run.pages[index];\n if (page === undefined) return undefined;\n const aligned = run.results[index];\n if (aligned !== undefined && aligned.file === page.file) return aligned;\n return run.results.find((r) => r.file === page.file);\n}\n\n/** Whether a finding is about this citation. Every entry has an index, in either channel. */\nfunction belongsTo(finding: CitationFinding, result: CitationResult): boolean {\n return finding.index !== undefined && finding.index === result.origin.index;\n}\n\n/** `<id>`, else nothing: the ends say which entry it is. */\nfunction labelOf(result: CitationResult): string {\n return result.citation.id ?? \"\";\n}\n\n/** A page-level finding's label: its id, its index, or the source it names. */\nfunction labelOfFinding(finding: CitationFinding): string {\n if (finding.id !== undefined) return finding.id;\n if (finding.index !== undefined) return `#${String(finding.index)}`;\n return finding.src ?? \"page\";\n}\n\n/** Whether the entry spelled this source encrypted. */\nfunction citesEncrypted(src: string): boolean {\n try {\n return parseSrc(src).encrypted;\n } catch {\n return false;\n }\n}\n\n/** The claim end column: where it is, in file lines, and how it reads. */\nfunction claimColumn(result: CitationResult): string {\n const { claim } = result;\n const where =\n result.anchor === \"marker\" && result.markerLine !== undefined\n ? `marker :${String(result.markerLine)}`\n : claim?.fileLines === undefined\n ? \"\"\n : `:${claim.fileLines}`;\n if (claim === null) return where;\n let status: string;\n switch (claim.status) {\n case \"moved\":\n status = `moved -> :${claim.newFileLines ?? \"?\"}`;\n break;\n case \"moved-ambiguous\": {\n const at = (claim.candidateFileLines ?? []).map((lines) => `:${lines}`);\n status = `moved, ${plural(at.length, \"candidate\")} (${at.join(\", \")})`;\n break;\n }\n default:\n status = claim.status;\n }\n return where === \"\" ? status : `${where} ${status}`;\n}\n\n/**\n * The source end column: the source as the entry spelled it, plus the\n * decrypted path only under `reveal`, and only beside an encrypted source,\n * the one spelling that hides it.\n */\nfunction sourceColumn(\n result: CitationResult,\n opts: PrettyOptions,\n dim: (s: string) => string,\n): string {\n const { source } = result;\n const src = shortSrc(source.src);\n const revealed =\n opts.reveal && source.resolvedPath !== undefined && citesEncrypted(source.src)\n ? ` ${dim(`(${source.resolvedPath})`)}`\n : \"\";\n return `${src}${revealed} ${messageFor(source)}`;\n}\n\n/** The subjects and diff under a changed source, dim, the diff capped. */\nfunction diffLines(result: CitationResult, dim: (s: string) => string): string[] {\n const out: string[] = [];\n for (const subject of result.source.commitsSince ?? []) out.push(dim(` ${subject}`));\n const diff = result.source.diff;\n if (diff === undefined || diff === \"\") return out;\n const lines = diff.split(/\\r?\\n/);\n while (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\n const shown = lines.slice(0, DIFF_LINE_CAP);\n for (const line of shown) out.push(dim(` ${line}`));\n const more = lines.length - shown.length;\n if (more > 0) out.push(dim(` … (${plural(more, \"more line\")})`));\n return out;\n}\n\n/** The page lines a changed claim covers now, dim and capped: what `--show-diff` adds. */\nfunction claimLines(result: CitationResult, dim: (s: string) => string): string[] {\n const text = result.claim?.text ?? [];\n const shown = text.slice(0, DIFF_LINE_CAP);\n const out = shown.map((line) => dim(` ${line}`));\n const more = text.length - shown.length;\n if (more > 0) out.push(dim(` … (${plural(more, \"more line\")})`));\n return out;\n}\n\n/**\n * The line a row sorts on: the marker's line for a marker-anchored entry,\n * else the claim's first file line. That is the line the row opens with, so\n * the claim column climbs down the page. A bare pin anchors nowhere and has\n * none.\n */\nfunction anchorSortLine(result: CitationResult): number | undefined {\n if (result.anchor === \"marker\" && result.markerLine !== undefined) return result.markerLine;\n const first = result.claim?.fileLines?.split(\"-\")[0];\n if (first === undefined) return undefined;\n const line = Number.parseInt(first, 10);\n return Number.isNaN(line) ? undefined : line;\n}\n\n/**\n * A page's citations in the order their rows print: by anchor line, with the\n * bare pins after them in the order the page keeps them. The entries\n * themselves are left alone, so json and the findings keep frontmatter order.\n */\nfunction rowOrder(citations: readonly CitationResult[]): CitationResult[] {\n return [...citations].sort((a, b) => {\n const left = anchorSortLine(a);\n const right = anchorSortLine(b);\n if (left === undefined) return right === undefined ? 0 : 1;\n if (right === undefined) return -1;\n return left - right;\n });\n}\n\n/** One row of a page's citation table, before the columns are padded. */\ninterface Row {\n mark: string;\n label: string;\n claim: string;\n source: string;\n where: string;\n /** Lines printed under the row: findings that are not an end, and diffs. */\n under: string[];\n}\n\nfunction padTo(text: string, width: number, plain: number): string {\n // Colour codes are not width, so the visible length is passed in.\n return width <= plain ? text : text + \" \".repeat(width - plain);\n}\n\nexport function renderCheckPretty(run: CheckRun, opts: PrettyOptions): string {\n const c = palette(opts.color);\n const lines: string[] = [];\n const quiet = opts.quiet ?? false;\n // A finding about an entry a manifest owns names the manifest, because\n // its line is a line of that file and not of the page above it.\n const location = (finding: CitationFinding): string => {\n const { file, line } = errorSite(finding);\n if (line === undefined) return \"\";\n if (file === undefined) return c.dim(` (line ${String(line)})`);\n return c.dim(` (${file}:${String(line)})`);\n };\n\n run.pages.forEach((page, index) => {\n const { reported, baselined } = splitBaselined(page, resultFor(run, index));\n const errors = reported.filter((f) => f.severity === \"error\").length;\n const warned = reported.some((f) => f.severity === \"warning\");\n // \"baselined\" is a participle, not a noun: 1 baselined, 2 baselined.\n const forgiven =\n baselined.length > 0 ? c.dim(` (${String(baselined.length)} baselined)`) : \"\";\n\n if (reported.length === 0) {\n if (quiet) return;\n lines.push(`${c.green(\"✓\")} ${page.file}${forgiven}`);\n } else {\n // The most severe finding marks the file. Only ✗ is a failure.\n const mark = errors > 0 ? c.red(\"✗\") : warned ? c.yellow(\"⚠\") : c.dim(\"ℹ\");\n lines.push(`${mark} ${page.file}${forgiven}`);\n }\n\n const isBaselined = new Set(baselined);\n const placed = new Set<CitationFinding>();\n const rows: Row[] = [];\n\n for (const result of rowOrder(page.citations)) {\n const own = page.findings.filter((f) => belongsTo(f, result) && !placed.has(f));\n for (const finding of own) placed.add(finding);\n const live = own.filter((f) => !isBaselined.has(f));\n if (own.length === 0 && quiet) continue;\n const worst =\n live.find((f) => f.severity === \"error\") ??\n live.find((f) => f.severity === \"warning\") ??\n live[0];\n const mark =\n worst !== undefined\n ? severityMark(worst.severity, c)\n : own.length > 0\n ? c.dim(\"·\")\n : result.source.status === \"skipped\" && result.claim === null\n ? c.dim(\"·\")\n : c.green(\"✓\");\n\n // The ends are the row; anything else about the entry is a line under it.\n const endRules = new Set([\"claim-\", \"source-\"]);\n const under: string[] = [];\n for (const finding of own) {\n const isEnd = [...endRules].some((prefix) => finding.rule.startsWith(prefix));\n if (isEnd) continue;\n const text = isBaselined.has(finding)\n ? c.dim(`${finding.message} (baselined)`)\n : finding.message;\n under.push(` ${severityMark(finding.severity, c)} ${text}${location(finding)}`);\n }\n if (opts.showDiff) {\n if (own.some((f) => f.rule === \"source-changed\")) under.push(...diffLines(result, c.dim));\n if (own.some((f) => f.rule === \"claim-changed\")) under.push(...claimLines(result, c.dim));\n }\n const forgivenEnd = own.length > 0 && live.length === 0 ? c.dim(\" (baselined)\") : \"\";\n rows.push({\n mark,\n label: labelOf(result),\n claim: claimColumn(result),\n source: `${sourceColumn(result, opts, c.dim)}${forgivenEnd}`,\n where:\n result.origin.kind === \"manifest\"\n ? `${result.origin.file}${result.origin.line === undefined ? \"\" : `:${String(result.origin.line)}`}`\n : \"\",\n under,\n });\n }\n\n // Columns are as wide as this page needs them, and no wider.\n const width = (pick: (row: Row) => string): number =>\n rows.reduce((n, row) => Math.max(n, pick(row).length), 0);\n const labelWidth = width((row) => row.label);\n const claimWidth = width((row) => row.claim);\n const anyWhere = rows.some((row) => row.where !== \"\");\n const sourceWidth = anyWhere ? width((row) => row.source) : 0;\n for (const row of rows) {\n const label = padTo(c.cyan(row.label), labelWidth, row.label.length);\n const source = padTo(row.source, sourceWidth, row.source.length);\n const text = ` ${row.mark} ${label} ${padTo(row.claim, claimWidth, row.claim.length)} ${source}${row.where === \"\" ? \"\" : ` ${c.dim(row.where)}`}`;\n lines.push(text.replace(/\\s+$/, \"\"));\n lines.push(...row.under);\n }\n\n // Findings about no entry: a marker naming nothing, a reserved page key.\n for (const finding of page.findings) {\n if (placed.has(finding)) continue;\n const label = c.cyan(labelOfFinding(finding));\n lines.push(\n isBaselined.has(finding)\n ? ` ${c.dim(\"·\")} ${label} ${c.dim(`${finding.message} (baselined)`)}${location(finding)}`\n : ` ${severityMark(finding.severity, c)} ${label} ${finding.message}${location(finding)}`,\n );\n }\n });\n\n const { summary } = run;\n const warnings = summary.warnings ?? 0;\n const notices = summary.notices ?? 0;\n const baselined = summary.baseline?.suppressed ?? 0;\n const findings = summary.errors + warnings + notices + baselined;\n const parts = [plural(findings, \"finding\")];\n if (warnings > 0) parts.push(`(${plural(warnings, \"warning\")})`);\n if (notices > 0) parts.push(`(${plural(notices, \"notice\")})`);\n if (baselined > 0) parts.push(`(${String(baselined)} baselined)`);\n const summaryText = `${plural(summary.files, \"file\")} checked, ${String(summary.passed)} passed, ${String(summary.failed)} failed, ${parts.join(\" \")}`;\n if (lines.length > 0) lines.push(\"\");\n lines.push(summary.failed > 0 ? c.red(summaryText) : c.green(summaryText));\n if (summary.baseline?.written) {\n lines.push(c.dim(`Baseline written to ${summary.baseline.path}`));\n }\n return lines.join(\"\\n\");\n}\n\n/** What one rewritten end says it did. */\nexport function rewriteLine(rewrite: UpdateRewrite): string {\n const word = rewrite.from.includes(\"-\") ? \"lines\" : \"line\";\n const status = rewrite.status === \"never-true\" ? \"never true\" : rewrite.status;\n if (rewrite.reason === \"moved\") {\n return rewrite.end === \"claim\"\n ? `claim ${word} ${rewrite.from} -> ${rewrite.to} (moved)`\n : `source ${shortSrc(rewrite.from)} -> ${shortSrc(rewrite.to)} (moved)`;\n }\n if (rewrite.end === \"claim\") {\n // A marker anchors its claim, so the marker's line is where the entry is,\n // as `check` reports it. A claim-lines entry reads at the claim.\n const where =\n rewrite.markerLine === undefined\n ? `line ${String(rewrite.at ?? 0)}`\n : `marker line ${String(rewrite.markerLine)}`;\n return `claim at ${where} re-pinned (${status}; now \"${rewrite.text ?? \"\"}\")`;\n }\n const at = rewrite.commitSha === undefined ? \"\" : ` at ${shortCommit(rewrite.commitSha)}`;\n return `source ${shortSrc(rewrite.src ?? \"\")} re-pinned${at} (${status}; ${shortPin(rewrite.from)} -> ${shortPin(rewrite.to)})`;\n}\n\nexport function renderUpdatePretty(run: UpdateRun, opts: PrettyOptions): string {\n const c = palette(opts.color);\n const lines: string[] = [];\n let files = 0;\n for (const page of run.pages) {\n if (page.rewritten.length > 0) files += 1;\n if (opts.showDiff && page.diff !== \"\") {\n for (const line of page.diff.split(/\\r?\\n/)) {\n if (line !== \"\") lines.push(c.dim(line));\n }\n }\n for (const rewrite of page.rewritten) {\n const label = rewrite.id ?? `#${String(rewrite.index)}`;\n lines.push(`${page.file}: ${c.cyan(label)} ${rewriteLine(rewrite)}`);\n }\n for (const finding of page.skipped) {\n const mark = severityMark(finding.severity, c);\n lines.push(\n `${page.file}: ${c.cyan(labelOfFinding(finding))} ${mark} skipped: ${finding.message}`,\n );\n }\n }\n // The manifests, after the pages: a dry run owes the diff of every file it\n // would have written, and an entry a manifest owns is written there.\n if (opts.showDiff) {\n for (const manifest of run.manifests ?? []) {\n for (const line of manifest.diff.split(/\\r?\\n/)) {\n if (line !== \"\") lines.push(c.dim(line));\n }\n }\n }\n const summary = `${plural(run.rewritten, \"citation\")} rewritten in ${plural(files, \"file\")}, ${String(run.skipped)} skipped`;\n lines.push(run.exitCode === 0 ? c.green(summary) : c.red(summary));\n return lines.join(\"\\n\");\n}\n","/**\n * JSON output. `{ summary, pages }` for check; the `UpdateRun` for update.\n *\n * A citation prints its two ends and how they are anchored. `resolvedPath`,\n * `diff`, `commitsSince` and a changed claim's current lines are left out of\n * every citation: output never says more than the page did. It is an\n * allowlist rather than a strip, so a field added to the result stays private\n * until someone decides here that it is safe to print.\n */\nimport type {\n CheckRun,\n CitationAnchor,\n CitationResult,\n OriginKind,\n PageCitationReport,\n UpdateRun,\n} from \"../types.js\";\n\nexport interface PublicClaimEnd {\n lines?: string;\n fileLines?: string;\n status: string;\n newLines?: string;\n candidates?: string[];\n}\n\nexport interface PublicSourceEnd {\n src: string;\n status: string;\n newLines?: string;\n newSrc?: string;\n candidates?: string[];\n commitSha?: string;\n historyAvailable?: boolean;\n truncatedSearch?: boolean;\n}\n\nexport interface PublicCitationResult {\n id?: string;\n origin: { kind: OriginKind; file: string; line?: number };\n anchor: CitationAnchor;\n claim: PublicClaimEnd | null;\n source: PublicSourceEnd;\n}\n\nexport function publicCitation(result: CitationResult): PublicCitationResult {\n const origin: PublicCitationResult[\"origin\"] = {\n kind: result.origin.kind,\n file: result.origin.file,\n };\n if (result.origin.line !== undefined) origin.line = result.origin.line;\n\n const source: PublicSourceEnd = { src: result.source.src, status: result.source.status };\n if (result.source.newLines !== undefined) source.newLines = result.source.newLines;\n if (result.source.newSrc !== undefined) source.newSrc = result.source.newSrc;\n if (result.source.candidates !== undefined) source.candidates = result.source.candidates;\n if (result.source.commitSha !== undefined) source.commitSha = result.source.commitSha;\n if (result.source.historyAvailable !== undefined) {\n source.historyAvailable = result.source.historyAvailable;\n }\n if (result.source.truncatedSearch !== undefined) {\n source.truncatedSearch = result.source.truncatedSearch;\n }\n\n let claim: PublicClaimEnd | null = null;\n if (result.claim !== null) {\n claim = { status: result.claim.status };\n if (result.claim.lines !== undefined) claim.lines = result.claim.lines;\n if (result.claim.fileLines !== undefined) claim.fileLines = result.claim.fileLines;\n if (result.claim.newLines !== undefined) claim.newLines = result.claim.newLines;\n if (result.claim.candidates !== undefined) claim.candidates = result.claim.candidates;\n }\n\n // Key order is the order the plan spells a citation in: what it is called,\n // where it is kept, what anchors it, then its two ends.\n return {\n ...(result.citation.id === undefined ? {} : { id: result.citation.id }),\n origin,\n anchor: result.anchor,\n claim,\n source,\n };\n}\n\nexport interface PublicPageReport extends Omit<PageCitationReport, \"citations\"> {\n citations: PublicCitationResult[];\n}\n\nexport function publicPage(page: PageCitationReport): PublicPageReport {\n return { ...page, citations: page.citations.map(publicCitation) };\n}\n\nexport function renderCheckJson(run: CheckRun): string {\n return JSON.stringify({ summary: run.summary, pages: run.pages.map(publicPage) }, null, 2);\n}\n\nexport function renderUpdateJson(run: UpdateRun): string {\n // `markerLine` is the pretty report's line for a marker-anchored claim.\n // `at` is the claim's own first file line, which is what data says.\n const pages = run.pages.map((page) => ({\n ...page,\n rewritten: page.rewritten.map(({ markerLine: _pretty, ...rewrite }) => rewrite),\n }));\n return JSON.stringify({ ...run, pages }, null, 2);\n}\n","/**\n * GitHub workflow commands, one per finding:\n * `::error file=<file>,line=<n>,title=<ruleId>::<id or src> (<src>): <message>`\n * with `::warning` and `::notice` for the lower levels: the family scale is\n * GitHub's, so the level is the severity. Uses meta's escapes. A baselined\n * finding is not an annotation; a clean run is the empty string.\n */\nimport {\n escapeWorkflowCommandMessage,\n escapeWorkflowCommandProperty,\n} from \"../../meta/internal.js\";\nimport { errorSite } from \"../core/adapt.js\";\nimport type { CheckRun, CitationFinding, CiteRule } from \"../types.js\";\nimport { resultFor, splitBaselined } from \"./pretty.js\";\n\n/**\n * The rules whose message already names what it is about: every claim,\n * marker and anchor message is written as a sentence about the entry, so\n * prefixing it with the subject again would say the name twice.\n */\nconst NAMES_ITS_SUBJECT = new Set<CiteRule>([\n \"claim-moved\",\n \"claim-moved-ambiguous\",\n \"claim-changed\",\n \"marker-orphan\",\n \"marker-invalid\",\n \"marker-repeated\",\n \"anchor-invalid\",\n]);\n\n/**\n * `<id> (<src>): <message>`, or `<src>: <message>` when the entry has no id.\n * A message that names its own subject, by its rule or by opening with the\n * id (an `entry-invalid` about a pin prefix does), is left to say it once.\n */\nfunction annotationMessage(finding: CitationFinding): string {\n const subject = finding.id ?? finding.src;\n if (subject === undefined) return finding.message;\n if (NAMES_ITS_SUBJECT.has(finding.rule)) return finding.message;\n if (finding.id !== undefined && finding.message.startsWith(finding.id)) return finding.message;\n const where = finding.id !== undefined && finding.src !== undefined ? ` (${finding.src})` : \"\";\n return `${subject}${where}: ${finding.message}`;\n}\n\nexport function renderCheckGithub(run: CheckRun): string {\n const lines: string[] = [];\n run.pages.forEach((page, index) => {\n const { reported } = splitBaselined(page, resultFor(run, index));\n for (const finding of reported) {\n // A finding about an entry a manifest owns is annotated on the\n // manifest, unless that manifest is outside the tree, where an\n // annotation would land nowhere: then the page carries it.\n const site = errorSite(finding);\n const params = [`file=${escapeWorkflowCommandProperty(site.file ?? page.file)}`];\n if (site.line !== undefined) params.push(`line=${String(site.line)}`);\n params.push(`title=${escapeWorkflowCommandProperty(finding.ruleId)}`);\n lines.push(\n `::${finding.severity} ${params.join(\",\")}::${escapeWorkflowCommandMessage(annotationMessage(finding))}`,\n );\n }\n });\n return lines.join(\"\\n\");\n}\n","import { ToolError } from \"../shared/errors.js\";\n\n/** An operational or usage error in the key domain: exit 2. */\nexport class KeyError extends ToolError {\n constructor(message: string) {\n super(message);\n this.name = \"KeyError\";\n }\n}\n","/**\n * `manni key rotate [paths...]`: re-encrypt every encrypted value under a new\n * key, then write the key (proposal 0045).\n *\n * Values are found by their ciphertext, never through schema marks: meta's\n * `reencryptMetadata` takes every string of the ciphertext shape in a page's\n * metadata, and cite's `reencryptCitations` every encrypted `source.file` with its\n * keyed pin. A value already under the new key counts as done, so a run can\n * always be repeated.\n *\n * A value does not have to sit in a page. An external-metadata manifest\n * (proposal 0037) holds the private half of the same documents, which is\n * where an encrypted value most often lives, so the local manifests of the\n * collections a run covers are re-encrypted with the pages. See\n * `planManifests`.\n *\n * Input resolution is `cite check`'s: positional paths from `cwd`, else the\n * selected collections' `paths:` from the config's directory, `--exclude`\n * added to a collection's own `exclude:`, and zero files an error unless\n * `--allow-empty`.\n *\n * Every page and manifest is re-encrypted in memory first. One skip and\n * nothing is written (exit 1). Otherwise a whole run whose key comes from the\n * config writes in three steps, so that an interruption at any point leaves\n * every value readable by the next run:\n *\n * 1. the config: `encryptionKey:` the new key, `encryptionKeyPrevious:` the\n * old one, in one atomic write;\n * 2. the pages, then the manifests;\n * 3. the config again, without `encryptionKeyPrevious:`.\n *\n * A run that finds `encryptionKeyPrevious:` finishes that rotation: from the\n * previous key to the current one. A narrowed run (paths or `--collection`)\n * and a run whose key comes from `MANNI_ENCRYPTION_KEY` write pages and\n * manifests and never the config. `--dry-run` writes nothing at all.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport {\n DEFAULT_CITE_BASELINE_PATH,\n GIT_UNAVAILABLE_HISTORY,\n ManifestSet,\n buildSourceIndex,\n gitClient,\n loadCitationSidecars,\n parseCiteConfig,\n readPage,\n sourceRange,\n reencryptCitationEntries,\n reencryptCitations,\n type CiteConfig,\n type CitationSidecars,\n type GitClient,\n type ReencryptCitationsResult,\n type SourceIndex,\n} from \"../../cite/index.js\";\nimport {\n PATH_JOIN,\n classifyRef,\n externalMetadataJoin,\n loadExternalMetadata,\n reencryptMetadata,\n supportedExtensions,\n writeFileAtomic,\n type ExternalMetadataEntry,\n type ExternalMetadataIndex,\n type ExternalMetadataValue,\n} from \"../../meta/index.js\";\nimport {\n STDIN_TOKEN,\n assertNonEmpty,\n extractorByName,\n gitignoreOptions,\n reencryptData,\n resolveTargetSet,\n spliceManifestValue,\n} from \"../../meta/internal.js\";\nimport { isMember, selectCollections, type CollectionConfig } from \"../../shared/collections.js\";\nimport type { ConfigFile } from \"../../shared/config-file.js\";\nimport { resolveEncryptionKey, writeEncryptionKey } from \"../../shared/encryption-key.js\";\nimport { generateEncryptionKey, isValidEncryptionKey } from \"../../shared/encryption.js\";\nimport { findGitRoot } from \"../../shared/git-root.js\";\nimport { readRotateConfig, toKeyError, unfinishedRotation } from \"../core/config.js\";\nimport { KeyError } from \"../errors.js\";\nimport type {\n KeyRotateOptions,\n KeyRotateResult,\n RotateManifest,\n RotateOutcome,\n RotatePage,\n RotatedValue,\n SkippedValue,\n} from \"../types.js\";\n\nconst BAD_TO = \"--to must be at least 32 hex or base64url characters.\";\nconst NO_STDIN =\n \"key rotate reads and writes files, so it takes no stdin (`-`). Name the files instead.\";\nconst WITH_PATHS =\n \"--collection selects a configured collection; it cannot be combined with paths.\";\nconst NEEDS_CONFIG = \"--collection needs a config file to select from.\";\nconst NO_KEY =\n \"No encryption key is available, so nothing can be re-encrypted. Run `manni key set` first.\";\nconst ENV_NEEDS_TO =\n \"The key comes from MANNI_ENCRYPTION_KEY; pass --to <value>, re-encrypt with it, then update the secret. Nothing is written to config.\";\nconst NARROWED_NEEDS_TO = \"A run over part of the family needs --to, and never writes the key.\";\nconst NO_FILES =\n \"No files to re-encrypt. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml.\";\n\n/**\n * Any ciphertext at all. A page without one has nothing to rotate, so it costs\n * no parse; with one, the page is parsed and the tag decides.\n */\nconst ANY_CIPHERTEXT = /~[A-Za-z0-9_-]{82,}/;\n\n/** The `cite:` section of the file, for `root:` and `baseline:`; `{}` without one. */\nfunction citeSection(file: ConfigFile | null): CiteConfig {\n if (file === null) return {};\n const doc: unknown = parseYaml(file.text);\n if (typeof doc !== \"object\" || doc === null || !(\"cite\" in doc)) return {};\n return parseCiteConfig(doc.cite, file.source);\n}\n\n/**\n * Where cited sources resolve from, as `cite` resolves it: `--root` (cwd\n * relative) > `cite.root` (config relative) > the git root > `cwd`.\n */\nfunction rootFor(\n flag: string | undefined,\n cite: CiteConfig,\n file: ConfigFile | null,\n cwd: string,\n): { root: string; fellBack: boolean } {\n if (flag !== undefined) return { root: resolve(cwd, flag), fellBack: false };\n if (file !== null && cite.root !== undefined) {\n return { root: resolve(file.dir, cite.root), fellBack: false };\n }\n const gitRoot = findGitRoot(cwd);\n return gitRoot === null ? { root: cwd, fellBack: true } : { root: gitRoot, fellBack: false };\n}\n\nfunction isEnoent(error: unknown): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nasync function indexFor(root: string, client: GitClient): Promise<SourceIndex> {\n try {\n return await buildSourceIndex(root, { gitClient: client });\n } catch (error) {\n if (isEnoent(error)) throw new KeyError(`Root directory not found: ${root}.`);\n throw error;\n }\n}\n\n/**\n * The page's encrypted citations, the only ones a rotation reads sources\n * for: whether it has any, and whether one carries a commit (its own or the\n * page's), which is when history would be read.\n */\nfunction encryptedCitations(\n file: string,\n content: string,\n format: string | undefined,\n): { any: boolean; withCommit: boolean } {\n const read = readPage(file, content, format === undefined ? undefined : { format });\n const encrypted = read.citations.filter(({ citation }) => sourceRange(citation.source).encrypted);\n return {\n any: encrypted.length > 0,\n withCommit: encrypted.some(({ citation }) => citation.source[\"commit-sha\"] !== undefined),\n };\n}\n\ninterface Planned {\n page: RotatePage;\n path: string;\n content: string;\n changed: boolean;\n}\n\n/**\n * The citations of one page that a manifest owns (proposal 0044). They are\n * re-encrypted exactly as a page's own are — a citation counts as done only\n * when its `source.file` decrypts under the new key *and* its pin holds —\n * and written back as one value per page, each manifest written once.\n *\n * Kept in its own function, and reached from one place in the loop below, so\n * nothing about how *meta* values are rotated changes.\n */\nasync function rotateManifestCitations(\n sidecars: CitationSidecars | null,\n manifests: ManifestSet,\n page: { file: string; content: string; format?: string },\n opts: {\n root: string;\n fromKey: string;\n toKey: string;\n gitClient: GitClient;\n sourceIndex: () => Promise<SourceIndex>;\n },\n): Promise<{ rewritten: RotatedValue[]; skipped: SkippedValue[]; wantsHistory: boolean }> {\n const none = { rewritten: [], skipped: [], wantsHistory: false };\n if (sidecars === null) return none;\n const sidecar = sidecars.forPage(page.file, page.content, page.format);\n const owner = sidecar.owner;\n if (owner === undefined || sidecar.citations === undefined) return none;\n // Only a manifest entry that actually holds a ciphertext costs an index.\n if (!sidecar.citations.some((input) => ANY_CIPHERTEXT.test(JSON.stringify(input.entry)))) {\n return none;\n }\n const result = await reencryptCitationEntries(\n { ...page, citations: sidecar.citations },\n {\n root: opts.root,\n fromKey: opts.fromKey,\n toKey: opts.toKey,\n gitClient: opts.gitClient,\n sourceIndex: await opts.sourceIndex(),\n },\n );\n if (result.changed && sidecar.entry !== undefined) {\n await manifests.write(owner, sidecar.entry, result.entries, 0);\n }\n return {\n rewritten: result.rewritten.map((r) => ({ kind: \"citation\" as const, ...r })),\n skipped: result.skipped.map((s) => ({ kind: \"citation\" as const, ...s })),\n // A pin that no longer holds is re-keyed from the lines at its commit.\n wantsHistory: sidecar.citations.some((input) =>\n /\"commit-sha\"\\s*:/.test(JSON.stringify(input.entry)),\n ),\n };\n}\n\ninterface PlannedManifest {\n manifest: RotateManifest;\n path: string;\n /** The manifest's text, with every rewritten value spliced into it. */\n text: string;\n changed: boolean;\n}\n\n/** How a run spells a manifest: relative to its base, like every file label. */\nfunction reportedPath(abs: string, base: string): string {\n const rel = relative(base, abs);\n return rel === \"\" ? \".\" : rel.split(sep).join(\"/\");\n}\n\n/**\n * The collections whose manifests this run covers. A run over every\n * collection, and one narrowed by `--collection`, covers the collections it\n * selected. A run over positional paths covers the collections those files\n * belong to, so the private half of a page a run re-encrypts moves with it.\n */\nfunction manifestCollections(\n collections: readonly CollectionConfig[],\n opts: {\n fromCollections: boolean;\n files: readonly string[];\n base: string;\n configDir: string;\n },\n): CollectionConfig[] {\n if (opts.fromCollections) return [...collections];\n const rels = opts.files.map((rel) =>\n reportedPath(resolve(opts.base, rel), opts.configDir),\n );\n return collections.filter((c) => rels.some((rel) => isMember(c, rel)));\n}\n\n/** The owned values one manifest entry supplies, or an empty map. */\nfunction valuesOf(\n index: ExternalMetadataIndex,\n entry: ExternalMetadataEntry,\n): ReadonlyMap<string, ExternalMetadataValue> {\n const empty = new Map<string, ExternalMetadataValue>();\n if (entry.join === PATH_JOIN) {\n return entry.abs === undefined ? empty : (index.byPath.get(entry.abs) ?? empty);\n }\n return index.byField.get(entry.join)?.get(entry.spelled) ?? empty;\n}\n\n/**\n * Re-encrypt the metadata values that live in the selected collections' local\n * manifests (proposals 0037, 0039 and 0041).\n *\n * A manifest is private by construction, so it is where an encrypted value is\n * most likely to sit. Rotation would otherwise leave it under the old key and\n * `meta validate` would report `encrypted:unreadable` on every page the\n * manifest feeds.\n *\n * Two things are left alone. A URL manifest is somebody else's file and\n * read-only (0038), so it is never loaded, and a rotation reaches no network.\n * The `citations` key is cite's: it re-keys a citation's source together with\n * its pin, under its own context, and re-encrypting the source alone would\n * break the pin. `reencryptData` skips it for the same reason\n * `reencryptMetadata` does on a page.\n *\n * Text in, text out. Each value is spliced into the manifest by\n * `spliceManifestValue`, which replaces that value's range and keeps every\n * other byte: the comments, the key order, the quoting and the line endings.\n * Nothing is written here; the caller writes when every value could be\n * re-encrypted.\n */\nasync function planManifests(opts: {\n collections: readonly CollectionConfig[];\n configDir: string;\n base: string;\n fromKey: string;\n toKey: string;\n}): Promise<PlannedManifest[]> {\n const local = opts.collections\n .map((c) => ({\n ...c,\n externalMetadata: c.externalMetadata.filter(\n (m) => classifyRef(m.file).kind !== \"url\",\n ),\n }))\n .filter((c) => c.externalMetadata.length > 0);\n if (local.length === 0) return [];\n\n const index = await loadExternalMetadata(local, {\n configDir: opts.configDir,\n base: opts.base,\n });\n if (index === null) return [];\n\n // One plan per manifest file, so a manifest two collections declare is read\n // once and spliced once. Its reported path and collection identify it the\n // way `index.entries` does.\n const plans = new Map<string, PlannedManifest>();\n const located = new Map<string, string>();\n for (const c of local) {\n for (const m of c.externalMetadata) {\n const join = externalMetadataJoin(m);\n const abs = isAbsolute(m.file) ? m.file : resolve(opts.configDir, m.file);\n const file = reportedPath(abs, opts.base);\n located.set(`${c.name}\\u0000${file}\\u0000${join}`, abs);\n if (plans.has(abs)) continue;\n plans.set(abs, {\n manifest: { file, collection: c.name, rewritten: [], skipped: [], written: false },\n path: abs,\n text: await readFile(abs, \"utf8\"),\n changed: false,\n });\n }\n }\n\n for (const entry of index.entries) {\n const abs = located.get(`${entry.collection}\\u0000${entry.file}\\u0000${entry.join}`);\n const plan = abs === undefined ? undefined : plans.get(abs);\n if (plan === undefined) continue;\n const data: Record<string, unknown> = {};\n for (const [key, supplied] of valuesOf(index, entry)) {\n if (supplied.file === entry.file && supplied.collection === entry.collection) {\n data[key] = supplied.value;\n }\n }\n const done = reencryptData(data, { fromKey: opts.fromKey, toKey: opts.toKey });\n for (const r of done.rewritten) {\n plan.manifest.rewritten.push({ entry: entry.spelled, ...r });\n }\n for (const s of done.skipped) {\n plan.manifest.skipped.push({ entry: entry.spelled, ...s });\n }\n for (const key of done.keys) {\n plan.text = spliceManifestValue(plan.text, {\n entry: entry.spelled,\n key,\n value: done.data[key],\n join: entry.join,\n file: plan.manifest.file,\n }).text;\n plan.changed = true;\n }\n }\n\n return [...plans.values()].filter(\n (p) => p.manifest.rewritten.length > 0 || p.manifest.skipped.length > 0,\n );\n}\n\nexport async function runKeyRotate(opts: KeyRotateOptions): Promise<KeyRotateResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const env = opts.env ?? process.env;\n if (opts.to !== undefined && !isValidEncryptionKey(opts.to)) throw new KeyError(BAD_TO);\n if (opts.inputs.includes(STDIN_TOKEN)) throw new KeyError(NO_STDIN);\n const wanted = opts.collection ?? [];\n if (wanted.length > 0 && opts.inputs.length > 0) throw new KeyError(WITH_PATHS);\n\n const file = await readRotateConfig(opts.configPath, cwd);\n if (wanted.length > 0 && file === null) throw new KeyError(NEEDS_CONFIG);\n const { key: current, source: keySource } = resolveEncryptionKey({\n env,\n file,\n toError: toKeyError,\n });\n if (current === undefined) throw new KeyError(NO_KEY);\n const narrowed = opts.inputs.length > 0 || wanted.length > 0;\n\n // Only a key from the config has a config a rotation can be finished in.\n const keyFile = keySource === \"config\" ? file : null;\n const previous = keyFile?.encryptionKeyPrevious;\n if (\n keyFile !== null &&\n previous !== undefined &&\n (narrowed || (opts.to !== undefined && opts.to !== current))\n ) {\n throw new KeyError(unfinishedRotation(keyFile.source));\n }\n if (keySource === \"env\" && opts.to === undefined) throw new KeyError(ENV_NEEDS_TO);\n if (narrowed && opts.to === undefined) throw new KeyError(NARROWED_NEEDS_TO);\n\n // Finishing an interrupted rotation goes from the key it replaced to the one\n // the config already holds; otherwise from the current key to the new one.\n const fromKey = previous ?? current;\n const toKey = previous === undefined ? (opts.to ?? generateEncryptionKey()) : current;\n\n const collections =\n file === null ? [] : selectCollections(file.collections, wanted, file.source, toKeyError);\n const fromCollections = opts.inputs.length === 0;\n const inputs = fromCollections ? collections.flatMap((c) => c.paths) : opts.inputs;\n if (inputs.length === 0) throw new KeyError(NO_FILES);\n // One base per run, as in cite and meta: typed paths from cwd, a\n // collection's `paths:` from the config's directory.\n const base = fromCollections && file !== null ? file.dir : cwd;\n\n const forced = opts.as === undefined ? undefined : extractorByName(opts.as);\n if (opts.as !== undefined && forced === undefined) {\n throw new KeyError(\n `Unknown format \"${opts.as}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n const format = forced?.name;\n const exts = opts.exts ?? forced?.extensions;\n const exclude = [\n ...new Set([\n ...(opts.exclude ?? []),\n ...(fromCollections ? collections.flatMap((c) => c.exclude) : []),\n ]),\n ];\n const { files, gitignoreSkipped } = await resolveTargetSet({\n inputs,\n exts,\n exclude,\n cwd: base,\n allowEmpty: opts.allowEmpty,\n ...gitignoreOptions({ flag: opts.respectGitignore, onNotice: opts.onNotice }),\n });\n assertNonEmpty({\n files,\n inputs,\n usingStdin: false,\n allowEmpty: opts.allowEmpty,\n exclude,\n exts,\n gitignoreSkipped,\n action: \"re-encrypted\",\n });\n\n const cite = citeSection(file);\n const { root, fellBack } = rootFor(opts.root, cite, file, cwd);\n const client = opts.gitClient ?? gitClient(root);\n // Built once, and only when a page cites an encrypted source.\n let index: Promise<SourceIndex> | undefined;\n const sourceIndex = (): Promise<SourceIndex> => {\n if (index === undefined) {\n if (fellBack) opts.onNotice?.(`No git root found; resolving src: paths from ${cwd}`);\n index = indexFor(root, client);\n }\n return index;\n };\n\n // The manifests that own `citations` (proposal 0044): a page whose entries\n // live in one carries no ciphertext of its own, so they are read for every\n // page of the run, not only the ones the shortcut below lets through.\n const sidecars =\n file === null\n ? null\n : await loadCitationSidecars({\n collections: file.collections,\n configDir: file.dir,\n base,\n configSource: file.source,\n key: current,\n toError: toKeyError,\n });\n const manifests = new ManifestSet();\n\n const planned: Planned[] = [];\n let wantsHistory = false;\n for (const rel of files) {\n const path = resolve(base, rel);\n const before = await readFile(path, \"utf8\");\n const page = { file: rel, content: before, ...(format === undefined ? {} : { format }) };\n // A page's own values first, then the entries its manifest holds.\n const sidecarWork = await rotateManifestCitations(sidecars, manifests, page, {\n root,\n fromKey,\n toKey,\n gitClient: client,\n sourceIndex,\n });\n if (sidecarWork.wantsHistory) wantsHistory = true;\n if (!ANY_CIPHERTEXT.test(before)) {\n if (sidecarWork.rewritten.length === 0 && sidecarWork.skipped.length === 0) continue;\n planned.push({\n page: { file: rel, rewritten: sidecarWork.rewritten, skipped: sidecarWork.skipped, written: false },\n path,\n content: before,\n changed: false,\n });\n continue;\n }\n const meta = reencryptMetadata(page, { fromKey, toKey });\n const encrypted = encryptedCitations(rel, meta.content, format);\n if (encrypted.withCommit) wantsHistory = true;\n const cited: ReencryptCitationsResult = encrypted.any\n ? await reencryptCitations(\n { ...page, content: meta.content },\n { root, fromKey, toKey, gitClient: client, sourceIndex: await sourceIndex() },\n )\n : { content: meta.content, rewritten: [], skipped: [] };\n const rewritten: RotatedValue[] = [\n ...meta.rewritten.map((r) => ({ kind: \"metadata\" as const, ...r })),\n ...cited.rewritten.map((r) => ({ kind: \"citation\" as const, ...r })),\n ...sidecarWork.rewritten,\n ];\n const skipped: SkippedValue[] = [\n ...meta.skipped.map((s) => ({ kind: \"metadata\" as const, ...s })),\n ...cited.skipped.map((s) => ({ kind: \"citation\" as const, ...s })),\n ...sidecarWork.skipped,\n ];\n if (rewritten.length === 0 && skipped.length === 0) continue;\n planned.push({\n page: { file: rel, rewritten, skipped, written: false },\n path,\n content: cited.content,\n changed: cited.content !== before,\n });\n }\n\n // A pin that no longer holds is re-keyed from the lines at its commit, so a\n // citation with one wants git. Where git is not there, said once.\n if (wantsHistory && !(await client.available())) opts.onNotice?.(GIT_UNAVAILABLE_HISTORY);\n\n // The private half of the same documents: every local manifest of the\n // collections this run covers. Planned in memory like the pages, and\n // counted with them, so one unreadable value anywhere stops the whole run.\n const valueManifests =\n file === null\n ? []\n : await planManifests({\n collections: manifestCollections(collections, {\n fromCollections,\n files,\n base,\n configDir: file.dir,\n }),\n configDir: file.dir,\n base,\n fromKey,\n toKey,\n });\n\n const reencrypted =\n planned.reduce((n, p) => n + p.page.rewritten.length, 0) +\n valueManifests.reduce((n, m) => n + m.manifest.rewritten.length, 0);\n const skipped =\n planned.reduce((n, p) => n + p.page.skipped.length, 0) +\n valueManifests.reduce((n, m) => n + m.manifest.skipped.length, 0);\n const writePage = opts.writePage ?? ((path: string, content: string) => writeFileAtomic(path, content));\n\n let outcome: RotateOutcome;\n if (skipped > 0) {\n // The new key is never written beside a value it cannot decrypt, and no\n // page is written without the key: nothing at all.\n outcome = \"skipped\";\n } else if (opts.dryRun === true) {\n outcome = \"dry-run\";\n } else {\n const writesKey = !narrowed && keyFile !== null;\n // (1) The new key, with the old one beside it. A rotation being finished\n // already has both.\n if (!narrowed && keyFile !== null && previous === undefined) {\n await writeEncryptionKey({ file: keyFile, key: toKey, previous: fromKey, cwd, toError: toKeyError });\n }\n // (2) The pages, then the manifests: the citations one owns, and the\n // encrypted values another holds. Each manifest is written once,\n // however many pages it keeps entries for.\n for (const p of planned) {\n if (!p.changed) continue;\n await writePage(p.path, p.content);\n p.page.written = true;\n }\n for (const changed of manifests.changed()) await writePage(changed.path, changed.text);\n for (const m of valueManifests) {\n if (!m.changed) continue;\n await writePage(m.path, m.text);\n m.manifest.written = true;\n }\n // (3) The old key goes, now that nothing is under it.\n if (!narrowed && keyFile !== null) {\n await writeEncryptionKey({ file: keyFile, key: toKey, previous: null, cwd, toError: toKeyError });\n }\n if (narrowed) outcome = \"narrowed\";\n else if (!writesKey) outcome = \"env\";\n else outcome = previous === undefined ? \"written\" : \"finished\";\n }\n\n const wrote = outcome !== \"skipped\" && outcome !== \"dry-run\";\n const baseline =\n file !== null && cite.baseline !== undefined\n ? resolve(file.dir, cite.baseline)\n : join(file?.dir ?? cwd, DEFAULT_CITE_BASELINE_PATH);\n\n return {\n pages: planned.map((p) => p.page),\n manifests: valueManifests.map((m) => m.manifest),\n reencrypted,\n skipped,\n keyWritten: outcome === \"written\" || outcome === \"finished\",\n outcome,\n ...(keyFile === null ? {} : { configSource: keyFile.source }),\n baselineStale: wrote && existsSync(baseline),\n exitCode: skipped > 0 ? 1 : 0,\n };\n}\n","/**\n * Which config file `manni key` reads and writes. `key` has no section of its\n * own (proposal 0045): the key it manages sits at the top of the family file,\n * beside `collections:`.\n *\n * - `set` writes the nearest family file whatever it carries, or the one `-c`\n * names, read as a family file (`findFamilyConfigFile`,\n * `readFamilyConfigFile`).\n * - `rotate` reads its key and collections from the file every sibling\n * without a section there would read them from: the nearest family file\n * carrying `collections:` or `encryptionKey:`. That is discovery with a\n * section name nothing uses.\n */\nimport {\n findConfigFile,\n findFamilyConfigFile,\n readConfigFile,\n readFamilyConfigFile,\n type ConfigFile,\n type ConfigFileOptions,\n} from \"../../shared/config-file.js\";\nimport { KeyError } from \"../errors.js\";\n\nexport const toKeyError = (message: string): KeyError => new KeyError(message);\n\nconst KEY_CONFIG: ConfigFileOptions = {\n section: \"key\",\n // The key never had a file of its own.\n legacyNames: [],\n toError: toKeyError,\n};\n\n/** The config `rotate` reads the current key and the collections from. */\nexport function readRotateConfig(\n configPath: string | undefined,\n cwd: string,\n): Promise<ConfigFile | null> {\n return configPath === undefined\n ? findConfigFile(cwd, KEY_CONFIG)\n : readConfigFile(configPath, cwd, KEY_CONFIG);\n}\n\n/** The config `set` writes to; `null` when discovery finds no family file. */\nexport function readSetConfig(\n configPath: string | undefined,\n cwd: string,\n): Promise<ConfigFile | null> {\n return configPath === undefined\n ? findFamilyConfigFile(cwd, toKeyError)\n : readFamilyConfigFile(configPath, cwd, toKeyError);\n}\n\n/** The refusal while `encryptionKeyPrevious:` says a rotation is unfinished. */\nexport const unfinishedRotation = (source: string): string =>\n `A rotation is unfinished in ${source}. Run \\`manni key rotate\\` with no --to to finish it.`;\n","/**\n * `manni key set [value]`: write the family encryption key (proposal 0045).\n *\n * Refusals, each exit 2 and none echoing a value: a value of the wrong shape;\n * `MANNI_ENCRYPTION_KEY` set, because it wins and the written key would never\n * be read; a rotation left unfinished; a key already configured, because\n * replacing one in place strands every value encrypted under it (`rotate` is\n * what replaces a key); and a new `manni.config.yaml` beside a legacy\n * `docmeta.config.yaml`, which the new file would hide from `manni meta`.\n *\n * It warns, and still writes, when git would publish the file.\n */\nimport { existsSync } from \"node:fs\";\nimport { basename, dirname, join, relative, resolve } from \"node:path\";\nimport { LEGACY_CONFIG_NAMES } from \"../../meta/internal.js\";\nimport {\n ENCRYPTION_KEY_ENV,\n committedKeyWarning,\n isIgnoredByGit,\n writeEncryptionKey,\n} from \"../../shared/encryption-key.js\";\nimport { generateEncryptionKey, isValidEncryptionKey } from \"../../shared/encryption.js\";\nimport { readSetConfig, toKeyError, unfinishedRotation } from \"../core/config.js\";\nimport { KeyError } from \"../errors.js\";\nimport type { KeySetOptions, KeySetResult } from \"../types.js\";\n\nconst BAD_VALUE =\n \"The key must be at least 32 hex or base64url characters. Run `manni key set` with no value to generate one.\";\nconst ENV_SET = `${ENCRYPTION_KEY_ENV} is set, so a key written to config would never be read. Unset it, or keep the key in the secret.`;\n\nconst alreadyConfigured = (source: string): string =>\n `An encryption key is already configured in ${source}. Run \\`manni key rotate\\` to replace it and re-encrypt every value.`;\n\n/**\n * A new family file beside a legacy per-tool file hides it: discovery reads\n * the family file first in a directory, and one holding only a key is every\n * tool's config, so `manni meta` would stop reading the options it had.\n */\nfunction refuseBesideLegacy(path: string, cwd: string): void {\n const dir = dirname(path);\n const name = basename(path);\n for (const legacy of LEGACY_CONFIG_NAMES) {\n const found = join(dir, legacy);\n if (!existsSync(found)) continue;\n const source = relative(cwd, found).replace(/\\\\/g, \"/\");\n throw new KeyError(\n `${source} is a single-tool config; a ${name} beside it would hide it. Move its keys under meta: in ${name} first.`,\n );\n }\n}\n\nexport async function runKeySet(opts: KeySetOptions): Promise<KeySetResult> {\n const cwd = resolve(opts.cwd ?? process.cwd());\n const env = opts.env ?? process.env;\n if (opts.value !== undefined && !isValidEncryptionKey(opts.value)) {\n throw new KeyError(BAD_VALUE);\n }\n // Empty counts as unset, as `resolveEncryptionKey` has it.\n const fromEnv = env[ENCRYPTION_KEY_ENV];\n if (fromEnv !== undefined && fromEnv !== \"\") throw new KeyError(ENV_SET);\n\n const file = await readSetConfig(opts.configPath, cwd);\n if (file?.encryptionKeyPrevious !== undefined) {\n throw new KeyError(unfinishedRotation(file.source));\n }\n if (file?.encryptionKey !== undefined) {\n throw new KeyError(alreadyConfigured(file.source));\n }\n\n const generated = opts.value === undefined;\n const key = opts.value ?? generateEncryptionKey();\n const dryRun = opts.dryRun === true;\n // Name the target before writing to it: the legacy check and the git\n // warning are both about the file the key is about to land in.\n const target = await writeEncryptionKey({ file, key, cwd, toError: toKeyError, dryRun: true });\n if (target.created) refuseBesideLegacy(target.path, cwd);\n if (isIgnoredByGit(target.path) === false) {\n opts.onNotice?.(committedKeyWarning(target.source));\n }\n if (!dryRun) await writeEncryptionKey({ file, key, cwd, toError: toKeyError });\n return { path: target.path, source: target.source, created: target.created, generated, dryRun };\n}\n"],"mappings":"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","names":["content","apply","CITATIONS_KEY","hashRange","sliceLines","sliceLines","hashRange","fenceFor","at","line","at","run","resolve","sliceLines","at","extname","extname","sep","CITATIONS_KEY","sep","at","run","readFile","isRecord","i","j","CONTEXT","readFile","CITATIONS_KEY","join","isAbsolute","candidates","at","named","finding","rule","isAbsolute","byLine","finding","at","sliceLines","named","sliceLines","resolve","resolve","readFile","resolve","join","resolve","run","sidecars","readFile","readFile","relative","resolve","ID","toPosix","isEnoent","readFile","sliceLines","resolve","run","relative","sidecars","at","resolve","isRecord","run","at","rewritten","skipped","finding","resolve","sliceLines","plural","finding","at","run","citesEncrypted","baselined","run","finding","run","existsSync","readFile","isAbsolute","join","relative","resolve","sep","resolve","isEnoent","sidecars","reportedPath","relative","sep","join","isAbsolute","readFile","skipped","existsSync","existsSync","join","relative","resolve","join","existsSync","relative","resolve"]}