@hawkeyexl/manni 2.8.2 → 2.8.3

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/cite/core/page.ts","../src/cite/schema/citations.json","../src/shared/code-regions.ts","../src/cite/core/statements.ts","../src/cite/core/reanchor.ts","../src/cite/core/claims.ts","../src/cite/core/git.ts","../src/cite/core/history.ts","../src/cite/core/classify.ts","../src/cite/core/shift.ts","../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/remove.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, shortLine, shortPin, shortSrc, spellAt } from \"./core/spell.js\";\nexport { buildSourceIndex, readSource } from \"./core/sources.js\";\nexport type { BuildIndexOptions, ReadSourceResult } from \"./core/sources.js\";\nexport {\n isUnitText,\n markerClaimEnd,\n markerRunAt,\n misplacedMarkerAt,\n misplacedMarkers,\n movedUnit,\n pre43Span,\n splitUnit,\n unitText,\n} from \"./core/reanchor.js\";\nexport type { MisplacedMarker } from \"./core/reanchor.js\";\nexport {\n anchoredLines,\n detectEol,\n fenceSpanAt,\n fencedBlockAfter,\n fencedBlockAt,\n fencedBlocks,\n formatStatement,\n insideFence,\n isBoundLine,\n isTableRow,\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 noUnitAt,\n normalizeWhitespace,\n pinOfLines,\n toBodyLines,\n toFileLines,\n unitAt,\n} from \"./core/claims.js\";\nexport type { ClaimUnit, NoUnit } from \"./core/claims.js\";\nexport {\n GIT_UNAVAILABLE_COMMIT,\n GIT_UNAVAILABLE_HISTORY,\n PAGE_HISTORY_UNAVAILABLE,\n gitClient,\n noGit,\n} from \"./core/git.js\";\nexport {\n MAX_PAGE_COMMITS,\n claimDiff,\n claimHistory,\n claimWords,\n holdsWords,\n refineClaim,\n runsHolding,\n sentencesOf,\n sharesSentence,\n stripMarkers,\n} from \"./core/history.js\";\nexport type { ClaimHistory, ClaimHistoryInput, RefineClaimInput } from \"./core/history.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 citationInputs,\n ownedMessage,\n pickExtractor,\n readPage,\n validateEntry,\n} from \"./core/page.js\";\nexport { shiftedEntries, withClaimLines } from \"./core/shift.js\";\nexport type { ShiftOptions, Shifted } from \"./core/shift.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 {\n claimMessageFor,\n errorSite,\n findingsFor,\n messageFor,\n misplacedMessageFor,\n toValidationResult,\n} from \"./core/adapt.js\";\nexport {\n appendFrontmatterCitation,\n entryObject,\n insertStatementBefore,\n removeFrontmatterCitations,\n removeLine,\n spliceEntryField,\n unifiedDiff,\n} 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 { runRemove } from \"./commands/remove.js\";\nexport { runUpdate } from \"./commands/update.js\";\nexport { reencryptCitationEntries, reencryptCitations } from \"./core/reencrypt.js\";\nexport type { ReencryptEntriesResult, ReencryptOptions } from \"./core/reencrypt.js\";\nexport {\n refusalLine,\n removalLine,\n renderCheckPretty,\n renderRemovePretty,\n renderUpdatePretty,\n rewriteLine,\n} from \"./reporters/pretty.js\";\nexport type { PrettyOptions } from \"./reporters/pretty.js\";\nexport { renderCheckJson, renderRemoveJson, 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 =\n | \"current\"\n | \"moved\"\n | \"moved-ambiguous\"\n | \"reanchored\"\n | \"changed\"\n | \"skipped\";\n\n/** Where a misplaced marker is, and where it belongs (proposal 0054). */\nexport interface MisplacedMarkerReport {\n /** The paragraph the marker's run splits, in file lines. */\n unit: string;\n /** The file line the marker takes once its run has moved. */\n to: number;\n}\n\n/** The marker that anchors a citation: its line, and its misplacement when it has one. */\nexport interface MarkerEnd {\n /** File line of the marker. */\n line: number;\n /** Present only when the marker line sits inside a paragraph. */\n misplaced?: MisplacedMarkerReport;\n}\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-reanchored\",\n \"claim-changed\",\n \"marker-orphan\",\n \"marker-invalid\",\n \"marker-repeated\",\n \"marker-misplaced\",\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 * For `changed` and `reanchored`: the baseline, the newest commit whose\n * page held the pin. Derived from the page's history, never stored (0053).\n */\n commitSha?: string;\n /** For `changed`: `false` when the walk hit a shallow boundary or its cap. */\n historyAvailable?: boolean;\n /** Subjects of the commits that touched the page since the baseline. Pretty-only. */\n commitsSince?: string[];\n /** Unified diff of the claim's lines since the baseline. Pretty-only, `--show-diff`. */\n diff?: string;\n /**\n * The claim's lines as they were at the baseline. Never serialized: it is\n * what `update --accept` reads to tell an edit from a replacement.\n */\n baselineText?: 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 /** The marker that names the entry, when one does, and its misplacement. */\n marker?: MarkerEnd;\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/** One commit that touched a path. */\nexport interface PageCommit {\n /** The full hash. */\n sha: string;\n subject: string;\n}\n\n/**\n * What `pageCommits` answers: the commits that touched a path, newest first.\n * `shallow` is a repository whose oldest commit may have an unfetched parent,\n * and `truncated` a list the cap cut short. Either means a walk that exhausts\n * the list cannot say the pin never held.\n */\nexport interface PageHistory {\n commits: PageCommit[];\n shallow: boolean;\n truncated: boolean;\n}\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 * The commits that touched `path`, newest first, at most `cap` of them. A\n * client without it reads no claim history, so a claim that no longer holds\n * is `changed` with no baseline.\n */\n pageCommits?(path: string, cap: number): Promise<PageHistory>;\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 /**\n * Directory the page's own path resolves from, and so the repository its\n * history is read in. Defaults to `root`, the same directory unless\n * `--root` sent the sources to another checkout.\n */\n pageRoot?: string;\n /** The client the page's history is read through. Defaults to one over `pageRoot`. */\n pageGitClient?: GitClient;\n /** How many commits the claim history walk reads. Defaults to `MAX_PAGE_COMMITS`. */\n pageCommitCap?: number;\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 /**\n * The client every page's own history is read through, over the directory\n * the page paths resolve from. Defaults to one there; a test hands in a fake.\n */\n pageGitClient?: 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 /**\n * The first pinned source line, as the file holds it, so a mis-typed range\n * is visible at write time. Absent for a whole file, which has no first\n * line worth naming, and for an encrypted source, which no output reveals.\n */\n sourceLine?: string;\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/**\n * One end `update` rewrote.\n *\n * Read the typed pairs: `fromLines`/`toLines` for lines, `fromPin`/`toPin`\n * for pins. `from` and `to` carry the same values, but which of the two a row\n * holds depends on the row, so they are easy to misuse.\n */\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\" | \"marker\";\n /**\n * `re-anchored` covers both re-pins: the pin held over another span (0054),\n * and the words held while the anchor moved (0053). `status` is what tells\n * those apart. `replaced` is a claim `--accept` refused to re-pin.\n */\n reason: \"moved\" | \"accepted\" | \"re-anchored\" | \"shifted\" | \"replaced\";\n /**\n * The status that was repaired. `replaced` is a claim whose line held\n * wholly other text, accepted because `--only` named it.\n */\n status: \"moved\" | \"changed\" | \"reanchored\" | \"replaced\" | \"never-true\" | \"misplaced\" | \"current\";\n /**\n * Before and after. A moved or shifted claim, and a moved marker: file\n * lines. A moved source: its `src`. An accepted or re-anchored end: its pin.\n * The typed pairs below say which, so prefer them.\n */\n from: string;\n to: string;\n /** A moved marker, or a moved or shifted claim: its file lines, before and after. */\n fromLines?: string;\n toLines?: string;\n /** An accepted or re-anchored end: its pin, before and after. */\n fromPin?: string;\n toPin?: string;\n /** A re-anchored claim: the span that held, in file lines. */\n lines?: string;\n /** A re-anchored claim: the span now pinned, in file lines. */\n newLines?: string;\n /** An accepted, re-anchored or refused claim: the file line of its first body 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 /**\n * An accepted source: the commit recorded in the entry, when it records\n * one. A re-anchored or refused claim: the baseline its words were read\n * against.\n */\n commitSha?: string;\n /**\n * A refused claim the word-overlap test refused: the share of the claim's\n * words, from 0 to 1, that its line still holds. Absent on a claim the\n * sentence test refused, which is how a report tells the two apart.\n */\n wordShare?: number;\n}\n\nexport interface UpdatePage {\n file: string;\n rewritten: UpdateRewrite[];\n /**\n * Claims `--accept` refused to re-pin, because the stored first line now\n * holds text that shares no sentence with the claim at its baseline, or too\n * few of its words. Each carries `reason: \"replaced\"`, and each is work left\n * undone: exit 1.\n */\n refused: 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\nexport interface RemoveOptions\n extends Omit<CheckOptions, \"baseline\" | \"writeBaseline\" | \"checkSources\" | \"showDiff\"> {\n /**\n * `--only <id>`, repeatable: the entries to remove, each named by its id or\n * by its pointer (`/citations/N`). Required, and an empty list is a\n * refusal: `remove` never takes every citation off a page.\n */\n only: string[];\n dryRun?: boolean;\n}\n\n/** One entry `remove` took out, and the markers that went with it. */\nexport interface Removal {\n id?: string;\n /** Index in the page's `citations`. Absent for a marker that named no entry. */\n index?: number;\n /** Where the entry was kept. Absent for a marker that named no entry. */\n origin?: { kind: OriginKind; file: string; line?: number };\n /** File lines of the markers removed with it, in the page as it was. */\n markerLines: number[];\n}\n\nexport interface RemovePage {\n file: string;\n removed: Removal[];\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\nexport interface RemoveRun {\n pages: RemovePage[];\n /** Entries removed, counting a marker that named no entry as one. */\n removed: number;\n /** The manifests this run rewrote, each written once however many pages it holds. */\n manifests?: ManifestChange[];\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-reanchored` is a notice for the same reason (proposal 0053): the\n * words the pin covered are found unchanged since the baseline, so only the\n * layout moved, and plain `cite update` re-pins it.\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 * `marker-misplaced` is a warning too: it annotates the pull request, and one\n * `cite update` clears it, so a job that failed on it would block on a page\n * that was fine yesterday (proposal 0054, stress test 15).\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-reanchored\": \"notice\",\n \"claim-changed\": \"warning\",\n \"marker-orphan\": \"error\",\n \"marker-invalid\": \"error\",\n \"marker-repeated\": \"warning\",\n \"marker-misplaced\": \"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 */\nimport type { PageLines } from \"../types.js\";\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/** The widest a quoted line of a file is printed at. */\nconst LINE_WIDTH = 60;\n\n/**\n * A line of a file as a report quotes it: whitespace collapsed to single\n * spaces, then sixty characters and an ellipsis. The report is one line, so\n * neither an indented source line nor a long one decides how it reads.\n */\nexport function shortLine(text: string): string {\n const one = text.replace(/\\s+/g, \" \").trim();\n return one.length <= LINE_WIDTH ? one : `${one.slice(0, LINE_WIDTH)}…`;\n}\n\n/**\n * `line 9`, or `lines 9-12`: where on a page a span sits. Every refusal,\n * report and message that names one reads it this way, so `add`, `update`\n * and the reporters spell it once.\n */\nexport function 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/** `a`, `a and b`, `a, b and c`: a list as a sentence reads it. */\nexport function 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 * 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 * 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 ExtractedMetadata,\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\n/**\n * A page's citation entries as they are written, each with where it sits: the\n * manifest's when one owns them, else the page's own frontmatter. The entries\n * are raw, so one the schema refuses is still in the list at its own index,\n * which is how `remove` reaches an entry `check` can only report.\n */\nexport function citationInputs(\n file: string,\n extracted: ExtractedMetadata,\n injected?: readonly CitationInput[],\n): CitationInput[] {\n if (injected !== undefined) return [...injected];\n const raw: unknown = extracted.data.citations;\n const list: unknown[] = Array.isArray(raw) ? (raw as unknown[]) : [];\n return list.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\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 = citationInputs(file, extracted, injected);\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 * 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` reads it whether or not it\n * was given a format, and so does the claim search (`claims.ts`), so every\n * family's opener counts; the per-format locators below are what `quote`\n * 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/** An ATX heading: one to six `#`, then a space or the end of the line. */\nconst ATX_HEADING = /^[ \\t]*#{1,6}([ \\t]|$)/;\n/** An asciidoc section title: one to six `=`, then a space. */\nconst ASCIIDOC_TITLE = /^={1,6}[ \\t]/;\n/**\n * A line of one punctuation character repeated three or more times, spaces\n * allowed: a setext underline, a thematic break, an rst adornment.\n */\nconst ADORNMENT = /^[ \\t]*([-=~^\"'*+#_:<>])(?:[ \\t]*\\1){2,}[ \\t]*$/;\n/** A line that is nothing but one JSX or HTML tag, opening or closing. */\nconst TAG_LINE = /^[ \\t]*<\\/?[A-Za-z][^<>]*>[ \\t]*$/;\n/** A table row: a line whose first non-blank character is a pipe. */\nconst TABLE_ROW = /^[ \\t]*\\|/;\n\n/**\n * Whether a line is a table row. The header row, the `|---|---|` delimiter row\n * and every body row all open with a pipe, so all three read as rows. Leading\n * whitespace is allowed, because a table inside a list item is indented and is\n * still a table.\n *\n * A row is a statement of its own. Nothing else separates one row from the\n * next, so a paragraph walk reads a whole table as one paragraph, and a claim\n * pinned to one row would re-pin every row below it. `unitAt` in\n * `src/cite/core/claims.ts` reads this instead, so a re-pin covers the row and\n * no more.\n */\nexport function isTableRow(line: string): boolean {\n return TABLE_ROW.test(line);\n}\n\n/**\n * A table rule: the `|---|---|` line under a header row. The outer pipes are\n * optional, a cell may carry `:` alignment markers, and the whole line may be\n * indented, because a table inside a list item is indented and is still a\n * table.\n *\n * A rule has to carry at least one `|`, which is what the leading lookahead\n * asks. Every pipe in the pattern that follows is optional on its own, so\n * without that test a bare `---` reads as a table rule, and `---` is a\n * thematic break or the underline of a setext heading instead.\n *\n * `isTableRow` reads a rule as a row, deliberately: a claim over a header, its\n * rule and a body row covers three rows and keeps all three. This asks the\n * narrower question `unitAt` needs, which is whether a span holds nothing but\n * rules. Such a span carries no words, so `update --accept` refuses to pin one.\n */\nconst TABLE_RULE = /^(?=[^|]*\\|)[ \\t]*\\|?(?:[ \\t]*:?-+:?[ \\t]*\\|)*[ \\t]*:?-+:?[ \\t]*\\|?[ \\t]*$/;\n\nexport function isTableSeparator(line: string): boolean {\n return TABLE_RULE.test(line);\n}\n\n/**\n * Whether a line is a **bound line**: one the format makes a block on its own,\n * so no paragraph continues across it, and no pin covers it beside text.\n *\n * | Format | Bound lines |\n * |---|---|\n * | markdown, mdx | An ATX heading, and a line that is nothing but one tag. |\n * | html, xml | A line that is nothing but one tag. |\n * | asciidoc | A section title. |\n * | every format | An adornment: one of `-=~^\"'*+#_:<>` repeated three or more times. |\n *\n * Proposal 0054 is the record, and its stress tests 8 and 9 say why a heading\n * and a tag line are read this way rather than joined to the text below them.\n * A tag line is bound in every format that reads one, so a marker under\n * `<body>` anchors the element below it and never the whole document.\n */\nexport function isBoundLine(line: string, format: string): boolean {\n if (ADORNMENT.test(line)) return true;\n switch (format) {\n case \"markdown\":\n case \"mdx\":\n return ATX_HEADING.test(line) || TAG_LINE.test(line);\n case \"html\":\n case \"xml\":\n return TAG_LINE.test(line);\n case \"asciidoc\":\n return ASCIIDOC_TITLE.test(line);\n default:\n return false;\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 * and a bound line is a unit of one line: it ends a paragraph above it, and\n * stands alone when it is the first line found.\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 const bound = (text: string): boolean => format !== undefined && isBoundLine(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 // A bound line is its own unit, so it never gathers the lines under it.\n let cursor = bound(text) ? content.length : 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) || bound(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, a bound line or the body's\n * start, and down as `paragraphAfter` reads it. Undefined for a blank line, a\n * marker-only 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 // A bound line is its own unit, so the walk up never leaves it.\n while (start - 1 >= body.line && !isBoundLine(own, format)) {\n const above = textOf(start - 1);\n if (\n above.trim() === \"\" ||\n ANY_FENCE.test(above) ||\n isMarkerLine(above, format) ||\n isBoundLine(above, format)\n ) {\n break;\n }\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 (\n above.trim() === \"\" ||\n ANY_FENCE.test(above) ||\n isMarkerLine(above, format) ||\n isBoundLine(above, format)\n ) {\n break;\n }\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 * Misplaced markers, and what to do about them. Proposal 0054 is the record.\n *\n * A **marker run** is one or more consecutive lines that each hold one marker\n * and nothing else. A run is **misplaced** when the line directly above it and\n * the line directly below it are both unit text: deleting the run would join\n * them into one paragraph. Such a marker splits the paragraph for the renderer\n * and for the tool, and the lines above it are anchored by nothing.\n *\n * A misplaced marker belongs where `add --marker` writes one: above the first\n * line of the unit, or, for a `quote: true` entry, above the block it anchors.\n * A run moves in its own order, so two markers that were stacked stay stacked.\n *\n * The claim of a marker-anchored entry is read against three spans, in order:\n * the unit the marker belongs to, the span it anchors now, and the span it was\n * pinned over before PR #43 (marker lines included, down to the next blank\n * line or fence). The second or third holding means the pinned text is on the\n * page and the marker anchors a different span: `claim-moved`.\n */\nimport type { ClaimEnd, PageCitation, PageCitations, PageLines } from \"../types.js\";\nimport { hashLines } from \"./hash.js\";\nimport { MAX_MARKERS_PER_PAGE } from \"./page.js\";\nimport { spellLines } from \"../../shared/pin.js\";\nimport { ANY_FENCE, anchoredLines, isBoundLine, isMarkerLine } from \"./statements.js\";\n\n/** Whether a line is text a paragraph is made of. */\nexport function isUnitText(line: string | undefined, format: string): boolean {\n if (line === undefined) return false;\n if (line.trim() === \"\") return false;\n if (ANY_FENCE.test(line)) return false;\n if (isMarkerLine(line, format)) return false;\n return !isBoundLine(line, format);\n}\n\n/** Whether the file line `n` holds one marker and nothing else. */\nfunction markerAt(lines: readonly string[], n: number, format: string): boolean {\n const line = lines[n - 1];\n return line !== undefined && isMarkerLine(line, format);\n}\n\n/** The run of marker-only lines that holds `line`. */\nexport function markerRunAt(\n lines: readonly string[],\n line: number,\n format: string,\n bodyLine: number,\n): PageLines {\n let start = line;\n while (start - 1 >= bodyLine && markerAt(lines, start - 1, format)) start--;\n let end = line;\n while (end + 1 <= lines.length && markerAt(lines, end + 1, format)) end++;\n return { start, end };\n}\n\n/**\n * The paragraph a run splits, in file lines, marker lines included.\n * `undefined` when the run sits where `add` writes markers: after a blank\n * line, a fence, a bound line, or the body's first line.\n */\nexport function splitUnit(\n lines: readonly string[],\n run: PageLines,\n format: string,\n bodyLine: number,\n): PageLines | undefined {\n if (run.start - 1 < bodyLine) return undefined;\n if (!isUnitText(lines[run.start - 2], format)) return undefined;\n if (!isUnitText(lines[run.end], format)) return undefined;\n let start = run.start - 1;\n while (start - 1 >= bodyLine && isUnitText(lines[start - 2], format)) start--;\n let end = run.end + 1;\n while (end + 1 <= lines.length && isUnitText(lines[end], format)) end++;\n return { start, end };\n}\n\n/**\n * The span a marker was pinned over before PR #43: from the line below it\n * through the next blank line or fence, marker lines included. `undefined`\n * when the line below is blank or a fence, so the old reading covered nothing.\n */\nexport function pre43Span(\n lines: readonly string[],\n markerLine: number,\n): PageLines | undefined {\n const start = markerLine + 1;\n const first = lines[start - 1];\n if (first === undefined || first.trim() === \"\" || ANY_FENCE.test(first)) return undefined;\n let end = start;\n while (end + 1 <= lines.length) {\n const next = lines[end];\n if (next === undefined || next.trim() === \"\" || ANY_FENCE.test(next)) break;\n end++;\n }\n return { start, end };\n}\n\n/** One marker line that splits a paragraph. */\nexport interface MisplacedMarker {\n /** File line of the marker. */\n line: number;\n /** The whole run of marker-only lines it belongs to. */\n run: PageLines;\n /** Its position in that run, counted from zero, so stacked markers keep their order. */\n order: number;\n /** The paragraph the run splits, in file lines as the page reads now. */\n unit: PageLines;\n /** The file line the marker belongs above. */\n place: number;\n /** Whether `place` is a fenced block the entry quotes rather than the unit's first line. */\n block: boolean;\n /** The file line the marker takes once the whole run has moved. */\n to: number;\n /** The entry the marker names, when one is anchored by it. */\n entry?: PageCitation;\n}\n\n/** The lines of a run, which is `end - start + 1` markers. */\nfunction runLength(run: PageLines): number {\n return run.end - run.start + 1;\n}\n\n/** Whether a misplaced marker at `line` splits a paragraph, and where it belongs. */\nexport function misplacedMarkerAt(\n page: PageCitations,\n lines: readonly string[],\n line: number,\n entry?: PageCitation,\n): MisplacedMarker | undefined {\n if (!markerAt(lines, line, page.format)) return undefined;\n const run = markerRunAt(lines, line, page.format, page.bodyLine);\n const unit = splitUnit(lines, run, page.format, page.bodyLine);\n if (unit === undefined) return undefined;\n const order = line - run.start;\n const quote = entry?.citation.quote === true;\n const marker = entry?.marker;\n const blockAt =\n quote && marker !== undefined\n ? anchoredLines(page.content, marker.end, page.format, true)?.start\n : undefined;\n const out: MisplacedMarker = blockAt === undefined\n ? { line, run, order, unit, place: unit.start, block: false, to: unit.start + order }\n : {\n line,\n run,\n order,\n unit,\n place: blockAt,\n block: true,\n to: blockAt - runLength(run) + order,\n };\n if (entry !== undefined) out.entry = entry;\n return out;\n}\n\n/**\n * Every misplaced marker on a page, in the order the page reads. An orphan,\n * repeated or invalid marker is reported like any other: it splits the\n * paragraph whether or not it names an entry.\n */\nexport function misplacedMarkers(\n page: PageCitations,\n lines: readonly string[],\n): MisplacedMarker[] {\n const out: MisplacedMarker[] = [];\n for (const statement of page.statements.slice(0, MAX_MARKERS_PER_PAGE)) {\n const entry = page.citations.find((c) => c.marker?.line === statement.line);\n const found = misplacedMarkerAt(page, lines, statement.line, entry);\n if (found !== undefined) out.push(found);\n }\n return out;\n}\n\n/**\n * The span the pin covers once a misplaced run has moved: the joined unit,\n * pushed down by the markers now above it. A quote marker's pin covers its\n * block, which no move touches, so this is never asked of one.\n */\nexport function movedUnit(misplaced: MisplacedMarker): PageLines {\n return { start: misplaced.unit.start + runLength(misplaced.run), end: misplaced.unit.end };\n}\n\n/** The unit's text, the run's marker lines left out: what the pin covers after the move. */\nexport function unitText(lines: readonly string[], misplaced: MisplacedMarker): string[] {\n const { unit, run } = misplaced;\n const out: string[] = [];\n for (let n = unit.start; n <= unit.end; n++) {\n if (n >= run.start && n <= run.end) continue;\n const line = lines[n - 1];\n if (line !== undefined) out.push(line);\n }\n return out;\n}\n\n/** One marker line a rewrite moves, and the file line it goes above. */\nexport interface MarkerMove {\n from: number;\n place: number;\n}\n\n/** A page with its markers moved, and where its lines went. */\nexport interface MovedPage {\n content: string;\n /** The new file line of an old one. */\n line(old: number): number;\n}\n\n/** A page split into line texts and the terminator each position carries. */\nfunction splitKeepingEol(content: string): { texts: string[]; eols: string[] } {\n const parts = content.match(/[^\\n]*\\n|[^\\n]+$/g) ?? [];\n const texts: string[] = [];\n const eols: string[] = [];\n for (const part of parts) {\n const eol = /\\r?\\n$/.exec(part)?.[0] ?? \"\";\n texts.push(part.slice(0, part.length - eol.length));\n eols.push(eol);\n }\n return { texts, eols };\n}\n\n/**\n * The page with each named marker line lifted out and written above its place,\n * in the order the moves are given, so a run that was stacked stays stacked.\n * A moved marker takes the indentation `add` would write it at, and the file's\n * terminators stay where they are: the lines are permuted, never re-joined.\n *\n * Read the join carefully. A line's text comes from where it was, and its\n * terminator from where it now sits. That asymmetry is deliberate: the last\n * position of a page with no final newline carries no terminator, and it has\n * to stay the last position. Were terminators to travel with their lines, a\n * move that lifted that last line would carry the missing terminator into the\n * middle of the page and glue two lines together.\n *\n * The cost is that a page mixing `\\r\\n` and `\\n` has the endings of the two\n * swapped positions trade places. No byte is gained or lost, and the file\n * still ends as it began. A uniform page, which is what a checkout gives,\n * cannot tell the difference.\n */\nexport function applyMarkerMoves(\n content: string,\n moves: readonly MarkerMove[],\n indentAt: (line: number) => string,\n): MovedPage {\n const { texts, eols } = splitKeepingEol(content);\n const moving = new Set(moves.map((move) => move.from));\n const inserts = new Map<number, number[]>();\n for (const move of moves) {\n const list = inserts.get(move.place) ?? [];\n list.push(move.from);\n inserts.set(move.place, list);\n }\n const order: number[] = [];\n for (let n = 1; n <= texts.length; n++) {\n for (const from of inserts.get(n) ?? []) order.push(from);\n if (!moving.has(n)) order.push(n);\n }\n const moved = new Map<number, string>();\n for (const move of moves) {\n moved.set(move.from, indentAt(move.place) + (texts[move.from - 1] ?? \"\").trim());\n }\n const at = new Map<number, number>();\n order.forEach((old, index) => at.set(old, index + 1));\n const out = order\n .map((old, index) => (moved.get(old) ?? texts[old - 1] ?? \"\") + (eols[index] ?? \"\"))\n .join(\"\");\n return { content: out, line: (old) => at.get(old) ?? old };\n}\n\n/** The plain pin of a span of lines, or of an explicit list of them. */\nfunction pinOf(lines: readonly string[], span: PageLines): string | undefined {\n if (span.start < 1 || span.end > lines.length || span.end < span.start) return undefined;\n return hashLines(lines.slice(span.start - 1, span.end).join(\"\\n\"));\n}\n\n/**\n * The claim end of a marker-anchored entry, read against proposal 0054's\n * three spans. `misplaced` is the marker's misplacement, when it has one.\n *\n * For a misplaced marker at `moved`, `fileLines` is the span that held and\n * `newLines` the span the pin will cover once the marker moves. Both are file\n * lines: a marker-anchored claim has no body lines of its own.\n */\nexport function markerClaimEnd(\n page: PageCitations,\n entry: PageCitation,\n lines: readonly string[],\n misplaced: MisplacedMarker | undefined,\n): ClaimEnd {\n const { citation, marker } = entry;\n const pin = citation.claim?.integrity;\n const quote = citation.quote === true;\n if (marker === undefined || pin === undefined) return { status: \"changed\" };\n const current = anchoredLines(page.content, marker.end, page.format, quote);\n if (current === undefined) return { status: \"changed\" };\n\n /** The claim end this span reads as, and where the move will take it. */\n const claimAt = (span: PageLines, status: ClaimEnd[\"status\"], to?: PageLines): ClaimEnd => {\n const end: ClaimEnd = { fileLines: spellLines(span), status };\n if (to !== undefined) {\n end.newLines = spellLines(to);\n end.newFileLines = end.newLines;\n }\n if (status === \"changed\") end.text = lines.slice(span.start - 1, Math.min(span.end, lines.length));\n return end;\n };\n\n // A quote marker's pin covers its block, which no move touches, and the\n // block reading never changed, so there is one span to read it against.\n if (quote) {\n return claimAt(current, pinOf(lines, current) === pin ? \"current\" : \"changed\");\n }\n\n if (misplaced !== undefined) {\n const to = movedUnit(misplaced);\n if (hashLines(unitText(lines, misplaced).join(\"\\n\")) === pin) return claimAt(to, \"current\");\n if (pinOf(lines, current) === pin) return claimAt(current, \"moved\", to);\n const pre43 = pre43Span(lines, marker.line);\n if (pre43 !== undefined && pinOf(lines, pre43) === pin) return claimAt(pre43, \"moved\", to);\n return claimAt(current, \"changed\");\n }\n\n if (pinOf(lines, current) === pin) return claimAt(current, \"current\");\n // Stacked markers written before PR #43 were pinned over a sibling marker\n // line and the paragraph. That renders fine, so only the pin is repaired.\n const pre43 = pre43Span(lines, marker.line);\n if (pre43 !== undefined && pinOf(lines, pre43) === pin) return claimAt(pre43, \"moved\", current);\n return claimAt(current, \"changed\");\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 its text never moves on the page; it is `current`,\n * `changed`, or, when the pin holds over a span the marker no longer anchors,\n * `moved`. `src/cite/core/reanchor.ts` reads those spans.\n */\nimport type {\n ClaimEnd,\n PageCitation,\n PageCitations,\n PageLines,\n} from \"../types.js\";\nimport {\n findWindows,\n parseLines,\n pinOfLines,\n spellLines,\n toBodyLines,\n toFileLines,\n} from \"../../shared/pin.js\";\nimport {\n markerClaimEnd,\n misplacedMarkerAt,\n type MisplacedMarker,\n} from \"./reanchor.js\";\nimport {\n anchoredLines,\n fenceSpanAt,\n insideFence,\n isMarkerLine,\n isTableRow,\n isTableSeparator,\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 misplaced?: MisplacedMarker,\n): ClaimEnd | null {\n const { citation, marker } = entry;\n const claim = citation.claim;\n if (claim === undefined) return null;\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 travels with its text, so what moves is the span the marker\n // anchors, not the text. `reanchor.ts` reads the three spans.\n return markerClaimEnd(\n page,\n entry,\n lines,\n misplaced ?? misplacedMarkerAt(page, lines, marker.line, entry),\n );\n }\n\n // A claim pin with neither lines nor a marker anchors nothing at all.\n return { status: \"changed\" };\n}\n\n/**\n * Where else in the body the claim's text sits, as file lines. A claim whose\n * text repeats is `moved-ambiguous` the moment it moves, so `add` says so\n * while the pin is still being written, and `update --accept` says so before\n * it mints a pin that cannot tell two copies apart. The search is the\n * classifier's own.\n */\nexport function otherClaimSpans(\n lines: readonly string[],\n pageLines: PageLines,\n pin: string,\n bodyLine: number,\n): PageLines[] {\n const width = pageLines.end - pageLines.start + 1;\n const found = findWindows(lines.slice(bodyLine - 1), width, pin, undefined, {\n around: toBodyLines(pageLines, bodyLine).start,\n });\n return found.starts\n .map((start) => toFileLines({ start, end: start + width - 1 }, bodyLine))\n .filter((span) => span.start !== pageLines.start);\n}\n\n/** How many other locations a notice names before it starts counting them. */\nconst NAMED_SPANS = 3;\n\n/** `line 17`, `lines 16 and 18`, `lines 16, 18, 20 and 2 more`. */\nexport function spellElsewhere(spans: readonly PageLines[]): string {\n const first = spans[0];\n const noun = spans.length === 1 && first !== undefined && first.start === first.end ? \"line\" : \"lines\";\n const named = spans.slice(0, NAMED_SPANS).map((span) => spellLines(span));\n const rest = spans.length - named.length;\n if (rest > 0) return `${noun} ${named.join(\", \")} and ${String(rest)} more`;\n const last = named.pop() ?? \"\";\n return named.length === 0 ? `${noun} ${last}` : `${noun} ${named.join(\", \")} and ${last}`;\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 * Why no unit sits at a file line. Each one is a different problem with a\n * different repair, so `update --accept` names which it hit rather than\n * leaving the entry skipped with no reason.\n */\nexport type NoUnit =\n | \"outside\"\n | \"blank\"\n | \"fenced\"\n | \"marker\"\n | \"not-a-paragraph\"\n | \"table-short\"\n | \"table-rule\";\n\n/**\n * The rows a claim on a table re-pins over, or why there are none.\n *\n * A row is a statement, so a claim over N rows is a claim over N statements.\n * The extent is the author's, and re-pinning re-mints the hash over it rather\n * than redesigning it: one recorded line gives one row, and five give five.\n * Rows below a one-line claim are other statements, and a table that no longer\n * reaches the recorded end is a question only the author can answer.\n *\n * The unit comes back as `kind: \"paragraph\"`, since `ClaimUnit` distinguishes\n * prose from a fenced block and nothing else. A caller wanting to know whether\n * it holds rows has to ask `isTableRow` about the text, not read `kind`.\n *\n * A span of nothing but `|---|---|` rules is refused. Those lines carry no\n * words, so a pin over them says nothing about what the page claims, and a\n * claim that shifted onto one is a claim the page lost. A header, its rule and\n * a body row is three rows and keeps all three.\n */\nfunction rowsAt(\n line: number,\n lines: readonly string[],\n recorded: PageLines | undefined,\n named: boolean,\n): ClaimUnit | NoUnit {\n const width = recorded === undefined ? 1 : Math.max(1, recorded.end - recorded.start + 1);\n const end = line + width - 1;\n if (end > lines.length) return \"table-short\";\n for (let n = line; n <= end; n++) {\n if (!isTableRow(lines[n - 1] ?? \"\")) return \"table-short\";\n }\n const text = lines.slice(line - 1, end);\n if (!named && text.every((row) => isTableSeparator(row))) return \"table-rule\";\n return { lines: { start: line, end }, kind: \"paragraph\", text };\n}\n\n/**\n * The unit at a file line, or why there is none. `unitAt` and `noUnitAt` are\n * the two halves a caller reads, so the guards are written once. `recorded` is\n * the span the claim holds now, which only a table reads. `named` is the\n * operator having named the entry with `--only`: the structural refusals a\n * blanket accept would hit are the ones they have looked at, so they stand\n * down and the line is read as the text it is.\n */\nfunction unitOrWhy(\n page: PageCitations,\n line: number,\n lines: readonly string[],\n recorded?: PageLines,\n named = false,\n): ClaimUnit | NoUnit {\n if (line < page.bodyLine || line > lines.length) return \"outside\";\n const own = lines[line - 1] ?? \"\";\n if (own.trim() === \"\") return \"blank\";\n // A line that is one marker and nothing else is another entry's anchor, not\n // claim text. Reading it as text is how a shifted claim gets a confident pin\n // over a comment.\n const marker = isMarkerLine(own, page.format);\n if (marker && !named) return \"marker\";\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 \"fenced\";\n // A table row is a statement of its own, and nothing between two rows ends a\n // paragraph, so the walk below would read the rest of the table as one.\n if (isTableRow(own)) return rowsAt(line, lines, recorded, named);\n // The format ends the paragraph at a marker under it, so a re-pin never\n // swallows another entry's anchor. A named entry sitting on a marker is read\n // without it, because there the marker is the line being accepted.\n const paragraph = paragraphAfter(\n page.content,\n offsetOfLine(page.content, line),\n marker ? undefined : page.format,\n );\n if (paragraph === undefined || paragraph.line !== line) return \"not-a-paragraph\";\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/**\n * The paragraph, fenced block or table rows at a file line. Undefined when the\n * line holds no claim at all: it is blank, outside the body, inside a fenced\n * block rather than opening one, another entry's marker, or a table rule.\n * Those are the claims `update --accept` skips, and `noUnitAt` says which of\n * them it is.\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. A paragraph that gained a sentence gained it as part of the\n * same statement, which is why a claim grows with it.\n *\n * A table does not work that way. Each row is a statement, so a claim keeps\n * the number of rows `recorded` gives it, and refuses when the table no longer\n * reaches that far. Callers that know the claim's current span pass it.\n */\nexport function unitAt(\n page: PageCitations,\n line: number,\n lines: readonly string[],\n recorded?: PageLines,\n named = false,\n): ClaimUnit | undefined {\n const found = unitOrWhy(page, line, lines, recorded, named);\n return typeof found === \"string\" ? undefined : found;\n}\n\n/** Why `unitAt` found nothing at a file line, or undefined when it found a unit. */\nexport function noUnitAt(\n page: PageCitations,\n line: number,\n lines: readonly string[],\n recorded?: PageLines,\n named = false,\n): NoUnit | undefined {\n const found = unitOrWhy(page, line, lines, recorded, named);\n return typeof found === \"string\" ? found : undefined;\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, PageCommit, PageHistory, 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 /**\n * Whether the repository is shallow. A shallow oldest commit has a parent\n * nobody fetched, so a walk that runs out of commits there has not reached\n * the beginning of anything.\n */\n const shallow = (): Promise<boolean> =>\n once(\"shallow\", async () => {\n const out = await run(root, [\"rev-parse\", \"--is-shallow-repository\"]);\n return out.ok && out.stdout.trim() === \"true\";\n });\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 pageCommits: (path, cap) =>\n once(`commits\\0${String(cap)}\\0${path}`, async (): Promise<PageHistory> => {\n if (!(await available())) return { commits: [], shallow: false, truncated: false };\n // One more than the cap, so a list the cap cut short says so rather\n // than reading as a history that simply ended there.\n // `--topo-order`, because the default date order interleaves the\n // lineages either side of a merge. A walk back through an interleaved\n // list reads one branch's commits as if they came before the other's.\n const out = await run(root, [\n \"log\",\n `--format=%H${UNIT}%s`,\n \"--topo-order\",\n `-n${String(cap + 1)}`,\n \"HEAD\",\n \"--\",\n path,\n ]);\n if (!out.ok) throw failed(\"log\", out);\n const commits: PageCommit[] = [];\n for (const line of out.stdout.split(/\\r?\\n/)) {\n if (line === \"\") continue;\n const at = line.indexOf(UNIT);\n if (at === -1) continue;\n commits.push({ sha: line.slice(0, at), subject: line.slice(at + 1) });\n }\n const truncated = commits.length > cap;\n return { commits: commits.slice(0, cap), shallow: await shallow(), truncated };\n }),\n };\n}\n\n/** The separator between a commit's hash and its subject: never in either. */\nconst UNIT = \"\u001f\";\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 reanchored claims, no diffs, no commit subjects.\";\n\n/**\n * What a run says, once, when a claim's walk ran out of commits before the\n * pin held: a shallow checkout, or the 256-commit cap. Without the rest of\n * the history a layout change and an edit read the same.\n */\nexport const PAGE_HISTORY_UNAVAILABLE =\n \"the page history ends before the pin held; use fetch-depth: 0 to tell reanchored claims from changed ones\";\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 pageCommits: () => Promise.resolve({ commits: [], shallow: false, truncated: false }),\n };\n}\n","/**\n * The claim end read against the page's own history. Proposal 0053 is the\n * record, and the source end's `historyOf` is the shape it follows.\n *\n * A claim that no longer holds says nothing on its own: the pin is a hash, and\n * 0044 chose never to copy the text. So the baseline is derived. It is the\n * newest commit whose page still held the pinned text, found by walking the\n * commits that touched the page, newest first. Nothing is stored, so a squash,\n * a rebase or an uncommitted page cannot make it wrong.\n *\n * With a baseline there are three strings, each normalized the same way.\n * `W0` is the text the pin covered then, `W1` the text the anchor covers now,\n * and `P0` the whole page body then. The claim is **reanchored** when `W0`\n * sits inside `W1` and `W1` sits inside `P0`: every word the pin covered is\n * still there, and every word the claim covers now was on the page already.\n * Anything else is **changed**, which is what the first condition catches for\n * an edit inside the claim and the second for a sentence added beside it.\n */\nimport type {\n ClaimEnd,\n GitClient,\n InlineStatement,\n PageCitation,\n PageCitations,\n PageLines,\n} from \"../types.js\";\nimport { spellLines, toBodyLines } from \"../../shared/pin.js\";\nimport { claimEnd } from \"./claims.js\";\nimport { hashLines, splitLines } from \"./hash.js\";\nimport { readPage } from \"./page.js\";\nimport { parseLines } from \"./range.js\";\nimport { misplacedMarkerAt, movedUnit, unitText } from \"./reanchor.js\";\nimport { shortCommit } from \"./spell.js\";\nimport { ANY_FENCE, isMarkerLine } from \"./statements.js\";\n\n/**\n * How many commits that touched the page one walk reads. A page with a long\n * history stops here, and the run says the history ended before the pin held.\n */\nexport const MAX_PAGE_COMMITS = 256;\n\n/** A page's marker-only lines dropped: the lines whose words a claim is made of. */\nexport function stripMarkers(lines: readonly string[], format: string): string[] {\n return lines.filter((line) => !isMarkerLine(line, format));\n}\n\n/**\n * The words a span of lines holds: marker-only lines dropped, then every run\n * of whitespace collapsed to one space and both ends trimmed. Punctuation,\n * emphasis and inline markup are words here, as 0044 stress test 18 has it.\n */\nexport function claimWords(lines: readonly string[], format: string): string {\n return stripMarkers(lines, format).join(\" \").replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * A text split into sentences, each with its whitespace collapsed and its\n * case dropped. What `update --accept` intersects, so a line that now holds\n * wholly other text is refused rather than blessed.\n */\nexport function sentencesOf(text: string): string[] {\n return text\n .split(/(?<=[.!?])\\s+/)\n .map((sentence) => sentence.replace(/\\s+/g, \" \").trim().toLowerCase())\n .filter((sentence) => sentence !== \"\");\n}\n\n/** Whether two texts share at least one sentence. */\nexport function sharesSentence(a: string, b: string): boolean {\n const left = new Set(sentencesOf(a));\n return sentencesOf(b).some((sentence) => left.has(sentence));\n}\n\n/** A text's distinct words, case dropped. Whitespace is the only separator. */\nfunction wordSet(text: string): Set<string> {\n return new Set(\n text\n .toLowerCase()\n .split(/\\s+/)\n .filter((word) => word !== \"\"),\n );\n}\n\n/**\n * How much of `was` the text `now` still holds, from 0 to 1: the size of the\n * two word sets' intersection over `was`'s own size.\n *\n * Intersection over the baseline, not over the union, so the number reads as\n * the share of the claim's words that survived, and a line that grew around\n * the claim is not punished for the words it gained.\n *\n * Distinct words, because a table row's repeated `|` says nothing about\n * whether this is the same statement. A baseline with no words scores 1:\n * there is nothing for the line to have lost.\n */\nexport function wordShare(was: string, now: string): number {\n const left = wordSet(was);\n if (left.size === 0) return 1;\n const right = wordSet(now);\n let held = 0;\n for (const word of left) if (right.has(word)) held++;\n return held / left.size;\n}\n\n/** `true` when `inner`'s words sit inside `outer`'s, in order, at word boundaries. */\nexport function holdsWords(outer: string, inner: string): boolean {\n if (inner === \"\") return true;\n if (outer === inner) return true;\n if (outer.startsWith(`${inner} `)) return true;\n if (outer.endsWith(` ${inner}`)) return true;\n return outer.includes(` ${inner} `);\n}\n\n/**\n * Every run of whole body lines whose words hold `inner`, minimal under\n * containment. The page's words are laid out once with the line each\n * character came from, so a run is read off each occurrence rather than\n * searched for line by line.\n */\nexport function runsHolding(\n lines: readonly string[],\n format: string,\n bodyLine: number,\n inner: string,\n): PageLines[] {\n if (inner === \"\") return [];\n let text = \"\";\n const at: number[] = [];\n for (let n = Math.max(bodyLine, 1); n <= lines.length; n++) {\n const line = lines[n - 1] ?? \"\";\n if (isMarkerLine(line, format)) continue;\n const words = line.replace(/\\s+/g, \" \").trim();\n if (words === \"\") continue;\n if (text !== \"\") {\n text += \" \";\n at.push(n);\n }\n for (let i = 0; i < words.length; i++) at.push(n);\n text += words;\n }\n const out: PageLines[] = [];\n let from = 0;\n for (;;) {\n const found = text.indexOf(inner, from);\n if (found === -1) break;\n from = found + 1;\n const before = found === 0 ? \" \" : text[found - 1];\n const afterAt = found + inner.length;\n const after = afterAt === text.length ? \" \" : text[afterAt];\n if (before !== \" \" || after !== \" \") continue;\n const start = at[found];\n const end = at[afterAt - 1];\n if (start === undefined || end === undefined) continue;\n if (!out.some((span) => span.start === start && span.end === end)) out.push({ start, end });\n }\n // A run that holds another is not minimal: the tighter one is the claim.\n return out.filter(\n (span) =>\n !out.some(\n (other) =>\n (other.start !== span.start || other.end !== span.end) &&\n other.start >= span.start &&\n other.end <= span.end,\n ),\n );\n}\n\n/** What the walk needs to read one entry's history. */\nexport interface ClaimHistoryInput {\n /** The page as it is now: its format, its body line, and the marker. */\n page: PageCitations;\n entry: PageCitation;\n /** The claim end `claimEnd` classified as `changed`. */\n claim: ClaimEnd;\n /** The page's path, as the client below resolves it. */\n path: string;\n git: GitClient;\n /** The manifest that owns the entry, at the path the config declares now. */\n manifest?: string;\n /** Commits to read. Defaults to `MAX_PAGE_COMMITS`. */\n cap?: number;\n}\n\n/**\n * What the page's history says about a claim that no longer holds.\n * `unavailable` is a walk that ran out of commits, so no verdict is safe.\n * `none` is a walk that reached the entry's birth, or a client with no\n * history to read.\n */\nexport type ClaimHistory =\n | { kind: \"unavailable\" }\n | { kind: \"none\" }\n | {\n kind: \"baseline\";\n /** The newest commit whose page held the pin, as the full hash. */\n commit: string;\n /** Subjects of the commits that touched the page after it, newest first. */\n commitsSince: string[];\n /** `W0`: the words the pin covered at the baseline. */\n words: string;\n /** `P0`: the words the whole page body held at the baseline. */\n pageWords: string;\n /** The pinned lines as they were, for the diff. */\n lines: string[];\n /** The file lines they sat at, for the diff's label. */\n at: string;\n };\n\n/** Whether a line closes the window a marker's anchor may reach. */\nfunction bounds(line: string | undefined): boolean {\n return line === undefined || line.trim() === \"\" || ANY_FENCE.test(line);\n}\n\n/** The plain pin over a span of lines, or undefined when the span is not there. */\nfunction pinOf(lines: readonly string[], span: PageLines): string | undefined {\n if (span.start < 1 || span.end > lines.length || span.end < span.start) return undefined;\n return hashLines(lines.slice(span.start - 1, span.end).join(\"\\n\"));\n}\n\n/** Where the pin sat in one older page, or why the walk should stop. */\ntype FoundAt =\n | { kind: \"found\"; span: PageLines; lines: string[] }\n | { kind: \"absent\" }\n /** The marker that anchors the entry is not in that page, so nothing older can hold it. */\n | { kind: \"no-marker\" };\n\n/** One older page, read as this page is read. */\ninterface ThenPage {\n page: PageCitations;\n lines: string[];\n /** The marker naming the entry, for a marker-anchored one. */\n marker?: InlineStatement;\n}\n\n/** An older page, with the marker that named the entry there. */\nfunction readThen(input: ClaimHistoryInput, text: string): ThenPage | undefined {\n const then = readPage(input.page.file, text, { format: input.page.format });\n const lines = splitLines(then.content);\n if (input.entry.citation.claim?.lines !== undefined) return { page: then, lines };\n const id = input.entry.citation.id;\n if (id === undefined) return undefined;\n const marker = then.statements.find(\n (statement) => statement.payload.kind === \"ref\" && statement.payload.id === id,\n );\n // A marker absent at a commit is looked for no further back: the entry was\n // a claim-lines entry then, or it did not exist.\n if (marker === undefined) return undefined;\n return { page: then, lines, marker };\n}\n\n/**\n * Whether the pin held on an older page, read by the classifier itself, and\n * over which lines.\n *\n * The classifier is what decides, rather than a bare search for the bytes,\n * because the baseline has to be the last moment the page *said* what the pin\n * recorded. A commit where the pinned sentence merely sits somewhere inside\n * the anchor is not that moment, and taking it as the baseline would let a\n * sentence added beside the claim pass condition 2 (0053 stress test 5).\n * `claimEnd` already knows today's anchor rule, the rule PR #43 replaced, and\n * 0054's joined unit, so all three read here.\n */\nfunction anchorHeldAt(input: ClaimHistoryInput, then: ThenPage): FoundAt {\n const pin = input.entry.citation.claim?.integrity;\n if (pin === undefined) return { kind: \"absent\" };\n const was: PageCitation = {\n citation: input.entry.citation,\n origin: input.entry.origin,\n ...(then.marker === undefined ? {} : { marker: then.marker }),\n };\n const split =\n then.marker === undefined\n ? undefined\n : misplacedMarkerAt(then.page, then.lines, then.marker.line, was);\n const end = claimEnd(then.page, was, then.lines, split);\n if (end === null || (end.status !== \"current\" && end.status !== \"moved\")) {\n return { kind: \"absent\" };\n }\n // Which of the two specs held depends on the anchor and the status, so the\n // pin says: it is the one it matches.\n for (const spec of [end.fileLines, end.newFileLines]) {\n const span = spec === undefined ? undefined : parseLines(spec);\n if (span !== undefined && pinOf(then.lines, span) === pin) {\n return { kind: \"found\", span, lines: then.lines.slice(span.start - 1, span.end) };\n }\n }\n // 0054's case: the pin covered the paragraph a misplaced marker splits,\n // whose lines are not one span.\n if (split !== undefined) {\n const text = unitText(then.lines, split);\n if (hashLines(text.join(\"\\n\")) === pin) {\n return { kind: \"found\", span: movedUnit(split), lines: text };\n }\n }\n return { kind: \"absent\" };\n}\n\n/**\n * The bounded window search, for a marker-anchored pin minted under an anchor\n * rule the tool no longer models. The window runs from the marker to the next\n * blank line or fence, the add rule's own anchor window. A span starts on the\n * marker's line, or on any non-blank, non-marker line inside the window, and\n * ends at or before the window's last line. Only a walk that found no commit\n * where the anchor held asks this, so a wider span never outranks an anchor.\n */\nfunction windowHeldAt(input: ClaimHistoryInput, then: ThenPage): FoundAt {\n const pin = input.entry.citation.claim?.integrity;\n const marker = then.marker;\n if (pin === undefined || marker === undefined) return { kind: \"absent\" };\n if (input.entry.citation.quote === true) return { kind: \"absent\" };\n const lines = then.lines;\n let stop = marker.line;\n for (let n = marker.line + 1; n <= lines.length; n++) {\n if (bounds(lines[n - 1])) break;\n stop = n;\n }\n const starts = [marker.line];\n for (let n = marker.line + 1; n <= stop; n++) {\n const line = lines[n - 1] ?? \"\";\n if (line.trim() === \"\" || isMarkerLine(line, then.page.format)) continue;\n starts.push(n);\n }\n for (const start of starts) {\n for (let end = start; end <= stop; end++) {\n if (pinOf(lines, { start, end }) === pin) {\n return { kind: \"found\", span: { start, end }, lines: lines.slice(start - 1, end) };\n }\n }\n }\n return { kind: \"absent\" };\n}\n\n/**\n * Whether the entry is still written down at a commit, which is how the walk\n * knows it has not passed the entry's birth.\n *\n * A manifest-owned entry is asked of the manifest at the path the current\n * config declares. Absent there means no baseline, which is a plainer verdict\n * rather than a wrong one, so the walk stops.\n *\n * A frontmatter entry is asked of the page. A page without the pin is *not*\n * a stop, because either side of a merge is a lineage the other's pins never\n * reached. It only records that the walk saw a page born without the entry.\n */\nasync function stillWritten(\n input: ClaimHistoryInput,\n commit: string,\n pageText: string,\n): Promise<{ stop: boolean; born: boolean }> {\n const pin = input.entry.citation.claim?.integrity;\n if (pin === undefined) return { stop: true, born: true };\n const manifest = input.manifest;\n if (manifest !== undefined) {\n const shown = await input.git.showFile(commit, manifest);\n const held = \"text\" in shown && shown.text.includes(pin);\n return { stop: !held, born: !held };\n }\n const held = pageText.includes(pin);\n return { stop: false, born: !held };\n}\n\n/**\n * The newest commit whose page held the pin, and what it held. Walks the\n * commits that touched the page, newest first, stopping at the entry's birth\n * and at the cap.\n */\nexport async function claimHistory(input: ClaimHistoryInput): Promise<ClaimHistory> {\n const { git, path } = input;\n if (git.pageCommits === undefined) return { kind: \"none\" };\n if (!(await git.available())) return { kind: \"none\" };\n const cap = input.cap ?? MAX_PAGE_COMMITS;\n const history = await git.pageCommits(path, cap);\n const { commits } = history;\n if (commits.length === 0) return { kind: \"none\" };\n\n const format = input.page.format;\n const baselineAt = (index: number, then: ThenPage, found: FoundAt): ClaimHistory => {\n if (found.kind !== \"found\") return { kind: \"none\" };\n const commit = commits[index];\n if (commit === undefined) return { kind: \"none\" };\n return {\n kind: \"baseline\",\n commit: commit.sha,\n commitsSince: commits.slice(0, index).map((c) => c.subject),\n words: claimWords(found.lines, format),\n pageWords: claimWords(then.lines.slice(then.page.bodyLine - 1), format),\n lines: found.lines,\n at: spellLines(found.span),\n };\n };\n\n /** The pages the walk read, so the fallback search does not re-read them. */\n const examined: ThenPage[] = [];\n let ended: \"birth\" | \"unavailable\" | \"cap\" = \"cap\";\n /** Whether any commit the walk read was older than the entry. */\n let born = false;\n for (let i = 0; i < commits.length; i++) {\n const commit = commits[i];\n if (commit === undefined) continue;\n const shown = await git.showFile(commit.sha, path);\n if (!(\"text\" in shown)) {\n // A commit git cannot show is a shallow boundary; a path absent there\n // is the page's own birth.\n ended = shown.missing === \"commit\" ? \"unavailable\" : \"birth\";\n break;\n }\n const then = readThen(input, shown.text);\n if (then === undefined) {\n ended = \"birth\";\n break;\n }\n examined.push(then);\n const found = anchorHeldAt(input, then);\n if (found.kind === \"found\") return baselineAt(i, then, found);\n const written = await stillWritten(input, commit.sha, shown.text);\n if (written.born) born = true;\n if (written.stop) {\n ended = \"birth\";\n break;\n }\n }\n\n // No commit held the pin at its anchor. A pin minted under an anchor rule\n // the tool no longer models still deserves a baseline, so the bounded\n // window search reads the same pages once.\n for (const [i, then] of examined.entries()) {\n const found = windowHeldAt(input, then);\n if (found.kind === \"found\") return baselineAt(i, then, found);\n }\n\n // Only a walk that reached the entry's birth can say the pin never held; a\n // cut-short one says the history is not all there. A walk that read a page\n // the entry was not on yet has reached that birth, wherever in the list it\n // sat, which is what `born` records.\n if (ended === \"birth\" || born) return { kind: \"none\" };\n if (ended === \"unavailable\") return { kind: \"unavailable\" };\n return history.truncated || history.shallow ? { kind: \"unavailable\" } : { kind: \"none\" };\n}\n\n/** A unified diff of the claim's lines, from the baseline to now, with file-line labels. */\nexport function claimDiff(input: {\n file: string;\n commit: string;\n was: { at: string; lines: readonly string[] };\n now: { at: string; lines: readonly string[] };\n}): string {\n const a = input.was.lines;\n const b = input.now.lines;\n let head = 0;\n while (head < a.length && head < b.length && a[head] === b[head]) head++;\n let tail = 0;\n while (\n tail < a.length - head &&\n tail < b.length - head &&\n a[a.length - 1 - tail] === b[b.length - 1 - tail]\n ) {\n tail++;\n }\n const out = [\n `--- ${input.file}@${shortCommit(input.commit)}:${input.was.at}`,\n `+++ ${input.file}:${input.now.at}`,\n ];\n for (const line of a.slice(0, head)) out.push(` ${line}`);\n for (const line of a.slice(head, a.length - tail)) out.push(`-${line}`);\n for (const line of b.slice(head, b.length - tail)) out.push(`+${line}`);\n for (const line of a.slice(a.length - tail)) out.push(` ${line}`);\n return out.join(\"\\n\");\n}\n\n/** What `refineClaim` needs beyond the history it was given. */\nexport interface RefineClaimInput extends Omit<ClaimHistoryInput, \"git\" | \"cap\"> {\n /** The page now, under the hashing rule. */\n lines: readonly string[];\n history: ClaimHistory;\n}\n\n/**\n * The claim end the words test leaves: `reanchored` where only the layout\n * moved, `moved-ambiguous` where the claim's words now sit in several runs,\n * and `changed` with its baseline otherwise.\n */\nexport function refineClaim(input: RefineClaimInput): ClaimEnd {\n const { claim, history, entry, page, lines } = input;\n if (history.kind === \"unavailable\") return { ...claim, historyAvailable: false };\n if (history.kind === \"none\") return claim;\n const format = page.format;\n const base: ClaimEnd = {\n ...claim,\n commitSha: history.commit,\n historyAvailable: true,\n commitsSince: history.commitsSince,\n baselineText: history.lines,\n };\n // The diff is attached whenever there is a baseline, as the source end's\n // is. `pretty` prints it under `--show-diff`, and no other reporter reads it.\n const withDiff = (end: ClaimEnd, now: { at: string; lines: readonly string[] }): ClaimEnd => {\n const diff = claimDiff({\n file: page.file,\n commit: history.commit,\n was: { at: history.at, lines: history.lines },\n now,\n });\n return { ...end, diff };\n };\n\n // A quote pins source code inside a fence, where collapsing whitespace\n // would hide a real change. So its words test is equality on the lines the\n // hashing rule reads, with only marker lines dropped.\n if (entry.citation.quote === true) {\n const now = claim.text ?? [];\n const same =\n stripMarkers(now, format).join(\"\\n\") === stripMarkers(history.lines, format).join(\"\\n\");\n const at = claim.fileLines ?? history.at;\n return withDiff(same ? { ...base, status: \"reanchored\" } : base, { at, lines: now });\n }\n\n // A marker travels with its text, so the span it anchors now is the claim.\n if (entry.citation.claim?.lines === undefined) {\n const now = claim.text ?? [];\n const w1 = claimWords(now, format);\n const at = claim.fileLines ?? history.at;\n const held = holdsWords(w1, history.words) && holdsWords(history.pageWords, w1);\n return withDiff(held ? { ...base, status: \"reanchored\" } : base, { at, lines: now });\n }\n\n const runs = runsHolding(lines, format, page.bodyLine, history.words);\n const [only] = runs;\n if (runs.length > 1) {\n return {\n ...claim,\n status: \"moved-ambiguous\",\n candidates: runs.map((span) => spellLines(toBodyLines(span, page.bodyLine))),\n candidateFileLines: runs.map(spellLines),\n };\n }\n if (only === undefined) {\n return withDiff(base, { at: claim.fileLines ?? history.at, lines: claim.text ?? [] });\n }\n const now = lines.slice(only.start - 1, only.end);\n const w1 = claimWords(now, format);\n if (!holdsWords(history.pageWords, w1)) {\n return withDiff(base, { at: claim.fileLines ?? history.at, lines: claim.text ?? [] });\n }\n return withDiff(\n {\n ...base,\n status: \"reanchored\",\n newLines: spellLines(toBodyLines(only, page.bodyLine)),\n newFileLines: spellLines(only),\n },\n { at: spellLines(only), lines: now },\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 * Moving claim lines when a marker line comes or goes.\n *\n * `add --marker` inserts one line above a paragraph; `remove` deletes the\n * marker lines of the entries it takes out. Either way the claims below the\n * change have to move with the text they pin, in the same write, or the next\n * check reports a page nobody edited. One rule decides both directions, so\n * the two commands cannot disagree about which entries move.\n *\n * A change that lands *inside* a claim's own lines is not a move: it would\n * change what the pin covers. That is a refusal, and nothing is written.\n */\nimport { CiteError } from \"../errors.js\";\nimport type { LineSpec, PageCitation } from \"../types.js\";\nimport { toFileLines } from \"./claims.js\";\nimport { lineSpec, parseLines } from \"./range.js\";\nimport { spellAt } from \"./spell.js\";\n\n/** The new `claim.lines` of each entry the change moves, by where the entry lives. */\nexport interface Shifted {\n frontmatter: { index: number; lines: LineSpec }[];\n manifest: Map<number, LineSpec>;\n}\n\nexport interface ShiftOptions {\n /** The entries to move: on a removal, the ones that survive it. */\n citations: readonly PageCitation[];\n /** File lines where a marker line is inserted, or where one is removed. */\n at: readonly number[];\n /** `1` for lines coming in, `-1` for lines going out. */\n delta: 1 | -1;\n /** File line of body line 1, since `claim.lines` count the body. */\n bodyLine: number;\n /** The page as the run reports it, for the refusal. */\n label: string;\n}\n\n/**\n * The entries whose claim lines move, each by however many of `at` sit above\n * them. An insertion at a claim's first line pushes the whole claim down; a\n * removal of that line is inside the claim instead, because the line is the\n * claim's own. Hence the two comparisons.\n */\nexport function shiftedEntries(opts: ShiftOptions): Shifted {\n const { citations, at, delta, bodyLine, label } = opts;\n const out: Shifted = { frontmatter: [], manifest: new Map() };\n if (at.length === 0) return out;\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 const inside = at.find((line) =>\n delta === 1\n ? line > file.start && line <= file.end\n : line >= file.start && line <= file.end,\n );\n if (inside !== undefined) {\n const whose =\n citation.id === undefined\n ? `the claim at ${spellAt(file)}`\n : `the claim of ${citation.id} (${spellAt(file)})`;\n const why =\n delta === 1\n ? \"A marker there would change its pin.\"\n : \"Removing the marker there would change its pin.\";\n throw new CiteError(`${label}:${String(inside)} is inside ${whose}. ${why}`);\n }\n const lines = at.filter((line) => (delta === 1 ? line <= file.start : line < file.start)).length;\n if (lines === 0) continue;\n const moved = lineSpec({\n start: recorded.start + lines * delta,\n end: recorded.end + lines * delta,\n });\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. */\nexport function 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","/**\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 * Only `commit` 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 *\n * That gap is why `commit` re-reads. A run holds a manifest from its first\n * `hold` to its last write, which is seconds of minting, hashing and git, and\n * two runs over one working copy overlap easily. The compare-and-swap that\n * makes the second write see the first is `src/shared/manifest-cas.ts`, which\n * `meta fill` and `meta derive` hold their manifests with too; what stays here\n * is what cite means by an edit, which is one entry's `citations`.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { posix } from \"node:path\";\nimport { LineCounter, isMap, isNode, isScalar, isSeq, parseDocument } from \"yaml\";\nimport { DocmetaError, writeFileAtomic } from \"../../meta/index.js\";\nimport {\n readManifestValue,\n removeManifestKey,\n spliceManifestValue,\n} from \"../../meta/internal.js\";\nimport {\n heldManifest,\n rebaseable,\n settle,\n type CommitIo as CasCommitIo,\n type HeldManifest as CasHeldManifest,\n type ManifestCodec,\n type ManifestOp as CasManifestOp,\n} from \"../../shared/manifest-cas.js\";\nimport { CiteError } from \"../errors.js\";\nimport { unifiedDiff } from \"./write.js\";\nimport { CITATIONS_KEY, type CitationManifest } from \"./sidecar.js\";\n\n/** One edit this run made, replayable onto bytes read later. */\ntype ManifestOp = CasManifestOp &\n ({ kind: \"splice\"; value: unknown[] } | { kind: \"remove\" });\n\n/** One manifest held for the length of a run: its text before, and now. */\nexport type HeldManifest = CasHeldManifest<ManifestOp>;\n\n/** One recorded edit, and one `citations` value read back, over a manifest. */\nconst codec: ManifestCodec<ManifestOp> = { apply, read: readManifestValue };\n\n/** One manifest this run rewrote, as `changed()` and `commit()` report it. */\nexport interface ManifestChange {\n path: string;\n file: string;\n before: string;\n text: string;\n /**\n * `before` against `text`. A commit that rebased moves `before` to the bytes\n * it compared against, so the diff then shows what this run added on top of\n * a concurrent write rather than against the read `hold()` made.\n */\n diff: string;\n}\n\n/** What `commit()` does with each manifest it settles. */\nexport type CommitIo = CasCommitIo<ManifestChange>;\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<ManifestOp>(manifest.path, manifest.file, 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 op: ManifestOp = {\n kind: \"splice\",\n entry,\n key: CITATIONS_KEY,\n join: manifest.join,\n file: manifest.file,\n value: [...citations],\n };\n rebaseable(held, op, codec);\n const spliced = splice(held.text, {\n entry,\n key: CITATIONS_KEY,\n value: op.value,\n join: manifest.join,\n file: manifest.file,\n });\n held.text = spliced.text;\n held.ops.push(op);\n return { file: manifest.file, line: itemLine(spliced.text, entry, index, manifest.join) ?? spliced.line };\n }\n\n /**\n * Where one item of an entry's `citations` sits in the manifest as this run\n * will write it. `add` names a line in its report, and `commit` may have\n * replayed the entry onto bytes that moved it, so the line is read back from\n * the settled text rather than kept from the splice.\n */\n lineOf(manifest: CitationManifest, entry: string, index: number): number | undefined {\n const held = this.held.get(manifest.path);\n if (held === undefined) return undefined;\n return itemLine(held.text, entry, index, manifest.join);\n }\n\n /**\n * Take a page's `citations` key out of the manifest, for the removal that\n * leaves it with no entries. The entry itself goes when that key was all it\n * had, so a manifest never keeps a document nothing is recorded about.\n */\n async remove(manifest: CitationManifest, entry: string): Promise<void> {\n const held = await this.hold(manifest);\n const op: ManifestOp = {\n kind: \"remove\",\n entry,\n key: CITATIONS_KEY,\n join: manifest.join,\n file: manifest.file,\n };\n rebaseable(held, op, codec);\n held.text = apply(held.text, op);\n held.ops.push(op);\n }\n\n /** The manifests this run rewrote, with the diff of each. */\n changed(): ManifestChange[] {\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 * Write every manifest this run rewrote, and report what landed.\n *\n * The write is the last thing a run does, so this is the one place that\n * knows a manifest is about to be replaced by bytes derived from a read\n * that may be seconds old.\n */\n async commit(io: CommitIo = {}): Promise<ManifestChange[]> {\n const write = io.write ?? writeFileAtomic;\n const read = io.read ?? ((at: string): Promise<string> => readFile(at, \"utf8\"));\n const landed: ManifestChange[] = [];\n for (const held of this.held.values()) {\n if (held.text === held.before) continue;\n try {\n await settle(held, { codec, write, read, toError: (message) => new CiteError(message) });\n } catch (error) {\n if (io.onError !== undefined) await io.onError(changeOf(held), error);\n throw error;\n }\n const change = changeOf(held);\n landed.push(change);\n io.after?.(change);\n }\n return landed;\n }\n}\n\n/** The change one held manifest reports, against the bytes it will replace. */\nfunction changeOf(held: HeldManifest): ManifestChange {\n return {\n path: held.path,\n file: held.file,\n before: held.before,\n text: held.text,\n diff: unifiedDiff(held.file, held.before, held.text),\n };\n}\n\n/** One recorded edit, against whatever text it is handed. */\nfunction apply(text: string, op: ManifestOp): string {\n const where = { entry: op.entry, key: op.key, join: op.join, file: op.file };\n if (op.kind === \"splice\") return splice(text, { ...where, value: op.value }).text;\n try {\n return removeManifestKey(text, where).text;\n } catch (error) {\n if (error instanceof DocmetaError) throw new CiteError(error.message);\n throw error;\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 * Take entries out of a page's `citations`, by their index in the list, and\n * write what is left back through the format's extractor. An empty list\n * removes the key: an entry deleted by hand once left a `citations:` with\n * nothing under it, and a page that carries no citations should say so by\n * carrying no key.\n *\n * The write is the inverse of `appendFrontmatterCitation` and goes the same\n * way, so a page manni can add to is a page manni can remove from.\n */\nexport function removeFrontmatterCitations(\n content: string,\n format: string,\n drop: ReadonlySet<number>,\n filePath?: string,\n): string {\n const label = filePath ?? \"the page\";\n const extractor = extractorFor(format);\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 if (locateFrontmatter(content)?.flavor === \"toml\") {\n throw new CiteError(\n `${label} has TOML frontmatter; manni cannot rewrite a citations table without re-emitting the whole block, which would drop its comments. Remove the entry by hand.`,\n );\n }\n const raw: unknown = extractor.extract(content, label).data.citations ?? [];\n if (!Array.isArray(raw)) {\n throw new CiteError(`${label}: \\`citations\\` is not a list; edit it by hand.`);\n }\n const existing: unknown[] = raw;\n const kept = existing.filter((_entry, index) => !drop.has(index));\n try {\n return kept.length === 0\n ? extractor.apply(content, {}, { deletions: [\"citations\"] })\n : extractor.apply(content, { citations: kept });\n } catch (e) {\n if (e instanceof DocmetaError) throw new CiteError(`${label}: ${e.message}`);\n throw e;\n }\n}\n\n/** Delete the whole of 1-based `line`, its terminator included. */\nexport function removeLine(content: string, line: number): string {\n const start = offsetOfLine(content, line);\n const nl = content.indexOf(\"\\n\", start);\n // The last line of a page with no final newline takes the break above it.\n // On CRLF that break is two bytes, and stopping at the LF would leave the\n // CR behind as the tail of a line that is gone; `spliceEntryField` pulls\n // back over a CR for the same reason.\n if (nl === -1) {\n let above = start > 0 ? content.lastIndexOf(\"\\n\", start - 1) : -1;\n if (above > 0 && content.charAt(above - 1) === \"\\r\") above--;\n return content.slice(0, above === -1 ? 0 : above);\n }\n return content.slice(0, start) + content.slice(nl + 1);\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\";\nimport { listOf } from \"./spell.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/** 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 \"reanchored\": {\n const since = claim.commitSha === undefined ? \"\" : ` since ${short(claim.commitSha)}`;\n // A claim-lines entry moved onto its new run; a marker-anchored one\n // never moves, because the marker travels with its own text.\n const to =\n claim.newFileLines === undefined ? \"\" : `, to ${at(claim.newFileLines)}`;\n return named(\n id,\n `the claim at ${at(where ?? \"?\")} was reanchored${since}${to}. Its words are unchanged.`,\n );\n }\n case \"changed\":\n if (where === undefined) {\n return named(\n id,\n \"the claim has no lines and no marker names the entry, so its pin anchors nothing.\",\n );\n }\n return named(id, `the claim at ${at(where)} has ${claimChange(claim)}`);\n case \"current\":\n case \"skipped\":\n return \"\";\n }\n}\n\n/** How a changed claim says since when, which is what its history could say. */\nfunction claimChange(claim: ClaimEnd): string {\n if (claim.historyAvailable === false) {\n return \"changed since it was pinned (history unavailable; fetch-depth: 0).\";\n }\n if (claim.commitSha === undefined) return \"changed since it was pinned.\";\n const at = short(claim.commitSha);\n // Zero commits since would read as \"just now\". The working tree holding the\n // change is what it actually means, so it says that.\n const since = claim.commitsSince ?? [];\n const count = since.length === 0 ? \"uncommitted\" : plural(since.length, \"commit\");\n return `changed since ${at}, ${count}.`;\n}\n\n/**\n * The one place a `marker-misplaced` message is composed. A quote marker's\n * place is above the block it anchors; every other marker's is the first line\n * of the paragraph its run splits.\n */\nexport function misplacedMessageFor(\n id: string | undefined,\n marker: { line: number; unit: string; place: number; block: boolean },\n): string {\n const place = marker.block\n ? `above the block at line ${String(marker.place)}`\n : `above line ${String(marker.place)}`;\n return named(\n id,\n `the marker at line ${String(marker.line)} splits the paragraph at ${at(marker.unit)}. Its place is ${place}.`,\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 GitClient,\n PageCitation,\n PageCitationReport,\n PageCitations,\n PageLines,\n SourceEnd,\n SourceIndex,\n} from \"../types.js\";\nimport { findingsFor, misplacedMessageFor } from \"./adapt.js\";\nimport { misplacedMarkers, type MisplacedMarker } from \"./reanchor.js\";\nimport { spellLines } from \"../../shared/pin.js\";\nimport { classifyCitation, MOVE_BUDGET_BYTES } from \"./classify.js\";\nimport { blockMatches, claimEnd, claimLineNow, claimLinesNow } from \"./claims.js\";\nimport { GIT_UNAVAILABLE_HISTORY, PAGE_HISTORY_UNAVAILABLE, gitClient } from \"./git.js\";\nimport { claimHistory, refineClaim } from \"./history.js\";\nimport { hashLines, sliceLines, splitLines } from \"./hash.js\";\nimport { readPage } from \"./page.js\";\nimport { STDIN_LABEL } from \"../../meta/internal.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/** The marker end of a result: its line, plus its misplacement when it has one. */\nfunction markerEnd(\n entry: PageCitation,\n misplaced: MisplacedMarker | undefined,\n): Pick<CitationResult, \"marker\"> {\n const { marker } = entry;\n if (marker === undefined) return {};\n if (misplaced === undefined) return { marker: { line: marker.line } };\n return {\n marker: {\n line: marker.line,\n misplaced: { unit: spellLines(misplaced.unit), to: misplaced.to },\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 // The page's history lives in the page's own repository, which is not the\n // sources' when `--root` sent those to another checkout.\n const pageGit =\n opts.pageGitClient ??\n (opts.pageRoot === undefined || opts.pageRoot === opts.root\n ? client\n : gitClient(opts.pageRoot));\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 // Every marker line that splits a paragraph, read once for the page: its\n // entry's claim is judged against it, and each one is its own finding.\n const misplaced = misplacedMarkers(read, lines);\n const misplacedAt = new Map(misplaced.map((found) => [found.line, found]));\n\n for (const entry of read.citations) {\n const split = entry.marker === undefined ? undefined : misplacedAt.get(entry.marker.line);\n const claim = await withClaimHistory(\n { page: read, entry, claim: claimEnd(read, entry, lines, split), lines },\n { path: read.file, git: pageGit, ...(opts.pageCommitCap === undefined ? {} : { cap: opts.pageCommitCap }), ...(opts.owned === undefined ? {} : { manifest: opts.owned.file }) },\n );\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 ...markerEnd(entry, split),\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 // One finding per misplaced marker, so a run of three is three. An orphan\n // in a run is reported too, with no id, beside its `marker-orphan`.\n const misplacedLevel = severity[\"marker-misplaced\"];\n if (misplacedLevel !== \"off\") {\n for (const found of misplaced) {\n const entry = found.entry;\n const finding: CitationFinding = {\n rule: \"marker-misplaced\",\n ruleId: ruleId(\"marker-misplaced\"),\n severity: misplacedLevel,\n message: misplacedMessageFor(entry?.citation.id, {\n line: found.line,\n unit: spellLines(found.unit),\n place: found.place,\n block: found.block,\n }),\n line: found.line,\n };\n if (entry !== undefined) {\n finding.index = entry.origin.index;\n finding.src = spellSource(entry.citation.source);\n if (entry.citation.id !== undefined) finding.id = entry.citation.id;\n }\n findings.push(finding);\n }\n }\n\n findings.push(...findingsFor(results, severity));\n\n // History is read for a citation with a commit, and for every claim that no\n // longer holds, so a page holding either and with no git to read it through\n // says why its verdicts are plainer. With the sources off nothing is\n // classified, but a claim end still is, and it still wants the page's past.\n const wantsSourceHistory =\n checkSources &&\n read.citations.some(({ citation }) => citation.source[\"commit-sha\"] !== undefined);\n const wantsClaimHistory = results.some((r) => r.claim?.status === \"changed\");\n if (wantsSourceHistory && !(await client.available())) notices.push(GIT_UNAVAILABLE_HISTORY);\n else if (wantsClaimHistory && !(await pageGit.available())) {\n notices.push(GIT_UNAVAILABLE_HISTORY);\n }\n // A claim whose walk ran out of commits: the rest of the history would have\n // told a layout change from an edit.\n if (results.some((r) => r.claim?.historyAvailable === false)) {\n notices.push(PAGE_HISTORY_UNAVAILABLE);\n }\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/**\n * The claim end read against the page's history, for a claim that no longer\n * holds. Every other status is what it was: the walk runs only where a\n * verdict is in doubt, so a clean corpus costs no git at all.\n */\nasync function withClaimHistory(\n now: {\n page: PageCitations;\n entry: PageCitation;\n claim: ClaimEnd | null;\n lines: readonly string[];\n },\n read: { path: string; git: GitClient; cap?: number; manifest?: string },\n): Promise<ClaimEnd | null> {\n const { claim } = now;\n if (claim === null || claim.status !== \"changed\") return claim;\n // A page read from stdin has no path in the repository, so it has no history.\n if (read.path === STDIN_LABEL) return claim;\n const input = { page: now.page, entry: now.entry, claim, ...read };\n const history = await claimHistory(input);\n return refineClaim({ ...input, lines: now.lines, history });\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 /**\n * Positional inputs; empty means fall back to the selected collections'\n * `paths:`. The stdin token `-` cancels that implicit fallback like any\n * other input, but never an explicit `--collection`: stdin is no path, so\n * it rides beside the flag and the named collection is still resolved.\n */\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 /**\n * Whether the run resolves `src:` paths at all. Default true. `false`\n * silences the notice about where they would resolve from, which `remove`\n * has no use for: it edits a page and never reads a source.\n */\n resolvesSources?: boolean;\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 // The paths the operator actually typed. Stdin is not one of them, which is\n // what lets a `-` ride beside the flag instead of being refused as a path.\n const typedInputs = opts.inputs.filter((input) => input !== STDIN);\n if (wanted.length > 0 && typedInputs.length > 0) {\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 // `--collection` is a request the run has to honour, as in meta: the named\n // collection's pages are resolved even when stdin rides beside the flag.\n // Counting `-` as a path made `cite check - --as markdown --collection\n // pages` check stdin, open no page of the collection, print no finding and\n // exit 0. The implicit fallback is not a request, and a lone `-` cancels it\n // as before: a piped page is a run of its own.\n const fromCollections = wanted.length > 0 || opts.inputs.length === 0;\n const collectionPaths = fromCollections ? collections.flatMap((c) => c.paths) : [];\n // Stdin keeps its typed position; the globs follow it in declaration order.\n const inputs = fromCollections ? [...opts.inputs, ...collectionPaths] : opts.inputs;\n // Only a path needs a base, so it follows the globs when they contributed\n // and stays at the working directory otherwise — stdin included.\n const base = collectionPaths.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 // Said only to a run that will resolve a source against it.\n if (opts.resolvesSources !== false) {\n opts.onNotice?.(`No git root found; resolving src: paths from ${cwd}`);\n }\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/** What a command's sources mean to it, where that is not `check`'s answer. */\nexport interface SourceNeeds {\n /** The run cannot work without them: `--no-check-sources` is refused (`update`). */\n require?: boolean;\n /** The run resolves `src:` paths at all. `false` for `remove`, which edits the page. */\n resolve?: boolean;\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 sources: SourceNeeds = {},\n): Promise<PreparedRun> {\n const requireSources = sources.require === true;\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 ...(sources.resolve === false ? { resolvesSources: false } : {}),\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 // A claim's history is the page's own, so it is read in the repository the\n // page paths resolve from, which is not the sources' under `--root`.\n const pageGit =\n opts.pageGitClient ?? (run.base === run.root ? git : gitClient(run.base));\n const pageOptions: CheckPageOptions = {\n root: run.root,\n checkSources,\n key: run.key,\n severity: config?.severity,\n gitClient: git,\n pageRoot: run.base,\n pageGitClient: pageGit,\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. Among them are\n * the pins the command can already see are wrong: a duplicate of an entry the\n * page has, and a claim whose lines hold no text at all.\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 { isEncryptedValue } from \"../../shared/encryption.js\";\nimport {\n blockMatches,\n otherClaimSpans,\n pinOfLines,\n spellElsewhere,\n toBodyLines,\n toFileLines,\n} 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 {\n formatSrc,\n lineSpec,\n parseLines,\n parseSrc,\n spellLines,\n spellSource,\n tooWide,\n} from \"../core/range.js\";\nimport { misplacedMarkers } from \"../core/reanchor.js\";\nimport { shiftedEntries, withClaimLines, type Shifted } from \"../core/shift.js\";\nimport { readSource, sourceIndexFor } from \"../core/sources.js\";\nimport { shortSrc, spellAt } from \"../core/spell.js\";\nimport { ManifestSet } from \"../core/manifest.js\";\nimport { sidecarsFor, type PageSidecar } from \"../core/sidecar.js\";\nimport {\n ANY_FENCE,\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 PageCitation,\n PageCitations,\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/** How a refusal names an entry: its id, or the pointer a report would use. */\nfunction entryName(entry: PageCitation): string {\n return entry.citation.id ?? `/citations/${String(entry.origin.index)}`;\n}\n\n/**\n * The entry that already pins these very page lines to this very source, in\n * the frontmatter or in the manifest that owns the page's citations. A bare\n * pin matches another bare pin over the same source.\n *\n * The source is compared as each end spells it, so an encrypted one compares\n * as its ciphertext and no path is decrypted to say so. A marker add is not\n * asked: it stores no claim lines, and its own id and anchor checks cover it.\n */\nfunction duplicateOf(\n page: PageCitations,\n src: string,\n pageLines: PageLines | undefined,\n): PageCitation | undefined {\n // opts.src is the caller's plain-path spelling; an existing entry encrypted\n // under a key compares as its ciphertext and will never match here.\n const wanted = formatSrc(parseSrc(src));\n return page.citations.find((entry) => {\n const { citation } = entry;\n if (spellSource(citation.source) !== wanted) return false;\n if (pageLines === undefined) return citation.claim === undefined;\n const spec = citation.claim?.lines;\n if (spec === undefined) return false;\n const recorded = parseLines(spec);\n if (recorded === undefined) return false;\n const file = toFileLines(recorded, page.bodyLine);\n return file.start === pageLines.start && file.end === pageLines.end;\n });\n}\n\n/** Whether a page line can hold no claim at all: it is blank, or it is a fence. */\nfunction holdsNoText(text: string): boolean {\n return text.trim() === \"\" || ANY_FENCE.test(text);\n}\n\n/**\n * The refusal for a claim whose lines hold no text, `at` being the page and\n * the lines as the caller spelled them. Undefined when at least one line\n * carries text. `--quote` never asks, because a quote is fences and content\n * by design.\n */\nfunction emptyClaimRefusal(\n lines: readonly string[],\n pageLines: PageLines,\n at: string,\n): string | undefined {\n const span = lines.slice(pageLines.start - 1, pageLines.end);\n if (span.some((text) => !holdsNoText(text))) return undefined;\n if (pageLines.start !== pageLines.end) return `${at} holds no claim text.`;\n const only = span[0] ?? \"\";\n return only.trim() === \"\" ? `${at} is blank.` : `${at} is a fence line, not claim text.`;\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 // The same claim on the same source twice is one citation reported twice,\n // and the second is what a re-run of a script writes.\n const duplicate = marker ? undefined : duplicateOf(page, opts.src, pageLines);\n if (duplicate !== undefined) {\n const src = shortSrc(spellSource(duplicate.citation.source));\n const what =\n pageLines === undefined\n ? `a bare pin for ${src}`\n : `an entry for ${spellAt(pageLines)} and ${src}`;\n throw new CiteError(`${label} already has ${what} (${entryName(duplicate)}).`);\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 } else if (!marker) {\n // A pin over a fence or a blank line holds for as long as the page has\n // one, so a check would call it `current` whatever the prose does.\n const empty = emptyClaimRefusal(lines, pageLines, at);\n if (empty !== undefined) throw new CiteError(empty);\n }\n // `add` does not move a marker it did not write, so it refuses to write\n // where a misplaced one would make its entry wrong (proposal 0054).\n const split = misplacedMarkers(page, lines);\n const held = split.find(\n (found) => found.line >= pageLines.start && found.line <= pageLines.end,\n );\n if (held !== undefined) {\n throw new CiteError(\n `${at} holds the marker at line ${String(held.line)}, which splits its paragraph. Run manni cite update first.`,\n );\n }\n const inside = marker\n ? split.find(\n (found) => pageLines.start >= found.unit.start && pageLines.start <= found.unit.end,\n )\n : undefined;\n if (inside !== undefined) {\n throw new CiteError(\n `${at} is in the paragraph at ${spellAt(inside.unit)}, which the marker at line ${String(inside.line)} splits. Run manni cite update first.`,\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 // Where else the claim's text sits, for the notice at the end of the run.\n let elsewhere: PageLines[] = [];\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 // A marker pins everything it anchors, so the range limit applies to that.\n const unitWide = tooWide({ start: holding.start, end: holding.end });\n if (unitWide !== undefined) {\n throw new CiteError(\n `${at} is in a ${holding.kind} at ${spellAt(holding)} that ${unitWide}. A marker anchors the whole ${holding.kind}.`,\n );\n }\n shifted = shiftedEntries({\n citations: page.citations,\n at: [holding.start],\n delta: 1,\n bodyLine: page.bodyLine,\n label,\n });\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 elsewhere = otherClaimSpans(lines, pageLines, pin, page.bodyLine);\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 // The first pinned source line, so the report shows what the range caught\n // and a mis-typed one is visible at write time. A whole file has no first\n // line worth naming, and an encrypted source is never spelled in the open.\n const srcRange = parseSrc(opts.src);\n let sourceLine: string | undefined;\n if (srcRange.start !== undefined && !isEncryptedValue(citation.source.file)) {\n const read = await readSource(root, sourceIndex, srcRange, undefined);\n if (read.kind === \"ok\") sourceLine = splitLines(read.text)[srcRange.start - 1];\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 /** Which item of the entry's `citations` this run added, for the line report. */\n let index = 0;\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 index = list.length - 1;\n const at = await manifests.write(owner, sidecar.entry, list, index);\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 ...(sourceLine === undefined ? {} : { sourceLine }),\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 // The entry goes in under compare-and-swap, so what lands may be a replay\n // onto a manifest another command wrote while this one was running. The\n // report names the bytes and the line that actually landed, not the ones\n // this run spliced from.\n if (result.manifest !== undefined && opts.dryRun !== true) {\n const [settled] = await manifests.commit();\n if (owner !== undefined && sidecar?.entry !== undefined) {\n result.manifest.line = manifests.lineOf(owner, sidecar.entry, index) ?? result.manifest.line;\n }\n if (settled !== undefined) {\n result.manifest.content = settled.text;\n result.manifest.diff = settled.diff;\n }\n result.manifest.written = true;\n }\n // The claim's text repeats, so a later move of it could not be told apart\n // from its copies. Said once the entry is written: it is not a refusal, and\n // the lines it names are the page's own after the write.\n if (elsewhere.length > 0) {\n const named = elsewhere.map((span) => ({ start: span.start + shift, end: span.end + shift }));\n const who = citation.id === undefined ? \"\" : `${citation.id}: `;\n opts.onNotice?.(\n `${who}the claim's text also appears at ${spellElsewhere(named)}, so a move would be ambiguous. Use --marker, or pin more lines.`,\n );\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 remove`: take a citation off a page.\n *\n * The inverse of `add`, and it undoes all of what `add` did. The entry goes\n * out of the page's frontmatter, or out of the manifest that owns the page's\n * citations, whichever `add` would have written to. Every marker naming it\n * goes out of the body. The claims below each removed marker line move up\n * with the text they pin, which is the inverse of the shift `add --marker`\n * performs and the same rule (`shiftedEntries`).\n *\n * `--only` is required, one entry per occurrence, and nothing is written\n * until every one of them has been found: a run either removes what it was\n * told to or writes nothing. That is `add`'s contract, and the reason there\n * is no exit 1 here.\n *\n * An id with a marker and no entry removes the marker alone, which is how a\n * `marker-orphan` is cleared.\n */\nimport { resolve } from \"node:path\";\nimport { writeFileAtomic } from \"../../meta/index.js\";\nimport { STDIN_LABEL } from \"../../meta/internal.js\";\nimport { ManifestSet } from \"../core/manifest.js\";\nimport { citationInputs, pickExtractor, readPage } from \"../core/page.js\";\nimport { shiftedEntries, withClaimLines } from \"../core/shift.js\";\nimport { isMarkerLine } from \"../core/statements.js\";\nimport { splitLines } from \"../core/hash.js\";\nimport { removeFrontmatterCitations, removeLine, spliceEntryField, unifiedDiff } from \"../core/write.js\";\nimport { CiteError } from \"../errors.js\";\nimport type {\n CitationInput,\n ManifestChange,\n Removal,\n RemoveOptions,\n RemovePage,\n RemoveRun,\n} from \"../types.js\";\nimport { assertNoOrphanJoins, assertNoOrphans, joinHits, prepareRun, readTarget } from \"./check.js\";\n\n/** How an entry with no id is named: its place in the page's list. */\nconst POINTER = /^\\/citations\\/(0|[1-9][0-9]*)$/;\n\n/** `4 entries`, `1 entry`. */\nfunction entryCount(n: number): string {\n return `${String(n)} ${n === 1 ? \"entry\" : \"entries\"}`;\n}\n\n/** The `id` of a raw entry, whether or not the schema would accept the rest of it. */\nfunction idOf(entry: unknown): string | undefined {\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) return undefined;\n const id: unknown = (entry as Record<string, unknown>).id;\n return typeof id === \"string\" ? id : undefined;\n}\n\n/** What one page's run found, before anything is written. */\ninterface Planned {\n page: RemovePage;\n /** The page as it will be written, when it changed. */\n content?: string;\n /** Absolute path to write it to; absent for the stdin page. */\n path?: string;\n}\n\nexport async function runRemove(opts: RemoveOptions): Promise<RemoveRun> {\n // Repeats collapse, as they do on `--collection`: naming one entry twice\n // asks for one removal, and would otherwise be counted twice.\n const only = [...new Set(opts.only)];\n // Asked before the config is read: it is a usage error, and the answer does\n // not depend on anything on disk.\n if (only.length === 0) {\n throw new CiteError(\"remove needs --only <id>; it never removes every citation on a page.\");\n }\n // Nothing here resolves a source: the run builds no index, and says\n // nothing about where `src:` paths would have come from.\n const prepared = await prepareRun({ ...opts, checkSources: false }, \"removed\", \"remove\", {\n resolve: false,\n });\n const { run, files, usingStdin, forced } = prepared;\n assertNoOrphans(prepared);\n const hits = joinHits();\n const manifests = new ManifestSet();\n /** Every `--only` value that named something, anywhere in the run. */\n const matched = new Set<string>();\n const pageCount = files.length + (usingStdin ? 1 : 0);\n\n const planned: Planned[] = [];\n const removeOne = async (label: string, content: string, path?: string): Promise<void> => {\n const setup = prepared.setupFor(label, content);\n if (setup.sidecar !== undefined) hits.record(setup.sidecar, label);\n const owner = setup.sidecar?.owner;\n const page = readPage(label, content, {\n ...(forced === undefined ? {} : { format: forced.name }),\n ...(setup.options.citations === undefined ? {} : { citations: setup.options.citations }),\n ...(owner === undefined ? {} : { owned: { file: owner.file, collection: owner.collection } }),\n });\n const { format } = page;\n const extractor = pickExtractor(label, forced?.name);\n const inputs: CitationInput[] = citationInputs(\n label,\n extractor.extract(content, label),\n setup.sidecar?.citations,\n );\n const lines = splitLines(content);\n\n /** The entries one `--only` value names on this page. */\n const entriesFor = (value: string): number[] => {\n // The digits of a pointer, or nothing for a value that is an id. Read\n // as a capture rather than through `exec(...) !== null`, so the index\n // is a string the compiler has seen narrowed.\n const [, digits] = POINTER.exec(value) ?? [];\n if (digits === undefined) {\n return inputs.flatMap((input, index) => (idOf(input.entry) === value ? [index] : []));\n }\n const index = Number(digits);\n if (index < inputs.length) return [index];\n // A pointer is a position, so over several pages it means the entry at\n // that position wherever there is one. Against one page there is no\n // other page it could have meant.\n if (pageCount === 1) {\n throw new CiteError(\n `\"${value}\" is past the last entry of ${label} (${entryCount(inputs.length)}).`,\n );\n }\n return [];\n };\n /** The markers naming an id, as file lines. */\n const markersFor = (id: string | undefined): number[] =>\n id === undefined\n ? []\n : page.statements\n .filter((s) => s.payload.kind === \"ref\" && s.payload.id === id)\n .map((s) => s.line);\n\n const removed: Removal[] = [];\n const indices = new Set<number>();\n const markerLines: number[] = [];\n for (const value of only) {\n const found = entriesFor(value);\n for (const index of found) {\n const input = inputs[index];\n const id = idOf(input?.entry);\n const markers = markersFor(id);\n indices.add(index);\n markerLines.push(...markers);\n removed.push({\n ...(id === undefined ? {} : { id }),\n index,\n ...(input === undefined ? {} : { origin: input.origin }),\n markerLines: markers,\n });\n matched.add(value);\n }\n if (found.length > 0) continue;\n // An id no entry carries, but a marker names: the marker alone.\n const markers = markersFor(value);\n if (markers.length === 0) continue;\n markerLines.push(...markers);\n removed.push({ id: value, markerLines: markers });\n matched.add(value);\n }\n const nothing: RemovePage = { file: label, removed: [], diff: \"\", written: false };\n if (removed.length === 0) {\n // The stdin page is printed whatever the run did to it.\n if (path === undefined) nothing.content = content;\n planned.push({ page: nothing, ...(path === undefined ? {} : { path }) });\n return;\n }\n\n // A marker sharing its line with text anchors that text, so the line is\n // not the tool's to delete.\n const ordered = [...new Set(markerLines)].sort((a, b) => a - b);\n for (const line of ordered) {\n if (!isMarkerLine(lines[line - 1] ?? \"\", format)) {\n const id = page.statements.find((s) => s.line === line)?.payload;\n const named = id?.kind === \"ref\" ? ` ${id.id}` : \"\";\n throw new CiteError(\n `the marker${named} at ${label}:${String(line)} shares its line with text; remove it by hand.`,\n );\n }\n }\n\n // What stays, moved up by the marker lines going out above it.\n const survivors = page.citations.filter((c) => !indices.has(c.origin.index));\n const shifted = shiftedEntries({\n citations: survivors,\n at: ordered,\n delta: -1,\n bodyLine: page.bodyLine,\n label,\n });\n\n let after = content;\n // The claim lines first, while the entries still stand where the page's\n // own pointers say. Splicing a scalar never changes the line count, and\n // the markers are in the body, so neither edit moves the other.\n for (const { index, lines: moved } of shifted.frontmatter) {\n after = spliceEntryField(after, format, index, [\"claim\", \"lines\"], moved);\n }\n // Bottom up, so every line above each one keeps its number.\n for (const line of [...ordered].sort((a, b) => b - a)) after = removeLine(after, line);\n if (owner === undefined) {\n after = removeFrontmatterCitations(after, format, indices, label);\n } else {\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 const kept = inputs\n .map((input, index) => {\n const moved = shifted.manifest.get(index);\n return moved === undefined ? input.entry : withClaimLines(input.entry, moved);\n })\n .filter((_entry, index) => !indices.has(index));\n if (kept.length === 0) await manifests.remove(owner, setup.sidecar.entry);\n // The line a written entry sits on is what `add` reports; a removal\n // reports the line the entry sat on before, from its origin. So the\n // answer is dropped here, and the index it is measured from is any\n // index at all.\n else void (await manifests.write(owner, setup.sidecar.entry, kept, 0));\n }\n\n const out: RemovePage = {\n file: label,\n removed,\n diff: after === content ? \"\" : unifiedDiff(label, content, after),\n written: false,\n };\n // The stdin page has nowhere to be written; the caller prints it instead.\n if (path === undefined) out.content = after;\n planned.push({ page: out, ...(after === content ? {} : { content: after }), ...(path === undefined ? {} : { path }) });\n };\n\n if (usingStdin) await removeOne(STDIN_LABEL, opts.stdinContent ?? \"\");\n for (const file of files) {\n await removeOne(file, await readTarget(run, file), resolve(run.base, file));\n }\n assertNoOrphanJoins(prepared, hits);\n\n // Every name has to have been found somewhere before a byte is written.\n const missing = only.find((value) => !matched.has(value));\n if (missing !== undefined) {\n const where =\n pageCount === 1\n ? `${planned[0]?.page.file ?? \"the page\"} has no`\n : `none of ${String(pageCount)} pages has an`;\n const what = POINTER.test(missing) ? `entry ${missing}` : `entry or marker ${missing}`;\n throw new CiteError(`${where} ${what}.`);\n }\n\n const write = opts.dryRun !== true;\n for (const item of planned) {\n if (item.content === undefined || item.path === undefined) continue;\n if (write) await writeFileAtomic(item.path, item.content);\n item.page.written = write;\n }\n const rewritten: ManifestChange[] = [];\n const record = (changed: { file: string; diff: string }): void => {\n rewritten.push({ file: changed.file, diff: changed.diff, written: write });\n };\n if (write) await manifests.commit({ after: record });\n else for (const changed of manifests.changed()) record(changed);\n\n const pages = planned.map((item) => item.page);\n return {\n pages,\n removed: pages.reduce((n, page) => n + page.removed.length, 0),\n ...(rewritten.length > 0 ? { manifests: rewritten } : {}),\n };\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,\n * fenced block or table rows now at its first line, and the report prints that\n * text, so the log shows exactly what was accepted. A paragraph grows with the\n * sentence it gained; a table keeps the number of rows the claim was minted\n * over, because a row is a statement of its own. A claim it cannot re-pin is\n * skipped with the reason named, and a sentence that was reworded *and* moved\n * is an `add` again. A source is re-minted at HEAD, with a new `commit-sha`\n * 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 noUnitAt,\n normalizeWhitespace,\n otherClaimSpans,\n pinOfLines,\n spellElsewhere,\n toBodyLines,\n toFileLines,\n unitAt,\n type ClaimUnit,\n type NoUnit,\n} from \"../core/claims.js\";\nimport { GIT_UNAVAILABLE_COMMIT } from \"../core/git.js\";\nimport { splitLines } from \"../core/hash.js\";\nimport { claimWords, sharesSentence, wordShare } from \"../core/history.js\";\nimport { mintCitation } from \"../core/mint.js\";\nimport { ManifestSet } from \"../core/manifest.js\";\nimport { readPage } from \"../core/page.js\";\nimport { lineSpec, parseLines, spellLines, tooWide } from \"../core/range.js\";\nimport {\n applyMarkerMoves,\n misplacedMarkers,\n type MisplacedMarker,\n} from \"../core/reanchor.js\";\nimport { resolveSeverity } from \"../core/severity.js\";\nimport { listOf, spellAt } from \"../core/spell.js\";\nimport { anchoredLines, markerIndent, offsetOfLine } from \"../core/statements.js\";\nimport { spliceEntryField, unifiedDiff } from \"../core/write.js\";\nimport { CiteError } from \"../errors.js\";\nimport type {\n Citation,\n CitationResult,\n CiteRule,\n ClaimEnd,\n LineSpec,\n ManifestChange,\n PageCitation,\n PageCitationReport,\n PageCitations,\n PageLines,\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 | {\n kind: \"claim-accepted\";\n result: CitationResult;\n unit: ClaimUnit;\n pin: string;\n lines?: LineSpec;\n /**\n * The line held wholly other text and `--only` named the entry, so the\n * accept stands. The report says so rather than reading as an edit.\n */\n replaced?: true;\n /** The marker's line on the page this run leaves, where one anchors. */\n markerLine?: number;\n }\n | { kind: \"source-accepted\"; result: CitationResult; minted: Citation }\n | { kind: \"marker-moved\"; result: CitationResult; from: number; to: number }\n | {\n kind: \"claim-reanchored\";\n result: CitationResult;\n pin: string;\n /** The span that held, in file lines, and the span now pinned. */\n held: string;\n now: string;\n }\n | {\n kind: \"claim-shifted\";\n result: CitationResult;\n lines: LineSpec;\n from: string;\n to: string;\n }\n /**\n * The words the pin covered are unchanged and only the layout moved\n * (proposal 0053). A plain `update` re-pins it, and rewrites its `lines:`\n * when the entry has them.\n */\n | {\n kind: \"claim-words-held\";\n result: CitationResult;\n pin: string;\n /** The file line of the claim's first body line, after any marker move. */\n at: number;\n /** The stored span and the span now pinned, in file lines. */\n fromLines: string;\n toLines: string;\n commitSha?: string;\n lines?: LineSpec;\n }\n /**\n * A changed claim `--accept` refused to re-pin: the line now holds text\n * sharing no sentence with the claim at its baseline, or too few of its\n * words. Nothing is written.\n */\n | {\n kind: \"claim-replaced\";\n result: CitationResult;\n at: number;\n commitSha: string;\n /** The share of the claim's words held, when overlap is what refused it. */\n wordShare?: number;\n /** The pin that stands, and the one that was not written. */\n pin: string;\n would: string;\n };\n\n/**\n * Why one repair was declined, and the rule whose finding says so. One entry\n * can carry findings about both ends, so the reason names which it is about.\n */\ninterface Declined {\n rule: string;\n why: string;\n}\n\n/**\n * Why `--accept` re-pinned nothing at the claim's line, said plainly. Each\n * reason is a different problem: a blank line lost the sentence, a fenced line\n * moved it into code, a line that starts no paragraph is a heading underline\n * or an unclosed fence, a line outside the body is a range the page no longer\n * reaches, a short table lost rows the claim was minted over, and a marker or\n * a table rule is a line that holds no claim text at all.\n */\nfunction sayNoUnit(reason: NoUnit): string {\n switch (reason) {\n case \"outside\":\n return \"the line is outside the page body\";\n case \"blank\":\n return \"the line is blank\";\n case \"fenced\":\n return \"the line sits inside a fenced block\";\n case \"marker\":\n return \"that line now holds a cite marker, not claim text\";\n case \"not-a-paragraph\":\n return \"the line does not start a paragraph\";\n case \"table-short\":\n return \"the table no longer holds every row the claim covers\";\n case \"table-rule\":\n return \"that line is a table rule, not claim text\";\n }\n}\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 case \"marker-moved\":\n return \"marker-misplaced\";\n case \"claim-reanchored\":\n return \"claim-moved\";\n case \"claim-words-held\":\n return \"claim-reanchored\";\n // A refused claim leaves nothing written, but its finding is the row the\n // refusal prints, so it is not also reported as skipped.\n case \"claim-replaced\":\n return \"claim-changed\";\n // A shifted entry was `current`, so it had no finding to settle.\n case \"claim-shifted\":\n return \"\";\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 case \"claim-shifted\":\n return spliceEntryField(content, format, index, [\"claim\", \"lines\"], plan.lines);\n case \"claim-reanchored\":\n return spliceEntryField(content, format, index, [\"claim\", \"integrity\"], plan.pin);\n case \"claim-words-held\": {\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 // Nothing is written for a refused claim; the report is the whole of it.\n case \"claim-replaced\":\n // The move is a page rewrite, applied to the whole page before any splice.\n case \"marker-moved\":\n return content;\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 case \"claim-shifted\": {\n const claim = end(\"claim\");\n if (claim === undefined) return false;\n claim.lines = plan.lines;\n return true;\n }\n case \"claim-reanchored\": {\n const claim = end(\"claim\");\n if (claim === undefined) return false;\n claim.integrity = plan.pin;\n return true;\n }\n case \"claim-words-held\": {\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 // Nothing is written for a refused claim.\n case \"claim-replaced\":\n // The page holds the marker, so the manifest has nothing to change.\n case \"marker-moved\":\n return true;\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 {\n ...base,\n end: \"claim\",\n reason: \"moved\",\n status: \"moved\",\n from: plan.from,\n to: plan.to,\n fromLines: plan.from,\n toLines: plan.to,\n };\n case \"marker-moved\": {\n const from = String(plan.from);\n const to = String(plan.to);\n return {\n ...base,\n end: \"marker\",\n reason: \"re-anchored\",\n status: \"misplaced\",\n from,\n to,\n fromLines: from,\n toLines: to,\n };\n }\n case \"claim-reanchored\": {\n const was = citation.claim?.integrity ?? \"\";\n return {\n ...base,\n end: \"claim\",\n reason: \"re-anchored\",\n status: \"moved\",\n from: was,\n to: plan.pin,\n fromPin: was,\n toPin: plan.pin,\n lines: plan.held,\n newLines: plan.now,\n };\n }\n case \"claim-words-held\": {\n const was = citation.claim?.integrity ?? \"\";\n const out: UpdateRewrite = {\n ...base,\n end: \"claim\",\n reason: \"re-anchored\",\n status: \"reanchored\",\n from: was,\n to: plan.pin,\n fromPin: was,\n toPin: plan.pin,\n fromLines: plan.fromLines,\n toLines: plan.toLines,\n at: plan.at,\n };\n if (plan.commitSha !== undefined) out.commitSha = plan.commitSha;\n return out;\n }\n case \"claim-replaced\":\n return {\n ...base,\n end: \"claim\",\n reason: \"replaced\",\n status: \"changed\",\n from: plan.pin,\n to: plan.would,\n fromPin: plan.pin,\n toPin: plan.would,\n at: plan.at,\n commitSha: plan.commitSha,\n ...(plan.wordShare === undefined ? {} : { wordShare: plan.wordShare }),\n };\n case \"claim-shifted\":\n return {\n ...base,\n end: \"claim\",\n reason: \"shifted\",\n status: \"current\",\n from: plan.from,\n to: plan.to,\n fromLines: plan.from,\n toLines: plan.to,\n };\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 was = citation.claim?.integrity ?? \"\";\n const out: UpdateRewrite = {\n ...base,\n end: \"claim\",\n reason: \"accepted\",\n // A bypassed guard reads `replaced`, so the log shows that the line\n // held other text and a named accept took it anyway.\n status: plan.replaced === true ? \"replaced\" : \"changed\",\n from: was,\n to: plan.pin,\n fromPin: was,\n toPin: plan.pin,\n at: plan.unit.lines.start,\n text: quoted(plan.unit.text),\n };\n // A re-pin over a unit wider than the stored lines names both spans.\n const stored = plan.result.claim?.fileLines;\n const now = spellLines(plan.unit.lines);\n if (stored !== undefined && stored !== now) {\n out.fromLines = stored;\n out.toLines = now;\n }\n // Where the report says the claim is: its marker, when one anchors it.\n // A marker this run moved reads at the line it now sits on, so the row\n // and the move above it name one line rather than two.\n const markerLine =\n plan.markerLine ?? (plan.result.anchor === \"marker\" ? plan.result.markerLine : undefined);\n if (markerLine !== undefined) out.markerLine = markerLine;\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 fromPin: citation.source.integrity,\n toPin: 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\n/**\n * How much of the claim's words its line must still hold for a blanket\n * `--accept` to re-pin it, as `wordShare` measures it.\n *\n * A replay of 65 proposed `--accept` re-pins over this repository's own\n * corpus, every one with a baseline to read, put the seven wrong re-pins at\n * 0.38 and below and every safe one at 0.74 and above. Each of the seven had\n * drifted onto a neighbouring table row, and the sentence test below let all\n * seven through. Nothing measured landed between the two bands, so the number\n * is fixed here. A config key would be a knob over a gap no corpus fills.\n */\nconst CLAIM_WORD_SHARE = 0.5;\n\n/** Why a re-pin was refused: the baseline, and the share when overlap is what fired. */\ninterface Replacement {\n /** The baseline the claim's words were read against. */\n commit: string;\n /** Set only when the overlap test fired: the share of the claim's words held. */\n share?: number;\n}\n\n/**\n * Why a re-pin over `text` would bless a line that no longer carries the\n * claim: a neighbouring table row after a shift, or a block inserted under a\n * marker. `undefined` lets the accept stand, which is also what happens with\n * no baseline to read the claim against.\n *\n * Two tests, either of which refuses. The first is sentence intersection: a\n * claim whose paragraph was edited still shares a sentence with what it said\n * at the baseline, and one whose line was replaced outright shares none. The\n * second is word overlap, for the drift the first misses. Two rows of one\n * table end alike often enough to share a sentence while saying different\n * things, so a line holding less than `CLAIM_WORD_SHARE` of the claim's words\n * is refused too, and the report names the share.\n *\n * The guard only asks about an entry the run did not name. Naming an id with\n * `--only` is the human judgement the guard exists to demand, so a reviewer\n * who has read the claim and its source re-pins a reworded sentence without a\n * remove and an add. What the guard is for is a blanket `--accept` quietly\n * re-pinning a hundred claims, one of which now holds a neighbouring table\n * row. A bypass is reported rather than hidden.\n */\nfunction replacementAt(\n claim: ClaimEnd,\n text: readonly string[],\n format: string,\n): Replacement | undefined {\n const was = claim.baselineText;\n const commit = claim.commitSha;\n if (was === undefined || commit === undefined) return undefined;\n const before = claimWords(was, format);\n const now = claimWords(text, format);\n if (!sharesSentence(before, now)) return { commit };\n const share = wordShare(before, now);\n if (share < CLAIM_WORD_SHARE) return { commit, share };\n return undefined;\n}\n\n/** How many characters of re-pinned text the report quotes before it elides. */\nconst QUOTE_CAP = 200;\n\n/**\n * The text a re-pin quotes: whitespace collapsed, and capped, because the\n * unit may be a whole paragraph and the report is one line per rewrite.\n */\nfunction quoted(text: readonly string[]): string {\n const all = normalizeWhitespace(text.join(\"\\n\"));\n return all.length <= QUOTE_CAP ? all : `${all.slice(0, QUOTE_CAP)}…`;\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/** One misplaced marker `update` left where it is, and the rule its line reads at. */\ninterface MarkerStay {\n line: number;\n rule: CiteRule;\n message: string;\n}\n\n/** What `update` will do to a page's misplaced markers. */\ninterface MarkerDecisions {\n moves: { result: CitationResult; entry: PageCitation; misplaced: MisplacedMarker }[];\n stays: MarkerStay[];\n}\n\n/**\n * A claim-lines entry the move would change: one whose range holds the\n * marker's line, or starts above the unit and reaches the place the marker\n * goes. Moving the marker would rewrite that entry's pinned text.\n */\nfunction crossing(\n page: PageCitations,\n misplaced: MisplacedMarker,\n): string | undefined {\n for (const other of page.citations) {\n const spec = other.citation.claim?.lines;\n const recorded = spec === undefined ? undefined : parseLines(spec);\n if (recorded === undefined) continue;\n const file = toFileLines(recorded, page.bodyLine);\n const holdsMarker = file.start <= misplaced.line && misplaced.line <= file.end;\n const holdsPlace = file.start < misplaced.place && misplaced.place <= file.end;\n if (!holdsMarker && !holdsPlace) continue;\n return other.citation.id === undefined\n ? `the claim at ${spellAt(file)}`\n : `the claim of ${other.citation.id} (${spellAt(file)})`;\n }\n return undefined;\n}\n\n/**\n * Which of a page's misplaced markers move, and why each of the rest stays.\n * Every decision is taken against the page as it was read, before any write.\n */\nfunction decideMarkers(input: {\n page: PageCitations;\n report: PageCitationReport;\n lines: readonly string[];\n accept: boolean;\n only?: Set<string>;\n}): MarkerDecisions {\n const { page, report, lines, accept, only } = input;\n const out: MarkerDecisions = { moves: [], stays: [] };\n for (const misplaced of misplacedMarkers(page, lines)) {\n const entry = misplaced.entry;\n const line = misplaced.line;\n const stay = (rule: CiteRule, message: string): void => {\n out.stays.push({ line, rule, message });\n };\n // An orphan, repeated or invalid marker names no entry that can be\n // checked, and `--only` selects entries, so it selects their markers.\n if (entry === undefined) {\n if (only !== undefined) continue;\n const own = report.findings.find(\n (finding) => finding.line === line && finding.rule.startsWith(\"marker-\") && finding.rule !== \"marker-misplaced\",\n );\n stay(\n own?.rule ?? \"marker-orphan\",\n `the marker at line ${String(line)} stays, because it names no entry update can check.`,\n );\n continue;\n }\n const id = entry.citation.id;\n if (only !== undefined && (id === undefined || !only.has(id))) continue;\n const result = report.citations.find((r) => r.origin.index === entry.origin.index);\n if (result === undefined) continue;\n // Claim lines and a marker both: neither anchor can be trusted.\n if (entry.citation.claim?.lines !== undefined) {\n stay(\n \"anchor-invalid\",\n named(id, `the marker at line ${String(line)} stays, because the entry also has claim lines. Keep one.`),\n );\n continue;\n }\n const across = crossing(page, misplaced);\n if (across !== undefined) {\n stay(\n \"marker-misplaced\",\n named(id, `the marker at line ${String(line)} stays, because moving it would change ${across}.`),\n );\n continue;\n }\n if (result.claim !== null && result.claim.status === \"changed\" && !accept) {\n stay(\n \"marker-misplaced\",\n named(\n id,\n `the marker at line ${String(line)} stays, because its claim changed since it was pinned. update --accept moves it and re-pins.`,\n ),\n );\n continue;\n }\n out.moves.push({ result, entry, misplaced });\n }\n return out;\n}\n\n/**\n * The lines the span an entry's marker anchors covers on the page as it now\n * stands, and the pin over them.\n */\nfunction anchoredNow(\n content: string,\n format: string,\n lines: readonly string[],\n markerLine: number,\n quote: boolean,\n): { span: PageLines; pin: string } | undefined {\n const at = offsetOfLine(content, markerLine) + (lines[markerLine - 1]?.length ?? 0);\n const span = anchoredLines(content, at, format, quote);\n if (span === undefined) return undefined;\n const pin = pinOfLines(lines, span);\n return pin === undefined ? undefined : { span, pin };\n}\n\n/** The errno a failed write carries, when it carries one. */\nfunction codeOf(error: unknown): string | undefined {\n if (typeof error !== \"object\" || error === null || !(\"code\" in error)) return undefined;\n const code: unknown = error.code;\n return typeof code === \"string\" ? code : undefined;\n}\n\n/**\n * A run writes a page and the manifest that keys it, and a marker move needs\n * both to land. So every file this run wrote, page and manifest alike, keeps\n * its original text until the run is done, and a failed write puts them back.\n * A manifest left pinned to text its page no longer holds would read as drift\n * that never happened.\n */\nclass WrittenFiles {\n private readonly before = new Map<string, string>();\n private readonly labels = new Map<string, string>();\n\n /** Remember what `path` held before this run wrote it. */\n record(path: string, label: string, content: string): void {\n if (!this.before.has(path)) {\n this.before.set(path, content);\n this.labels.set(path, label);\n }\n }\n\n /**\n * Put every file back, and say what happened: `<file> could not be written\n * (<code>). <pages> was restored.`\n */\n async restore(file: string, error: unknown): Promise<CiteError> {\n const restored: string[] = [];\n const failed: string[] = [];\n for (const [path, content] of this.before) {\n const label = this.labels.get(path) ?? path;\n try {\n await writeFileAtomic(path, content);\n restored.push(label);\n } catch {\n failed.push(label);\n }\n }\n const code = codeOf(error);\n const why = code === undefined ? \"\" : ` (${code})`;\n const parts = [`${file} could not be written${why}.`];\n if (restored.length > 0) {\n parts.push(`${listOf(restored)} ${restored.length === 1 ? \"was\" : \"were\"} restored.`);\n }\n if (failed.length > 0) {\n parts.push(\n `${listOf(failed)} could not be restored, and ${failed.length === 1 ? \"holds\" : \"hold\"} an intermediate state.`,\n );\n }\n return new CiteError(parts.join(\" \"));\n }\n}\n\n/**\n * Citations counted as a summary counts them: an entry whose marker moved and\n * whose claim was re-pinned is one citation, not two.\n */\nfunction citationsIn(rows: readonly UpdateRewrite[]): number {\n const withMarker = new Set(rows.filter((row) => row.end === \"marker\").map((row) => row.index));\n return withMarker.size + rows.filter((row) => !withMarker.has(row.index)).length;\n}\n\nexport async function runUpdate(opts: UpdateOptions): Promise<UpdateRun> {\n const prepared = await prepareRun(opts, \"updated\", \"update\", { require: 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 // What every file this run wrote held before, so a failed write is undone.\n const writes = new WrittenFiles();\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 lineNow: (line: number) => number,\n declined: Map<number, Declined>,\n ): Promise<Plan[]> => {\n const out: Plan[] = [];\n const claim = result.claim;\n // A marker-anchored claim has no `lines:` to splice; its repair is a\n // re-pin over the span the marker anchors, planned by the caller.\n if (\n result.anchor !== \"marker\" &&\n claim !== null &&\n claim.status === \"moved\" &&\n claim.newLines !== undefined\n ) {\n const at = parseLines(claim.newLines);\n // A marker that moved shifted the page under the window the search\n // found, so the lines it reported are read through the move.\n const shifted =\n at === undefined\n ? undefined\n : (() => {\n const file = toFileLines(at, page.bodyLine);\n const to = { start: lineNow(file.start), end: lineNow(file.end) };\n return to.end - to.start === file.end - file.start\n ? toBodyLines(to, page.bodyLine)\n : undefined;\n })();\n if (at !== undefined && shifted !== undefined) {\n out.push({\n kind: \"claim-moved\",\n result,\n lines: lineSpec(shifted),\n from: claim.fileLines ?? \"\",\n to: spellLines(toFileLines(shifted, page.bodyLine)),\n });\n }\n }\n // The words the pin covered are unchanged, and the run they sit in moved.\n // A plain `update` re-pins it and rewrites the entry's lines (0053).\n if (\n result.anchor !== \"marker\" &&\n claim !== null &&\n claim.status === \"reanchored\" &&\n claim.newLines !== undefined\n ) {\n const at = parseLines(claim.newLines);\n const file = at === undefined ? undefined : toFileLines(at, page.bodyLine);\n const pin = file === undefined ? undefined : pinOfLines(lines, file);\n const to =\n file === undefined ? undefined : { start: lineNow(file.start), end: lineNow(file.end) };\n if (\n file !== undefined &&\n to !== undefined &&\n pin !== undefined &&\n to.end - to.start === file.end - file.start\n ) {\n const plan: Plan = {\n kind: \"claim-words-held\",\n result,\n pin,\n at: to.start,\n fromLines: claim.fileLines ?? \"\",\n toLines: spellLines(to),\n lines: lineSpec(toBodyLines(to, page.bodyLine)),\n };\n if (claim.commitSha !== undefined) plan.commitSha = claim.commitSha;\n out.push(plan);\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 // A marker-anchored claim is re-pinned against the page the move left,\n // so the caller plans that one.\n if (claim !== null && claim.status === \"changed\" && entry !== undefined && result.anchor !== \"marker\") {\n // The paragraph, block or row now at the claim's first line. Anything\n // else is left for a fresh `cite add`, and says why.\n // The span the claim holds now, and the line it starts on. A table keeps\n // the span: the author chose how many rows the claim covers, and\n // `--accept` re-mints, never redesigns.\n //\n // Both are set for every claim that reaches here. `claimEnd` fills\n // `fileLines` only on the `claim.lines` branch, and the marker branch is\n // already excluded above, so the `undefined` arms below are the types\n // being honest rather than a case a run can land in.\n const held = claim.fileLines === undefined ? undefined : parseLines(claim.fileLines);\n const at = held?.start;\n // Naming an id is the operator saying they have read the line, so the\n // refusals that ask whether it can be claim text at all stand down.\n const named = only !== undefined;\n const unit: ClaimUnit | undefined =\n at === undefined ? undefined : unitAt(page, at, lines, held, named);\n const wantsBlock = entry.citation.quote === true;\n const pin = unit === undefined ? undefined : pinOfLines(lines, unit.lines);\n // A unit past the range limit would pin more than a citation may hold.\n const wide = unit === undefined ? undefined : tooWide(unit.lines);\n if (unit !== undefined && wide !== undefined) {\n declined.set(result.origin.index, {\n rule: \"claim-changed\",\n why: `Not re-pinned: the ${unit.kind} ${wide}.`,\n });\n } else if (unit === undefined) {\n const why = at === undefined ? undefined : noUnitAt(page, at, lines, held, named);\n if (why !== undefined) {\n declined.set(result.origin.index, {\n rule: \"claim-changed\",\n why: `Not re-pinned: ${sayNoUnit(why)}.`,\n });\n }\n } else if (pin !== undefined && (!wantsBlock || unit.kind === \"block\")) {\n // Where else the same text sits. A pin cannot tell two copies apart,\n // so re-pinning over one of them writes a claim that is\n // `moved-ambiguous` the moment anything above it shifts. `add` refuses\n // the same pin for the same reason, before it is ever written.\n const elsewhere = named ? [] : otherClaimSpans(lines, unit.lines, pin, page.bodyLine);\n const replaced = replacementAt(claim, unit.text, page.format);\n // The order of these two matters, and it is the baseline that goes\n // first. Both refusals stop the same re-pin, but they do not carry the\n // same weight. The one the baseline earns says the line no longer\n // holds the claim, which is work left undone, and it exits 1. The\n // uniqueness refusal only reads the line as it stands and exits 0. So\n // a claim that trips both has to keep the stronger signal, or a\n // repeated line would quietly turn a failing run green.\n if (replaced !== undefined && only === undefined) {\n // `plansFor` runs only for a selected entry, so a run with `only`\n // set has named this one. `selected` says which repairs run; the\n // bypass says which entries `--accept` may re-pin, and both hold\n // here.\n out.push({\n kind: \"claim-replaced\",\n result,\n at: unit.lines.start,\n commitSha: replaced.commit,\n ...(replaced.share === undefined ? {} : { wordShare: replaced.share }),\n pin: entry.citation.claim?.integrity ?? \"\",\n would: pin,\n });\n } else if (elsewhere.length > 0) {\n // `--only` takes an id, so an entry without one has no way to say\n // \"accept it anyway\"; the advice is left off rather than made up.\n const id = result.citation.id;\n const anyway = id === undefined ? \"\" : ` Re-run with --only ${id} to accept it anyway.`;\n declined.set(result.origin.index, {\n rule: \"claim-changed\",\n why: `Not re-pinned: the text there also appears at ${spellElsewhere(elsewhere)}, so a pin cannot identify it.${anyway}`,\n });\n } else {\n const plan: Plan = { kind: \"claim-accepted\", result, unit, pin };\n if (replaced !== undefined) plan.replaced = true;\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 (\n recorded === undefined ||\n recorded.start !== body.start ||\n recorded.end !== body.end\n ) {\n plan.lines = lineSpec(body);\n }\n }\n out.push(plan);\n }\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 severity = resolveSeverity(setup.options.severity);\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 const refused: UpdateRewrite[] = [];\n /** `<index>\\0<rule>` of every finding a rewrite settled. */\n const settled = new Set<string>();\n /**\n * Why a repair was declined, by entry index, said with the skipped\n * finding it concerns. The rule is carried so the reason lands on that\n * finding and not on another one about the same entry.\n */\n const declined = new Map<number, Declined>();\n\n // Misplaced markers first: the page is rewritten once, with every movable\n // marker relocated, and every pin below is taken against that page.\n const markers = decideMarkers({ page, report, lines, accept, only });\n const movedPage =\n markers.moves.length === 0\n ? undefined\n : applyMarkerMoves(\n content,\n markers.moves.map(({ misplaced }) => ({\n from: misplaced.line,\n place: misplaced.place,\n })),\n (line) => markerIndent(content, line, format, page.bodyLine),\n );\n let after = movedPage?.content ?? content;\n const afterLines = movedPage === undefined ? lines : splitLines(after);\n const movedIndexes = new Set(markers.moves.map(({ entry }) => entry.origin.index));\n const lineNow = (line: number): number => movedPage?.line(line) ?? line;\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 // `--only` selects the repairs to make. It does not select the shift a\n // marker move forces on the entries below it, which is planned for\n // every entry further down.\n const selected =\n only === undefined ||\n (result.citation.id !== undefined && only.has(result.citation.id));\n const entry = page.citations.find((c) => c.origin.index === result.origin.index);\n const plans: Plan[] = [];\n\n const move = selected\n ? markers.moves.find((m) => m.entry.origin.index === result.origin.index)\n : undefined;\n if (move !== undefined) {\n plans.push({\n kind: \"marker-moved\",\n result,\n from: move.misplaced.line,\n to: lineNow(move.misplaced.line),\n });\n }\n // The pin a marker anchors is taken against the page the moves left, so\n // the next check reads it as current however the run split.\n const marker = entry?.marker;\n const recorded = entry?.citation.claim?.integrity;\n if (\n selected &&\n result.anchor === \"marker\" &&\n marker !== undefined &&\n recorded !== undefined &&\n result.claim !== null\n ) {\n const quote = entry?.citation.quote === true;\n const now = anchoredNow(after, format, afterLines, lineNow(marker.line), quote);\n const status = result.claim.status;\n if (now !== undefined && now.pin !== recorded) {\n // A `current` claim already covers the unit the marker belongs to,\n // so only a move that split its run can leave it needing a pin.\n const unitText = afterLines.slice(now.span.start - 1, now.span.end);\n if (status === \"moved\" || (status === \"current\" && move !== undefined)) {\n plans.push({\n kind: \"claim-reanchored\",\n result,\n pin: now.pin,\n held: result.claim.fileLines ?? \"\",\n now: spellLines(now.span),\n });\n } else if (status === \"reanchored\") {\n // The marker travels with its text, so nothing moves but the pin.\n const held: Plan = {\n kind: \"claim-words-held\",\n result,\n pin: now.pin,\n at: now.span.start,\n fromLines: result.claim.fileLines ?? \"\",\n toLines: spellLines(now.span),\n };\n if (result.claim.commitSha !== undefined) held.commitSha = result.claim.commitSha;\n plans.push(held);\n } else if (status === \"changed\" && accept) {\n const kind = quote ? \"block\" : \"paragraph\";\n // A marker pins everything it anchors, so the range limit applies\n // to that, exactly as it does to a claim-lines re-pin.\n const wide = tooWide(now.span);\n if (wide !== undefined) {\n declined.set(result.origin.index, {\n rule: \"claim-changed\",\n why: `Not re-pinned: the ${kind} ${wide}.`,\n });\n } else {\n const replaced = replacementAt(result.claim, unitText, format);\n // `--only` naming the entry is the judgement the guard demands,\n // so a named accept stands and says `replaced` in the log.\n plans.push(\n replaced === undefined || only !== undefined\n ? {\n kind: \"claim-accepted\",\n result,\n pin: now.pin,\n markerLine: lineNow(marker.line),\n unit: { lines: now.span, kind, text: unitText },\n ...(replaced === undefined ? {} : { replaced: true as const }),\n }\n : {\n kind: \"claim-replaced\",\n result,\n at: now.span.start,\n commitSha: replaced.commit,\n ...(replaced.share === undefined ? {} : { wordShare: replaced.share }),\n pin: recorded,\n would: now.pin,\n },\n );\n }\n }\n }\n }\n\n if (selected) {\n plans.push(...(await plansFor(result, entry, page, lines, lineNow, declined)));\n }\n\n // A claim-lines entry the moves pushed along keeps its pinned text, so\n // its lines are rewritten in the same write. This one runs outside\n // `--only`: the page has already moved under the entry, so leaving its\n // lines behind would need a second run to put right.\n const spec = entry?.citation.claim?.lines;\n // A claim whose text moved is repaired by `claim-moved`, which finds\n // where the text went. Shifting its lines by the marker's delta would\n // point them somewhere else again, so the shift leaves it alone.\n const wentElsewhere = result.claim?.status === \"moved\";\n if (\n movedPage !== undefined &&\n spec !== undefined &&\n !wentElsewhere &&\n !plans.some((p) => p.kind === \"claim-moved\")\n ) {\n const at = parseLines(spec);\n const file = at === undefined ? undefined : toFileLines(at, page.bodyLine);\n const to =\n file === undefined ? undefined : { start: lineNow(file.start), end: lineNow(file.end) };\n if (\n file !== undefined &&\n to !== undefined &&\n to.end - to.start === file.end - file.start &&\n (to.start !== file.start || to.end !== file.end)\n ) {\n plans.push({\n kind: \"claim-shifted\",\n result,\n lines: lineSpec(toBodyLines(to, page.bodyLine)),\n from: spellLines(file),\n to: spellLines(to),\n });\n }\n }\n\n for (const plan of plans) {\n // A refused claim writes nothing, in either channel; its row is the\n // whole of it, and it keeps the finding from being reported twice.\n if (plan.kind === \"claim-replaced\") {\n refused.push(rewriteOf(plan));\n settled.add(`${String(result.origin.index)}\\0${settles(plan)}`);\n continue;\n }\n if (plan.kind === \"marker-moved\") {\n // The page already carries the move.\n } else if (result.origin.kind === \"manifest\") {\n // The manifest's entry list is shorter than the report's index, so\n // there is nothing to splice. Said rather than dropped: a silent\n // skip would report the check's own message and no reason.\n const held = entries?.[result.origin.index];\n if (held === undefined) {\n declined.set(result.origin.index, {\n rule: settles(plan),\n why: `Not rewritten: ${owner?.file ?? \"the manifest\"} has no entry at index ${String(result.origin.index)}.`,\n });\n continue;\n }\n if (!applyToEntry(held, 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 // A marker that moved settles its finding even where the entry is out of\n // the loop's reach, and a stacked run that split keeps the rest reported.\n for (const index of movedIndexes) settled.add(`${String(index)}\\0marker-misplaced`);\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 // A marker that stays says so in place of the check's wording, at the\n // severity of the rule that kept it there. An accept this run declined\n // says why beside the finding that kept its work undone.\n const stayAt = new Map(markers.stays.map((stay) => [stay.line, stay]));\n const skipped = report.findings\n .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 .map((finding) => {\n if (finding.rule === \"marker-misplaced\") {\n const stay = stayAt.get(finding.line ?? -1);\n if (stay === undefined) return finding;\n const level = severity[stay.rule];\n return {\n ...finding,\n message: stay.message,\n ...(level === \"off\" ? {} : { severity: level }),\n };\n }\n const turned = finding.index === undefined ? undefined : declined.get(finding.index);\n const why = turned?.rule === finding.rule ? turned.why : undefined;\n return why === undefined ? finding : { ...finding, message: `${finding.message} ${why}` };\n });\n const diff = after === content ? \"\" : unifiedDiff(label, content, after);\n const written = after !== content && path !== undefined && opts.dryRun !== true;\n if (written) {\n try {\n await writeFileAtomic(path, after);\n } catch (error) {\n throw await writes.restore(label, error);\n }\n writes.record(path, label, content);\n }\n const out: UpdatePage = { file: label, rewritten, refused, 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 write = opts.dryRun !== true;\n const rewrittenManifests: ManifestChange[] = [];\n const record = (changed: { file: string; diff: string }): void => {\n rewrittenManifests.push({ file: changed.file, diff: changed.diff, written: write });\n };\n if (write) {\n await manifests.commit({\n // A manifest joins the run's written files the moment it lands, so a\n // later manifest's failure puts this one back with the pages. Without\n // it the tree would keep pins no page content matches.\n after: (changed) => {\n writes.record(changed.path, changed.file, changed.before);\n record(changed);\n },\n onError: async (changed, error) => {\n throw await writes.restore(changed.file, error);\n },\n });\n } else for (const changed of manifests.changed()) record(changed);\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 + citationsIn(page.rewritten), 0);\n // A refused claim counts as skipped: `--accept` was asked for it and the\n // run left it undone, which is what the summary's second number means.\n const skipped = pages.reduce((n, page) => n + page.skipped.length + page.refused.length, 0);\n const undone = pages.some(\n (page) =>\n page.refused.length > 0 || page.skipped.some((finding) => finding.severity === \"error\"),\n );\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, spellAt } from \"../core/spell.js\";\nimport type {\n CheckRun,\n CitationFinding,\n CitationResult,\n PageCitationReport,\n Removal,\n RemoveRun,\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 /** `remove --dry-run`: the footer says what the run would have removed. */\n dryRun?: 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/**\n * The claim end column: where it is, in file lines, and how it reads. A marker\n * says where it is and, when it is misplaced, where it belongs. Its claim\n * status reads bare: the marker's own line is what a reader acts on.\n */\nfunction claimColumn(result: CitationResult): string {\n const { claim, marker } = result;\n const anchoredByMarker = result.anchor === \"marker\" && result.markerLine !== undefined;\n const moves = marker?.misplaced === undefined ? \"\" : ` -> :${String(marker.misplaced.to)}`;\n const where = anchoredByMarker\n ? `marker :${String(result.markerLine ?? 0)}${moves}`\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 = anchoredByMarker ? \"moved\" : `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 case \"reanchored\": {\n const since = claim.commitSha === undefined ? \"\" : ` since ${shortCommit(claim.commitSha)}`;\n const to = claim.newFileLines === undefined ? \"\" : ` -> :${claim.newFileLines}`;\n status = `reanchored${since}${to}`;\n break;\n }\n case \"changed\":\n status = changedText(claim);\n break;\n default:\n status = claim.status;\n }\n return where === \"\" ? status : `${where} ${status}`;\n}\n\n/** How a changed claim's column says since when, as the source column does. */\nfunction changedText(claim: NonNullable<CitationResult[\"claim\"]>): string {\n if (claim.historyAvailable === false) return \"changed (history unavailable; fetch-depth: 0)\";\n if (claim.commitSha === undefined) return \"changed\";\n const since = claim.commitsSince ?? [];\n const count = since.length === 0 ? \"uncommitted\" : plural(since.length, \"commit\");\n return `changed since ${shortCommit(claim.commitSha)}, ${count}`;\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/**\n * What `--show-diff` adds under a claim row: the page's commit subjects since\n * the baseline and the claim's own diff. With no baseline there is no diff to\n * print, so a changed claim shows the lines it covers now instead.\n */\nfunction claimLines(result: CitationResult, dim: (s: string) => string): string[] {\n const claim = result.claim;\n const diff = claim?.diff;\n if (claim === null || diff === undefined || diff === \"\") {\n return capped(claim?.text ?? [], dim);\n }\n const out: string[] = [];\n for (const subject of claim.commitsSince ?? []) out.push(dim(` ${subject}`));\n return [...out, ...capped(diff.split(/\\r?\\n/), dim)];\n}\n\n/** Lines under a row, dim and capped, with a count of the ones left out. */\nfunction capped(lines: readonly string[], dim: (s: string) => string): string[] {\n const shown = lines.slice(0, DIFF_LINE_CAP);\n const out = shown.map((line) => 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/**\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\n // it. A misplaced marker is part of the row too: it reads there as\n // `marker :<line> -> :<place>`.\n const endRules = new Set([\"claim-\", \"source-\", \"marker-misplaced\"]);\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\" || f.rule === \"claim-reanchored\")) {\n under.push(...claimLines(result, c.dim));\n }\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/** `line 9`, or `lines 9-12`, from a line spec. */\nfunction spellAtSpec(spec: string): string {\n const span = spanOf(spec);\n return span === undefined ? `lines ${spec}` : spellAt(span);\n}\n\n/** A line spec as numbers, or undefined when it does not read as one. */\nfunction spanOf(spec: string): { start: number; end: number } | undefined {\n const [first, second] = spec.split(\"-\");\n const start = Number(first);\n const end = second === undefined ? start : Number(second);\n if (!Number.isFinite(start) || !Number.isFinite(end)) return undefined;\n return { start, end };\n}\n\n/**\n * What a re-pin over the unit newly covers, so the widening is in the log as\n * well as in the diff. A span that only lost marker lines gains nothing, and\n * says that instead.\n */\nfunction widening(held: string, now: string): string {\n const was = spanOf(held);\n const is = spanOf(now);\n if (was === undefined || is === undefined) return \"\";\n const parts: string[] = [];\n if (is.start < was.start) {\n parts.push(spellAt({ start: is.start, end: Math.min(was.start - 1, is.end) }));\n }\n if (is.end > was.end) {\n parts.push(spellAt({ start: Math.max(was.end + 1, is.start), end: is.end }));\n }\n if (parts.length === 0) return \", which held a marker line\";\n return `, ${parts.join(\" and \")} newly pinned`;\n}\n\n/** Whether a re-pin covered a span other than the stored one. */\nfunction widened(rewrite: UpdateRewrite): boolean {\n return (\n rewrite.fromLines !== undefined &&\n rewrite.toLines !== undefined &&\n rewrite.fromLines !== rewrite.toLines\n );\n}\n\n/** `lines 9 -> 9-12` for a re-pin that moved, `at line 9` for one that did not. */\nfunction movedSpan(rewrite: UpdateRewrite): string {\n if (widened(rewrite)) return `lines ${rewrite.fromLines ?? \"\"} -> ${rewrite.toLines ?? \"\"}`;\n const at = rewrite.toLines ?? rewrite.fromLines ?? String(rewrite.at ?? 0);\n return `at ${spellAtSpec(at)}`;\n}\n\n/**\n * What one claim `--accept` refused to re-pin says, and what to do about it.\n * The line names which test refused it: the share is printed when overlap is\n * what fired, and the text is called different when no sentence was shared.\n */\nexport function refusalLine(rewrite: UpdateRewrite): string {\n const at = shortCommit(rewrite.commitSha ?? \"\");\n const where = `claim at ${spellAtSpec(String(rewrite.at ?? 0))} skipped:`;\n if (rewrite.wordShare !== undefined) {\n const share = Math.round(rewrite.wordShare * 100);\n return `${where} that line now holds text sharing ${String(share)}% of the claim's words at ${at}. Re-add it with cite add.`;\n }\n return `${where} that line now holds different text than the claim at ${at}. Re-add it with cite add.`;\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.end === \"marker\") {\n return `marker line ${rewrite.from} -> ${rewrite.to} (misplaced)`;\n }\n if (rewrite.reason === \"shifted\") {\n return `claim ${word} ${rewrite.from} -> ${rewrite.to} (shifted by a marker)`;\n }\n // The words held while the anchor moved (0053). A claim-lines entry moved\n // onto its new run, so the row names both spans.\n if (rewrite.reason === \"re-anchored\" && rewrite.status === \"reanchored\") {\n const since = rewrite.commitSha === undefined ? \"\" : ` since ${shortCommit(rewrite.commitSha)}`;\n return `claim ${movedSpan(rewrite)} re-pinned (reanchored; words unchanged${since})`;\n }\n if (rewrite.reason === \"re-anchored\") {\n const held = rewrite.lines ?? \"\";\n const now = rewrite.newLines ?? \"\";\n return `claim re-pinned over ${spellAtSpec(now)} (moved; was ${spellAtSpec(held)}${widening(held, now)})`;\n }\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 re-pin over a unit wider than the stored lines names both spans, so\n // the widening is in the log as well as in the diff.\n if (widened(rewrite)) {\n return `claim ${movedSpan(rewrite)} re-pinned (${status}; now \"${rewrite.text ?? \"\"}\")`;\n }\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 // A claim `--accept` refused reads beside the rewrites, because it is the\n // one row `--accept` was asked for and did not write.\n for (const rewrite of page.refused) {\n const label = rewrite.id ?? `#${String(rewrite.index)}`;\n lines.push(`${page.file}: ${c.cyan(label)} ${refusalLine(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/** `line 30`, or `lines 30 and 42` for several, as a sentence reads them. */\nfunction spellLineList(at: readonly number[], noun: string): string {\n // No lines is the noun alone. Every caller has at least one, and a\n // sentence reading \"lines and \" would be the only sign that one did not.\n if (at.length === 0) return noun;\n const spelled = at.map((line) => String(line));\n if (spelled.length === 1) return `${noun} ${spelled[0] ?? \"\"}`;\n const last = spelled[spelled.length - 1] ?? \"\";\n return `${noun}s ${spelled.slice(0, -1).join(\", \")} and ${last}`;\n}\n\n/** What one removal says it did: the entry, where it was kept, and its markers. */\nexport function removalLine(removal: Removal, c: ReturnType<typeof palette>): string {\n const markers = spellLineList(removal.markerLines, \"line\");\n if (removal.origin === undefined) {\n // A marker naming no entry: there is nothing else to report about it.\n const named = removal.markerLines.length === 1 ? \"the marker\" : \"the markers\";\n return `removed ${named} ${c.cyan(removal.id ?? \"\")} at ${markers}, which named no entry`;\n }\n const name = removal.id ?? `/citations/${String(removal.index ?? 0)}`;\n const where =\n removal.origin.kind === \"manifest\"\n ? `${removal.origin.file}${removal.origin.line === undefined ? \"\" : `:${String(removal.origin.line)}`}`\n : \"frontmatter\";\n const also =\n removal.markerLines.length === 0\n ? \"\"\n : `, and ${removal.markerLines.length === 1 ? \"its marker\" : \"its markers\"} at ${markers}`;\n return `removed ${c.cyan(name)} from ${where}${also}`;\n}\n\nexport function renderRemovePretty(run: RemoveRun, 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.removed.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 removal of page.removed) {\n lines.push(`${page.file}: ${removalLine(removal, c)}`);\n }\n }\n // The manifests, after the pages, as `update` prints them.\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 verb = opts.dryRun === true ? \"would be removed\" : \"removed\";\n lines.push(c.green(`${plural(run.removed, \"citation\")} ${verb} from ${plural(files, \"file\")}`));\n return lines.join(\"\\n\");\n}\n","/**\n * JSON output. `{ summary, pages }` for check; the run itself for update and\n * remove.\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 MarkerEnd,\n OriginKind,\n PageCitationReport,\n RemoveRun,\n UpdateRewrite,\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 /** The baseline the claim was read against: the page's own history says it. */\n commitSha?: string;\n historyAvailable?: boolean;\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 /** The marker that names the entry: its line, and its misplacement when it has one. */\n marker?: MarkerEnd;\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 if (result.claim.commitSha !== undefined) claim.commitSha = result.claim.commitSha;\n if (result.claim.historyAvailable !== undefined) {\n claim.historyAvailable = result.claim.historyAvailable;\n }\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 ...(result.marker === undefined ? {} : { marker: result.marker }),\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 renderRemoveJson(run: RemoveRun): string {\n // The whole run, with nothing stripped: `RemoveRun` carries no\n // pretty-only field, as `UpdateRewrite.markerLine` is below. A field added\n // to it for the terminal alone is stripped here, as that one is.\n return JSON.stringify(run, 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 strip = (rows: readonly UpdateRewrite[]): Omit<UpdateRewrite, \"markerLine\">[] =>\n rows.map(({ markerLine: _pretty, ...rewrite }) => rewrite);\n const pages = run.pages.map((page) => ({\n ...page,\n rewritten: strip(page.rewritten),\n refused: strip(page.refused),\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. Exported so\n * a test asserting the composed messages reads this set rather than a copy.\n */\nexport const 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 * SARIF and JUnit carry the same message.\n */\nexport function findingMessage(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(findingMessage(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","extname","fenceFor","at","line","extname","run","at","pre43","at","named","run","resolve","at","at","pinOf","held","now","w1","sliceLines","at","at","sep","CITATIONS_KEY","sep","at","run","readFile","isRecord","i","j","CONTEXT","readFile","CITATIONS_KEY","at","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","at","resolve","run","relative","sidecars","markerAt","index","named","resolve","run","index","markers","named","resolve","resolve","apply","isRecord","named","finding","at","run","rewritten","unitText","skipped","resolve","sliceLines","plural","finding","at","run","citesEncrypted","baselined","named","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"]}