@hawkeyexl/manni 1.1.0 → 2.0.0

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.
package/dist/index.d.ts CHANGED
@@ -16,6 +16,23 @@ declare class ToolError extends Error {
16
16
  constructor(message: string);
17
17
  }
18
18
 
19
+ /**
20
+ * The one severity scale every manni tool speaks. Least to most severe.
21
+ *
22
+ * Three values, chosen to match the sinks every tool writes to and the
23
+ * linters that sit beside it. GitHub annotations are `error`, `warning` and
24
+ * `notice`; so are ESLint's and Vale's levels, and pa11y's. A flag or config
25
+ * key that two domains both have carries the same name and the same values,
26
+ * and this is where the values for `severity` are defined once.
27
+ *
28
+ * A domain whose source speaks another scale maps onto this one and keeps
29
+ * the source's value in a field of its own, so nothing is lost for lookup.
30
+ * a11y is the first case: axe reports four impacts, the analyzer folds them
31
+ * onto these three, and each finding still carries axe's word as `impact`.
32
+ */
33
+ declare const SEVERITIES: readonly ["notice", "warning", "error"];
34
+ type Severity = (typeof SEVERITIES)[number];
35
+
19
36
  /**
20
37
  * Shared types for docmeta.
21
38
  *
@@ -185,7 +202,33 @@ interface FieldError {
185
202
  * and its SARIF location, and this names where the *value* was written.
186
203
  */
187
204
  file?: string;
205
+ /**
206
+ * How much the finding weighs, on the family scale (`src/shared/severity.ts`).
207
+ *
208
+ * The invariant, stated here and nowhere else: a result's `ok` is true iff
209
+ * no entry of its `errors` has severity `error`, and an **absent** severity
210
+ * means `error`. So every producer that never sets this field is unchanged,
211
+ * and a `warning` or `notice` is a finding that is reported, baselined and
212
+ * fingerprinted like any other but never fails a file, and so never moves
213
+ * the exit code. Nothing in meta's own validation sets one today; a sibling
214
+ * tool's findings ride these types and reporters, and some of theirs are
215
+ * advisory.
216
+ *
217
+ * Deliberately not part of the fingerprint: a rule that is downgraded from
218
+ * error to warning is the same finding, and a baseline that forgot it on
219
+ * the way down would re-open every instance.
220
+ *
221
+ * `isErrorSeverity` is the one reading of this field; derive `ok` through
222
+ * it rather than restating the absent-means-error rule.
223
+ */
224
+ severity?: Severity;
188
225
  }
226
+ /**
227
+ * Whether a finding counts against `ok`: true for `error` and for an absent
228
+ * severity, false for `warning` and `notice`. See `FieldError.severity` for
229
+ * the invariant.
230
+ */
231
+ declare function isErrorSeverity(e: Pick<FieldError, "severity">): boolean;
189
232
  /** Validation outcome for a single file. */
