@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/chunk-7ZN43F3Y.js +4492 -0
- package/dist/chunk-7ZN43F3Y.js.map +1 -0
- package/dist/{chunk-WP2BP3ZX.js → chunk-GGVNTB7W.js} +69 -43
- package/dist/chunk-GGVNTB7W.js.map +1 -0
- package/dist/{chunk-7SE7XDCL.js → chunk-XU2QTJQQ.js} +13461 -12212
- package/dist/chunk-XU2QTJQQ.js.map +1 -0
- package/dist/cli.js +558 -27
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +2 -2
- package/dist/index.d.ts +2098 -12
- package/dist/index.js +30 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-7SE7XDCL.js.map +0 -1
- package/dist/chunk-WP2BP3ZX.js.map +0 -1
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
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 };
|