190
233
  interface ValidationResult {
191
234
  /** Absolute or cwd-relative path of the file. */
@@ -229,8 +272,22 @@ interface RunSummary {
229
272
  files: number;
230
273
  passed: number;
231
274
  failed: number;
232
- /** Violations reported. Baselined ones are excluded — see `baseline`. */
275
+ /**
276
+ * Error-severity findings reported. Baselined ones are excluded — see
277
+ * `baseline` — and so are warnings, which have their own count.
278
+ */
233
279
  errors: number;
280
+ /**
281
+ * Warning-severity findings reported. Omitted when there are none, which is
282
+ * every run of meta's own validation today, so the JSON summary is unchanged
283
+ * for them. A warning never fails a file or the run.
284
+ */
285
+ warnings?: number;
286
+ /**
287
+ * Notice-severity findings reported. Omitted when there are none, as
288
+ * `warnings` is. A notice never fails a file or the run.
289
+ */
290
+ notices?: number;
234
291
  /**
235
292
  * Candidate documents `.gitignore` removed from the walk. Omitted when it
236
293
  * removed none. Reported because silent removal is what makes the filter
@@ -301,6 +358,50 @@ declare function selectCollections(collections: readonly CollectionConfig[], nam
301
358
  */
302
359
  declare function isMember(collection: CollectionConfig, relPath: string): boolean;
303
360
 
361
+ interface ConfigFile {
362
+ /** Absolute path to the file. */
363
+ path: string;
364
+ /** Directory holding it; relative paths in the config resolve from here. */
365
+ dir: string;
366
+ /**
367
+ * The file as the user would name it: relative to `cwd`, posix separators,
368
+ * or the spelling they typed for an explicit path. For error messages.
369
+ */
370
+ source: string;
371
+ /** The file's text, for a tool that rewrites the file in place. */
372
+ text: string;
373
+ /**
374
+ * The tool's slice: the value under `section:` when `wrapped`, otherwise
375
+ * the whole document. `null` for an empty file or an empty section; the
376
+ * tool decides what empty means.
377
+ */
378
+ value: unknown;
379
+ /** Whether `value` came from under `section:`. */
380
+ wrapped: boolean;
381
+ /** How the file was found. Explicit paths are never warned about. */
382
+ kind: "manni" | "moose" | "legacy" | "explicit";
383
+ /**
384
+ * The document's top-level `collections:` (proposal 0041), parsed once here
385
+ * because every tool reads the same declaration. `[]` when the key is
386
+ * absent, and always `[]` for a `legacy` file: a per-tool file's whole
387
+ * document *is* the tool's section, so it carries no family-wide keys.
388
+ */
389
+ collections: CollectionConfig[];
390
+ /**
391
+ * The document's top-level `encryptionKey:` (proposal 0045), validated
392
+ * here. Absent when the key is, and always absent for a `legacy` file, for
393
+ * the same reason as `collections`. `MANNI_ENCRYPTION_KEY` wins over it;
394
+ * read it through `resolveEncryptionKey`, not directly.
395
+ */
396
+ encryptionKey?: string;
397
+ /**
398
+ * The document's top-level `encryptionKeyPrevious:`, validated here as
399
+ * `encryptionKey` is. Present only while a rotation is unfinished, and read
400
+ * only by `manni key rotate`, which finishes it.
401
+ */
402
+ encryptionKeyPrevious?: string;
403
+ }
404
+
304
405
  /**
305
406
  * The derived metadata channel: values computed from git history, CODEOWNERS
306
407
  * and the review record on GitHub or GitLab rather than written by hand.
@@ -355,7 +456,7 @@ interface DerivedRecord {
355
456
  fields: Record<DerivableField, DerivedValue | null>;
356
457
  }
357
458
  /** Whether a source can answer at all; `reason` names the fix when not. */
358
- interface SourceStatus {
459
+ interface SourceStatus$1 {
359
460
  available: boolean;
360
461
  reason?: string;
361
462
  }
@@ -389,7 +490,7 @@ interface MergedChange {
389
490
  interface ReviewClient {
390
491
  detect(): Promise<RemoteIdentity | null>;
391
492
  /** Binary on PATH and authenticated for the host; `reason` names the fix. */
392
- status(): Promise<SourceStatus>;
493
+ status(): Promise<SourceStatus$1>;
393
494
  /** The merged PR/MR that contains the commit, or null (open, none, or unknown). */
394
495
  mergedChangeFor(sha: string): Promise<MergedChange | null>;
395
496
  }
@@ -716,6 +817,18 @@ interface LoadedConfig {
716
817
  * order. `[]` for a legacy per-tool file, which carries no family-wide keys.
717
818
  */
718
819
  collections: CollectionConfig[];
820
+ /**
821
+ * The family file's top-level `encryptionKey:` (proposal 0045), when it has
822
+ * one. `MANNI_ENCRYPTION_KEY` wins over it: read the run's key through
823
+ * `resolveEncryptionKey`, never from here directly.
824
+ */
825
+ encryptionKey?: string;
826
+ /**
827
+ * The file itself, as family discovery found it. What a write that needs a
828
+ * key hands `ensureEncryptionKey`, so the key lands in the file that
829
+ * governs the run.
830
+ */
831
+ configFile?: ConfigFile;
719
832
  }
720
833
 
721
834
  /**
@@ -857,6 +970,12 @@ interface RunConfig {
857
970
  * operator chose part of the corpus.
858
971
  */
859
972
  fromCollections: boolean;
973
+ /**
974
+ * The governing config file, when one governs the run: what the run's
975
+ * encryption key resolves from (proposal 0045), with `MANNI_ENCRYPTION_KEY`
976
+ * winning over it, and where a write that needs a key writes one.
977
+ */
978
+ configFile?: ConfigFile;
860
979
  }
861
980
  /**
862
981
  * Settle the three things every command core needs from config before it can
@@ -924,6 +1043,12 @@ interface ValidateOptions {
924
1043
  * set is the config-resolved corpus (proposal 0026).
925
1044
  */
926
1045
  checks?: boolean;
1046
+ /**
1047
+ * The environment `MANNI_ENCRYPTION_KEY` is read from (proposal 0045).
1048
+ * Defaults to `process.env`; tests pass their own so a developer's key is
1049
+ * never read.
1050
+ */
1051
+ env?: NodeJS.ProcessEnv;
927
1052
  /**
928
1053
  * `--no-derive` (false): skip comparing each managed field (`derive.fields`
929
1054
  * in the config, proposal 0040) with what the evidence says. Absent leaves
@@ -1059,6 +1184,9 @@ interface GetFileResult {
1059
1184
  }
1060
1185
  declare function runGet(opts: GetOptions): Promise<GetFileResult[]>;
1061
1186
 
1187
+ /** Ask a yes/no question; `true` only for a yes. */
1188
+ type Confirm = (question: string) => Promise<boolean>;
1189
+
1062
1190
  interface QueryOptions {
1063
1191
  /**
1064
1192
  * One SQL statement. The table is `docs`; see the system columns below.
@@ -1141,6 +1269,19 @@ interface QueryOptions {
1141
1269
  * applied — a flag that would silently mean nothing must refuse.
1142
1270
  */
1143
1271
  schemas?: string[];
1272
+ /**
1273
+ * How to ask for a new encryption key when an `UPDATE` or `INSERT` writes
1274
+ * a column its schema marks `x-manni-encrypt` and no key is available
1275
+ * (proposal 0045). The CLI passes `terminalConfirm()`, which is
1276
+ * `undefined` off a terminal; absent, such a write refuses (exit 2). A dry
1277
+ * run never asks: it writes nothing.
1278
+ */
1279
+ confirm?: Confirm;
1280
+ /**
1281
+ * The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
1282
+ * `process.env`; tests pass their own.
1283
+ */
1284
+ env?: NodeJS.ProcessEnv;
1144
1285
  /** The clock an uncommitted body change is dated by. Test seam; default `new Date()`. */
1145
1286
  now?: () => Date;
1146
1287
  }
@@ -1444,10 +1585,19 @@ interface FilledField {
1444
1585
  required: boolean;
1445
1586
  confidence: number;
1446
1587
  reasoning: string;
1447
- /** Absent when the field was skipped. */
1588
+ /**
1589
+ * Absent when the field was skipped. `(encrypted)` when the field's schema
1590
+ * marks it `x-manni-encrypt`: the page holds the ciphertext, and no report
1591
+ * prints either that or the plaintext (proposal 0045).
1592
+ */
1448
1593
  value?: unknown;
1449
1594
  written: boolean;
1450
1595
  skipReason?: SkipReason;
1596
+ /**
1597
+ * The value was written encrypted, because the field's schema marks it
1598
+ * `x-manni-encrypt`. Absent otherwise.
1599
+ */
1600
+ encrypted?: boolean;
1451
1601
  }
1452
1602
  interface FillFileResult {
1453
1603
  file: string;
@@ -1544,6 +1694,19 @@ interface FillOptions {
1544
1694
  includeContent?: boolean;
1545
1695
  /** Test seam: bypasses `makeProvider`, so no API key is needed. */
1546
1696
  inferenceProvider?: InferenceProvider;
1697
+ /**
1698
+ * How to ask for a new encryption key when a field its schema marks
1699
+ * `x-manni-encrypt` is about to be written and no key is available
1700
+ * (proposal 0045). The CLI passes `terminalConfirm()`, which is `undefined`
1701
+ * off a terminal; absent, the run refuses (exit 2) before the first model
1702
+ * request.
1703
+ */
1704
+ confirm?: Confirm;
1705
+ /**
1706
+ * The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
1707
+ * `process.env`; tests pass their own.
1708
+ */
1709
+ env?: NodeJS.ProcessEnv;
1547
1710
  }
1548
1711
 
1549
1712
  declare function runFill(opts: FillOptions): Promise<FillRun>;
@@ -1589,6 +1752,19 @@ interface DeriveOptions {
1589
1752
  now?: () => Date;
1590
1753
  /** The review client, for every repository in the run. Test seam; default `gh` / `glab`. */
1591
1754
  reviews?: ReviewClient;
1755
+ /**
1756
+ * How to ask for a new encryption key when a field its schema marks
1757
+ * `x-manni-encrypt` is about to be stamped and no key is available
1758
+ * (proposal 0045). The CLI passes `terminalConfirm()`, which is `undefined`
1759
+ * off a terminal; absent, such a stamp refuses (exit 2). A dry run never
1760
+ * asks: it writes nothing.
1761
+ */
1762
+ confirm?: Confirm;
1763
+ /**
1764
+ * The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
1765
+ * `process.env`; tests pass their own.
1766
+ */
1767
+ env?: NodeJS.ProcessEnv;
1592
1768
  }
1593
1769
  interface DeriveFileResult {
1594
1770
  file: string;
@@ -1627,7 +1803,7 @@ interface DeriveRun {
1627
1803
  dryRun: boolean;
1628
1804
  check: boolean;
1629
1805
  /** One status per source the run consulted; a source nobody asked for is absent. */
1630
- sources: Partial<Record<DeriveSource, SourceStatus>>;
1806
+ sources: Partial<Record<DeriveSource, SourceStatus$1>>;
1631
1807
  /** Where the run stood, for the SARIF reporter under `check`. See `ValidateRun.frame`. */
1632
1808
  frame: FingerprintContext;
1633
1809
  }
@@ -1662,6 +1838,14 @@ interface ExternalMetadataValue {
1662
1838
  file: string;
1663
1839
  /** 1-based line of the key in the manifest, when known. */
1664
1840
  line?: number;
1841
+ /**
1842
+ * 1-based manifest line of every node inside `value`, keyed by the JSON
1843
+ * Pointer relative to `value` (`/2/source/file`). A mapping member sits on
1844
+ * its key's line, and a list item on the line its node starts. Present only
1845
+ * when `value` is a mapping or a list with members; `line` answers for the
1846
+ * value itself.
1847
+ */
1848
+ lines?: ReadonlyMap<string, number>;
1665
1849
  }
1666
1850
  /** One manifest entry, for the orphan checks. */
1667
1851
  interface ExternalMetadataEntry {
@@ -1728,7 +1912,14 @@ interface ExternalMetadataCollision {
1728
1912
  /** A field-joined entry a document matched (0039). */
1729
1913
  interface ExternalMetadataJoin {
1730
1914
  field: string;
1915
+ /** The value matched: the field's plaintext, decrypted first when the page holds it encrypted. */
1731
1916
  value: string;
1917
+ /**
1918
+ * The field as the page holds it, when that differs from `value`: the
1919
+ * ciphertext of an encrypted join field (proposal 0045). A finding about
1920
+ * the join names this, never the plaintext.
1921
+ */
1922
+ pageValue?: string;
1732
1923
  /** The manifest, as the run reports it. */
1733
1924
  file: string;
1734
1925
  /** The collection that manifest belongs to (proposal 0041). */
@@ -1751,6 +1942,11 @@ interface MergedMetadata {
1751
1942
  * manifest supplied — a bare key or its `/key` pointer, and anything
1752
1943
  * beneath it — and `undefined` for everything the document owns, which is
1753
1944
  * what `lineFor` is for.
1945
+ *
1946
+ * The line is the deepest manifest node the pointer reaches, so
1947
+ * `/citations/2` is the third item's line and `/citations/2/source/file`
1948
+ * that member's. A pointer past what the manifest holds falls back to the
1949
+ * nearest ancestor that exists, and at worst to the owned key's line.
1754
1950
  */
1755
1951
  locate: (pointer: string) => SourceLocation | undefined;
1756
1952
  }
@@ -1783,8 +1979,15 @@ declare function loadExternalMetadata(collections: readonly CollectionConfig[],
1783
1979
  * `present`, `format` and the document's own positions are untouched. A
1784
1980
  * manifest key is not in the document, so `lineFor` keeps answering
1785
1981
  * `undefined` for it, and `locate` answers instead.
1982
+ *
1983
+ * A join field the page holds encrypted (proposal 0045) is decrypted with
1984
+ * `options.encryptionKey` before it is matched. With no key, and a manifest
1985
+ * of this document's collections joining on that field, the run cannot match
1986
+ * and refuses. A ciphertext that does not decrypt matches nothing.
1786
1987
  */
1787
- declare function mergeExternalMetadata(label: string, extracted: ExtractedMetadata, index: ExternalMetadataIndex | null, memberOf: readonly string[], base: string): MergedMetadata;
1988
+ declare function mergeExternalMetadata(label: string, extracted: ExtractedMetadata, index: ExternalMetadataIndex | null, memberOf: readonly string[], base: string, options?: {
1989
+ encryptionKey?: () => string | undefined;
1990
+ }): MergedMetadata;
1788
1991
  /** The `/key` pointer for an external-metadata finding, RFC 6901 escaped. */
1789
1992
  declare function externalMetadataPointer(key: string): string;
1790
1993
  /**
@@ -1841,6 +2044,19 @@ declare class Validator {
1841
2044
  */
1842
2045
  private compile;
1843
2046
  private compileUncached;
2047
+ /**
2048
+ * The instance pointers of `data` that carry `x-manni-encrypt: true` under
2049
+ * any schema in `refs`, in the order the validator evaluated them.
2050
+ *
2051
+ * A first pass with the recording keyword, so a mark counts exactly where
2052
+ * validation would evaluate it. Only present values are marked: Ajv applies
2053
+ * a property's subschema to a property that exists. A branch Ajv does not
2054
+ * take (`then` behind a failing `if`, an `anyOf` branch after a passing
2055
+ * one) contributes nothing; a branch it takes contributes its marks
2056
+ * whether or not the branch passes, because a ciphertext routinely fails
2057
+ * the rest of its own subschema until it is decrypted.
2058
+ */
2059
+ markedPointers(data: Record<string, unknown>, refs: string[]): Promise<Set<string>>;
1844
2060
  /**
1845
2061
  * Validate `data` against every schema in `refs`. Returns all violations,
1846
2062
  * each tagged with the schema that produced it and a source line via
@@ -1860,6 +2076,45 @@ declare class Validator {
1860
2076
  locate?: (pointer: string) => SourceLocation | undefined): Promise<FieldError[]>;
1861
2077
  }
1862
2078
 
2079
+ /** One value re-encrypted: where, and the ciphertext before and after. */
2080
+ interface ReencryptedValue {
2081
+ pointer: string;
2082
+ from: string;
2083
+ to: string;
2084
+ }
2085
+ interface ReencryptMetadataResult {
2086
+ /** The page with every rewritten value; the input itself when nothing was. */
2087
+ content: string;
2088
+ rewritten: ReencryptedValue[];
2089
+ /** Values that could not be re-encrypted, and why. */
2090
+ skipped: {
2091
+ pointer: string;
2092
+ message: string;
2093
+ }[];
2094
+ }
2095
+ /**
2096
+ * Re-encrypt every encrypted value in one page's metadata from `fromKey` to
2097
+ * `toKey`.
2098
+ *
2099
+ * - A value that decrypts under `fromKey` is rewritten under `toKey`.
2100
+ * - One that already decrypts under `toKey` is done: an interrupted rotation
2101
+ * can be run again. It is neither rewritten nor skipped.
2102
+ * - One that decrypts under neither is skipped.
2103
+ *
2104
+ * The format is `page.format` (an extractor name) when given, else the
2105
+ * file's extension. A nested value rewrites its top-level key; everything
2106
+ * else in the page is kept. A format that cannot be written lists every value
2107
+ * it would have rewritten as skipped, and returns the content unchanged.
2108
+ */
2109
+ declare function reencryptMetadata(page: {
2110
+ file: string;
2111
+ content: string;
2112
+ format?: string;
2113
+ }, opts: {
2114
+ fromKey: string;
2115
+ toKey: string;
2116
+ }): ReencryptMetadataResult;
2117
+
1863
2118
  /**
1864
2119
  * Applied when nothing else resolves. Seven-Action is safe to include here
1865
2120
  * because it constrains `action` — a key documents don't otherwise carry — and
@@ -2041,7 +2296,7 @@ interface DeriveResult {
2041
2296
  * absent, and so is whichever of `github` and `gitlab` the origin remote does
2042
2297
  * not point at. Absent means not applicable here, never unavailable.
2043
2298
  */
2044
- sources: Partial<Record<DeriveSource, SourceStatus>>;
2299
+ sources: Partial<Record<DeriveSource, SourceStatus$1>>;
2045
2300
  }
2046
2301
  /**
2047
2302
  * Which sources can state a field, in precedence order: the built-in table
@@ -2055,7 +2310,7 @@ declare function consultedSources(fields: readonly DerivableField[], sources: re
2055
2310
  * Throw the exit-2 error for the first consulted source that could not
2056
2311
  * answer. `hint` is the command's own way out, appended after a semicolon.
2057
2312
  */
2058
- declare function assertSourcesAvailable(sources: Partial<Record<DeriveSource, SourceStatus>>, hint?: string): void;
2313
+ declare function assertSourcesAvailable(sources: Partial<Record<DeriveSource, SourceStatus$1>>, hint?: string): void;
2059
2314
  declare function deriveMetadata(inputs: readonly DeriveInput[], ctx: DeriveContext): Promise<DeriveResult>;
2060
2315
 
2061
2316
  /** How a client reaches the binary; tests point `bin` at node and a fake script. */
@@ -2109,7 +2364,7 @@ interface CommandSourceOptions {
2109
2364
  spawn?: Partial<SpawnOptions>;
2110
2365
  }
2111
2366
  interface CommandSourceResult {
2112
- status: SourceStatus;
2367
+ status: SourceStatus$1;
2113
2368
  /** By label; every input present when available, keyed by field within. */
2114
2369
  records: Map<string, Record<string, DerivedValue | null>>;
2115
2370
  }
@@ -2167,7 +2422,7 @@ declare abstract class CliClient implements ReviewClient {
2167
2422
  protected abstract readonly tool: "gh" | "glab";
2168
2423
  constructor(identity: RemoteIdentity | null, spawnOpts: SpawnOptions);
2169
2424
  detect(): Promise<RemoteIdentity | null>;
2170
- status(): Promise<SourceStatus>;
2425
+ status(): Promise<SourceStatus$1>;
2171
2426
  mergedChangeFor(sha: string): Promise<MergedChange | null>;
2172
2427
  protected abstract lookup(identity: RemoteIdentity, sha: string): Promise<MergedChange | null>;
2173
2428
  protected get bin(): string;
@@ -2242,7 +2497,7 @@ interface ReviewFacts {
2242
2497
  "last-reviewed": DerivedValue | null;
2243
2498
  }
2244
2499
  interface ReviewSourceResult {
2245
- status: SourceStatus;
2500
+ status: SourceStatus$1;
2246
2501
  /** By label. Empty when the source is unavailable. */
2247
2502
  records: Map<string, ReviewFacts>;
2248
2503
  }
@@ -2449,6 +2704,11 @@ declare function renderSarif(results: ValidationResult[], opts?: SarifOptions):
2449
2704
  * Violation-as-testcase would make the test count rise and fall with document
2450
2705
  * quality, which reads as a suite someone broke.
2451
2706
  *
2707
+ * **A warning is not a `<failure>`.** JUnit has no level below failure, and a
2708
+ * `<failure>` that did not fail the run would make the tab disagree with the
2709
+ * exit code. A warning-only file is a passing testcase; the warning is still
2710
+ * in the JSON and SARIF output, which have somewhere to put it.
2711
+ *
2452
2712
  * Escaping is the one thing a hand-rolled writer gets wrong. Messages carry
2453
2713
  * schema-authored text — a `pattern` regex may hold `<`, `&`, and quotes — and
2454
2714
  * paths can hold `&`. Every attribute value goes through `xmlEscape`; nothing
@@ -2718,4 +2978,1830 @@ declare function extractorForExtension(ext: string): MetadataExtractor | undefin
2718
2978
  /** Extensions handled by implemented extractors (used for directory walks). */
2719
2979
  declare function supportedExtensions(): string[];
2720
2980
 
2721
- export { type ApplyOptions, type Approval, type BaselineSummary, BinMissing, type BuiltinDerivableField, COMMON_FORMATS, type CheckConfig, type CollectionConfig, type CommandSourceOptions, type CommandSourceResult, type CommonFormat, type ConfigNotice, DEFAULT_SCHEMAS, DEFAULT_TTL_HOURS, DEFAULT_VENDOR_DIR, DERIVABLE_FIELDS, DERIVED_KEYWORD, DERIVED_STALE_SCHEMA, DERIVE_FORMATS, DERIVE_SOURCES, type DerivableField, type DeriveCommand, type DeriveCommandConfig, type DeriveConfig, type DeriveContext, type DeriveFileResult, type DeriveInput, type DeriveOptions, type DeriveReportFormat, type DeriveReportOptions, type DeriveResult, type DeriveRun, type DeriveSource, type DeriveSummary, type DerivedField, type DerivedRecord, type DerivedStatus, type DerivedValue, type DocmetaConfig, DocmetaError, type DocumentRefTrust, EXTERNAL_DUPLICATE_SCHEMA, EXTERNAL_KEYWORD, EXTERNAL_METADATA_FETCH_MAX_BYTES, EXTERNAL_METADATA_FETCH_TIMEOUT_MS, EXTERNAL_OWNED_SCHEMA, type ExternalMetadataCollision, type ExternalMetadataConfig, type ExternalMetadataEntry, type ExternalMetadataFetchOptions, type ExternalMetadataIndex, type ExternalMetadataJoin, type ExternalMetadataValue, type ExtractOptions, type ExtractedMetadata, FIELD_SOURCES, FILL_FORMATS, type FetchedSchema, type FieldError, type FillConfig, type FillFileResult, type FillOptions, type FillReportFormat, type FillReportOptions, type FillRun, type FillSummary, type FilledField, type FingerprintContext, type FrontmatterFlavor, type FrontmatterLocation, type GetFileResult, type GetOptions, type GetReportOptions, GitHubClient, GitLabClient, INTEGRITY_SHAPE, type JunitOptions, type LoadExternalMetadataOptions, type LoadSchemaOptions, type LoadedConfig, type MergedChange, type MergedMetadata, type MetadataExtractor, type MetadataPatch, PATH_JOIN, PATH_PLACEHOLDER, QUERY_FORMATS, type QueryChange, type QueryFormat, type QueryOptions, type QueryReportOptions, type QueryRun, REPORT_FORMATS, RESOLVED_VIEW, REVIEW_CACHE_DIR, REVIEW_CACHE_VERSION, type ReadOptions, type RemoteIdentity, type ReportFormat, type ReportOptions, ReviewCache, type ReviewClient, type ReviewFacts, type ReviewSourceInput, type ReviewSourceResult, type Run, type RunConfig, type RunConfigOptions, type RunSummary, SCHEMA_CACHE_DIR, SCHEMA_CACHE_VERSION, type SarifOptions, SchemaCache, type SchemaCacheConfig, type SchemaCacheEntry, type SchemaEntry, type SchemaPin, type SchemaRefEntry, type SchemaTrustConfig, type SkipReason, type SourceLocation, type SourceStatus, type SpawnOptions, type ValidateOptions, type ValidateRun, type ValidationResult, Validator, type VendorOptions, type VendorResult, applyFrontmatter, argvFor, assertSourcesAvailable, cachedClient, classifyRef, collectSchemaPins, compareDerived, consultedSources, createResolvedView, createReviewClient, deriveFromCommands, deriveFromReviews, deriveMetadata, externalMetadataJoin, externalMetadataPointer, externalMetadataUrlProblem, extractFrontmatter, extractorForExtension, fetchExternalMetadata, fetchSchemaBytes, frontmatterInnerText, getSchemasInfo, identityFromOrigin, integrityOf, isBuiltinField, isCommonFormat, isDeriveFormat, isDeriveSource, isFillFormat, isIntegrity, isMember, isPerFile, isQueryFormat, isReportFormat, listBuiltins, loadConfig, loadExternalMetadata, loadSchema, locateFrontmatter, memberOf, mentionsResolved, mergeExternalMetadata, orphanEntries, orphanError, orphanJoins, parseCollections, parseConfig, parseOriginUrl, rebaseConfigSchemaRefs, render, renderDerive, renderFill, renderFillGithub, renderGet, renderJunit, renderQuery, renderQueryCsv, renderSarif, resolveRunConfig, resolveSchemaSet, resolvedColumns, run, runDerive, runFill, runGet, runQuery, runValidate, runVendorSchema, schemaCacheDir, schemaEntryRef, schemaLoadOptions, selectCollections, sourcesFor, staleFindings, stringifyValue, supportedExtensions, valueOf, vendorFileName, writeFileAtomic };
2981
+ type KeySource = "env" | "config" | "none";
2982
+ interface ResolvedKey {
2983
+ key: string | undefined;
2984
+ source: KeySource;
2985
+ }
2986
+ type ToError = (message: string) => Error;
2987
+ /**
2988
+ * The key a run uses: the environment's, else the config file's, else none.
2989
+ *
2990
+ * An empty `MANNI_ENCRYPTION_KEY` counts as unset, because that is what an
2991
+ * absent CI secret expands to (a fork's pull request, say), and refusing the
2992
+ * run there would fail every such build for a key it was never going to get.
2993
+ * A non-empty value of the wrong shape is refused, and never echoed.
2994
+ */
2995
+ declare function resolveEncryptionKey(opts: {
2996
+ env?: NodeJS.ProcessEnv;
2997
+ file: ConfigFile | null;
2998
+ toError: ToError;
2999
+ }): ResolvedKey;
3000
+
3001
+ /** A parsed `<src>` or `source`: a path or `~` ciphertext, and an optional line range. */
3002
+ interface SourceRange {
3003
+ /** Repo-root-relative posix path, or the `~` ciphertext when `encrypted`. */
3004
+ path: string;
3005
+ /** `true` when `path` is an encrypted source (`~` and 82+ base64url characters) rather than a path. */
3006
+ encrypted: boolean;
3007
+ /** 1-based, inclusive. Both absent for a whole-file citation. */
3008
+ start?: number;
3009
+ end?: number;
3010
+ }
3011
+ /** Lines as an entry writes them: an integer for one line, `"L1-L2"` for several. */
3012
+ type LineSpec = number | string;
3013
+ /** The page text a citation supports. */
3014
+ interface CitationClaim {
3015
+ /** Body lines: counted from the first line after the frontmatter. Absent when a marker anchors the entry. */
3016
+ lines?: LineSpec;
3017
+ /** `sha256-<64 hex>` over the claimed lines, always plain. */
3018
+ integrity: string;
3019
+ }
3020
+ /** The lines a claim rests on. */
3021
+ interface CitationSource {
3022
+ /** Root-relative posix path, or `~` and the path encrypted with the family key. */
3023
+ file: string;
3024
+ /** File lines. Absent pins the whole file. */
3025
+ lines?: LineSpec;
3026
+ /** `sha256-<64 hex>`, or `hmac-sha256-<64 hex>` exactly when `file` is encrypted. */
3027
+ integrity: string;
3028
+ /** The git commit hash the pin was taken at: 7 to 64 lowercase hex. */
3029
+ "commit-sha"?: string;
3030
+ }
3031
+ /** One entry of `citations`, as the schema (`manni:citations:1.0.0-proposal.3`) spells it. */
3032
+ interface Citation {
3033
+ id?: string;
3034
+ claim?: CitationClaim;
3035
+ source: CitationSource;
3036
+ quote?: boolean;
3037
+ }
3038
+ /** Where an entry is kept: the page's frontmatter, or a manifest a collection declares. */
3039
+ type OriginKind = "frontmatter" | "manifest";
3040
+ /** Where an entry sits. */
3041
+ interface CitationOrigin {
3042
+ kind: OriginKind;
3043
+ /** The file the entry sits in: the page for frontmatter, the manifest otherwise. */
3044
+ file: string;
3045
+ /** Line of the entry in that file. */
3046
+ line?: number;
3047
+ /** Index in the page's `citations` list. */
3048
+ index: number;
3049
+ }
3050
+ /**
3051
+ * One entry handed to `checkCitations` from outside the page, already merged
3052
+ * from a manifest. `entry` is the raw value and is validated as a frontmatter
3053
+ * entry is; its index is its position in the list.
3054
+ */
3055
+ interface CitationInput {
3056
+ entry: unknown;
3057
+ origin: {
3058
+ kind: OriginKind;
3059
+ file: string;
3060
+ line?: number;
3061
+ };
3062
+ }
3063
+ /** How a citation's claim is anchored: by its lines, by a body marker, or not at all. */
3064
+ type CitationAnchor = "claim" | "marker" | null;
3065
+ type SourceStatus = "current" | "moved" | "moved-ambiguous" | "changed" | "missing" | "never-true" | "skipped";
3066
+ type ClaimStatus = "current" | "moved" | "moved-ambiguous" | "changed" | "skipped";
3067
+ /**
3068
+ * Why a source could not be read: not a tracked file under the root, an
3069
+ * encrypted source with no key to decrypt it, one that does not decrypt under
3070
+ * the key there is, or a tracked file that could not be read.
3071
+ */
3072
+ type MissingReason = "untracked" | "no-key" | "undecryptable" | "unreadable";
3073
+ /**
3074
+ * Every rule a finding can carry, stated once. The union and the default
3075
+ * severity table are derived from this array so the three cannot disagree.
3076
+ */
3077
+ declare const CITE_RULES: readonly ["source-moved", "source-moved-ambiguous", "source-changed", "source-never-true", "source-missing", "claim-moved", "claim-moved-ambiguous", "claim-changed", "marker-orphan", "marker-invalid", "marker-repeated", "anchor-invalid", "entry-invalid", "quote-drift"];
3078
+ type CiteRule = (typeof CITE_RULES)[number];
3079
+ /**
3080
+ * A rule's level: the family scale (`src/shared/severity.ts`) plus `off`,
3081
+ * which drops the rule's findings altogether.
3082
+ */
3083
+ type CiteSeverity = Severity | "off";
3084
+ /** The claim end of a classified citation. Line specs are `"L"` or `"L1-L2"`. */
3085
+ interface ClaimEnd {
3086
+ /** The entry's body lines. Absent when a marker anchors the claim. */
3087
+ lines?: string;
3088
+ /** Where the claim is judged, in file lines: the recorded lines, or what the marker anchors. */
3089
+ fileLines?: string;
3090
+ status: ClaimStatus;
3091
+ /** For `moved`: the new body lines. */
3092
+ newLines?: string;
3093
+ /** For `moved-ambiguous`: every candidate, in body lines. */
3094
+ candidates?: string[];
3095
+ /** For `moved`: the new file lines. Pretty-only. */
3096
+ newFileLines?: string;
3097
+ /** For `moved-ambiguous`: every candidate, in file lines. Pretty-only. */
3098
+ candidateFileLines?: string[];
3099
+ /** For `changed`: the page lines at the claim now, for `--show-diff`. Pretty-only. */
3100
+ text?: string[];
3101
+ }
3102
+ /** The source end of a classified citation. */
3103
+ interface SourceEnd {
3104
+ /** `file` and `lines` as the entry spells them: `path`, `path:L`, `path:L1-L2`, the ciphertext for `path`. */
3105
+ src: string;
3106
+ status: SourceStatus;
3107
+ /**
3108
+ * The path an encrypted source decrypted to. Never printed except by the
3109
+ * pretty reporter under `--reveal`; never serialized to a machine format.
3110
+ */
3111
+ resolvedPath?: string;
3112
+ /** For `missing`: why the source could not be read. Composes the message, which never names a path. */
3113
+ missingReason?: MissingReason;
3114
+ /** For `moved`: the new file lines. */
3115
+ newLines?: string;
3116
+ /** For `moved`: the new `src`, spelled as the entry spells sources. */
3117
+ newSrc?: string;
3118
+ /** For `moved-ambiguous`: every candidate `src`. */
3119
+ candidates?: string[];
3120
+ /** The commit the pin was taken at. */
3121
+ commitSha?: string;
3122
+ /** For `changed` with a commit: whether git could show that commit. */
3123
+ historyAvailable?: boolean;
3124
+ /** Subjects of commits touching the path since the commit. Pretty-only. */
3125
+ commitsSince?: string[];
3126
+ /** Unified diff of the path since the commit. Pretty-only, `--show-diff`. */
3127
+ diff?: string;
3128
+ /** The move search hit its byte budget before covering the file. */
3129
+ truncatedSearch?: boolean;
3130
+ }
3131
+ /** One classified citation: both ends, and how it is anchored. */
3132
+ interface CitationResult {
3133
+ citation: Citation;
3134
+ origin: CitationOrigin;
3135
+ anchor: CitationAnchor;
3136
+ /** File line of the marker that names the entry, when one does. */
3137
+ markerLine?: number;
3138
+ /**
3139
+ * File line the citation anchors to now: the claim's first line, or the
3140
+ * first line of the text a marker anchors. Where its findings sit.
3141
+ */
3142
+ anchorLine?: number;
3143
+ /** `null` for an entry with no `claim`: a bare pin, or a marker with no drift check. */
3144
+ claim: ClaimEnd | null;
3145
+ source: SourceEnd;
3146
+ }
3147
+ interface CitationFinding {
3148
+ rule: CiteRule;
3149
+ /** `manni:cite/<rule>`. */
3150
+ ruleId: string;
3151
+ /** On the family scale: an `error` fails the file; a `warning` or a `notice` is reported and never does. */
3152
+ severity: Severity;
3153
+ message: string;
3154
+ /** Line the finding anchors to: in the page, or in `file` when that is set. */
3155
+ line?: number;
3156
+ /** The manifest, when the finding sits there rather than on the page. */
3157
+ file?: string;
3158
+ id?: string;
3159
+ /** The source, spelled as the entry spells it. */
3160
+ src?: string;
3161
+ newSrc?: string;
3162
+ /** Index in the page's `citations` for a finding about one entry. */
3163
+ index?: number;
3164
+ }
3165
+ interface PageCitationReport {
3166
+ file: string;
3167
+ format: string;
3168
+ citations: CitationResult[];
3169
+ findings: CitationFinding[];
3170
+ /** Run-level advice, said once per run by the caller: shallow clone, root fallback. */
3171
+ notices: string[];
3172
+ }
3173
+ /** What `showFile` answers: the bytes, or why it could not. */
3174
+ type ShownFile = {
3175
+ text: string;
3176
+ } | {
3177
+ missing: "commit" | "path";
3178
+ };
3179
+ /**
3180
+ * A thin git client over `execFile("git", …)`, memoized per call shape so a
3181
+ * page with a thousand citations against one path runs one `git show`.
3182
+ */
3183
+ interface GitClient {
3184
+ available(): Promise<boolean>;
3185
+ head(): Promise<string | null>;
3186
+ /** Tracked files, posix, relative to the root. */
3187
+ lsFiles(): Promise<string[]>;
3188
+ showFile(commit: string, path: string): Promise<ShownFile>;
3189
+ subjectsSince(commit: string, path: string): Promise<string[]>;
3190
+ diffSince(commit: string, path: string): Promise<string>;
3191
+ }
3192
+ /**
3193
+ * The files a source may resolve to. Built from `git ls-files` when git is
3194
+ * available, else from a walk that follows no symlinks. Every entry is
3195
+ * realpath-contained in the root.
3196
+ */
3197
+ interface SourceIndex {
3198
+ files(): readonly string[];
3199
+ /** Whether `path` is a tracked file under the root. An encrypted source is decrypted first, then asked here. */
3200
+ has(path: string): boolean;
3201
+ }
3202
+ interface CheckPageOptions {
3203
+ /** Absolute directory source paths resolve from. */
3204
+ root: string;
3205
+ /** Default true. False: page-side rules only; every source status is `skipped`. Claim ends are still judged. */
3206
+ checkSources?: boolean;
3207
+ /**
3208
+ * The encryption key: decrypts encrypted sources and keys their pins.
3209
+ * Absent, an encrypted citation is `missing` (no key to decrypt it).
3210
+ */
3211
+ key?: string;
3212
+ severity?: Partial<Record<CiteRule, CiteSeverity>>;
3213
+ /**
3214
+ * The git client the source index and history are read through. Defaults
3215
+ * to one over the root, which is used whenever git is on PATH and the root
3216
+ * is inside a work tree. A caller that wants no git at all passes `noGit()`.
3217
+ */
3218
+ gitClient?: GitClient;
3219
+ sourceIndex?: SourceIndex;
3220
+ /**
3221
+ * The page's citations as merged from a manifest, each with where it sits.
3222
+ * Given, the page's own frontmatter `citations` is not read. Without it, a
3223
+ * grader calling `checkCitations` on a sidecar page would find no citations.
3224
+ */
3225
+ citations?: readonly CitationInput[];
3226
+ /**
3227
+ * The manifest that owns this page's `citations`, when one does. A page
3228
+ * that carries its own anyway is `entry-invalid`, in meta's `external:owned`
3229
+ * words.
3230
+ */
3231
+ owned?: {
3232
+ file: string;
3233
+ collection: string;
3234
+ };
3235
+ }
3236
+ interface MintOptions {
3237
+ root: string;
3238
+ /** `path`, `path:L`, `path:L1-L2`, or an encrypted `~file` with the same line forms. */
3239
+ src: string;
3240
+ id?: string;
3241
+ /** The claim pin, already taken over the page lines. */
3242
+ claim?: CitationClaim;
3243
+ quote?: boolean;
3244
+ /** A commit to record; `false` records none; absent records HEAD when git has one. */
3245
+ commitSha?: string | false;
3246
+ /**
3247
+ * Write `file` encrypted and pin the lines with the keyed pin; needs `key`.
3248
+ * A source that is already encrypted stays encrypted either way.
3249
+ */
3250
+ encrypt?: boolean;
3251
+ /** The encryption key: encrypts, decrypts an encrypted source, and keys its pin. */
3252
+ key?: string;
3253
+ gitClient?: GitClient;
3254
+ sourceIndex?: SourceIndex;
3255
+ }
3256
+ /** One marker found in a page body: `cite <id>` in the format's comment syntax. */
3257
+ interface InlineStatement {
3258
+ /** File line of the marker. */
3259
+ line: number;
3260
+ /** File line of the anchored text: the rest of the marker's line, else the paragraph or block that follows. */
3261
+ anchorLine?: number;
3262
+ payload: {
3263
+ kind: "ref";
3264
+ id: string;
3265
+ } | {
3266
+ kind: "bad";
3267
+ reason: string;
3268
+ json?: boolean;
3269
+ };
3270
+ /** The marker text between the delimiters, trimmed. */
3271
+ raw: string;
3272
+ /** Character offsets of the whole marker in the file, for rewriting. */
3273
+ start: number;
3274
+ end: number;
3275
+ }
3276
+ /** A validated citation with where it sits and the marker that names it, before classification. */
3277
+ interface PageCitation {
3278
+ citation: Citation;
3279
+ origin: CitationOrigin;
3280
+ /** The first marker naming the entry's id. */
3281
+ marker?: InlineStatement;
3282
+ }
3283
+ /** What `readPage` returns: the entries, the markers, and page-side findings. */
3284
+ interface PageCitations {
3285
+ file: string;
3286
+ format: string;
3287
+ content: string;
3288
+ /** Offset where the body starts (just past the closing fence, or 0). */
3289
+ bodyOffset: number;
3290
+ /** File line of body line 1: the first line after the frontmatter, or 1. */
3291
+ bodyLine: number;
3292
+ citations: PageCitation[];
3293
+ statements: InlineStatement[];
3294
+ findings: CitationFinding[];
3295
+ }
3296
+ interface CheckOptions {
3297
+ /** Positional inputs; empty means the configured collections' `paths:` (0041). */
3298
+ inputs: string[];
3299
+ /**
3300
+ * `--collection <name>`, repeatable: the collections this run covers. Empty
3301
+ * or absent means every declared one; see `selectCollections`.
3302
+ */
3303
+ collection?: string[];
3304
+ exts?: string[];
3305
+ /** `--exclude`, appended to the selected collections' `exclude:` when the run reads from them. */
3306
+ exclude?: string[];
3307
+ as?: string;
3308
+ configPath?: string;
3309
+ noConfig?: boolean;
3310
+ cwd?: string;
3311
+ stdinContent?: string;
3312
+ allowEmpty?: boolean;
3313
+ respectGitignore?: boolean;
3314
+ onNotice?: (message: string) => void;
3315
+ onConfigLoaded?: (info: {
3316
+ path: string;
3317
+ dir: string;
3318
+ }) => void;
3319
+ baseline?: string | boolean;
3320
+ writeBaseline?: string | boolean;
3321
+ /** `--no-check-sources` (false): page-side rules only. Absent leaves `checkSources:` in charge. */
3322
+ checkSources?: boolean;
3323
+ /**
3324
+ * `--show-diff`: the report will want diffs and commit subjects. The check
3325
+ * is the same either way; the run only says, once, when git is not there
3326
+ * to give them.
3327
+ */
3328
+ showDiff?: boolean;
3329
+ root?: string;
3330
+ /**
3331
+ * The git client every page is checked through. Defaults to one over the
3332
+ * root, used whenever git is on PATH and the root is inside a work tree; a
3333
+ * test hands in a fake.
3334
+ */
3335
+ gitClient?: GitClient;
3336
+ /** Defaults to `process.env`; read for `MANNI_ENCRYPTION_KEY`. A test hands in its own. */
3337
+ env?: NodeJS.ProcessEnv;
3338
+ }
3339
+ interface CheckRun {
3340
+ results: ValidationResult[];
3341
+ summary: RunSummary;
3342
+ frame: FingerprintContext;
3343
+ pages: PageCitationReport[];
3344
+ warnings: number;
3345
+ notices: number;
3346
+ }
3347
+ /** Page lines as an editor numbers them, 1-based and inclusive. */
3348
+ interface PageLines {
3349
+ start: number;
3350
+ end: number;
3351
+ }
3352
+ interface AddOptions {
3353
+ page: string;
3354
+ /** The claim's lines as an editor numbers them (`page:L`, `page:L1-L2`). Absent: a bare pin. */
3355
+ pageLines?: PageLines;
3356
+ src: string;
3357
+ id?: string;
3358
+ /** Write a marker above the page lines instead of claim lines, and pin the text it anchors. Needs `pageLines` and `id`. */
3359
+ marker?: boolean;
3360
+ /** The page lines are a fenced block that reproduces the source. Needs `pageLines`. */
3361
+ quote?: boolean;
3362
+ /**
3363
+ * `--encrypt`: write `file` encrypted, with a keyed pin, even when no key is
3364
+ * available yet, in which case `confirm` is asked whether to generate one.
3365
+ * An available key encrypts every add without it, so `false` and absent
3366
+ * are the same.
3367
+ */
3368
+ encrypt?: boolean;
3369
+ /** `false` records no `commit-sha`. */
3370
+ commitSha?: boolean;
3371
+ dryRun?: boolean;
3372
+ as?: string;
3373
+ configPath?: string;
3374
+ noConfig?: boolean;
3375
+ cwd?: string;
3376
+ stdinContent?: string;
3377
+ root?: string;
3378
+ /**
3379
+ * The git client HEAD and the source index are read through. Defaults to
3380
+ * one over the root; a test hands in a fake.
3381
+ */
3382
+ gitClient?: GitClient;
3383
+ /** Defaults to `process.env`; read for `MANNI_ENCRYPTION_KEY`. A test hands in its own. */
3384
+ env?: NodeJS.ProcessEnv;
3385
+ onNotice?: (message: string) => void;
3386
+ onConfigLoaded?: (info: {
3387
+ path: string;
3388
+ dir: string;
3389
+ }) => void;
3390
+ /**
3391
+ * Asked when `encrypt` needs a key and there is none; the CLI passes
3392
+ * `terminalConfirm()`. Absent, the add refuses instead of asking.
3393
+ */
3394
+ confirm?: Confirm;
3395
+ }
3396
+ /** The manifest half of a write: what it says now, and whether it was saved. */
3397
+ interface ManifestWrite {
3398
+ /** The manifest as the run reports it. */
3399
+ file: string;
3400
+ /** 1-based line the written entry now sits on. */
3401
+ line: number;
3402
+ /** The whole manifest, rewritten. */
3403
+ content: string;
3404
+ diff: string;
3405
+ written: boolean;
3406
+ }
3407
+ interface AddResult {
3408
+ file: string;
3409
+ citation: Citation;
3410
+ /**
3411
+ * Where the entry was written: the page's frontmatter, or the manifest the
3412
+ * page's collection declares. The config decides, not a flag.
3413
+ */
3414
+ placed: "frontmatter" | "manifest";
3415
+ /** The manifest the entry went to, under `placed: "manifest"`. */
3416
+ manifest?: ManifestWrite;
3417
+ /** File lines of the claim after the write: the claim lines, or the text the marker anchors. */
3418
+ claimLines?: PageLines;
3419
+ /** File line of the marker written above the claim, under `marker`. */
3420
+ markerLine?: number;
3421
+ /** The rewritten page. */
3422
+ content: string;
3423
+ diff: string;
3424
+ written: boolean;
3425
+ }
3426
+ interface UpdateOptions extends Omit<CheckOptions, "baseline" | "writeBaseline"> {
3427
+ accept?: boolean;
3428
+ only?: string[];
3429
+ dryRun?: boolean;
3430
+ }
3431
+ /** One end `update` rewrote. */
3432
+ interface UpdateRewrite {
3433
+ id?: string;
3434
+ /** Index in the page's `citations`. */
3435
+ index: number;
3436
+ /** File line of the entry. */
3437
+ line?: number;
3438
+ end: "claim" | "source";
3439
+ reason: "moved" | "accepted";
3440
+ /** The status that was repaired. */
3441
+ status: "moved" | "changed" | "never-true";
3442
+ /**
3443
+ * Before and after. A moved claim: its file lines. A moved source: its
3444
+ * `src`. An accepted end: its pin.
3445
+ */
3446
+ from: string;
3447
+ to: string;
3448
+ /** An accepted claim: its first file line. */
3449
+ at?: number;
3450
+ /** An accepted claim: the text now pinned, whitespace collapsed. */
3451
+ text?: string;
3452
+ /** An accepted source: its `src`. */
3453
+ src?: string;
3454
+ /** An accepted source: the commit recorded in the entry, when it records one. */
3455
+ commitSha?: string;
3456
+ }
3457
+ interface UpdatePage {
3458
+ file: string;
3459
+ rewritten: UpdateRewrite[];
3460
+ skipped: CitationFinding[];
3461
+ diff: string;
3462
+ written: boolean;
3463
+ /** The rewritten page, for the stdin input only: it has no file to be written to. */
3464
+ content?: string;
3465
+ }
3466
+ /** One manifest a run rewrote: what changed in it, and whether it was saved. */
3467
+ interface ManifestChange {
3468
+ /** The manifest as the run reports it. */
3469
+ file: string;
3470
+ diff: string;
3471
+ written: boolean;
3472
+ }
3473
+ interface UpdateRun {
3474
+ pages: UpdatePage[];
3475
+ rewritten: number;
3476
+ skipped: number;
3477
+ /** The manifests this run rewrote, each written once however many pages it holds. */
3478
+ manifests?: ManifestChange[];
3479
+ exitCode: 0 | 1;
3480
+ }
3481
+ /** One citation `reencryptCitations` rewrote: where it sits, and its source before and after. */
3482
+ interface ReencryptedCitation {
3483
+ id?: string;
3484
+ /** Index in `citations`. */
3485
+ index?: number;
3486
+ /** File line of the entry. */
3487
+ line?: number;
3488
+ /** `file` and its line suffix, under the old key and under the new. */
3489
+ from: string;
3490
+ to: string;
3491
+ }
3492
+ /** What `reencryptCitations` did to one page. */
3493
+ interface ReencryptCitationsResult {
3494
+ /** The page with every re-encrypted citation rewritten; the input itself when none was. */
3495
+ content: string;
3496
+ rewritten: ReencryptedCitation[];
3497
+ /** Citations that could not be re-encrypted, and why. A message never names a path. */
3498
+ skipped: {
3499
+ id?: string;
3500
+ index?: number;
3501
+ line?: number;
3502
+ message: string;
3503
+ }[];
3504
+ }
3505
+ /**
3506
+ * Config under `cite:` in manni.config.yaml, camelCase as `meta:` is. The
3507
+ * document set is not here: proposal 0041 moved `paths` and `exclude` to the
3508
+ * family-level `collections:` list, which every tool reads. Neither is the
3509
+ * encryption key, the top-level `encryptionKey:` every tool reads (0045).
3510
+ */
3511
+ interface CiteConfig {
3512
+ allowEmpty?: boolean;
3513
+ respectGitignore?: boolean;
3514
+ root?: string;
3515
+ baseline?: string;
3516
+ checkSources?: boolean;
3517
+ severity?: Partial<Record<CiteRule, CiteSeverity>>;
3518
+ }
3519
+ interface LoadedCiteConfig {
3520
+ config: CiteConfig;
3521
+ path: string;
3522
+ dir: string;
3523
+ /** The file as the user would name it, for messages. */
3524
+ source: string;
3525
+ /** The family file's top-level `collections:`, parsed by the shared layer (0041). */
3526
+ collections: CollectionConfig[];
3527
+ }
3528
+ /** What every command core resolves before touching a file. */
3529
+ interface CiteRun {
3530
+ config: CiteConfig | null;
3531
+ /** The positional inputs, or the selected collections' `paths:` in declaration order. */
3532
+ inputs: string[];
3533
+ /** Directory the inputs resolve from: cwd for positional inputs, the config directory for collections. */
3534
+ base: string;
3535
+ /**
3536
+ * The collections this run covers: every declared one, or the ones
3537
+ * `--collection` named. `[]` when no config governs the run.
3538
+ */
3539
+ collections: CollectionConfig[];
3540
+ /** Whether `inputs` came from the collections rather than the command line. */
3541
+ fromCollections: boolean;
3542
+ configDir?: string;
3543
+ configPath?: string;
3544
+ /** The config file as the user would name it, for messages. */
3545
+ configSource?: string;
3546
+ /** Absolute root source paths resolve from. */
3547
+ root: string;
3548
+ /**
3549
+ * The family encryption key (proposal 0045): `MANNI_ENCRYPTION_KEY`, else
3550
+ * the config's top-level `encryptionKey:`. Absent when neither is set.
3551
+ */
3552
+ key?: string;
3553
+ /** Where `key` came from. The environment wins over the config. */
3554
+ keySource: KeySource;
3555
+ /**
3556
+ * The config file that governs the run, as discovery found it. A write
3557
+ * that needs a key (`add --encrypt` with none) puts one there.
3558
+ */
3559
+ configFile?: ConfigFile;
3560
+ }
3561
+
3562
+ /** An operational or usage error in the citation tool: exit 2. */
3563
+ declare class CiteError extends ToolError {
3564
+ constructor(message: string);
3565
+ }
3566
+
3567
+ /**
3568
+ * Which rules fail a run, which only warn, and which are notices.
3569
+ *
3570
+ * Warnings and notices never affect the exit code (docevals' rule).
3571
+ * `source-moved` is a warning because `cite update` fixes it mechanically,
3572
+ * and a PR job that failed on it would make the ratchet noisy. `claim-moved`
3573
+ * is a notice: the text is found verbatim, so nothing drifted.
3574
+ * `claim-changed` is a warning, since it fires on any edit to a pinned
3575
+ * paragraph, a typo fix beside the cited sentence included. A repository that
3576
+ * wants either hard sets `severity: { claim-changed: error }`.
3577
+ */
3578
+
3579
+ declare const DEFAULT_SEVERITY: Readonly<Record<CiteRule, CiteSeverity>>;
3580
+ declare const RULE_ID_PREFIX = "manni:cite";
3581
+ /** `manni:cite/<rule>`: the SARIF rule id and the JUnit failure type. */
3582
+ declare function ruleId(rule: CiteRule): string;
3583
+ declare function isCiteRule(value: string): value is CiteRule;
3584
+ /** The effective severity table: defaults with the config's overrides. */
3585
+ declare function resolveSeverity(overrides?: Partial<Record<CiteRule, CiteSeverity>>): Record<CiteRule, CiteSeverity>;
3586
+
3587
+ /** The schema's `$defs.fileRef.pattern`, as a RegExp. */
3588
+ declare const FILE_PATTERN: RegExp;
3589
+ /** A source on the command line: a `file`, then an optional `:L` or `:L1-L2`. */
3590
+ declare const SRC_PATTERN: RegExp;
3591
+ /**
3592
+ * Parse a command-line source. Throws `CiteError` on bad grammar or an end
3593
+ * line before the start. A one-line `path:L` comes back with `end` equal to
3594
+ * `start`, so a range's width is always `end - start + 1`.
3595
+ */
3596
+ declare function parseSrc(src: string): SourceRange;
3597
+ /** The canonical spelling: `path:L` for one line, `path:L1-L2` otherwise. */
3598
+ declare function formatSrc(range: SourceRange): string;
3599
+ /**
3600
+ * The lines an entry's `lines` names. Undefined for a value that is neither
3601
+ * a positive integer nor `"L1-L2"` with `L1 <= L2`: the schema refuses the
3602
+ * first, and `readPage` reports the second.
3603
+ */
3604
+ declare function parseLines(spec: LineSpec): PageLines | undefined;
3605
+ /** Lines as an entry writes them: the integer for one line, `"L1-L2"` otherwise. */
3606
+ declare function lineSpec(lines: PageLines): LineSpec;
3607
+ /** Lines as a report spells them: `"9"` or `"9-12"`. */
3608
+ declare function spellLines(lines: PageLines): string;
3609
+ /** An entry's source as a range. Its lines must already be valid (see `parseLines`). */
3610
+ declare function sourceRange(source: CitationSource): SourceRange;
3611
+ /** An entry's source spelled as one string, `path:L1-L2`, the way the command line takes it. */
3612
+ declare function spellSource(source: CitationSource): string;
3613
+ /** A range's lines as an entry writes them; undefined for a whole file. */
3614
+ declare function rangeLines(range: SourceRange): LineSpec | undefined;
3615
+
3616
+ /** BOM stripped, CRLF folded to LF. */
3617
+ declare function normalizeText(text: string): string;
3618
+ /** The normalized lines, without the empty element a trailing LF leaves. */
3619
+ declare function splitLines(text: string): string[];
3620
+ /**
3621
+ * The cited lines joined by LF. Throws `CiteError` when the range runs past
3622
+ * the end of the text (`<path> has N lines; line M is out of range`).
3623
+ */
3624
+ declare function sliceLines(lines: readonly string[], range?: {
3625
+ start?: number;
3626
+ end?: number;
3627
+ }, label?: string): string;
3628
+ /** The pin of the cited lines: plain, or the keyed pin under `key` when one is given. */
3629
+ declare function hashRange(text: string, range?: {
3630
+ start?: number;
3631
+ end?: number;
3632
+ }, key?: string): string;
3633
+ /**
3634
+ * The pin of already-joined lines: `sha256-<hex>`, or with `key` the
3635
+ * `hmac-sha256-<hex>` keyed pin an encrypted source carries. A plain pin
3636
+ * passes `undefined`.
3637
+ */
3638
+ declare function hashLines(joined: string, key?: string): string;
3639
+ /** Whether a pin is keyed (`hmac-sha256-`), the form an encrypted source carries. */
3640
+ declare function isKeyedPin(pin: string): boolean;
3641
+
3642
+ /**
3643
+ * How a citation reads on a terminal. A pin is sixty-four hex digits and a
3644
+ * ciphertext is longer still, so both are abbreviated for a person, and every
3645
+ * report and every `add` line abbreviates them the same way.
3646
+ */
3647
+ /** `sha256-78af1d33…`, `hmac-sha256-5e0c1a2b…`: the prefix and eight hex digits. */
3648
+ declare function shortPin(integrity: string): string;
3649
+ /** The seven characters a person reads a commit by. */
3650
+ declare function shortCommit(commit: string): string;
3651
+ /**
3652
+ * `~AQx7…:2`: an encrypted source, abbreviated, with its line suffix kept. A
3653
+ * plain path is spelled in full, because that is what a reader has to find.
3654
+ */
3655
+ declare function shortSrc(src: string): string;
3656
+
3657
+ interface BuildIndexOptions {
3658
+ /** `git ls-files` when this client reports git available; a walk when it does not, or with no client. */
3659
+ gitClient?: GitClient;
3660
+ }
3661
+ declare function buildSourceIndex(root: string, opts?: BuildIndexOptions): Promise<SourceIndex>;
3662
+ type ReadSourceResult = {
3663
+ kind: "ok";
3664
+ resolvedPath: string;
3665
+ text: string;
3666
+ } | {
3667
+ kind: "missing";
3668
+ reason: MissingReason;
3669
+ };
3670
+ /**
3671
+ * Read the file a range names. An encrypted source is decrypted under `key`
3672
+ * first: with no key it is `no-key`, under another key `undecryptable`. Never
3673
+ * reads a path the index does not hold.
3674
+ */
3675
+ declare function readSource(root: string, index: SourceIndex, range: SourceRange, key?: string): Promise<ReadSourceResult>;
3676
+
3677
+ /**
3678
+ * Markers: `cite <id>` inside the format's comment syntax.
3679
+ *
3680
+ * | Format | Forms |
3681
+ * |---------------|--------------------------------------------------------------|
3682
+ * | markdown, mdx | `<!-- cite … -->`, `{/* cite … *\/}`, `[comment]: # (cite …)` |
3683
+ * | html, xml | `<!-- cite … -->` |
3684
+ * | asciidoc | `// (cite …)` |
3685
+ * | rst | `.. (cite …)` |
3686
+ *
3687
+ * A marker carries an id and nothing else (`cite true` names id `true`). A
3688
+ * payload starting with `{` was the inline entry of proposal 0044's first
3689
+ * draft; it is `marker-invalid` now, because an entry lives in frontmatter or
3690
+ * a manifest and a source is never written into the body. The scanner uses
3691
+ * `indexOf` for the delimiters, never a regex over the whole page, and is
3692
+ * handed the body only, so a `cite` inside frontmatter is never matched.
3693
+ *
3694
+ * It does not read code. An opener inside a fenced block (``` or ~~~ in
3695
+ * markdown and mdx, indented or not; `----` in asciidoc; an unclosed fence
3696
+ * runs to the end, as a renderer reads it) or inside a backtick span (a run of
3697
+ * backticks closed by a run of the same length on the same line) is skipped,
3698
+ * so a page that documents the syntax carries no statements. html and xml
3699
+ * have neither; a `<pre>` is not code to this scanner.
3700
+ *
3701
+ * Every form parses in both markdown and mdx. The first form is what
3702
+ * `formatStatement` writes: the html comment for markdown, the jsx comment
3703
+ * for mdx, which rejects an html comment.
3704
+ */
3705
+
3706
+ interface StatementForm {
3707
+ open: string;
3708
+ close: string;
3709
+ }
3710
+ /** The forms per extractor name. Unknown formats have none. */
3711
+ declare function statementForms(format: string): readonly StatementForm[];
3712
+ /** Scan a body for statements. `from` maps body offsets/lines to file offsets/lines. */
3713
+ declare function parseStatements(body: string, format: string, from?: {
3714
+ offset: number;
3715
+ line: number;
3716
+ }): InlineStatement[];
3717
+ /** `"\r\n"` when the text's first line break is CRLF, else `"\n"`. */
3718
+ declare function detectEol(text: string): "\n" | "\r\n";
3719
+ /**
3720
+ * The paragraph starting at or after `offset` (skipping blank lines), as
3721
+ * `{ start, end, line }` file offsets and the file line it starts on. A fence
3722
+ * opener ends the search with no paragraph.
3723
+ */
3724
+ declare function paragraphAfter(content: string, offset: number): {
3725
+ start: number;
3726
+ end: number;
3727
+ line: number;
3728
+ } | undefined;
3729
+ /**
3730
+ * The fenced code block starting at or after `offset` (``` or ~~~; asciidoc
3731
+ * `----`), as file offsets of its content lines and the file line of the
3732
+ * opening fence. `undefined` for formats with no locator (html, xml, rst).
3733
+ */
3734
+ declare function fencedBlockAfter(content: string, offset: number, format: string): {
3735
+ start: number;
3736
+ end: number;
3737
+ line: number;
3738
+ text: string;
3739
+ } | undefined;
3740
+ /**
3741
+ * The fenced block at `offset` in any fence family, for callers that have no
3742
+ * format at hand (the claim search). Undefined when the line at `offset` is
3743
+ * not an opener.
3744
+ */
3745
+ declare function fencedBlockAt(content: string, offset: number): {
3746
+ start: number;
3747
+ end: number;
3748
+ line: number;
3749
+ text: string;
3750
+ } | undefined;
3751
+ /** Every fenced block in the body, for `--quote` without `--claim`. */
3752
+ declare function fencedBlocks(content: string, bodyOffset: number, format: string): {
3753
+ start: number;
3754
+ end: number;
3755
+ line: number;
3756
+ text: string;
3757
+ }[];
3758
+ /** Render a marker in the format's first form, e.g. `<!-- cite fetch-timeout -->`. */
3759
+ declare function formatStatement(format: string, payload: {
3760
+ kind: "ref";
3761
+ id: string;
3762
+ }): string;
3763
+ /**
3764
+ * The fenced block opening on `line`, as the lines it spans, fences included.
3765
+ * Undefined when that line is not an opener the format knows, or the block is
3766
+ * never closed.
3767
+ */
3768
+ declare function fenceSpanAt(text: string, line: number, format: string): {
3769
+ start: number;
3770
+ end: number;
3771
+ } | undefined;
3772
+ /** Whether `line` sits inside a fenced block rather than opening one. */
3773
+ declare function insideFence(text: string, bodyOffset: number, line: number, format: string): boolean;
3774
+ /**
3775
+ * The lines a marker anchors, as 1-based lines of `text`: the rest of its own
3776
+ * line when that carries text, else the paragraph or fenced block that
3777
+ * follows. With `quote`, the next fenced block after it, wherever that is.
3778
+ * Undefined when nothing follows to anchor.
3779
+ */
3780
+ declare function anchoredLines(text: string, after: number, format: string, quote?: boolean): {
3781
+ start: number;
3782
+ end: number;
3783
+ } | undefined;
3784
+ /** 1-based file line of a file offset, counting CRLF once. */
3785
+ declare function lineAt(content: string, offset: number): number;
3786
+ /** File offset of the first character of a 1-based line (the length when past the end). */
3787
+ declare function offsetOfLine(content: string, line: number): number;
3788
+
3789
+ /**
3790
+ * The claim end: the page text a citation supports, classified by the same
3791
+ * machinery as the source end and against the page as it is now.
3792
+ *
3793
+ * The claim's lines are body-relative, so editing the frontmatter never moves
3794
+ * them; every line a person reads is a file line, translated here. The pin
3795
+ * holds at the recorded lines: `current`. The same text is found verbatim
3796
+ * elsewhere in the body: `moved`, once, or `moved-ambiguous`. Nowhere:
3797
+ * `changed`, the sentence was edited. A marker-anchored claim pins what the
3798
+ * marker anchors, so it never moves; it is `current` or `changed`.
3799
+ */
3800
+
3801
+ declare function normalizeWhitespace(text: string): string;
3802
+ /** `true` when the block's normalized text equals the cited lines under the hashing rule. */
3803
+ declare function blockMatches(blockText: string, citedJoined: string): boolean;
3804
+ /** Body lines as file lines: body line 1 is the first line after the frontmatter. */
3805
+ declare function toFileLines(lines: PageLines, bodyLine: number): PageLines;
3806
+ /** File lines as body lines. */
3807
+ declare function toBodyLines(lines: PageLines, bodyLine: number): PageLines;
3808
+ /** The pin of a page range, under the claim rule: always plain. */
3809
+ declare function pinOfLines(lines: readonly string[], range: PageLines): string | undefined;
3810
+ /** The first file line of a classified claim: where its findings sit. */
3811
+ declare function claimLine(claim: ClaimEnd): number | undefined;
3812
+ /**
3813
+ * Classify one entry's claim end against the page. `lines` is the page under
3814
+ * the hashing rule (`splitLines`). `null` for an entry with no `claim`: a
3815
+ * bare pin, or a marker with no drift check on its sentence.
3816
+ */
3817
+ declare function claimEnd(page: PageCitations, entry: PageCitation, lines: readonly string[]): ClaimEnd | null;
3818
+ /** What `update --accept` re-pins over: the paragraph or fenced block at a line. */
3819
+ interface ClaimUnit {
3820
+ lines: PageLines;
3821
+ kind: "paragraph" | "block";
3822
+ text: string[];
3823
+ }
3824
+ /**
3825
+ * The paragraph or fenced block at a file line. Undefined when the line is
3826
+ * blank, outside the body, or inside a fenced block rather than opening one:
3827
+ * those are the claims `update --accept` skips.
3828
+ *
3829
+ * A paragraph runs from this line to its end, not from the paragraph's own
3830
+ * first line. The line asked about is the claim's first line, and re-pinning
3831
+ * has to leave that where it is, so a claim that started mid-paragraph keeps
3832
+ * starting there.
3833
+ */
3834
+ declare function unitAt(page: PageCitations, line: number, lines: readonly string[]): ClaimUnit | undefined;
3835
+ /** The lines a marker anchors now, for `update --accept` on a marker-anchored claim. */
3836
+ declare function markerUnit(page: PageCitations, entry: PageCitation, lines: readonly string[]): ClaimUnit | undefined;
3837
+
3838
+ /** `git` at `root`, as a client; see the module comment for the call shapes. */
3839
+ declare function gitClient(root: string): GitClient;
3840
+ /**
3841
+ * What a run says, once, when git is not there and the run wanted it: a
3842
+ * citation carries a commit, or `--show-diff` asked for diffs, so history
3843
+ * would have been read. Said through `onNotice`; never a finding.
3844
+ */
3845
+ declare const GIT_UNAVAILABLE_HISTORY = "git is not available here, so citations are checked without history: no never-true, no diffs, no commit subjects.";
3846
+ /** What `add` and `update --accept` say, once, when a commit would have been recorded and git is not there. */
3847
+ declare const GIT_UNAVAILABLE_COMMIT = "git is not available here, so the citation records no commit.";
3848
+ /**
3849
+ * A client that answers "no git": `available()` false, everything else empty.
3850
+ * What a caller passes as `gitClient` to run without git where git is there.
3851
+ */
3852
+ declare function noGit(): GitClient;
3853
+
3854
+ /**
3855
+ * Source-side classification of one citation.
3856
+ *
3857
+ * current: the range hashes to the pin. moved / moved-ambiguous: a window of
3858
+ * the same length hashes equal elsewhere (once / more than once); whole-file
3859
+ * citations never move. changed: none equal; with a commit and history,
3860
+ * the diff and commit subjects are attached (pretty-only). never-true: no
3861
+ * window of the range's length anywhere in the file at the commit hashes to
3862
+ * the pin, or the path is absent there. The recorded lines are tried first;
3863
+ * the rest of the file is searched because `update` rewrites `src` for a move
3864
+ * without touching `commit`, so the lines a pin was minted from may sit
3865
+ * elsewhere in the file as it was then. A window that matches there is the
3866
+ * original for the move search below. missing: the source cannot be read.
3867
+ *
3868
+ * Move search: with the original text (git could show the commit), candidate
3869
+ * offsets are where the first line matches, compared lexically, hashed only on
3870
+ * a full match. Without it, a ±2000-line window around the original position
3871
+ * first, then the rest of the file under a 64 MiB hashing budget; past the
3872
+ * budget the result is `changed` with `truncatedSearch`.
3873
+ *
3874
+ * Order, as the ladder has it: the move search runs whenever the pin does not
3875
+ * hold, and history decides only what a non-match is called. So a pin that
3876
+ * never held at its commit but whose bytes sit elsewhere in the file is
3877
+ * `moved`, not `never-true`; the search sees the file as it is.
3878
+ */
3879
+
3880
+ declare const MOVE_WINDOW_LINES = 2000;
3881
+ declare const MOVE_BUDGET_BYTES: number;
3882
+ declare const MAX_RANGE_LINES = 5000;
3883
+ interface ClassifyOptions {
3884
+ root: string;
3885
+ index: SourceIndex;
3886
+ /** History is read through it when it reports git available, and never otherwise. */
3887
+ git: GitClient;
3888
+ /** The encryption key: decrypts an encrypted source and keys its pin. */
3889
+ key?: string;
3890
+ /** Hashing budget for the blind move search, in bytes. Default `MOVE_BUDGET_BYTES`. */
3891
+ budget?: number;
3892
+ }
3893
+ interface FindWindowsOptions {
3894
+ /** The 1-based start line the range was pinned at: the blind search begins around it. */
3895
+ around?: number;
3896
+ /** The cited lines at the commit, when git could show them: enables the first-line filter. */
3897
+ original?: readonly string[];
3898
+ /** Hashing budget for the blind search, in bytes. Default `MOVE_BUDGET_BYTES`. */
3899
+ budget?: number;
3900
+ }
3901
+ /**
3902
+ * Pure move search over normalized lines: the 1-based start lines where a
3903
+ * window of `length` lines hashes to `pin`. `original` (the cited lines at the
3904
+ * commit, when known) enables the first-line filter. `key` keys the hash for
3905
+ * an encrypted source's pin and is `undefined` for a plain one.
3906
+ */
3907
+ declare function findWindows(lines: readonly string[], length: number, pin: string, key: string | undefined, opts?: FindWindowsOptions): {
3908
+ starts: number[];
3909
+ truncated: boolean;
3910
+ };
3911
+ /**
3912
+ * What git could say about the pin at the recorded commit. `unknown` is a
3913
+ * file at the commit too large to search under the budget with the pin found
3914
+ * nowhere in the part that was: neither true nor never true. `original`
3915
+ * carries the cited lines as they were then, which `reencryptCitations` re-keys
3916
+ * from when the pin no longer holds today.
3917
+ */
3918
+ type History = {
3919
+ kind: "none";
3920
+ } | {
3921
+ kind: "unavailable";
3922
+ } | {
3923
+ kind: "never-true";
3924
+ } | {
3925
+ kind: "unknown";
3926
+ } | {
3927
+ kind: "original";
3928
+ lines: string[];
3929
+ };
3930
+ declare function historyOf(git: GitClient, commit: string, path: string, range: SourceRange, pin: string, key: string | undefined, budget: number | undefined): Promise<History>;
3931
+ declare function classifyCitation(entry: PageCitation, opts: ClassifyOptions): Promise<SourceEnd>;
3932
+
3933
+ declare const MAX_MARKERS_PER_PAGE = 500;
3934
+ /** What a marker with a JSON payload is told, since an entry never lives in the body. */
3935
+ declare const MARKER_JSON = "A marker names an entry by id. Write the entry in frontmatter or the sidecar.";
3936
+ interface ReadPageOptions {
3937
+ /** Extractor name; derived from the file's extension when absent. */
3938
+ format?: string;
3939
+ /**
3940
+ * The page's citations as a manifest owns them, already merged. Given, the
3941
+ * page's own frontmatter `citations` is not read.
3942
+ */
3943
+ citations?: readonly CitationInput[];
3944
+ /**
3945
+ * The manifest that owns this page's `citations`, when one does. A page
3946
+ * that also carries its own is `entry-invalid`: neither channel wins, and
3947
+ * the discarded value would be exactly the one nobody checked.
3948
+ */
3949
+ owned?: {
3950
+ file: string;
3951
+ collection: string;
3952
+ };
3953
+ }
3954
+ /** Meta's `external:owned` sentence, said by `cite check` under `entry-invalid`. */
3955
+ declare function ownedMessage(owner: {
3956
+ file: string;
3957
+ collection: string;
3958
+ }): string;
3959
+ /** Ajv validation of one entry object against `$defs.citationEntry`; the first error text, or undefined. */
3960
+ declare function validateEntry(entry: unknown): string | undefined;
3961
+ declare function pickExtractor(file: string, format: string | undefined): MetadataExtractor;
3962
+ /** File line of body line 1: the first line after the frontmatter, or 1. */
3963
+ declare function bodyLineOf(content: string, bodyOffset: number): number;
3964
+ declare function readPage(file: string, content: string, opts?: ReadPageOptions): PageCitations;
3965
+
3966
+ /** The one key cite keeps in a manifest. */
3967
+ declare const CITATIONS_KEY = "citations";
3968
+ /** A manifest that owns `citations` for one collection. */
3969
+ interface CitationManifest {
3970
+ /** The collection that declares it. */
3971
+ collection: string;
3972
+ /** Absolute path of the manifest file. */
3973
+ path: string;
3974
+ /** The manifest as the run reports it. */
3975
+ file: string;
3976
+ /** `path`, or the page field the manifest joins on. */
3977
+ join: string;
3978
+ }
3979
+ /** Where one page's citations are kept, and what the manifest already holds. */
3980
+ interface PageSidecar {
3981
+ /** The manifest that owns this page's citations, when one does. */
3982
+ owner?: CitationManifest;
3983
+ /**
3984
+ * The key under which this page is written in the manifest: its path
3985
+ * relative to the config directory, or its value of the join field.
3986
+ * Undefined when the manifest joins on a field the page does not carry, so
3987
+ * a writer refuses rather than inventing a key.
3988
+ */
3989
+ entry?: string;
3990
+ /** The manifest's entries for this page, when it supplies any. */
3991
+ citations?: CitationInput[];
3992
+ /** Field-joined entries this page matched, for the duplicate-join check. */
3993
+ joins: readonly ExternalMetadataJoin[];
3994
+ }
3995
+ interface CitationSidecars {
3996
+ /** The manifests that own `citations`, by collection. */
3997
+ manifests: readonly CitationManifest[];
3998
+ /** Directory manifest paths and manifest keys resolve from. */
3999
+ configDir: string;
4000
+ /** Directory the run's file labels are relative to. */
4001
+ base: string;
4002
+ forPage(label: string, content: string, format?: string): PageSidecar;
4003
+ /**
4004
+ * Manifest entries naming a page this run did not load, under meta's own
4005
+ * corpus invariant. `covered` names the collections a `--collection` run
4006
+ * narrowed to, or `undefined` for a whole-corpus run.
4007
+ */
4008
+ orphans(loaded: readonly string[], covered?: readonly string[]): ExternalMetadataEntry[];
4009
+ /** Field entries no loaded page matched, same invariant. */
4010
+ orphanJoins(matched: ReadonlyMap<string, ReadonlySet<string>>, covered?: readonly string[]): ExternalMetadataEntry[];
4011
+ }
4012
+ interface LoadSidecarOptions {
4013
+ /** Every collection the config declares, not only the ones the run selected. */
4014
+ collections: readonly CollectionConfig[];
4015
+ /** The config file's directory. */
4016
+ configDir: string;
4017
+ /** Directory the run's file labels are relative to. */
4018
+ base: string;
4019
+ /** The config file as the user would name it, for the URL refusal. */
4020
+ configSource: string;
4021
+ /** The family encryption key, for a join field a page holds encrypted. */
4022
+ key?: string;
4023
+ /** The tool's error class; `CiteError` unless a sibling command says otherwise. */
4024
+ toError?: (message: string) => Error;
4025
+ }
4026
+ /** `collection <name>: citations cannot come from a URL manifest, because cite writes them.` */
4027
+ declare function urlManifestRefusal(source: string, collection: string): string;
4028
+ /** `<page> is in collections a and b, and both keep citations in a manifest.` */
4029
+ declare function twoManifestsRefusal(label: string, a: string, b: string): string;
4030
+ /**
4031
+ * Load every manifest that owns `citations`, or `null` when none does — which
4032
+ * is every setup that keeps its citations in frontmatter, and costs nothing.
4033
+ *
4034
+ * Only the citations-owning manifests are loaded. A sibling manifest of the
4035
+ * same collection, supplying meta's own keys from a URL, is none of cite's
4036
+ * business and is never fetched here.
4037
+ */
4038
+ declare function loadCitationSidecars(opts: LoadSidecarOptions): Promise<CitationSidecars | null>;
4039
+ /** The refusal a whole-corpus run raises for a manifest entry naming nothing. */
4040
+ declare function orphanRefusal(orphans: readonly ExternalMetadataEntry[], toError?: (message: string) => Error): Error;
4041
+ /**
4042
+ * Two pages carrying one `join:` value: the manifest cannot tell them apart,
4043
+ * and cite would write one page's entry over the other's. Meta files this as
4044
+ * a finding on each document; here it is the run's problem, because the run
4045
+ * writes.
4046
+ */
4047
+ declare function duplicateJoinRefusal(field: string, value: string, file: string, labels: readonly string[]): string;
4048
+ /**
4049
+ * Load the sidecars a resolved run governs; `null` with no config, or no
4050
+ * citations manifest. `base` overrides the run's when a command labels its
4051
+ * pages from somewhere else — `add` takes one page from the command line and
4052
+ * labels it from the working directory, whatever the collections would.
4053
+ */
4054
+ declare function sidecarsFor(run: CiteRun, over?: {
4055
+ base?: string;
4056
+ toError?: (message: string) => Error;
4057
+ }): Promise<CitationSidecars | null>;
4058
+
4059
+ interface SpliceManifestOptions {
4060
+ /**
4061
+ * The document entry: its path relative to the config's directory, or its
4062
+ * value of the join field when `join` names one. A path entry matches
4063
+ * however the manifest spells it (`./docs/a.md` is `docs/a.md`); a join
4064
+ * value matches exactly.
4065
+ */
4066
+ entry: string;
4067
+ /** The owned key to write. */
4068
+ key: string;
4069
+ /** The value to write. Mappings and lists are written in block style. */
4070
+ value: unknown;
4071
+ /** `path` (the default) or the frontmatter field the manifest joins on. */
4072
+ join?: string;
4073
+ /** The manifest as the run reports it, for error messages. */
4074
+ file?: string;
4075
+ }
4076
+ interface SplicedManifest {
4077
+ /** The whole manifest, with the one value rewritten. */
4078
+ text: string;
4079
+ /** 1-based line where the written value now starts. */
4080
+ line: number;
4081
+ }
4082
+ /**
4083
+ * Rewrite `options.key` of `options.entry` in the manifest `text` to
4084
+ * `options.value`, and return the new text and the line the value starts on.
4085
+ *
4086
+ * Throws `DocmetaError`, and never returns a partial result, when:
4087
+ * - the text is not valid YAML, or its top level is not a mapping;
4088
+ * - the entry is named twice, or is not a mapping;
4089
+ * - the key is set twice in the entry, or is `$schema`;
4090
+ * - the value is `undefined`;
4091
+ * - the key or entry is absent and would go into a flow mapping that has
4092
+ * members (`{ jira: A }`), which this writer does not add to;
4093
+ * - the key is written as an explicit `? key`;
4094
+ * - the result does not read back as written.
4095
+ */
4096
+ declare function spliceManifestValue(text: string, options: SpliceManifestOptions): SplicedManifest;
4097
+
4098
+ /** One manifest held for the length of a run: its text before, and now. */
4099
+ interface HeldManifest {
4100
+ /** Absolute path, the write target. */
4101
+ path: string;
4102
+ /** The manifest as the run reports it. */
4103
+ file: string;
4104
+ /** The bytes as they were read. */
4105
+ before: string;
4106
+ /** The bytes as the run has rewritten them. */
4107
+ text: string;
4108
+ }
4109
+ /** Every manifest one run writes, read once and spliced in memory. */
4110
+ declare class ManifestSet {
4111
+ private readonly held;
4112
+ /** Read a manifest, or hand back the copy this run has already rewritten. */
4113
+ hold(manifest: CitationManifest): Promise<HeldManifest>;
4114
+ /**
4115
+ * Write one page's whole `citations` list into its entry, and answer where
4116
+ * the entry at `index` now sits. The manifest is not saved: `changed()`
4117
+ * lists what the run would write.
4118
+ */
4119
+ write(manifest: CitationManifest, entry: string, citations: readonly unknown[], index: number): Promise<{
4120
+ file: string;
4121
+ line: number;
4122
+ }>;
4123
+ /** The manifests this run rewrote, with the diff of each. */
4124
+ changed(): {
4125
+ path: string;
4126
+ file: string;
4127
+ before: string;
4128
+ text: string;
4129
+ diff: string;
4130
+ }[];
4131
+ }
4132
+ /** `spliceManifestValue`, with meta's refusal reported as this tool's. */
4133
+ declare function splice(text: string, options: Parameters<typeof spliceManifestValue>[1]): {
4134
+ text: string;
4135
+ line: number;
4136
+ };
4137
+ /**
4138
+ * The 1-based line of one item of an entry's `citations`, in a manifest that
4139
+ * may not have been written yet. The loader answers this for a manifest on
4140
+ * disk; a freshly spliced one has to be read where it stands, so `add` can
4141
+ * say where the entry it just wrote went.
4142
+ */
4143
+ declare function itemLine(text: string, entry: string, index: number, join: string): number | undefined;
4144
+
4145
+ /**
4146
+ * `checkCitations`: the programmatic core a docevals `tool:cite` grader calls
4147
+ * for one page. Reads the entries and markers, classifies both ends of each
4148
+ * citation, applies the severity table, and returns findings whose messages
4149
+ * spell sources exactly as the entry spelled them.
4150
+ *
4151
+ * The claim end is page-side, so it is judged even under `--no-check-sources`,
4152
+ * which a public docs checkout runs. The source end needs the files.
4153
+ *
4154
+ * `quote: true` is settled here. The claim must still be a fenced block
4155
+ * (`anchor-invalid`), and the block is faithful when it reproduces the cited
4156
+ * lines as pinned (which survives a move and a missing source) or as they are
4157
+ * now (a block someone refreshed ahead of a re-mint). Neither: `quote-drift`.
4158
+ */
4159
+
4160
+ declare function checkCitations(page: {
4161
+ file: string;
4162
+ content: string;
4163
+ format?: string;
4164
+ }, opts: CheckPageOptions): Promise<PageCitationReport>;
4165
+
4166
+ /** The one place a source end's message is composed, per status. */
4167
+ declare function messageFor(source: SourceEnd): string;
4168
+ /** The one place a claim end's message is composed, per status. */
4169
+ declare function claimMessageFor(result: CitationResult): string;
4170
+ /** Findings for classified citations under a severity table; `off` rules produce none. */
4171
+ declare function findingsFor(results: readonly CitationResult[], severity: Readonly<Record<CiteRule, CiteSeverity>>): CitationFinding[];
4172
+ /**
4173
+ * Where a finding is located once it becomes a `FieldError`: the page, or
4174
+ * the manifest the entry sits in.
4175
+ *
4176
+ * A manifest outside the repository has no location any reporter can use —
4177
+ * SARIF drops a uri that rebases to `../…`, and a GitHub annotation on one
4178
+ * lands nowhere — so the finding falls back to the page, and its line goes
4179
+ * with the file it belonged to. Inside the tree, both travel, and `file`
4180
+ * is what every reporter reads to annotate the manifest instead.
4181
+ */
4182
+ declare function errorSite(finding: CitationFinding): Pick<CitationFinding, "line" | "file">;
4183
+ declare function toValidationResult(report: PageCitationReport): ValidationResult;
4184
+
4185
+ /** Append one entry to `citations` (creating the key), via the format's extractor. */
4186
+ declare function appendFrontmatterCitation(content: string, format: string, citation: Citation, filePath?: string): string;
4187
+ /**
4188
+ * The entry as a plain object, in the order a reader scans it, with every
4189
+ * absent optional left out rather than written as `null`.
4190
+ */
4191
+ declare function entryObject(citation: Citation): Record<string, unknown>;
4192
+ /** One scalar of an entry a repair may rewrite: a file, an end's lines, its pin, or the commit. */
4193
+ type EntryPath = readonly [
4194
+ end: "claim" | "source",
4195
+ field: "file" | "lines" | "integrity" | "commit-sha"
4196
+ ];
4197
+ /** Replace the scalar on one line of entry N, e.g. `source.lines` after a move. */
4198
+ declare function spliceEntryField(content: string, format: string, index: number, path: EntryPath, value: LineSpec): string;
4199
+ /** Insert a statement line before the line containing `offset`, with the page's EOL. */
4200
+ declare function insertStatementBefore(content: string, offset: number, statement: string): string;
4201
+ /**
4202
+ * A unified diff of two texts, `---`/`+++` headers with the same label. Lines
4203
+ * are the hashing rule's (`splitLines`): a BOM is never part of a line, so a
4204
+ * page that carries one diffs the same as one that does not.
4205
+ */
4206
+ declare function unifiedDiff(label: string, before: string, after: string): string;
4207
+
4208
+ declare function mintCitation(opts: MintOptions): Promise<Citation>;
4209
+
4210
+ declare const CITE_SECTION = "cite";
4211
+ declare const DEFAULT_CITE_BASELINE_PATH = ".manni-cite-baseline.json";
4212
+ /**
4213
+ * Validate the `cite:` slice of a family file. `raw` is what the loader cut
4214
+ * out: `null` for an empty section, which is the same as no keys at all.
4215
+ * `source` is the file as the user would name it, for the messages.
4216
+ */
4217
+ declare function parseCiteConfig(raw: unknown, source: string): CiteConfig;
4218
+ /**
4219
+ * The family file itself, found as `loadCiteConfig` finds it but before its
4220
+ * `cite:` slice is parsed: the text, the section shape and the family keys
4221
+ * (`collections:`, `encryptionKey:`), for a caller that needs more than the
4222
+ * values, such as a write that puts a key there. `null` when discovery finds
4223
+ * nothing.
4224
+ */
4225
+ declare function readCiteConfigFile(explicitPath: string | undefined, cwd: string): Promise<ConfigFile | null>;
4226
+ /**
4227
+ * Load the config from an explicit path (an error if missing) or by
4228
+ * discovery: cwd and each ancestor up to the nearest `.git` boundary, reading
4229
+ * `manni.config.yaml` at its `cite:` key. A family file with neither `cite:`
4230
+ * nor `collections:` belongs to a sibling tool and discovery keeps looking;
4231
+ * one with `collections:` alone is this tool's config with no options of its
4232
+ * own (0041). See src/shared/config-file.ts for the rules. `null` when
4233
+ * discovery finds nothing.
4234
+ */
4235
+ declare function loadCiteConfig(explicitPath?: string, cwd?: string): Promise<LoadedCiteConfig | null>;
4236
+ interface CiteRunOptions {
4237
+ cwd: string;
4238
+ /** `-c/--config`. */
4239
+ configPath?: string;
4240
+ /** `--no-config`: skip discovery and run on the built-in defaults. */
4241
+ noConfig?: boolean;
4242
+ /** Positional inputs; empty means fall back to the selected collections' `paths:`. */
4243
+ inputs: string[];
4244
+ /**
4245
+ * `--collection <name>`, repeatable: the collections this run covers. Empty
4246
+ * or absent means every declared one, the same thing, because commander's
4247
+ * collector hands `[]` over when the flag was never typed.
4248
+ */
4249
+ collection?: string[];
4250
+ /** `--root`, cwd-relative. */
4251
+ root?: string;
4252
+ onConfigLoaded?: (info: {
4253
+ path: string;
4254
+ dir: string;
4255
+ }) => void;
4256
+ /** Told once when the root fell back to cwd. */
4257
+ onNotice?: (message: string) => void;
4258
+ /** Defaults to `process.env`; a test hands in its own. */
4259
+ env?: NodeJS.ProcessEnv;
4260
+ }
4261
+ /**
4262
+ * Settle what every command core needs before it touches a file: which
4263
+ * config governs the run, what to resolve and from where, the root `src:`
4264
+ * paths resolve against, and the encryption key.
4265
+ */
4266
+ declare function resolveCiteRun(opts: CiteRunOptions): Promise<CiteRun>;
4267
+
4268
+ declare function runCheck(opts: CheckOptions): Promise<CheckRun>;
4269
+
4270
+ declare function runAdd(opts: AddOptions): Promise<AddResult>;
4271
+
4272
+ declare function runUpdate(opts: UpdateOptions): Promise<UpdateRun>;
4273
+
4274
+ /**
4275
+ * `reencryptCitations`: re-encrypt one page's encrypted citations under a new
4276
+ * key, for `manni key rotate` (proposal 0045). It reads sources and never
4277
+ * writes: the caller gets the rewritten page back, and writes it only once
4278
+ * every page in the run could be re-encrypted.
4279
+ *
4280
+ * A citation counts as done only when its `source.file` decrypts under the
4281
+ * new key *and* its pin holds under the new key. Either alone is a half
4282
+ * rotation, and a rerun has to finish it rather than declare it done. Meta's
4283
+ * walker cannot leave one today, because it skips the whole `citations` key
4284
+ * and cite encrypts in its own `cite-src` context; an interrupted run, a hand
4285
+ * edit, or a second writer of the same manifest can.
4286
+ *
4287
+ * The path must be tracked, and the pin must hold under the old key, over the
4288
+ * lines as they are today or, with git, as they were at the entry's
4289
+ * `commit-sha` (the classifier's history search). Then `file` becomes the
4290
+ * path's ciphertext under the new key, its lines kept, and `integrity` the
4291
+ * keyed pin under it, so a `changed` citation stays exactly as changed. A pin
4292
+ * that holds nowhere is skipped, with `update --accept` named as the repair.
4293
+ * No message names a path.
4294
+ */
4295
+
4296
+ /** Options every re-encryption takes, whichever channel the entry lives in. */
4297
+ interface ReencryptOptions {
4298
+ root: string;
4299
+ fromKey: string;
4300
+ toKey: string;
4301
+ /** History and the source index are read through it; defaults to one over the root. */
4302
+ gitClient?: GitClient;
4303
+ sourceIndex?: SourceIndex;
4304
+ }
4305
+ declare function reencryptCitations(page: {
4306
+ file: string;
4307
+ content: string;
4308
+ format?: string;
4309
+ }, opts: ReencryptOptions): Promise<ReencryptCitationsResult>;
4310
+ /** What `reencryptCitationEntries` did to one page's manifest entries. */
4311
+ interface ReencryptEntriesResult {
4312
+ /** The entries as they should now be written, a copy of what came in. */
4313
+ entries: unknown[];
4314
+ /** Whether any of them changed. */
4315
+ changed: boolean;
4316
+ rewritten: ReencryptedCitation[];
4317
+ skipped: {
4318
+ id?: string;
4319
+ index?: number;
4320
+ line?: number;
4321
+ message: string;
4322
+ }[];
4323
+ }
4324
+ /**
4325
+ * The same rotation, for a page whose citations live in a manifest.
4326
+ *
4327
+ * The entries come from meta's merge, so they are plain values; each one is
4328
+ * validated as `readPage` validates a frontmatter entry, and an encrypted
4329
+ * source's `file` and `integrity` are rewritten in place. The caller writes
4330
+ * the whole list back with one splice, once every page of the run could be
4331
+ * re-encrypted.
4332
+ */
4333
+ declare function reencryptCitationEntries(page: {
4334
+ file: string;
4335
+ content: string;
4336
+ format?: string;
4337
+ citations: readonly CitationInput[];
4338
+ }, opts: ReencryptOptions): Promise<ReencryptEntriesResult>;
4339
+
4340
+ /**
4341
+ * Pretty output for `check` and `update`.
4342
+ *
4343
+ * A citation is one row: its name, its claim end, its source end, and, when a
4344
+ * manifest owns the entry, where that is. Both ends read in file lines, the
4345
+ * only lines a person sees. Marks: ✓ current, ✗ error, ↕ warning, ℹ notice,
4346
+ * · skipped or baselined; a file line is ✓, ✗ (an error), ⚠ (a warning, no
4347
+ * error) or ℹ (notices only). Diffs, commit subjects and a changed claim's
4348
+ * current lines print only under `showDiff`; a decrypted path only under
4349
+ * `reveal`. Colour via `shouldColor`; never under `--no-color`/`NO_COLOR`.
4350
+ */
4351
+
4352
+ interface PrettyOptions {
4353
+ color: boolean;
4354
+ quiet?: boolean;
4355
+ showDiff?: boolean;
4356
+ reveal?: boolean;
4357
+ }
4358
+ declare function renderCheckPretty(run: CheckRun, opts: PrettyOptions): string;
4359
+ /** What one rewritten end says it did. */
4360
+ declare function rewriteLine(rewrite: UpdateRewrite): string;
4361
+ declare function renderUpdatePretty(run: UpdateRun, opts: PrettyOptions): string;
4362
+
4363
+ /**
4364
+ * JSON output. `{ summary, pages }` for check; the `UpdateRun` for update.
4365
+ *
4366
+ * A citation prints its two ends and how they are anchored. `resolvedPath`,
4367
+ * `diff`, `commitsSince` and a changed claim's current lines are left out of
4368
+ * every citation: output never says more than the page did. It is an
4369
+ * allowlist rather than a strip, so a field added to the result stays private
4370
+ * until someone decides here that it is safe to print.
4371
+ */
4372
+
4373
+ declare function renderCheckJson(run: CheckRun): string;
4374
+ declare function renderUpdateJson(run: UpdateRun): string;
4375
+
4376
+ declare function renderCheckGithub(run: CheckRun): string;
4377
+
4378
+ /**
4379
+ * The citation tool's programmatic API, exported from the package as the
4380
+ * `cite` namespace: `import { cite } from "@hawkeyexl/manni"`.
4381
+ */
4382
+
4383
+ type index$1_AddOptions = AddOptions;
4384
+ type index$1_AddResult = AddResult;
4385
+ type index$1_BuildIndexOptions = BuildIndexOptions;
4386
+ declare const index$1_CITATIONS_KEY: typeof CITATIONS_KEY;
4387
+ declare const index$1_CITE_RULES: typeof CITE_RULES;
4388
+ declare const index$1_CITE_SECTION: typeof CITE_SECTION;
4389
+ type index$1_CheckOptions = CheckOptions;
4390
+ type index$1_CheckPageOptions = CheckPageOptions;
4391
+ type index$1_CheckRun = CheckRun;
4392
+ type index$1_Citation = Citation;
4393
+ type index$1_CitationAnchor = CitationAnchor;
4394
+ type index$1_CitationClaim = CitationClaim;
4395
+ type index$1_CitationFinding = CitationFinding;
4396
+ type index$1_CitationInput = CitationInput;
4397
+ type index$1_CitationManifest = CitationManifest;
4398
+ type index$1_CitationOrigin = CitationOrigin;
4399
+ type index$1_CitationResult = CitationResult;
4400
+ type index$1_CitationSidecars = CitationSidecars;
4401
+ type index$1_CitationSource = CitationSource;
4402
+ type index$1_CiteConfig = CiteConfig;
4403
+ type index$1_CiteError = CiteError;
4404
+ declare const index$1_CiteError: typeof CiteError;
4405
+ type index$1_CiteRule = CiteRule;
4406
+ type index$1_CiteRun = CiteRun;
4407
+ type index$1_CiteRunOptions = CiteRunOptions;
4408
+ type index$1_CiteSeverity = CiteSeverity;
4409
+ type index$1_ClaimEnd = ClaimEnd;
4410
+ type index$1_ClaimStatus = ClaimStatus;
4411
+ type index$1_ClaimUnit = ClaimUnit;
4412
+ type index$1_ClassifyOptions = ClassifyOptions;
4413
+ declare const index$1_DEFAULT_CITE_BASELINE_PATH: typeof DEFAULT_CITE_BASELINE_PATH;
4414
+ declare const index$1_DEFAULT_SEVERITY: typeof DEFAULT_SEVERITY;
4415
+ type index$1_EntryPath = EntryPath;
4416
+ declare const index$1_FILE_PATTERN: typeof FILE_PATTERN;
4417
+ type index$1_FindWindowsOptions = FindWindowsOptions;
4418
+ declare const index$1_GIT_UNAVAILABLE_COMMIT: typeof GIT_UNAVAILABLE_COMMIT;
4419
+ declare const index$1_GIT_UNAVAILABLE_HISTORY: typeof GIT_UNAVAILABLE_HISTORY;
4420
+ type index$1_GitClient = GitClient;
4421
+ type index$1_HeldManifest = HeldManifest;
4422
+ type index$1_History = History;
4423
+ type index$1_InlineStatement = InlineStatement;
4424
+ type index$1_LineSpec = LineSpec;
4425
+ type index$1_LoadSidecarOptions = LoadSidecarOptions;
4426
+ type index$1_LoadedCiteConfig = LoadedCiteConfig;
4427
+ declare const index$1_MARKER_JSON: typeof MARKER_JSON;
4428
+ declare const index$1_MAX_MARKERS_PER_PAGE: typeof MAX_MARKERS_PER_PAGE;
4429
+ declare const index$1_MAX_RANGE_LINES: typeof MAX_RANGE_LINES;
4430
+ declare const index$1_MOVE_BUDGET_BYTES: typeof MOVE_BUDGET_BYTES;
4431
+ declare const index$1_MOVE_WINDOW_LINES: typeof MOVE_WINDOW_LINES;
4432
+ type index$1_ManifestChange = ManifestChange;
4433
+ type index$1_ManifestSet = ManifestSet;
4434
+ declare const index$1_ManifestSet: typeof ManifestSet;
4435
+ type index$1_ManifestWrite = ManifestWrite;
4436
+ type index$1_MintOptions = MintOptions;
4437
+ type index$1_MissingReason = MissingReason;
4438
+ type index$1_OriginKind = OriginKind;
4439
+ type index$1_PageCitation = PageCitation;
4440
+ type index$1_PageCitationReport = PageCitationReport;
4441
+ type index$1_PageCitations = PageCitations;
4442
+ type index$1_PageLines = PageLines;
4443
+ type index$1_PageSidecar = PageSidecar;
4444
+ type index$1_PrettyOptions = PrettyOptions;
4445
+ declare const index$1_RULE_ID_PREFIX: typeof RULE_ID_PREFIX;
4446
+ type index$1_ReadPageOptions = ReadPageOptions;
4447
+ type index$1_ReadSourceResult = ReadSourceResult;
4448
+ type index$1_ReencryptCitationsResult = ReencryptCitationsResult;
4449
+ type index$1_ReencryptEntriesResult = ReencryptEntriesResult;
4450
+ type index$1_ReencryptOptions = ReencryptOptions;
4451
+ type index$1_ReencryptedCitation = ReencryptedCitation;
4452
+ declare const index$1_SRC_PATTERN: typeof SRC_PATTERN;
4453
+ type index$1_ShownFile = ShownFile;
4454
+ type index$1_SourceEnd = SourceEnd;
4455
+ type index$1_SourceIndex = SourceIndex;
4456
+ type index$1_SourceRange = SourceRange;
4457
+ type index$1_SourceStatus = SourceStatus;
4458
+ type index$1_StatementForm = StatementForm;
4459
+ type index$1_UpdateOptions = UpdateOptions;
4460
+ type index$1_UpdatePage = UpdatePage;
4461
+ type index$1_UpdateRewrite = UpdateRewrite;
4462
+ type index$1_UpdateRun = UpdateRun;
4463
+ declare const index$1_anchoredLines: typeof anchoredLines;
4464
+ declare const index$1_appendFrontmatterCitation: typeof appendFrontmatterCitation;
4465
+ declare const index$1_blockMatches: typeof blockMatches;
4466
+ declare const index$1_bodyLineOf: typeof bodyLineOf;
4467
+ declare const index$1_buildSourceIndex: typeof buildSourceIndex;
4468
+ declare const index$1_checkCitations: typeof checkCitations;
4469
+ declare const index$1_claimEnd: typeof claimEnd;
4470
+ declare const index$1_claimLine: typeof claimLine;
4471
+ declare const index$1_claimMessageFor: typeof claimMessageFor;
4472
+ declare const index$1_classifyCitation: typeof classifyCitation;
4473
+ declare const index$1_detectEol: typeof detectEol;
4474
+ declare const index$1_duplicateJoinRefusal: typeof duplicateJoinRefusal;
4475
+ declare const index$1_entryObject: typeof entryObject;
4476
+ declare const index$1_errorSite: typeof errorSite;
4477
+ declare const index$1_fenceSpanAt: typeof fenceSpanAt;
4478
+ declare const index$1_fencedBlockAfter: typeof fencedBlockAfter;
4479
+ declare const index$1_fencedBlockAt: typeof fencedBlockAt;
4480
+ declare const index$1_fencedBlocks: typeof fencedBlocks;
4481
+ declare const index$1_findWindows: typeof findWindows;
4482
+ declare const index$1_findingsFor: typeof findingsFor;
4483
+ declare const index$1_formatSrc: typeof formatSrc;
4484
+ declare const index$1_formatStatement: typeof formatStatement;
4485
+ declare const index$1_gitClient: typeof gitClient;
4486
+ declare const index$1_hashLines: typeof hashLines;
4487
+ declare const index$1_hashRange: typeof hashRange;
4488
+ declare const index$1_historyOf: typeof historyOf;
4489
+ declare const index$1_insertStatementBefore: typeof insertStatementBefore;
4490
+ declare const index$1_insideFence: typeof insideFence;
4491
+ declare const index$1_isCiteRule: typeof isCiteRule;
4492
+ declare const index$1_isKeyedPin: typeof isKeyedPin;
4493
+ declare const index$1_itemLine: typeof itemLine;
4494
+ declare const index$1_lineAt: typeof lineAt;
4495
+ declare const index$1_lineSpec: typeof lineSpec;
4496
+ declare const index$1_loadCitationSidecars: typeof loadCitationSidecars;
4497
+ declare const index$1_loadCiteConfig: typeof loadCiteConfig;
4498
+ declare const index$1_markerUnit: typeof markerUnit;
4499
+ declare const index$1_messageFor: typeof messageFor;
4500
+ declare const index$1_mintCitation: typeof mintCitation;
4501
+ declare const index$1_noGit: typeof noGit;
4502
+ declare const index$1_normalizeText: typeof normalizeText;
4503
+ declare const index$1_normalizeWhitespace: typeof normalizeWhitespace;
4504
+ declare const index$1_offsetOfLine: typeof offsetOfLine;
4505
+ declare const index$1_orphanRefusal: typeof orphanRefusal;
4506
+ declare const index$1_ownedMessage: typeof ownedMessage;
4507
+ declare const index$1_paragraphAfter: typeof paragraphAfter;
4508
+ declare const index$1_parseCiteConfig: typeof parseCiteConfig;
4509
+ declare const index$1_parseLines: typeof parseLines;
4510
+ declare const index$1_parseSrc: typeof parseSrc;
4511
+ declare const index$1_parseStatements: typeof parseStatements;
4512
+ declare const index$1_pickExtractor: typeof pickExtractor;
4513
+ declare const index$1_pinOfLines: typeof pinOfLines;
4514
+ declare const index$1_rangeLines: typeof rangeLines;
4515
+ declare const index$1_readCiteConfigFile: typeof readCiteConfigFile;
4516
+ declare const index$1_readPage: typeof readPage;
4517
+ declare const index$1_readSource: typeof readSource;
4518
+ declare const index$1_reencryptCitationEntries: typeof reencryptCitationEntries;
4519
+ declare const index$1_reencryptCitations: typeof reencryptCitations;
4520
+ declare const index$1_renderCheckGithub: typeof renderCheckGithub;
4521
+ declare const index$1_renderCheckJson: typeof renderCheckJson;
4522
+ declare const index$1_renderCheckPretty: typeof renderCheckPretty;
4523
+ declare const index$1_renderUpdateJson: typeof renderUpdateJson;
4524
+ declare const index$1_renderUpdatePretty: typeof renderUpdatePretty;
4525
+ declare const index$1_resolveCiteRun: typeof resolveCiteRun;
4526
+ declare const index$1_resolveSeverity: typeof resolveSeverity;
4527
+ declare const index$1_rewriteLine: typeof rewriteLine;
4528
+ declare const index$1_ruleId: typeof ruleId;
4529
+ declare const index$1_runAdd: typeof runAdd;
4530
+ declare const index$1_runCheck: typeof runCheck;
4531
+ declare const index$1_runUpdate: typeof runUpdate;
4532
+ declare const index$1_shortCommit: typeof shortCommit;
4533
+ declare const index$1_shortPin: typeof shortPin;
4534
+ declare const index$1_shortSrc: typeof shortSrc;
4535
+ declare const index$1_sidecarsFor: typeof sidecarsFor;
4536
+ declare const index$1_sliceLines: typeof sliceLines;
4537
+ declare const index$1_sourceRange: typeof sourceRange;
4538
+ declare const index$1_spellLines: typeof spellLines;
4539
+ declare const index$1_spellSource: typeof spellSource;
4540
+ declare const index$1_splice: typeof splice;
4541
+ declare const index$1_spliceEntryField: typeof spliceEntryField;
4542
+ declare const index$1_splitLines: typeof splitLines;
4543
+ declare const index$1_statementForms: typeof statementForms;
4544
+ declare const index$1_toBodyLines: typeof toBodyLines;
4545
+ declare const index$1_toFileLines: typeof toFileLines;
4546
+ declare const index$1_toValidationResult: typeof toValidationResult;
4547
+ declare const index$1_twoManifestsRefusal: typeof twoManifestsRefusal;
4548
+ declare const index$1_unifiedDiff: typeof unifiedDiff;
4549
+ declare const index$1_unitAt: typeof unitAt;
4550
+ declare const index$1_urlManifestRefusal: typeof urlManifestRefusal;
4551
+ declare const index$1_validateEntry: typeof validateEntry;
4552
+ declare namespace index$1 {
4553
+ export { type index$1_AddOptions as AddOptions, type index$1_AddResult as AddResult, type index$1_BuildIndexOptions as BuildIndexOptions, index$1_CITATIONS_KEY as CITATIONS_KEY, index$1_CITE_RULES as CITE_RULES, index$1_CITE_SECTION as CITE_SECTION, type index$1_CheckOptions as CheckOptions, type index$1_CheckPageOptions as CheckPageOptions, type index$1_CheckRun as CheckRun, type index$1_Citation as Citation, type index$1_CitationAnchor as CitationAnchor, type index$1_CitationClaim as CitationClaim, type index$1_CitationFinding as CitationFinding, type index$1_CitationInput as CitationInput, type index$1_CitationManifest as CitationManifest, type index$1_CitationOrigin as CitationOrigin, type index$1_CitationResult as CitationResult, type index$1_CitationSidecars as CitationSidecars, type index$1_CitationSource as CitationSource, type index$1_CiteConfig as CiteConfig, index$1_CiteError as CiteError, type index$1_CiteRule as CiteRule, type index$1_CiteRun as CiteRun, type index$1_CiteRunOptions as CiteRunOptions, type index$1_CiteSeverity as CiteSeverity, type index$1_ClaimEnd as ClaimEnd, type index$1_ClaimStatus as ClaimStatus, type index$1_ClaimUnit as ClaimUnit, type index$1_ClassifyOptions as ClassifyOptions, index$1_DEFAULT_CITE_BASELINE_PATH as DEFAULT_CITE_BASELINE_PATH, index$1_DEFAULT_SEVERITY as DEFAULT_SEVERITY, type index$1_EntryPath as EntryPath, index$1_FILE_PATTERN as FILE_PATTERN, type index$1_FindWindowsOptions as FindWindowsOptions, index$1_GIT_UNAVAILABLE_COMMIT as GIT_UNAVAILABLE_COMMIT, index$1_GIT_UNAVAILABLE_HISTORY as GIT_UNAVAILABLE_HISTORY, type index$1_GitClient as GitClient, type index$1_HeldManifest as HeldManifest, type index$1_History as History, type index$1_InlineStatement as InlineStatement, type index$1_LineSpec as LineSpec, type index$1_LoadSidecarOptions as LoadSidecarOptions, type index$1_LoadedCiteConfig as LoadedCiteConfig, index$1_MARKER_JSON as MARKER_JSON, index$1_MAX_MARKERS_PER_PAGE as MAX_MARKERS_PER_PAGE, index$1_MAX_RANGE_LINES as MAX_RANGE_LINES, index$1_MOVE_BUDGET_BYTES as MOVE_BUDGET_BYTES, index$1_MOVE_WINDOW_LINES as MOVE_WINDOW_LINES, type index$1_ManifestChange as ManifestChange, index$1_ManifestSet as ManifestSet, type index$1_ManifestWrite as ManifestWrite, type index$1_MintOptions as MintOptions, type index$1_MissingReason as MissingReason, type index$1_OriginKind as OriginKind, type index$1_PageCitation as PageCitation, type index$1_PageCitationReport as PageCitationReport, type index$1_PageCitations as PageCitations, type index$1_PageLines as PageLines, type index$1_PageSidecar as PageSidecar, type index$1_PrettyOptions as PrettyOptions, index$1_RULE_ID_PREFIX as RULE_ID_PREFIX, type index$1_ReadPageOptions as ReadPageOptions, type index$1_ReadSourceResult as ReadSourceResult, type index$1_ReencryptCitationsResult as ReencryptCitationsResult, type index$1_ReencryptEntriesResult as ReencryptEntriesResult, type index$1_ReencryptOptions as ReencryptOptions, type index$1_ReencryptedCitation as ReencryptedCitation, index$1_SRC_PATTERN as SRC_PATTERN, type index$1_ShownFile as ShownFile, type index$1_SourceEnd as SourceEnd, type index$1_SourceIndex as SourceIndex, type index$1_SourceRange as SourceRange, type index$1_SourceStatus as SourceStatus, type index$1_StatementForm as StatementForm, type index$1_UpdateOptions as UpdateOptions, type index$1_UpdatePage as UpdatePage, type index$1_UpdateRewrite as UpdateRewrite, type index$1_UpdateRun as UpdateRun, index$1_anchoredLines as anchoredLines, index$1_appendFrontmatterCitation as appendFrontmatterCitation, index$1_blockMatches as blockMatches, index$1_bodyLineOf as bodyLineOf, index$1_buildSourceIndex as buildSourceIndex, index$1_checkCitations as checkCitations, index$1_claimEnd as claimEnd, index$1_claimLine as claimLine, index$1_claimMessageFor as claimMessageFor, index$1_classifyCitation as classifyCitation, index$1_detectEol as detectEol, index$1_duplicateJoinRefusal as duplicateJoinRefusal, index$1_entryObject as entryObject, index$1_errorSite as errorSite, index$1_fenceSpanAt as fenceSpanAt, index$1_fencedBlockAfter as fencedBlockAfter, index$1_fencedBlockAt as fencedBlockAt, index$1_fencedBlocks as fencedBlocks, index$1_findWindows as findWindows, index$1_findingsFor as findingsFor, index$1_formatSrc as formatSrc, index$1_formatStatement as formatStatement, index$1_gitClient as gitClient, index$1_hashLines as hashLines, index$1_hashRange as hashRange, index$1_historyOf as historyOf, index$1_insertStatementBefore as insertStatementBefore, index$1_insideFence as insideFence, index$1_isCiteRule as isCiteRule, index$1_isKeyedPin as isKeyedPin, index$1_itemLine as itemLine, index$1_lineAt as lineAt, index$1_lineSpec as lineSpec, index$1_loadCitationSidecars as loadCitationSidecars, index$1_loadCiteConfig as loadCiteConfig, index$1_markerUnit as markerUnit, index$1_messageFor as messageFor, index$1_mintCitation as mintCitation, index$1_noGit as noGit, index$1_normalizeText as normalizeText, index$1_normalizeWhitespace as normalizeWhitespace, index$1_offsetOfLine as offsetOfLine, index$1_orphanRefusal as orphanRefusal, index$1_ownedMessage as ownedMessage, index$1_paragraphAfter as paragraphAfter, index$1_parseCiteConfig as parseCiteConfig, index$1_parseLines as parseLines, index$1_parseSrc as parseSrc, index$1_parseStatements as parseStatements, index$1_pickExtractor as pickExtractor, index$1_pinOfLines as pinOfLines, index$1_rangeLines as rangeLines, index$1_readCiteConfigFile as readCiteConfigFile, index$1_readPage as readPage, index$1_readSource as readSource, index$1_reencryptCitationEntries as reencryptCitationEntries, index$1_reencryptCitations as reencryptCitations, index$1_renderCheckGithub as renderCheckGithub, index$1_renderCheckJson as renderCheckJson, index$1_renderCheckPretty as renderCheckPretty, index$1_renderUpdateJson as renderUpdateJson, index$1_renderUpdatePretty as renderUpdatePretty, index$1_resolveCiteRun as resolveCiteRun, index$1_resolveSeverity as resolveSeverity, index$1_rewriteLine as rewriteLine, index$1_ruleId as ruleId, index$1_runAdd as runAdd, index$1_runCheck as runCheck, index$1_runUpdate as runUpdate, index$1_shortCommit as shortCommit, index$1_shortPin as shortPin, index$1_shortSrc as shortSrc, index$1_sidecarsFor as sidecarsFor, index$1_sliceLines as sliceLines, index$1_sourceRange as sourceRange, index$1_spellLines as spellLines, index$1_spellSource as spellSource, index$1_splice as splice, index$1_spliceEntryField as spliceEntryField, index$1_splitLines as splitLines, index$1_statementForms as statementForms, index$1_toBodyLines as toBodyLines, index$1_toFileLines as toFileLines, index$1_toValidationResult as toValidationResult, index$1_twoManifestsRefusal as twoManifestsRefusal, index$1_unifiedDiff as unifiedDiff, index$1_unitAt as unitAt, index$1_urlManifestRefusal as urlManifestRefusal, index$1_validateEntry as validateEntry };
4554
+ }
4555
+
4556
+ /**
4557
+ * The key domain's option and result types (proposal 0045). `key` manages a
4558
+ * family resource, the encryption key, rather than documents of its own: `set`
4559
+ * writes it, and `rotate` re-encrypts every value the family's tools wrote
4560
+ * under it before writing a new one.
4561
+ */
4562
+
4563
+ interface KeySetOptions {
4564
+ /** `[value]`: the key to write. Omitted: 64 random hex characters (256 bits). */
4565
+ value?: string;
4566
+ /**
4567
+ * `-c, --config <path>`, relative to `cwd`: the config file to write, which
4568
+ * must exist. Omitted: the nearest `manni.config.yaml` whatever it carries,
4569
+ * else a new one at the git root (else `cwd`).
4570
+ */
4571
+ configPath?: string;
4572
+ /** `--dry-run`: name the target and write nothing. */
4573
+ dryRun?: boolean;
4574
+ cwd?: string;
4575
+ /** Read for `MANNI_ENCRYPTION_KEY`. Defaults to `process.env`; tests pass their own. */
4576
+ env?: NodeJS.ProcessEnv;
4577
+ /** A stderr diagnostic (the git warning); the CLI adds the `manni: ` prefix. */
4578
+ onNotice?: (message: string) => void;
4579
+ }
4580
+ /** What `set` wrote, or would have. Never the key. */
4581
+ interface KeySetResult {
4582
+ /** Absolute path of the config file. */
4583
+ path: string;
4584
+ /** The file as the user would name it, for the report. */
4585
+ source: string;
4586
+ /** Whether the write creates the file. */
4587
+ created: boolean;
4588
+ /** Whether the key was generated rather than given. */
4589
+ generated: boolean;
4590
+ dryRun: boolean;
4591
+ }
4592
+ interface KeyRotateOptions {
4593
+ /** `[paths...]`: files, directories or globs. Empty: every collection. Any makes the run narrowed. */
4594
+ inputs: string[];
4595
+ /** `--collection <name>`, repeatable. Empty or absent: every collection. Any makes the run narrowed. */
4596
+ collection?: string[];
4597
+ /**
4598
+ * `--to <value>`: the new key. Omitted on a whole run with a key from the
4599
+ * config: 64 random hex characters. Required for a narrowed run and for a
4600
+ * key from `MANNI_ENCRYPTION_KEY`.
4601
+ */
4602
+ to?: string;
4603
+ /** `--ext <list>`, already split: extensions for directory walks. */
4604
+ exts?: string[];
4605
+ /** `--exclude <glob>`, repeatable; added to the selected collections' `exclude:` on a collection run. */
4606
+ exclude?: string[];
4607
+ /** `--as <format>`: force an extractor for every input. */
4608
+ as?: string;
4609
+ /** `-c, --config <path>`: the config the current key is read from and the new one written to. */
4610
+ configPath?: string;
4611
+ /** `--allow-empty`: zero matched files is success. */
4612
+ allowEmpty?: boolean;
4613
+ /** `--no-gitignore` (false). Absent: `.gitignore` is respected. */
4614
+ respectGitignore?: boolean;
4615
+ /** `--root <dir>`, cwd-relative: where cited sources resolve from. Else `cite.root`, else the git root, else `cwd`. */
4616
+ root?: string;
4617
+ /** `--dry-run`: re-encrypt in memory, write nothing. */
4618
+ dryRun?: boolean;
4619
+ cwd?: string;
4620
+ /** Read for `MANNI_ENCRYPTION_KEY`. Defaults to `process.env`; tests pass their own. */
4621
+ env?: NodeJS.ProcessEnv;
4622
+ /** Stderr diagnostics; the CLI adds the `manni: ` prefix. */
4623
+ onNotice?: (message: string) => void;
4624
+ /**
4625
+ * The git client sources and history are read through. Defaults to one
4626
+ * over the root, used whenever git is on PATH and the root is inside a
4627
+ * work tree; a test hands in a fake.
4628
+ */
4629
+ gitClient?: GitClient;
4630
+ /**
4631
+ * How a page or a manifest is written. Defaults to an atomic write; tests
4632
+ * inject a failure.
4633
+ */
4634
+ writePage?: (path: string, content: string) => Promise<void>;
4635
+ }
4636
+ /** A metadata value re-encrypted: its JSON pointer, and the ciphertext before and after. */
4637
+ interface RotatedMetadata {
4638
+ kind: "metadata";
4639
+ pointer: string;
4640
+ from: string;
4641
+ to: string;
4642
+ }
4643
+ /** A citation re-encrypted: where it sits, and its `src` (line suffix kept) before and after. */
4644
+ interface RotatedCitation {
4645
+ kind: "citation";
4646
+ id?: string;
4647
+ /** Index in `citations` for a frontmatter entry. */
4648
+ index?: number;
4649
+ line?: number;
4650
+ from: string;
4651
+ to: string;
4652
+ }
4653
+ type RotatedValue = RotatedMetadata | RotatedCitation;
4654
+ interface SkippedMetadata {
4655
+ kind: "metadata";
4656
+ pointer: string;
4657
+ message: string;
4658
+ }
4659
+ interface SkippedCitation {
4660
+ kind: "citation";
4661
+ id?: string;
4662
+ index?: number;
4663
+ line?: number;
4664
+ message: string;
4665
+ }
4666
+ /** A value that could not be re-encrypted, and why. A message never names a path or a value. */
4667
+ type SkippedValue = SkippedMetadata | SkippedCitation;
4668
+ /** One page with something encrypted on it. */
4669
+ interface RotatePage {
4670
+ file: string;
4671
+ rewritten: RotatedValue[];
4672
+ skipped: SkippedValue[];
4673
+ /** Whether this run wrote the page. */
4674
+ written: boolean;
4675
+ }
4676
+ /**
4677
+ * A value re-encrypted in an external-metadata manifest (proposals 0037 and
4678
+ * 0041): which document entry supplied it, and where it sits in that entry.
4679
+ */
4680
+ interface RotatedManifestValue {
4681
+ /** The document entry, exactly as the manifest spells it. */
4682
+ entry: string;
4683
+ /** JSON pointer into the entry's owned keys: `/owner`, `/contacts/0/email`. */
4684
+ pointer: string;
4685
+ from: string;
4686
+ to: string;
4687
+ }
4688
+ /** A manifest value that could not be re-encrypted, and why. */
4689
+ interface SkippedManifestValue {
4690
+ entry: string;
4691
+ pointer: string;
4692
+ message: string;
4693
+ }
4694
+ /**
4695
+ * One local external-metadata manifest with something encrypted in it. A URL
4696
+ * manifest is read-only (0038) and is never planned, so it never appears.
4697
+ */
4698
+ interface RotateManifest {
4699
+ /** The manifest as the run reports it, relative to the run's base. */
4700
+ file: string;
4701
+ /** The collection whose `externalMetadata:` declared it. */
4702
+ collection: string;
4703
+ rewritten: RotatedManifestValue[];
4704
+ skipped: SkippedManifestValue[];
4705
+ /** Whether this run wrote the manifest. */
4706
+ written: boolean;
4707
+ }
4708
+ /**
4709
+ * How a run ended, which decides its last line:
4710
+ *
4711
+ * - `written`: a whole run wrote the pages, then the new key to the config.
4712
+ * - `finished`: a whole run finished a rotation an interruption left behind.
4713
+ * - `narrowed`: paths or `--collection`; pages written, key not.
4714
+ * - `env`: the key comes from `MANNI_ENCRYPTION_KEY`; pages written, key not.
4715
+ * - `skipped`: a value could not be re-encrypted; nothing written (exit 1).
4716
+ * - `dry-run`: nothing written.
4717
+ */
4718
+ type RotateOutcome = "written" | "finished" | "narrowed" | "env" | "skipped" | "dry-run";
4719
+ interface KeyRotateResult {
4720
+ /** Pages that had something to re-encrypt or skip, in the order they were read. */
4721
+ pages: RotatePage[];
4722
+ /**
4723
+ * Local external-metadata manifests that had something to re-encrypt or
4724
+ * skip, in the order the selected collections declare them.
4725
+ */
4726
+ manifests: RotateManifest[];
4727
+ /** Values re-encrypted, in memory under `--dry-run` and a skip. */
4728
+ reencrypted: number;
4729
+ skipped: number;
4730
+ /** Whether the config now holds the new key because of this run. */
4731
+ keyWritten: boolean;
4732
+ outcome: RotateOutcome;
4733
+ /** The config file the key comes from, as the user would name it; absent for an environment key. */
4734
+ configSource?: string;
4735
+ /** A citation baseline exists and this run wrote pages, so its pins are stale. */
4736
+ baselineStale: boolean;
4737
+ /** `0` everything re-encrypted, `1` something skipped. Operational errors throw. */
4738
+ exitCode: 0 | 1;
4739
+ }
4740
+
4741
+ /** An operational or usage error in the key domain: exit 2. */
4742
+ declare class KeyError extends ToolError {
4743
+ constructor(message: string);
4744
+ }
4745
+
4746
+ declare function runKeySet(opts: KeySetOptions): Promise<KeySetResult>;
4747
+
4748
+ declare function runKeyRotate(opts: KeyRotateOptions): Promise<KeyRotateResult>;
4749
+
4750
+ /** Which kind of value a token holds. Bound as associated data. */
4751
+ type EncryptionContext = "meta" | "cite-src";
4752
+ /** Whether `value` is shaped like a token. Says nothing about which key. */
4753
+ declare function isEncryptedValue(value: unknown): value is string;
4754
+ /**
4755
+ * Encrypt any JSON value. Throws for a value that is not JSON (`undefined`, a
4756
+ * function) and for a key that is not key-shaped: both are programming
4757
+ * errors, since keys arrive through `resolveEncryptionKey`.
4758
+ */
4759
+ declare function encryptValue(value: unknown, key: string, context: EncryptionContext): string;
4760
+ /**
4761
+ * Decrypt a token. `{ ok: false }` for anything that is not a canonical token
4762
+ * under this key and context; never throws.
4763
+ */
4764
+ declare function decryptValue(token: string, key: string, context: EncryptionContext): {
4765
+ ok: true;
4766
+ value: unknown;
4767
+ } | {
4768
+ ok: false;
4769
+ };
4770
+
4771
+ /**
4772
+ * The key domain's programmatic API, exported from the package as the `key`
4773
+ * namespace: `import { key } from "@hawkeyexl/manni"`. The command cores, and
4774
+ * the family's encryption primitives a caller needs beside them.
4775
+ */
4776
+
4777
+ type index_EncryptionContext = EncryptionContext;
4778
+ type index_KeyError = KeyError;
4779
+ declare const index_KeyError: typeof KeyError;
4780
+ type index_KeyRotateOptions = KeyRotateOptions;
4781
+ type index_KeyRotateResult = KeyRotateResult;
4782
+ type index_KeySetOptions = KeySetOptions;
4783
+ type index_KeySetResult = KeySetResult;
4784
+ type index_KeySource = KeySource;
4785
+ type index_ResolvedKey = ResolvedKey;
4786
+ type index_RotateManifest = RotateManifest;
4787
+ type index_RotateOutcome = RotateOutcome;
4788
+ type index_RotatePage = RotatePage;
4789
+ type index_RotatedCitation = RotatedCitation;
4790
+ type index_RotatedManifestValue = RotatedManifestValue;
4791
+ type index_RotatedMetadata = RotatedMetadata;
4792
+ type index_RotatedValue = RotatedValue;
4793
+ type index_SkippedCitation = SkippedCitation;
4794
+ type index_SkippedManifestValue = SkippedManifestValue;
4795
+ type index_SkippedMetadata = SkippedMetadata;
4796
+ type index_SkippedValue = SkippedValue;
4797
+ declare const index_decryptValue: typeof decryptValue;
4798
+ declare const index_encryptValue: typeof encryptValue;
4799
+ declare const index_isEncryptedValue: typeof isEncryptedValue;
4800
+ declare const index_resolveEncryptionKey: typeof resolveEncryptionKey;
4801
+ declare const index_runKeyRotate: typeof runKeyRotate;
4802
+ declare const index_runKeySet: typeof runKeySet;
4803
+ declare namespace index {
4804
+ export { type index_EncryptionContext as EncryptionContext, index_KeyError as KeyError, type index_KeyRotateOptions as KeyRotateOptions, type index_KeyRotateResult as KeyRotateResult, type index_KeySetOptions as KeySetOptions, type index_KeySetResult as KeySetResult, type index_KeySource as KeySource, type index_ResolvedKey as ResolvedKey, type index_RotateManifest as RotateManifest, type index_RotateOutcome as RotateOutcome, type index_RotatePage as RotatePage, type index_RotatedCitation as RotatedCitation, type index_RotatedManifestValue as RotatedManifestValue, type index_RotatedMetadata as RotatedMetadata, type index_RotatedValue as RotatedValue, type index_SkippedCitation as SkippedCitation, type index_SkippedManifestValue as SkippedManifestValue, type index_SkippedMetadata as SkippedMetadata, type index_SkippedValue as SkippedValue, index_decryptValue as decryptValue, index_encryptValue as encryptValue, index_isEncryptedValue as isEncryptedValue, index_resolveEncryptionKey as resolveEncryptionKey, index_runKeyRotate as runKeyRotate, index_runKeySet as runKeySet };
4805
+ }
4806
+
4807
+ export { type ApplyOptions, type Approval, type BaselineSummary, BinMissing, type BuiltinDerivableField, COMMON_FORMATS, type CheckConfig, type CollectionConfig, type CommandSourceOptions, type CommandSourceResult, type CommonFormat, type ConfigNotice, DEFAULT_SCHEMAS, DEFAULT_TTL_HOURS, DEFAULT_VENDOR_DIR, DERIVABLE_FIELDS, DERIVED_KEYWORD, DERIVED_STALE_SCHEMA, DERIVE_FORMATS, DERIVE_SOURCES, type DerivableField, type DeriveCommand, type DeriveCommandConfig, type DeriveConfig, type DeriveContext, type DeriveFileResult, type DeriveInput, type DeriveOptions, type DeriveReportFormat, type DeriveReportOptions, type DeriveResult, type DeriveRun, type DeriveSource, type DeriveSummary, type DerivedField, type DerivedRecord, type DerivedStatus, type DerivedValue, type DocmetaConfig, DocmetaError, type DocumentRefTrust, EXTERNAL_DUPLICATE_SCHEMA, EXTERNAL_KEYWORD, EXTERNAL_METADATA_FETCH_MAX_BYTES, EXTERNAL_METADATA_FETCH_TIMEOUT_MS, EXTERNAL_OWNED_SCHEMA, type ExternalMetadataCollision, type ExternalMetadataConfig, type ExternalMetadataEntry, type ExternalMetadataFetchOptions, type ExternalMetadataIndex, type ExternalMetadataJoin, type ExternalMetadataValue, type ExtractOptions, type ExtractedMetadata, FIELD_SOURCES, FILL_FORMATS, type FetchedSchema, type FieldError, type FillConfig, type FillFileResult, type FillOptions, type FillReportFormat, type FillReportOptions, type FillRun, type FillSummary, type FilledField, type FingerprintContext, type FrontmatterFlavor, type FrontmatterLocation, type GetFileResult, type GetOptions, type GetReportOptions, GitHubClient, GitLabClient, INTEGRITY_SHAPE, type JunitOptions, type LoadExternalMetadataOptions, type LoadSchemaOptions, type LoadedConfig, type MergedChange, type MergedMetadata, type MetadataExtractor, type MetadataPatch, PATH_JOIN, PATH_PLACEHOLDER, QUERY_FORMATS, type QueryChange, type QueryFormat, type QueryOptions, type QueryReportOptions, type QueryRun, REPORT_FORMATS, RESOLVED_VIEW, REVIEW_CACHE_DIR, REVIEW_CACHE_VERSION, type ReadOptions, type ReencryptMetadataResult, type ReencryptedValue, type RemoteIdentity, type ReportFormat, type ReportOptions, ReviewCache, type ReviewClient, type ReviewFacts, type ReviewSourceInput, type ReviewSourceResult, type Run, type RunConfig, type RunConfigOptions, type RunSummary, SCHEMA_CACHE_DIR, SCHEMA_CACHE_VERSION, type SarifOptions, SchemaCache, type SchemaCacheConfig, type SchemaCacheEntry, type SchemaEntry, type SchemaPin, type SchemaRefEntry, type SchemaTrustConfig, type SkipReason, type SourceLocation, type SourceStatus$1 as SourceStatus, type SpawnOptions, type ValidateOptions, type ValidateRun, type ValidationResult, Validator, type VendorOptions, type VendorResult, applyFrontmatter, argvFor, assertSourcesAvailable, cachedClient, index$1 as cite, classifyRef, collectSchemaPins, compareDerived, consultedSources, createResolvedView, createReviewClient, deriveFromCommands, deriveFromReviews, deriveMetadata, externalMetadataJoin, externalMetadataPointer, externalMetadataUrlProblem, extractFrontmatter, extractorForExtension, fetchExternalMetadata, fetchSchemaBytes, frontmatterInnerText, getSchemasInfo, identityFromOrigin, integrityOf, isBuiltinField, isCommonFormat, isDeriveFormat, isDeriveSource, isErrorSeverity, isFillFormat, isIntegrity, isMember, isPerFile, isQueryFormat, isReportFormat, index as key, listBuiltins, loadConfig, loadExternalMetadata, loadSchema, locateFrontmatter, memberOf, mentionsResolved, mergeExternalMetadata, orphanEntries, orphanError, orphanJoins, parseCollections, parseConfig, parseOriginUrl, rebaseConfigSchemaRefs, reencryptMetadata, render, renderDerive, renderFill, renderFillGithub, renderGet, renderJunit, renderQuery, renderQueryCsv, renderSarif, resolveRunConfig, resolveSchemaSet, resolvedColumns, run, runDerive, runFill, runGet, runQuery, runValidate, runVendorSchema, schemaCacheDir, schemaEntryRef, schemaLoadOptions, selectCollections, sourcesFor, staleFindings, stringifyValue, supportedExtensions, valueOf, vendorFileName, writeFileAtomic };