@cosyte/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1360 @@
1
+ import { R as RunDeps } from './io-B2EobRzC.js';
2
+ export { r as readFileBytes, a as readStreamBytes } from './io-B2EobRzC.js';
3
+ import 'node:stream';
4
+
5
+ /**
6
+ * The CLI version string, synced with `package.json#version` on release by the Changesets `version`
7
+ * script. Kept in its own module so both the programmatic entry point and the dispatcher share one
8
+ * source of truth.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ /**
13
+ * The `@cosyte/cli` version. On the uniform `v0.0.x-until-first-alpha` ladder.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { VERSION } from "@cosyte/cli";
18
+ *
19
+ * typeof VERSION; // => "string"
20
+ * ```
21
+ */
22
+ declare const VERSION = "0.0.0";
23
+
24
+ /**
25
+ * The `cosyte` CLI **exit-code contract**: a designed, documented surface that CI pipelines and
26
+ * shell scripts branch on. Grounded in the Unix `sysexits.h` conventions.
27
+ *
28
+ * The load-bearing rule: **the CLI never prints a reassuring line and exits `0` on input it could not
29
+ * handle.** An undetectable format, an unreadable file, or a parser that throws each map to a
30
+ * distinct, stable non-zero code, never a silent success.
31
+ *
32
+ * | Code | Name | Meaning |
33
+ * |------|------------|----------------------------------------------------------------------|
34
+ * | `0` | `OK` | success: the operation completed; `validate` found the input **valid** |
35
+ * | `1` | `INVALID` | operation-level failure: `validate` found the input **invalid** (a real, expected CI signal: the message is bad, the tool worked) |
36
+ * | `2` | `USAGE` | usage error: unknown command, bad flag, missing argument (EX_USAGE) |
37
+ * | `65` | `DATAERR` | data error: input could not be parsed / format not detected (EX_DATAERR) |
38
+ * | `66` | `NOINPUT` | no input: the file does not exist or is unreadable (EX_NOINPUT) |
39
+ * | `69` | `UNAVAILABLE` | a required capability is not yet available: e.g. `redact` before `@cosyte/deid` ships (EX_UNAVAILABLE) |
40
+ * | `70` | `SOFTWARE` | internal error: an unexpected exception, i.e. a bug (EX_SOFTWARE) |
41
+ *
42
+ * The load-bearing `validate` rule: a **parseable-but-invalid** message is exit `1`, never exit `0`.
43
+ * The CLI must never print a reassuring line and exit green on a bad message. Exit `65` is reserved
44
+ * for input that could not be **parsed** at all (a distinct signal from "parsed, but does not
45
+ * conform").
46
+ *
47
+ * @packageDocumentation
48
+ */
49
+ /**
50
+ * The stable exit-code map. Adding a code is a documented, tested change to the CLI's contract;
51
+ * renaming or repurposing one is a breaking change.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * import { EXIT } from "@cosyte/cli";
56
+ *
57
+ * process.exitCode = EXIT.OK; // => 0
58
+ * ```
59
+ */
60
+ declare const EXIT: {
61
+ /** Success: the operation completed; `validate` found the input **valid**. */
62
+ readonly OK: 0;
63
+ /** Operation-level failure: `validate` found the input **invalid** (parseable but non-conformant):
64
+ * a real, expected CI signal that the message is bad and the tool worked. Never emitted for
65
+ * unparseable input (that is `DATAERR`). */
66
+ readonly INVALID: 1;
67
+ /** Usage error: unknown command, bad flag, missing argument (`EX_USAGE`). */
68
+ readonly USAGE: 2;
69
+ /** Data error: input could not be parsed or its format could not be detected (`EX_DATAERR`). */
70
+ readonly DATAERR: 65;
71
+ /** No input: the named file does not exist or is unreadable (`EX_NOINPUT`). */
72
+ readonly NOINPUT: 66;
73
+ /** Unavailable: a required capability is not yet built (e.g. `redact` before `@cosyte/deid`), a
74
+ * distinct non-zero signal that is never a fake success (`EX_UNAVAILABLE`). */
75
+ readonly UNAVAILABLE: 69;
76
+ /** Internal error: an unexpected exception (a bug), distinct from a handled bad input (`EX_SOFTWARE`). */
77
+ readonly SOFTWARE: 70;
78
+ };
79
+ /**
80
+ * A value from {@link EXIT}: the exit code a CLI invocation resolves to.
81
+ */
82
+ type ExitCode = (typeof EXIT)[keyof typeof EXIT];
83
+
84
+ /**
85
+ * The result of running a CLI invocation, as data: decoupled from `process` so the whole command
86
+ * tree is testable. The thin `bin` entry writes {@link RunResult.stdout} to `process.stdout`,
87
+ * {@link RunResult.stderr} to `process.stderr`, and exits with {@link RunResult.exit}.
88
+ *
89
+ * The two channels carry the CLI's PHI posture: **stdout is the data channel** (the
90
+ * user's explicit request: the parsed model), while **stderr is value-free**: codes and positions
91
+ * only, never an input value.
92
+ *
93
+ * @packageDocumentation
94
+ */
95
+
96
+ /**
97
+ * A fully-resolved CLI invocation.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * import { EXIT, type RunResult } from "@cosyte/cli";
102
+ *
103
+ * const r: RunResult = { stdout: "{}\n", stderr: "", exit: EXIT.OK };
104
+ * r.exit; // => 0
105
+ * ```
106
+ */
107
+ interface RunResult {
108
+ /** The data channel: the parsed model or requested output. May contain the user's data by design. */
109
+ readonly stdout: string;
110
+ /** The diagnostic channel is **value-free**: codes, positions, file paths, format names only. */
111
+ readonly stderr: string;
112
+ /** The exit code the invocation resolves to. */
113
+ readonly exit: ExitCode;
114
+ }
115
+
116
+ /**
117
+ * The CLI's **value-free diagnostic channel**. Every error the CLI raises on its own behalf carries a
118
+ * stable `CLI_*` code, a fixed exit code, and a **PHI-safe** message built only from positional /
119
+ * structural context: a segment or field index, a byte offset, a file path, a format name, a warning
120
+ * code. **A diagnostic never echoes an input value** (a name, a DOB, an MRN, a result). This is the
121
+ * parsers' "warning = code + position, never a value" rule applied at the CLI edge.
122
+ *
123
+ * @packageDocumentation
124
+ */
125
+
126
+ /**
127
+ * Stable **CLI diagnostic code** registry: errors the CLI owns (routing, I/O, argument handling),
128
+ * distinct from the wrapped library's own warning/issue codes which are passed through unchanged.
129
+ * Each code is its own value (`key === value`) so the set survives `Object.values(...)`; renaming or
130
+ * removing one is a **breaking change** because scripts branch on the stderr text.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * import { CLI_CODES } from "@cosyte/cli";
135
+ *
136
+ * if (diagnostic.code === CLI_CODES.CLI_FORMAT_UNDETECTED) {
137
+ * // ask the user for --format
138
+ * }
139
+ * ```
140
+ */
141
+ declare const CLI_CODES: {
142
+ /** A required argument was missing or a flag was invalid. Exit `2`. */
143
+ readonly CLI_USAGE: "CLI_USAGE";
144
+ /** The named file does not exist or could not be read. Exit `66`. */
145
+ readonly CLI_NO_INPUT: "CLI_NO_INPUT";
146
+ /** The input was empty, no bytes to detect or parse. Exit `65`. */
147
+ readonly CLI_EMPTY_INPUT: "CLI_EMPTY_INPUT";
148
+ /** No format signature matched; the CLI will not guess. Names the candidates, never the bytes. Exit `65`. */
149
+ readonly CLI_FORMAT_UNDETECTED: "CLI_FORMAT_UNDETECTED";
150
+ /** More than one format signature matched; the CLI will not guess. Names the candidates, never the bytes. Exit `65`. */
151
+ readonly CLI_FORMAT_AMBIGUOUS: "CLI_FORMAT_AMBIGUOUS";
152
+ /** A recognised format whose parser does not support the requested operation (e.g. `parse` on a
153
+ * format wired only for `inspect`). Names the format + operation, never the bytes. Exit `65`. */
154
+ readonly CLI_FORMAT_UNSUPPORTED: "CLI_FORMAT_UNSUPPORTED";
155
+ /** The optional parser package for a recognised format is not installed. The six breadth parsers
156
+ * (dicom/x12/ccda/ncpdp/astm/mllp) are `optionalDependencies`: normally installed, but if
157
+ * one is absent the CLI degrades to this value-free signal rather than crashing. Exit `69`. */
158
+ readonly CLI_PARSER_UNAVAILABLE: "CLI_PARSER_UNAVAILABLE";
159
+ /** The wrapped parser rejected the input. Positional context only, never the offending bytes. Exit `65`. */
160
+ readonly CLI_PARSE_FAILED: "CLI_PARSE_FAILED";
161
+ /** The BYO ConceptMap supplied to `map-codes` is not valid JSON or not a loadable FHIR ConceptMap.
162
+ * Names the stable terminology-loader code, never the map's bytes. Exit `65`. */
163
+ readonly CLI_MAP_INVALID: "CLI_MAP_INVALID";
164
+ /** A command whose ground-layer library is not yet built (e.g. `redact` before `@cosyte/deid`
165
+ * ships). Never a fake success: a distinct, value-free "unavailable" signal. Exit `69`. */
166
+ readonly CLI_NOT_IMPLEMENTED: "CLI_NOT_IMPLEMENTED";
167
+ /** An unexpected internal error (a bug). Exit `70`. */
168
+ readonly CLI_INTERNAL: "CLI_INTERNAL";
169
+ };
170
+ /**
171
+ * A value from {@link CLI_CODES}: the stable code carried by a {@link CliError}.
172
+ */
173
+ type CliCode = (typeof CLI_CODES)[keyof typeof CLI_CODES];
174
+ /**
175
+ * A typed, PHI-safe CLI error. Its {@link CliError.message | message} is **value-free by
176
+ * construction**: callers must build it from codes, indices, offsets, format names, and file paths,
177
+ * never from an input value. It carries the {@link ExitCode} the invocation resolves to.
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * import { CliError, CLI_CODES, EXIT } from "@cosyte/cli";
182
+ *
183
+ * throw new CliError(CLI_CODES.CLI_NO_INPUT, EXIT.NOINPUT, "cannot read the named file");
184
+ * ```
185
+ */
186
+ declare class CliError extends Error {
187
+ /** The stable diagnostic code. */
188
+ readonly code: CliCode;
189
+ /** The exit code this error resolves the invocation to. */
190
+ readonly exit: ExitCode;
191
+ /**
192
+ * @param code - A stable {@link CliCode}.
193
+ * @param exit - The {@link ExitCode} to resolve to.
194
+ * @param message - A **value-free** explanation (positional/structural context only, never PHI).
195
+ */
196
+ constructor(code: CliCode, exit: ExitCode, message: string);
197
+ }
198
+ /**
199
+ * Render a {@link CliError} as a single value-free `stderr` line: `cosyte: <CODE>: <message>`. The
200
+ * message is already value-free by the {@link CliError} contract; this only prefixes the tool name
201
+ * and the code so scripts and humans can branch on a stable token.
202
+ *
203
+ * @param err - The CLI error to render.
204
+ * @returns The stderr line (no trailing newline).
205
+ * @example
206
+ * ```ts
207
+ * import { CliError, CLI_CODES, EXIT, formatDiagnostic } from "@cosyte/cli";
208
+ *
209
+ * formatDiagnostic(new CliError(CLI_CODES.CLI_USAGE, EXIT.USAGE, "missing <file> argument"));
210
+ * // => "cosyte: CLI_USAGE: missing <file> argument"
211
+ * ```
212
+ */
213
+ declare function formatDiagnostic(err: CliError): string;
214
+ /**
215
+ * Resolve a {@link CliError} into a value-free {@link RunResult}: empty `stdout` (nothing reaches the
216
+ * data channel on an error), the rendered diagnostic on `stderr`, and the error's exit code. The
217
+ * single place the CLI turns an owned error into a result, so every command and the dispatcher render
218
+ * errors identically.
219
+ *
220
+ * @param err - The CLI error to resolve.
221
+ * @returns The value-free {@link RunResult}.
222
+ * @example
223
+ * ```ts
224
+ * import { CliError, CLI_CODES, EXIT, errorResult } from "@cosyte/cli";
225
+ *
226
+ * errorResult(new CliError(CLI_CODES.CLI_USAGE, EXIT.USAGE, "missing <file>")).exit; // => 2
227
+ * ```
228
+ */
229
+ declare function errorResult(err: CliError): RunResult;
230
+ /**
231
+ * Coerce an unknown thrown value into a {@link CliError}. A {@link CliError} passes through; anything
232
+ * else becomes a `CLI_INTERNAL` / {@link EXIT.SOFTWARE} error whose message is a **fixed, value-free
233
+ * string**: the original message is deliberately discarded so a parser exception that embedded input
234
+ * bytes can never reach stderr.
235
+ *
236
+ * @param err - The caught value.
237
+ * @returns A {@link CliError} safe to render to stderr.
238
+ * @example
239
+ * ```ts
240
+ * import { toCliError } from "@cosyte/cli";
241
+ *
242
+ * toCliError(new Error("boom")).code; // => "CLI_INTERNAL"
243
+ * ```
244
+ */
245
+ declare function toCliError(err: unknown): CliError;
246
+
247
+ /**
248
+ * **Content-based format autodetection**: the feature that makes `cosyte parse <file>` feel magic,
249
+ * and the one that must **fail safe**. Detection sniffs the leading bytes' *content*, never the file
250
+ * extension: a `.txt` full of `MSH|^~\&…` is HL7; a `.json` with a `resourceType` is FHIR.
251
+ *
252
+ * The hazard is a wrong sniff routing bytes to the wrong parser and yielding confident garbage. So
253
+ * detection is **conservative**: a single confident signature match parses; **zero or more than one**
254
+ * match is *not* a guess. It is a typed `none`/`ambiguous` result the caller turns into a data-error
255
+ * exit asking for `--format`. This is the parsers' "never a confident wrong value" rule at the
256
+ * routing layer.
257
+ *
258
+ * All eight cosyte formats carry a signature: **hl7** (`MSH` + field separator), **mllp**
259
+ * (a leading `0x0B` VT frame byte: an MLLP-framed stream, de-framed to its enclosed HL7), **fhir** (a
260
+ * JSON object declaring `resourceType`), **x12** (a leading `ISA` interchange header), **astm** (a
261
+ * leading `H` record whose second byte is the field delimiter), **ccda** (a `<ClinicalDocument>` root),
262
+ * **ncpdp** (a `<Message>` root in the NCPDP SCRIPT namespace), and **dicom** (the `DICM` magic at byte
263
+ * 128). The signatures are **conservative and, on realistic inputs, mutually exclusive**: the
264
+ * distinctive-lead formats (`MSH`, `ISA`, `H`+delimiter, `<ClinicalDocument>`, `<Message>`+ncpdp, the
265
+ * `DICM` magic, `0x0B` VT, `{…"resourceType"`) don't overlap on a real message of any one type. They
266
+ * are **not** disjoint in the absolute sense: a pathological input could satisfy two (an MLLP frame
267
+ * enclosing a `<ClinicalDocument>` payload matches both `mllp` and `ccda`; a text file whose byte 128
268
+ * is `DICM` matches both), which is exactly why the **`ambiguous` branch is load-bearing, not dead
269
+ * code**: any co-match is a *detected* ambiguity (a value-free data error asking for `--format`),
270
+ * **never a silent mis-route**.
271
+ *
272
+ * @packageDocumentation
273
+ */
274
+
275
+ /** The set of formats the `cosyte` command names. */
276
+ type CosyteFormat = "hl7" | "fhir" | "dicom" | "x12" | "ccda" | "ncpdp" | "astm" | "mllp";
277
+ /**
278
+ * How confident autodetection is:
279
+ * - `certain`: exactly one signature matched (`format` names it);
280
+ * - `ambiguous`: more than one matched (`format` is `null`; `candidates` names them);
281
+ * - `none`: nothing matched (`format` is `null`; `candidates` is empty).
282
+ *
283
+ * `format` is `null` unless `confidence` is `certain`, so a non-certain result can never be mistaken
284
+ * for a routable format.
285
+ */
286
+ interface DetectResult {
287
+ /** The detected format, or `null` when `confidence` is not `certain`. */
288
+ readonly format: CosyteFormat | null;
289
+ /** The detection confidence. */
290
+ readonly confidence: "certain" | "ambiguous" | "none";
291
+ /** The matching candidate formats (0 for `none`, 1 for `certain`, ≥2 for `ambiguous`). Value-free. */
292
+ readonly candidates: readonly CosyteFormat[];
293
+ }
294
+ /** The formats content-autodetection can recognise (every format now carries a signature). */
295
+ declare const DETECTABLE_FORMATS: readonly CosyteFormat[];
296
+ /**
297
+ * Detect the healthcare format of `bytes` by content, conservatively.
298
+ *
299
+ * @param bytes - The input bytes (a whole file or a stdin buffer). Only the leading prefix is sniffed.
300
+ * @returns A {@link DetectResult}: `certain` + a `format` on a single match, else `ambiguous`/`none`
301
+ * with `format: null` and the value-free `candidates` list. **Never guesses.**
302
+ * @example
303
+ * ```ts
304
+ * import { detectFormat } from "@cosyte/cli";
305
+ *
306
+ * const enc = new TextEncoder();
307
+ * detectFormat(enc.encode("MSH|^~\\&|A|B\r")).format; // => "hl7"
308
+ * detectFormat(enc.encode('{"resourceType":"Patient"}')).format; // => "fhir"
309
+ * detectFormat(enc.encode("hello")).confidence; // => "none"
310
+ * ```
311
+ */
312
+ declare function detectFormat(bytes: Uint8Array): DetectResult;
313
+ /**
314
+ * Classify a list of matched candidate formats into a {@link DetectResult}: exactly one → `certain`,
315
+ * zero → `none`, two-or-more → `ambiguous` (all with `format` `null` unless certain). Split out and
316
+ * exported so the **ambiguity** contract is directly testable. It is otherwise unreachable while
317
+ * every signature is disjoint, and it must stay a *detected* ambiguity, never a mis-route.
318
+ *
319
+ * @param candidates - The formats whose signatures matched the input.
320
+ * @returns The classified {@link DetectResult}.
321
+ * @example
322
+ * ```ts
323
+ * import { classifyCandidates } from "@cosyte/cli";
324
+ *
325
+ * classifyCandidates(["hl7"]).confidence; // => "certain"
326
+ * classifyCandidates([]).confidence; // => "none"
327
+ * classifyCandidates(["hl7", "fhir"]).confidence; // => "ambiguous"
328
+ * ```
329
+ */
330
+ declare function classifyCandidates(candidates: readonly CosyteFormat[]): DetectResult;
331
+ /**
332
+ * Build the value-free {@link CliError} for a **non-certain** detection: the data error the caller
333
+ * returns instead of guessing a parser. `ambiguous` names the matching candidates (a value-free code
334
+ * list); `none` asks for `--format`. Both map to the data-error exit (`65`). Never echoes input bytes.
335
+ *
336
+ * @param detected - A {@link DetectResult} whose `format` is `null` (i.e. not `certain`).
337
+ * @returns A value-free `CLI_FORMAT_AMBIGUOUS` or `CLI_FORMAT_UNDETECTED` error.
338
+ * @example
339
+ * ```ts
340
+ * import { classifyCandidates, detectionError } from "@cosyte/cli";
341
+ *
342
+ * detectionError(classifyCandidates([])).code; // => "CLI_FORMAT_UNDETECTED"
343
+ * detectionError(classifyCandidates(["hl7", "fhir"])).code; // => "CLI_FORMAT_AMBIGUOUS"
344
+ * ```
345
+ */
346
+ declare function detectionError(detected: DetectResult): CliError;
347
+ /** The full set of format names `--format` accepts as syntactically valid (a bad value is a usage error). */
348
+ declare const KNOWN_FORMATS: readonly CosyteFormat[];
349
+ /**
350
+ * Narrow an arbitrary `--format` string to a {@link CosyteFormat}, or `null` if it is not a known
351
+ * format name (which the caller turns into a usage error, exit `2`).
352
+ *
353
+ * @param value - The raw `--format` argument.
354
+ * @returns The narrowed format, or `null`.
355
+ * @example
356
+ * ```ts
357
+ * import { asCosyteFormat } from "@cosyte/cli";
358
+ *
359
+ * asCosyteFormat("hl7"); // => "hl7"
360
+ * asCosyteFormat("nope"); // => null
361
+ * ```
362
+ */
363
+ declare function asCosyteFormat(value: string): CosyteFormat | null;
364
+
365
+ /**
366
+ * The CLI's **value-free finding** shape and the positional locators that populate it. A finding says
367
+ * *what kind* of thing was observed (a stable code + severity) and *where* (a positional locator),
368
+ * **never** the offending value. Shared by `validate` (conformance findings) and
369
+ * `inspect` (structural summary) so both render locations identically and value-free.
370
+ *
371
+ * @packageDocumentation
372
+ */
373
+ /**
374
+ * A single value-free finding: a stable code, a severity, and a positional locator. Every field is
375
+ * safe to print, log, or serialize. None carries a name, DOB, MRN, or field value.
376
+ */
377
+ interface Finding {
378
+ /** The stable diagnostic/warning code (the wrapped library's or the CLI's). */
379
+ readonly code: string;
380
+ /** The R4-style severity (`fatal` | `error` | `warning` | `information`), or `warning` for HL7. */
381
+ readonly severity: string;
382
+ /** A value-free positional locator: a FHIRPath expression, or an HL7 segment/field index path. */
383
+ readonly location: string;
384
+ }
385
+ /** The minimal, value-free positional shape shared by HL7 warnings (indices only, never a value). */
386
+ interface Hl7PositionLike {
387
+ readonly segmentIndex: number;
388
+ readonly fieldIndex?: number;
389
+ readonly repetitionIndex?: number;
390
+ readonly componentIndex?: number;
391
+ readonly subcomponentIndex?: number;
392
+ }
393
+ /**
394
+ * Render an HL7 warning position as a **value-free** locator string built only from its numeric
395
+ * indices: e.g. `seg[3].field[5].comp[1]`. No segment content, no field value, ever appears; only the
396
+ * structural coordinates the parser reported.
397
+ *
398
+ * @param pos - The HL7 position (segment/field/repetition/component/subcomponent indices).
399
+ * @returns A value-free locator, e.g. `"seg[3].field[5]"`.
400
+ * @example
401
+ * ```ts
402
+ * import { formatHl7Position } from "@cosyte/cli";
403
+ *
404
+ * formatHl7Position({ segmentIndex: 3, fieldIndex: 5 }); // => "seg[3].field[5]"
405
+ * formatHl7Position({ segmentIndex: 0 }); // => "seg[0]"
406
+ * ```
407
+ */
408
+ declare function formatHl7Position(pos: Hl7PositionLike): string;
409
+
410
+ /**
411
+ * The **per-format parser adapter registry**: the single place the CLI routes a resolved format to
412
+ * its wrapped `@cosyte/*` parser, for each of the four wrapping operations (`parse` / `inspect` /
413
+ * `fmt` / `validate`). One lazy, value-free registry, so the wrapper boundary lives in exactly one
414
+ * file.
415
+ *
416
+ * **Capability is per (format, operation).** Not every parser faithfully supports every operation:
417
+ * DICOM's model is binary (no faithful JSON `parse`, no text `fmt`), C-CDA's canonical form is XML (no
418
+ * library-blessed JSON `parse`), MLLP is a transport container (de-framed to HL7, `parse`/`inspect`
419
+ * only). {@link OP_SUPPORT} is the honest matrix; an unsupported (format, op) is a value-free
420
+ * `CLI_FORMAT_UNSUPPORTED`, **never** a faked result.
421
+ *
422
+ * **Lazy + optional.** Every parser is imported dynamically inside its branch, so `cosyte parse msg.hl7`
423
+ * never loads the DICOM or X12 code. The six breadth parsers are `optionalDependencies`: if
424
+ * one is absent the dynamic import is caught and degrades to a value-free `CLI_PARSER_UNAVAILABLE`
425
+ * (exit `69`) rather than an unhandled crash: the CLI core still works with any of them missing.
426
+ *
427
+ * @packageDocumentation
428
+ */
429
+
430
+ /** The four wrapping operations a command can ask a format's adapter to perform. */
431
+ type Op = "parse" | "inspect" | "fmt" | "validate";
432
+ /** A value-free parse warning: a stable code plus the parser's positional (index-only) context. */
433
+ type ParseWarning = {
434
+ readonly code: string;
435
+ } & Readonly<Record<string, unknown>>;
436
+ /** The result of wrapping a parser's `parse`: the library's parsed model + its value-free warnings. */
437
+ interface ParseResult {
438
+ /** The wrapped library's parsed model: emitted verbatim as JSON on the data channel. */
439
+ readonly model: unknown;
440
+ /** The parser's value-free warnings (code + position). */
441
+ readonly warnings: readonly ParseWarning[];
442
+ }
443
+ /** The result of a canonical re-serialization (`fmt`): the spec-clean text + a value-free warning count. */
444
+ interface FmtResult {
445
+ /** The wrapped serializer's output text. */
446
+ readonly output: string;
447
+ /** How many parse warnings the round-trip surfaced (value-free count only). */
448
+ readonly warningCount: number;
449
+ }
450
+ /** The verdict of running a format's validation surface: value-free findings + the validity boolean. */
451
+ interface Verdict {
452
+ /** The value-free findings (code + severity + positional locator). */
453
+ readonly findings: readonly Finding[];
454
+ /** `true` iff the input is valid (no error/fatal-severity finding). */
455
+ readonly valid: boolean;
456
+ }
457
+ /** Value-free structural summary of an HL7 v2 message. */
458
+ interface Hl7Summary {
459
+ readonly format: "hl7";
460
+ readonly messageType: string | null;
461
+ readonly version: string | null;
462
+ readonly segmentCount: number;
463
+ readonly segments: Readonly<Record<string, number>>;
464
+ readonly warningCount: number;
465
+ }
466
+ /** Value-free structural summary of a FHIR resource. */
467
+ interface FhirSummary {
468
+ readonly format: "fhir";
469
+ readonly resourceType: string | null;
470
+ readonly bundleType?: string | null;
471
+ readonly entryCount?: number;
472
+ readonly entryResourceTypes?: Readonly<Record<string, number>>;
473
+ readonly issueCount: number;
474
+ }
475
+ /** Value-free structural summary of an X12 interchange (envelope counts + transaction-set ids). */
476
+ interface X12Summary {
477
+ readonly format: "x12";
478
+ readonly groupCount: number;
479
+ readonly transactionCount: number;
480
+ /** Count of each transaction-set identifier code (ST-01), e.g. `{ "834": 1 }`: value-free codes. */
481
+ readonly transactionSetIds: Readonly<Record<string, number>>;
482
+ readonly segmentCount: number;
483
+ readonly warningCount: number;
484
+ }
485
+ /** Value-free structural summary of an ASTM record message. */
486
+ interface AstmSummary {
487
+ readonly format: "astm";
488
+ /** The host-query classification kind (`results` | `orders` | `host-query` | `indeterminate`). */
489
+ readonly messageKind: string;
490
+ readonly recordCount: number;
491
+ /** Count of each single-letter record type, e.g. `{ H: 1, P: 1, O: 2, R: 4, L: 1 }`. */
492
+ readonly recordTypes: Readonly<Record<string, number>>;
493
+ readonly warningCount: number;
494
+ }
495
+ /** Value-free structural summary of a C-CDA document (document type + section LOINC codes). */
496
+ interface CcdaSummary {
497
+ readonly format: "ccda";
498
+ readonly documentType: string | null;
499
+ readonly sectionCount: number;
500
+ /** The LOINC `code` of each top-level section (value-free classification codes). */
501
+ readonly sectionCodes: readonly string[];
502
+ readonly warningCount: number;
503
+ }
504
+ /** Value-free structural summary of a DICOM dataset (classification UIDs + element count). */
505
+ interface DicomSummary {
506
+ readonly format: "dicom";
507
+ /** The SOP Class UID (a standard OID identifying the object type: value-free classification). */
508
+ readonly sopClassUid: string | null;
509
+ /** The Transfer Syntax UID (encoding classification: value-free). */
510
+ readonly transferSyntaxUid: string | null;
511
+ readonly elementCount: number;
512
+ readonly warningCount: number;
513
+ }
514
+ /** Value-free structural summary of an NCPDP SCRIPT message. */
515
+ interface NcpdpSummary {
516
+ readonly format: "ncpdp";
517
+ readonly standard: "SCRIPT";
518
+ /** The SCRIPT message type (e.g. `NewRx`, `CancelRx`: a value-free classification). */
519
+ readonly messageType: string | null;
520
+ /** The SCRIPT version (e.g. `2017071`: value-free). */
521
+ readonly version: string | null;
522
+ readonly warningCount: number;
523
+ }
524
+ /** Value-free structural summary of an MLLP stream (frame count only; the payloads are HL7). */
525
+ interface MllpSummary {
526
+ readonly format: "mllp";
527
+ readonly frameCount: number;
528
+ readonly warningCount: number;
529
+ }
530
+ /** The discriminated value-free structural summary `inspect` renders. */
531
+ type InspectSummary = Hl7Summary | FhirSummary | X12Summary | AstmSummary | CcdaSummary | DicomSummary | NcpdpSummary | MllpSummary;
532
+ /**
533
+ * The honest per-format operation matrix. A (format, op) pair absent here is a value-free
534
+ * `CLI_FORMAT_UNSUPPORTED`, never a faked result. The unsupported cells and why:
535
+ * - **dicom** `parse`/`fmt`. The model is binary (no faithful JSON view; `serializeDicom` emits a
536
+ * Part-10 byte stream, not text). `inspect`/`validate` are supported.
537
+ * - **ccda** `parse`: the canonical form is XML; there is no library-blessed JSON model, so `fmt`
538
+ * (XML re-serialize) is the faithful surface. `inspect`/`fmt`/`validate` are supported.
539
+ * - **mllp** `fmt`/`validate`: MLLP is a transport container the CLI de-frames to HL7; `parse` yields
540
+ * the enclosed HL7 message(s) and `inspect` reports the frame count.
541
+ *
542
+ * @example
543
+ * ```ts
544
+ * import { OP_SUPPORT } from "@cosyte/cli";
545
+ *
546
+ * OP_SUPPORT.dicom.has("parse"); // => false
547
+ * OP_SUPPORT.hl7.has("validate"); // => true
548
+ * ```
549
+ */
550
+ declare const OP_SUPPORT: Readonly<Record<CosyteFormat, ReadonlySet<Op>>>;
551
+ /**
552
+ * True iff `format`'s wrapped parser supports `op` in this build (see {@link OP_SUPPORT}).
553
+ *
554
+ * @param format - The resolved format.
555
+ * @param op - The wrapping operation.
556
+ * @returns Whether the (format, op) pair is wired.
557
+ * @example
558
+ * ```ts
559
+ * import { supportsOp } from "@cosyte/cli";
560
+ *
561
+ * supportsOp("x12", "fmt"); // => true
562
+ * supportsOp("dicom", "parse"); // => false
563
+ * ```
564
+ */
565
+ declare function supportsOp(format: CosyteFormat, op: Op): boolean;
566
+ /**
567
+ * The formats that support `op`, as a sorted, value-free list: used to build the "does not support"
568
+ * diagnostic so the user is told which formats *do* support the operation they asked for.
569
+ *
570
+ * @param op - The wrapping operation.
571
+ * @returns The supporting format names, sorted.
572
+ * @example
573
+ * ```ts
574
+ * import { formatsSupporting } from "@cosyte/cli";
575
+ *
576
+ * formatsSupporting("fmt"); // => ["astm", "ccda", "fhir", "hl7", "ncpdp", "x12"]
577
+ * ```
578
+ */
579
+ declare function formatsSupporting(op: Op): readonly CosyteFormat[];
580
+ /**
581
+ * Render an arbitrary parser **position** object as a value-free locator string, keeping **only**
582
+ * number-valued own properties (the parsers' positions are index-only): e.g. `{ segmentIndex: 3,
583
+ * elementIndex: 2 }` → `segmentIndex[3].elementIndex[2]`. A non-number field (which a position should
584
+ * never carry) is dropped, so a stray value can never reach a diagnostic. Falls back to `"?"` when no
585
+ * numeric index is present.
586
+ *
587
+ * @param pos - A parser position object (index-only by the parser's contract).
588
+ * @returns A value-free locator built solely from numeric indices.
589
+ * @example
590
+ * ```ts
591
+ * import { valueFreeLocator } from "@cosyte/cli";
592
+ *
593
+ * valueFreeLocator({ segmentIndex: 3, elementIndex: 2 }); // => "segmentIndex[3].elementIndex[2]"
594
+ * valueFreeLocator({}); // => "?"
595
+ * ```
596
+ */
597
+ declare function valueFreeLocator(pos: unknown): string;
598
+ /**
599
+ * Lazy-import an **optional** parser package, mapping an *absent* package to a value-free
600
+ * `CLI_PARSER_UNAVAILABLE` (exit `69`): the graceful-degradation path for the `optionalDependencies`
601
+ * breadth parsers. A genuine import that succeeds passes straight through; any error whose
602
+ * shape is "module not found" becomes the value-free CLI error. Other errors propagate unchanged.
603
+ *
604
+ * @template T - The imported module's type.
605
+ * @param format - The format whose optional parser is being loaded (named in the diagnostic).
606
+ * @param load - A thunk performing the dynamic import.
607
+ * @returns The imported module.
608
+ * @throws {CliError} `CLI_PARSER_UNAVAILABLE` (exit `69`) when the package is absent; any other error
609
+ * propagates unchanged.
610
+ * @example
611
+ * ```ts
612
+ * import { loadOptional } from "@cosyte/cli";
613
+ *
614
+ * // a present parser resolves; an absent one throws CLI_PARSER_UNAVAILABLE
615
+ * await loadOptional("x12", () => import("@cosyte/x12"));
616
+ * ```
617
+ */
618
+ declare function loadOptional<T>(format: CosyteFormat, load: () => Promise<T>): Promise<T>;
619
+ /**
620
+ * Parse one record of `format` into the wrapped library's model + its value-free warnings. The model
621
+ * is emitted verbatim on the data channel; the CLI adds no parsing of its own.
622
+ *
623
+ * @param format - A format for which `supportsOp(format, "parse")` is true.
624
+ * @param bytes - The single record's bytes (already de-framed for MLLP: callers pass `"hl7"` there).
625
+ * @returns The parsed model + value-free warnings.
626
+ * @throws {CliError} `CLI_PARSER_UNAVAILABLE` if the optional parser is absent; the wrapped parser's
627
+ * own rejection propagates for the command's value-free failure boundary to catch.
628
+ * @example
629
+ * ```ts
630
+ * import { parseFormat } from "@cosyte/cli";
631
+ *
632
+ * const bytes = new TextEncoder().encode('{"resourceType":"Patient","id":"x"}');
633
+ * (await parseFormat("fhir", bytes)).warnings.length; // => 0
634
+ * ```
635
+ */
636
+ declare function parseFormat(format: CosyteFormat, bytes: Uint8Array): Promise<ParseResult>;
637
+ /**
638
+ * Build the value-free structural summary of one input of `format`: counts and structural type codes
639
+ * only, never a field value.
640
+ *
641
+ * @param format - A format for which `supportsOp(format, "inspect")` is true.
642
+ * @param bytes - The input bytes.
643
+ * @returns A {@link InspectSummary} variant for the format.
644
+ * @throws {CliError} `CLI_PARSER_UNAVAILABLE` if the optional parser is absent; the wrapped parser's
645
+ * rejection propagates for the command's value-free failure boundary.
646
+ * @example
647
+ * ```ts
648
+ * import { inspectFormat } from "@cosyte/cli";
649
+ *
650
+ * const bytes = new TextEncoder().encode('{"resourceType":"Patient"}');
651
+ * (await inspectFormat("fhir", bytes)).format; // => "fhir"
652
+ * ```
653
+ */
654
+ declare function inspectFormat(format: CosyteFormat, bytes: Uint8Array): Promise<InspectSummary>;
655
+ /**
656
+ * Canonically re-serialize one input of `format` via the wrapped library's spec-clean serializer. The
657
+ * CLI never re-canonicalizes on its own; the output is exactly the serializer's.
658
+ *
659
+ * @param format - A format for which `supportsOp(format, "fmt")` is true.
660
+ * @param bytes - The input bytes.
661
+ * @returns The serialized text + a value-free warning count.
662
+ * @throws {CliError} `CLI_PARSER_UNAVAILABLE` if the optional parser is absent; the wrapped parser's
663
+ * rejection propagates for the command's value-free failure boundary (no partial emit).
664
+ * @example
665
+ * ```ts
666
+ * import { fmtFormat } from "@cosyte/cli";
667
+ *
668
+ * const bytes = new TextEncoder().encode('{ "resourceType":"Patient" , "id":"x" }');
669
+ * (await fmtFormat("fhir", bytes)).output.startsWith("{"); // => true
670
+ * ```
671
+ */
672
+ declare function fmtFormat(format: CosyteFormat, bytes: Uint8Array): Promise<FmtResult>;
673
+ /**
674
+ * Run the format's validation surface and return a value-free {@link Verdict}. For the Postel's-Law
675
+ * lenient parsers, a **parseable** input is valid: recovered deviations are non-fatal warnings the
676
+ * library surfaces, never a stricter verdict the CLI invents. FHIR additionally runs `validateResource`
677
+ * and is invalid on any error/fatal-severity issue.
678
+ *
679
+ * @param format - A format for which `supportsOp(format, "validate")` is true.
680
+ * @param bytes - The input bytes.
681
+ * @returns The value-free verdict (findings + validity).
682
+ * @throws {CliError} `CLI_PARSER_UNAVAILABLE` if the optional parser is absent; an unparseable input
683
+ * propagates as the wrapped parser's throw for the command to map to a data error (`65`).
684
+ * @example
685
+ * ```ts
686
+ * import { validateFormat } from "@cosyte/cli";
687
+ *
688
+ * const bytes = new TextEncoder().encode('{"resourceType":"Patient","gender":"male"}');
689
+ * (await validateFormat("fhir", bytes)).valid; // => true
690
+ * ```
691
+ */
692
+ declare function validateFormat(format: CosyteFormat, bytes: Uint8Array): Promise<Verdict>;
693
+ /**
694
+ * De-frame an MLLP byte stream into its enclosed HL7 payloads via `@cosyte/mllp`'s `FrameReader`. MLLP
695
+ * is a transport container, not a document format: each frame's payload is an HL7 v2 message the CLI
696
+ * then parses/inspects with the `hl7` adapter. Multi-frame streams are the CLI's multi-message surface.
697
+ *
698
+ * @param bytes - The MLLP-framed input.
699
+ * @returns The de-framed HL7 payloads (in stream order) + a value-free framing-warning count.
700
+ * **Truncation is a data error, never a silent drop.** The `FrameReader` is a streaming decoder: an
701
+ * unterminated trailing frame (a VT opened with no closing FS/CR) is left buffered and delivered by
702
+ * *no* callback, so feeding a whole file and reading only `onFrame` would silently lose the partial
703
+ * message with a green exit. We therefore detect an open trailing frame at the byte level (the last
704
+ * VT sits after the last FS: MLLP payloads are HL7 v2 text and never carry the `0x0B`/`0x1C` framing
705
+ * bytes) and reject the whole stream as a value-free `CLI_PARSE_FAILED` data error.
706
+ *
707
+ * @throws {CliError} `CLI_PARSER_UNAVAILABLE` if `@cosyte/mllp` is absent; `CLI_PARSE_FAILED` (exit
708
+ * `65`) on a truncated stream; a hard framing error propagates for the caller's value-free boundary.
709
+ * @example
710
+ * ```ts
711
+ * import { deframeMllp } from "@cosyte/cli";
712
+ *
713
+ * // a VT-framed "MSH|..." message → one payload
714
+ * (await deframeMllp(new Uint8Array([0x0b, 0x4d, 0x53, 0x48, 0x1c, 0x0d]))).payloads.length; // => 1
715
+ * ```
716
+ */
717
+ declare function deframeMllp(bytes: Uint8Array): Promise<{
718
+ payloads: Buffer[];
719
+ warningCount: number;
720
+ }>;
721
+
722
+ /**
723
+ * The shared **input + format resolution** every file-consuming command runs before it touches a
724
+ * wrapped parser: resolve the `<file|->` argument, read its bytes (a file, or stdin for `-`), reject
725
+ * empty input, then resolve the format: an explicit `--format` override (validated) or conservative
726
+ * content autodetection, and confirm the format is actually wired in this build. Factored out of the
727
+ * commands so `parse`/`validate`/`inspect`/`fmt` share one identical, value-free front door and the
728
+ * exit-code contract is applied in exactly one place.
729
+ *
730
+ * Every failure is a value-free {@link CliError} rendered to a {@link RunResult}: a missing argument
731
+ * is a usage error (`2`), an unreadable file a no-input error (`66`), empty/undetected/unwired input a
732
+ * data error (`65`). None ever echoes an input byte.
733
+ *
734
+ * @packageDocumentation
735
+ */
736
+
737
+ /** A successfully-resolved input: the format (guaranteed to support the requested op) and the bytes. */
738
+ interface ResolvedInput {
739
+ /** The resolved format: guaranteed to satisfy `supportsOp(format, op)` for the requested op. */
740
+ readonly format: CosyteFormat;
741
+ /** The input bytes (a whole file or a drained stdin buffer); guaranteed non-empty. */
742
+ readonly bytes: Uint8Array;
743
+ }
744
+ /**
745
+ * The outcome of {@link resolveInput}: either the resolved input, or a ready-to-return value-free
746
+ * {@link RunResult} carrying the diagnostic + exit code for whatever went wrong. A discriminated union
747
+ * so a command reads `if (!r.ok) return r.result;` and then works with `r.input`.
748
+ */
749
+ type InputResolution = {
750
+ readonly ok: true;
751
+ readonly input: ResolvedInput;
752
+ } | {
753
+ readonly ok: false;
754
+ readonly result: RunResult;
755
+ };
756
+ /**
757
+ * Resolve and read the input, and resolve its format, for a file-consuming command.
758
+ *
759
+ * @param source - The positional `<file|->` argument (or `undefined` when it was omitted).
760
+ * @param formatOverride - The raw `--format` value, or `undefined` to autodetect by content.
761
+ * @param deps - Injected input readers ({@link RunDeps}).
762
+ * @param op - The wrapping operation the caller will run; the resolved format is confirmed to support
763
+ * it (else a value-free `CLI_FORMAT_UNSUPPORTED` naming the supporting formats).
764
+ * @returns `{ ok: true, input }` when the bytes read and the format resolved to a parser supporting
765
+ * `op`; else `{ ok: false, result }` with a value-free usage/no-input/data-error {@link RunResult}.
766
+ * @throws Propagates a **non-`CliError`** read failure unchanged, so the dispatcher maps it to
767
+ * `CLI_INTERNAL` (a `CliError` read failure, e.g. a missing file, is caught and returned).
768
+ * @example
769
+ * ```ts
770
+ * import { resolveInput } from "@cosyte/cli";
771
+ *
772
+ * const deps = {
773
+ * readFile: async () => new TextEncoder().encode('{"resourceType":"Patient"}'),
774
+ * readStdin: async () => new Uint8Array(),
775
+ * };
776
+ * const r = await resolveInput("patient.json", undefined, deps, "parse");
777
+ * if (r.ok) r.input.format; // => "fhir"
778
+ * ```
779
+ */
780
+ declare function resolveInput(source: string | undefined, formatOverride: string | undefined, deps: RunDeps, op: Op): Promise<InputResolution>;
781
+
782
+ /**
783
+ * The CLI's **global PHI display posture**: the single mechanism that gates whether *any* input
784
+ * value may appear on a **secondary surface** (stderr, a diagnostic, a warning, a log line). The CLI
785
+ * is **value-free by default**: every secondary surface carries only positional/structural context
786
+ * (a stable code, a segment/field index, a byte offset, a file path, a format name), never a name, a
787
+ * DOB, an MRN, or a field value. `stdout` is the **data channel** (the user's explicit request) and
788
+ * is exempt: the posture governs everything *but* stdout.
789
+ *
790
+ * `--unsafe-show-values` is the **single, explicit, loud door** to a value on a secondary surface. It
791
+ * is off by default, PHI-exposing by design, and its effect flows through exactly one chokepoint here
792
+ * ({@link unsafeInputSuffix}) so the "a value appears on a secondary surface **iff** the flag is set"
793
+ * property is provable in one place rather than scattered across commands.
794
+ *
795
+ * @packageDocumentation
796
+ */
797
+ /**
798
+ * The resolved PHI display posture for one invocation. `showValues` is `true` **only** when the user
799
+ * passed `--unsafe-show-values`; every value-echoing decision reads this one flag.
800
+ */
801
+ interface PhiPosture {
802
+ /** `true` iff `--unsafe-show-values` was given: a value may appear on a secondary surface. */
803
+ readonly showValues: boolean;
804
+ }
805
+ /** The default, safe posture: no value ever reaches a secondary surface. */
806
+ declare const VALUE_FREE: PhiPosture;
807
+ /** The opted-in, PHI-exposing posture selected by `--unsafe-show-values`. */
808
+ declare const SHOW_VALUES: PhiPosture;
809
+ /** The single global flag token that opts into showing values on secondary surfaces. */
810
+ declare const UNSAFE_SHOW_VALUES_FLAG = "--unsafe-show-values";
811
+ /**
812
+ * The maximum number of leading input bytes an `--unsafe-show-values` diagnostic may echo. Bounded so
813
+ * an unsafe excerpt stays a single, readable diagnostic line rather than dumping a whole message.
814
+ */
815
+ declare const UNSAFE_EXCERPT_MAX = 200;
816
+ /**
817
+ * Resolve the global `--unsafe-show-values` flag out of an argument vector, **order-independently**
818
+ * (it may appear before or after the subcommand), and return the posture plus the argv with every
819
+ * occurrence of the flag removed, so each command's own `parseArgs` never sees it and cannot reject
820
+ * it as unknown. This is the one place the flag is recognised.
821
+ *
822
+ * @param argv - The raw arguments (after the program name).
823
+ * @returns The resolved {@link PhiPosture} and the flag-stripped argv.
824
+ * @example
825
+ * ```ts
826
+ * import { extractPhiPosture } from "@cosyte/cli";
827
+ *
828
+ * extractPhiPosture(["parse", "x.hl7"]).posture.showValues; // => false
829
+ * extractPhiPosture(["--unsafe-show-values", "parse", "x.hl7"]).posture.showValues; // => true
830
+ * extractPhiPosture(["parse", "x.hl7", "--unsafe-show-values"]).argv; // => ["parse", "x.hl7"]
831
+ * ```
832
+ */
833
+ declare function extractPhiPosture(argv: readonly string[]): {
834
+ posture: PhiPosture;
835
+ argv: string[];
836
+ };
837
+ /**
838
+ * Build the **only** value-bearing addition the CLI ever appends to a secondary (stderr) surface: a
839
+ * bounded, single-line excerpt of the offending input, shown **iff** `--unsafe-show-values` is set.
840
+ * Under the default value-free posture it returns the empty string, so a diagnostic stays value-free
841
+ * unless the user explicitly opted in. This is the single chokepoint the PHI-leak matrix pins.
842
+ *
843
+ * @param bytes - The input the CLI is operating on (only the leading {@link UNSAFE_EXCERPT_MAX} bytes
844
+ * are considered).
845
+ * @param posture - The resolved {@link PhiPosture}.
846
+ * @returns `""` under the value-free default; otherwise a ` [unsafe-show-values] …` suffix carrying a
847
+ * bounded, newline-flattened prefix of `bytes`.
848
+ * @example
849
+ * ```ts
850
+ * import { unsafeInputSuffix, VALUE_FREE, SHOW_VALUES } from "@cosyte/cli";
851
+ *
852
+ * const bytes = new TextEncoder().encode("bad message");
853
+ * unsafeInputSuffix(bytes, VALUE_FREE); // => ""
854
+ * unsafeInputSuffix(bytes, SHOW_VALUES); // => " [unsafe-show-values] offending input …: bad message"
855
+ * ```
856
+ */
857
+ declare function unsafeInputSuffix(bytes: Uint8Array, posture: PhiPosture): string;
858
+
859
+ /**
860
+ * The **wrapped-parser failure boundary**: the single, value-free way every command turns a thrown
861
+ * parser/codec exception into a {@link RunResult}. A wrapped library raises a fatal on genuinely
862
+ * unparseable input; its message (and, for HL7, its `snippet`) can embed the offending bytes, so the
863
+ * CLI **never** surfaces that message. It surfaces only a stable, PHI-free code token (via
864
+ * {@link extractStableCode}) plus the format name: the parsers' "warning = code + position, never a
865
+ * value" rule at the CLI edge.
866
+ *
867
+ * The one, opt-in exception is `--unsafe-show-values`, whose bounded excerpt is appended through the
868
+ * lone chokepoint in `core/phi.ts` ({@link unsafeInputSuffix}), so the "a value appears on a
869
+ * secondary surface **iff** the flag is set" property stays provable in one place, uniformly across
870
+ * `parse`/`validate`/`inspect`/`fmt`.
871
+ *
872
+ * @packageDocumentation
873
+ */
874
+
875
+ /**
876
+ * Pull a `code` off a thrown value **only** when it is a PHI-free constant token
877
+ * (`^[A-Z][A-Z0-9_]*$`: a letter-led UPPER_SNAKE code like `MALFORMED_JSON`), e.g. a wrapped
878
+ * parser's stable fatal code. Anything else (no `code`, a non-string, a non-token, or a **pure-digit**
879
+ * value that could be a raw identifier) yields `null`, so a parser exception that embedded input bytes
880
+ * in a `code`-shaped field can never reach a diagnostic.
881
+ *
882
+ * @param e - A caught value.
883
+ * @returns The stable code token, or `null`.
884
+ * @example
885
+ * ```ts
886
+ * import { extractStableCode } from "@cosyte/cli";
887
+ *
888
+ * extractStableCode({ code: "MALFORMED_JSON" }); // => "MALFORMED_JSON"
889
+ * extractStableCode(new Error("boom")); // => null
890
+ * ```
891
+ */
892
+ declare function extractStableCode(e: unknown): string | null;
893
+ /**
894
+ * Build the value-free {@link RunResult} for a **wrapped-parser rejection**: a `CLI_PARSE_FAILED`
895
+ * data error (exit `65`). The stderr line names the format and, when the thrown value carried one, a
896
+ * stable code token in parentheses; it **never** echoes the parser's message or the input bytes. Under
897
+ * `--unsafe-show-values` (and only then) a bounded excerpt of the offending input is appended via the
898
+ * single {@link unsafeInputSuffix} chokepoint.
899
+ *
900
+ * @param format - The format whose parser rejected the input.
901
+ * @param bytes - The offending input (only consulted for the opt-in unsafe excerpt).
902
+ * @param posture - The resolved {@link PhiPosture}; the excerpt is appended only when it opts in.
903
+ * @param e - The caught exception (its `code`, if a stable token, is surfaced: nothing else).
904
+ * @returns A value-free `CLI_PARSE_FAILED` / exit-`65` {@link RunResult}.
905
+ * @example
906
+ * ```ts
907
+ * import { parseFailureResult, VALUE_FREE } from "@cosyte/cli";
908
+ *
909
+ * const bytes = new TextEncoder().encode("not hl7");
910
+ * parseFailureResult("hl7", bytes, VALUE_FREE, { code: "MISSING_MSH" }).exit; // => 65
911
+ * ```
912
+ */
913
+ declare function parseFailureResult(format: CosyteFormat, bytes: Uint8Array, posture: PhiPosture, e: unknown): RunResult;
914
+
915
+ /**
916
+ * The **de-identification seam**: the single, documented plug-in point where the `redact` / `deid`
917
+ * command will delegate to **`@cosyte/deid`** once that library ships and is vetted.
918
+ *
919
+ * ## Why the CLI ships no built-in redactor (the boundary decision)
920
+ *
921
+ * `@cosyte/deid` is **unpublished**, and the wrapped
922
+ * parsers (`@cosyte/hl7`, `@cosyte/fhir`) expose **no de-identification API**: they redact only
923
+ * their own *diagnostics*, not the parsed model. So there is nothing to delegate to today, and adding
924
+ * `@cosyte/deid` would depend on unbuilt code.
925
+ *
926
+ * A tempting alternative, a "minimal built-in Safe-Harbor pass over the obvious PHI loci" (e.g. the
927
+ * HL7 `PID` segment, `Patient.name`/`Patient.address` in FHIR), is **deliberately rejected**. Real
928
+ * messages carry PHI far beyond those loci: HL7 `NK1`/`GT1`/`IN1`/`OBX`/`NTE`, FHIR extensions and
929
+ * contained resources, free-text notes. A redactor that scrubs the obvious fields and emits output
930
+ * that *looks* de-identified while silently leaving PHI behind is a **false-safety impression**. A
931
+ * `redact` that under-redacts is worse than no `redact`.
932
+ *
933
+ * So `redact` is an **honest, typed `CLI_NOT_IMPLEMENTED`** (never a fake success, never a partial
934
+ * scrub presented as de-identified, never invent a capability the ground layer lacks),
935
+ * gated on `@cosyte/deid`, with this seam as its one drop-in point. When `@cosyte/deid` lands and is
936
+ * conformance-graded, {@link deidStatus} flips to `available` and the command reads the input, calls
937
+ * the delegated de-identifier, and emits the de-identified model: the command surface (`redact`,
938
+ * `deid`, `<file|->`, `--format`) already exists so that change is additive.
939
+ *
940
+ * @packageDocumentation
941
+ */
942
+ /** The value-free reason `redact`/`deid` reports while the ground-layer library is unavailable. */
943
+ declare const DEID_UNAVAILABLE_REASON: string;
944
+ /**
945
+ * Whether de-identification is available, and (while it is not) the value-free reason why. The one
946
+ * function the `redact` command consults **before reading any input**, so a `redact` invocation never
947
+ * touches the PHI it cannot yet safely strip.
948
+ */
949
+ interface DeidAvailability {
950
+ /** `true` once `@cosyte/deid` is wired; `false` today. */
951
+ readonly available: boolean;
952
+ /** A value-free explanation shown when {@link DeidAvailability.available} is `false`. */
953
+ readonly reason: string;
954
+ }
955
+ /**
956
+ * Report the current de-identification availability. Today it is always unavailable (see the module
957
+ * docs); this is the single line that flips when `@cosyte/deid` is wired.
958
+ *
959
+ * @returns The {@link DeidAvailability}: `{ available: false, reason }` until `@cosyte/deid` ships.
960
+ * @example
961
+ * ```ts
962
+ * import { deidStatus } from "@cosyte/cli";
963
+ *
964
+ * deidStatus().available; // => false
965
+ * ```
966
+ */
967
+ declare function deidStatus(): DeidAvailability;
968
+
969
+ /**
970
+ * The top-level **subcommand dispatcher**: a small hand-rolled router over Node's built-in
971
+ * `util.parseArgs`, deliberately **third-party-framework-free** so the CLI core keeps zero third-party
972
+ * runtime dependencies. It maps `argv[0]` to a command handler, serves `--help`
973
+ * and `--version`, and turns any unexpected exception into a value-free `CLI_INTERNAL` result so a
974
+ * stack trace carrying input can never reach the terminal.
975
+ *
976
+ * @packageDocumentation
977
+ */
978
+
979
+ /**
980
+ * Run a full `cosyte` invocation as data.
981
+ *
982
+ * @param argv - The arguments after the program name (i.e. `process.argv.slice(2)`).
983
+ * @param deps - Injected input readers ({@link RunDeps}).
984
+ * @returns The {@link RunResult} to write to the process streams and exit with.
985
+ * @example
986
+ * ```ts
987
+ * import { run } from "@cosyte/cli";
988
+ *
989
+ * const deps = { readFile: async () => new Uint8Array(), readStdin: async () => new Uint8Array() };
990
+ * const { exit } = await run(["--version"], deps);
991
+ * exit; // => 0
992
+ * ```
993
+ */
994
+ declare function run(argv: string[], deps: RunDeps): Promise<RunResult>;
995
+
996
+ /**
997
+ * `cosyte parse <file|-> [--format …] [--ndjson] [--json] [--quiet] [--no-color]`
998
+ *
999
+ * Read a file (or stdin via `-`), **autodetect the format by content** (or honour `--format`), route to
1000
+ * the wrapped parser via the lazy per-format registry (`core/parsers.ts`) (so `cosyte parse msg.hl7`
1001
+ * never loads the DICOM or X12 code) and emit the parsed model as **typed JSON on stdout**. Every
1002
+ * failure is a value-free diagnostic on stderr with a stable `CLI_*` code and the documented exit code.
1003
+ *
1004
+ * **Multi-message / streaming.** A single message emits one pretty (or compact under `--json`)
1005
+ * JSON envelope, exactly as before. A **multi-record** input emits **NDJSON** (one compact envelope
1006
+ * per line) with per-record isolation: a record that fails to parse becomes a value-free
1007
+ * `{ record, error }` line and the stream continues, and the overall exit is a data error (`65`) if any
1008
+ * record failed. Two inputs are multi-record: an **MLLP** stream (each VT-framed frame is an enclosed
1009
+ * HL7 message) and any input under **`--ndjson`** (each non-empty line is a record: the FHIR bulk-data
1010
+ * convention).
1011
+ *
1012
+ * The CLI adds **no** parsing of its own: it routes, reads, and shapes output; `cosyte parse` equals the
1013
+ * wrapped library's programmatic parse.
1014
+ *
1015
+ * @packageDocumentation
1016
+ */
1017
+
1018
+ /**
1019
+ * Run the `parse` command.
1020
+ *
1021
+ * @param args - The arguments after the `parse` subcommand token.
1022
+ * @param deps - Injected input readers ({@link RunDeps}).
1023
+ * @param posture - The resolved {@link PhiPosture}. Defaults to {@link VALUE_FREE}; under
1024
+ * `--unsafe-show-values` a bounded excerpt of the offending input is appended to a `CLI_PARSE_FAILED`
1025
+ * diagnostic (the single, opt-in value-echoing surface): single-record mode only.
1026
+ * @returns A {@link RunResult}: the typed-JSON model (or NDJSON records) on `stdout`, a value-free note
1027
+ * (or nothing) on `stderr`, and the resolved exit code. Never throws a {@link CliError}: it resolves
1028
+ * it to a result; unexpected exceptions are caught by the dispatcher and mapped to `CLI_INTERNAL`.
1029
+ * @throws Never {@link CliError}; may propagate a truly unexpected error for the dispatcher to map.
1030
+ * @example
1031
+ * ```ts
1032
+ * import { parseCommand } from "@cosyte/cli";
1033
+ *
1034
+ * const enc = new TextEncoder();
1035
+ * const deps = {
1036
+ * readFile: async () => enc.encode('{"resourceType":"Patient","id":"x"}'),
1037
+ * readStdin: async () => new Uint8Array(),
1038
+ * };
1039
+ * (await parseCommand(["patient.json"], deps)).exit; // => 0
1040
+ * ```
1041
+ */
1042
+ declare function parseCommand(args: string[], deps: RunDeps, posture?: PhiPosture): Promise<RunResult>;
1043
+
1044
+ /**
1045
+ * `cosyte validate <file|-> [--format …] [--json] [--quiet] [--no-color]`
1046
+ *
1047
+ * Parse the input, run the **wrapped parser's own validation/conformance surface**, and let the
1048
+ * **exit code carry the verdict** so `cosyte validate` is usable as a CI gate: **`0` valid, `1`
1049
+ * invalid** (parseable but non-conformant), `65` unparseable, `66` no input, `2` usage. The
1050
+ * load-bearing rule: the CLI never prints a reassuring line and exits `0` on an invalid message.
1051
+ *
1052
+ * Findings are **value-free**: a stable code, a severity, and a positional locator (a FHIRPath, or an
1053
+ * HL7 segment/field index), never a field value. By default they render on **stderr**; `--json`
1054
+ * emits the same value-free verdict + findings as machine JSON on stdout. The CLI invents **no**
1055
+ * verdict of its own: FHIR validity is `@cosyte/fhir`'s `validateResource().valid` (plus any
1056
+ * error-severity read issue); HL7 validity is "parseable": its parser is Postel's-Law lenient and its
1057
+ * warnings are, by the library's design, non-fatal deviations (surfaced, never failing).
1058
+ *
1059
+ * @packageDocumentation
1060
+ */
1061
+
1062
+ /**
1063
+ * Run the `validate` command.
1064
+ *
1065
+ * @param args - The arguments after the `validate` subcommand token.
1066
+ * @param deps - Injected input readers ({@link RunDeps}).
1067
+ * @param posture - The resolved {@link PhiPosture} (governs only the opt-in unsafe excerpt on a
1068
+ * parse-failure diagnostic; a validation verdict is always value-free).
1069
+ * @returns A {@link RunResult} whose **exit code carries the verdict** (`0` valid / `1` invalid /
1070
+ * `65` unparseable / `66` no input / `2` usage). Value-free findings on `stderr`, or value-free
1071
+ * JSON on stdout under `--json`.
1072
+ * @throws Never {@link CliError}; may propagate a truly unexpected error for the dispatcher to map.
1073
+ * @example
1074
+ * ```ts
1075
+ * import { validateCommand } from "@cosyte/cli";
1076
+ *
1077
+ * const deps = {
1078
+ * readFile: async () => new TextEncoder().encode('{"resourceType":"Patient","gender":"male"}'),
1079
+ * readStdin: async () => new Uint8Array(),
1080
+ * };
1081
+ * (await validateCommand(["patient.json"], deps)).exit; // => 0
1082
+ * ```
1083
+ */
1084
+ declare function validateCommand(args: string[], deps: RunDeps, posture?: PhiPosture): Promise<RunResult>;
1085
+
1086
+ /**
1087
+ * `cosyte inspect <file|-> [--format …] [--json] [--quiet] [--no-color]`
1088
+ *
1089
+ * A human-readable, **value-free-by-default** structural summary of a message: its type, structural
1090
+ * counts, and a warning count: the "what shape is this?" answer, without ever printing a field
1091
+ * value. Unlike `parse`, whose stdout is the parsed model (the data channel), `inspect`'s
1092
+ * stdout is a *structural* summary composed only of counts and structural type **codes** (an HL7 message
1093
+ * type like `ADT^A01`, a FHIR `resourceType` like `Patient`, an X12 transaction-set id like `834`, a
1094
+ * DICOM SOP Class UID, an NCPDP `NewRx`): classification, never PHI. `--json` emits the same value-free
1095
+ * summary as machine JSON. The per-format summaries are built by the shared registry (`core/parsers.ts`).
1096
+ *
1097
+ * @packageDocumentation
1098
+ */
1099
+
1100
+ /**
1101
+ * Run the `inspect` command.
1102
+ *
1103
+ * @param args - The arguments after the `inspect` subcommand token.
1104
+ * @param deps - Injected input readers ({@link RunDeps}).
1105
+ * @param posture - The resolved {@link PhiPosture} (governs only the opt-in unsafe excerpt on a
1106
+ * parse-failure diagnostic; the summary itself is always value-free).
1107
+ * @returns A {@link RunResult}: the value-free structural summary on `stdout` (human, or JSON under
1108
+ * `--json`), exit `0`; a parse failure is a data error (`65`), an unreadable file `66`, a bad flag `2`.
1109
+ * @throws Never {@link CliError}; may propagate a truly unexpected error for the dispatcher to map.
1110
+ * @example
1111
+ * ```ts
1112
+ * import { inspectCommand } from "@cosyte/cli";
1113
+ *
1114
+ * const deps = {
1115
+ * readFile: async () => new TextEncoder().encode('{"resourceType":"Patient"}'),
1116
+ * readStdin: async () => new Uint8Array(),
1117
+ * };
1118
+ * (await inspectCommand(["patient.json", "--json"], deps)).exit; // => 0
1119
+ * ```
1120
+ */
1121
+ declare function inspectCommand(args: string[], deps: RunDeps, posture?: PhiPosture): Promise<RunResult>;
1122
+
1123
+ /**
1124
+ * `cosyte fmt <file|-> [--format …] [--quiet] [--no-color]`
1125
+ *
1126
+ * **Canonical re-serialization.** Parse the input and emit it back through the wrapped library's
1127
+ * **conservative, spec-clean serializer**: HL7 via `Hl7Message.toString()` (CR-separated, spec-clean
1128
+ * HL7), FHIR via `serializeResource` (canonical JSON, decimals byte-exact). The CLI **never
1129
+ * re-canonicalizes on its own**: the output is exactly the wrapped serializer's, so
1130
+ * `fmt` round-trips a spec-clean input through the parser.
1131
+ *
1132
+ * `fmt`'s stdout **is** the data channel: a re-serialization of the message, values included, going to
1133
+ * the sink the user chose. Every *secondary* surface stays value-free: a warning-count note on stderr
1134
+ * (suppressible with `--quiet`), and an unparseable input is a data error (`65`) with **no partial
1135
+ * emit**, never a half-serialized message.
1136
+ *
1137
+ * @packageDocumentation
1138
+ */
1139
+
1140
+ /**
1141
+ * Run the `fmt` command.
1142
+ *
1143
+ * @param args - The arguments after the `fmt` subcommand token.
1144
+ * @param deps - Injected input readers ({@link RunDeps}).
1145
+ * @param posture - The resolved {@link PhiPosture} (governs only the opt-in unsafe excerpt on a
1146
+ * parse-failure diagnostic).
1147
+ * @returns A {@link RunResult}: the canonical re-serialization on `stdout` (exit `0`), a value-free
1148
+ * warning-count note on `stderr` unless `--quiet`; an unparseable input is a data error (`65`) with
1149
+ * no partial emit, an unreadable file `66`, a bad flag `2`.
1150
+ * @throws Never {@link CliError}; may propagate a truly unexpected error for the dispatcher to map.
1151
+ * @example
1152
+ * ```ts
1153
+ * import { fmtCommand } from "@cosyte/cli";
1154
+ *
1155
+ * const deps = {
1156
+ * readFile: async () => new TextEncoder().encode('{ "resourceType":"Patient" , "id":"x" }'),
1157
+ * readStdin: async () => new Uint8Array(),
1158
+ * };
1159
+ * (await fmtCommand(["patient.json"], deps)).exit; // => 0
1160
+ * ```
1161
+ */
1162
+ declare function fmtCommand(args: string[], deps: RunDeps, posture?: PhiPosture): Promise<RunResult>;
1163
+
1164
+ /**
1165
+ * `cosyte convert <file|-> --to fhir [--json] [--quiet] [--no-color]`
1166
+ *
1167
+ * Convert an **HL7 v2** message to **FHIR R4** via **`@cosyte/transform`**: the
1168
+ * consumer-of-consumers command. The CLI adds **no** mapping logic of its own: it parses the input
1169
+ * with `@cosyte/hl7`, hands the parsed message to `transform`'s `toFhir`, and serializes the resulting
1170
+ * FHIR `Bundle` with `@cosyte/fhir`. The mapping guarantees are the library's, graded by *its* gate;
1171
+ * `cosyte convert` equals `transform`'s programmatic output.
1172
+ *
1173
+ * The converted FHIR `Bundle` is the user's explicit request, so it goes to **stdout** (the data
1174
+ * channel). Every conversion problem is one of `transform`'s value-free {@link TransformIssue}s: a
1175
+ * stable code, a severity, and a positional locator (a v2 index and an optional FHIRPath), **never** a
1176
+ * field value: surfaced on stderr (or as value-free JSON under `--json`). The load-bearing rule
1177
+ * (mirroring `validate`): a conversion that produces an **error-severity** issue exits **`1`**, never
1178
+ * `0`: the tool worked, but the conversion has a real problem a CI gate must see.
1179
+ *
1180
+ * `--to fhir` is required and is the only supported target (HL7 v2 → FHIR R4). The source must be
1181
+ * HL7 v2: a recognised-but-non-HL7 input (e.g. a FHIR document) is a value-free
1182
+ * `CLI_FORMAT_UNSUPPORTED` data error (`65`), never a fake conversion.
1183
+ *
1184
+ * @packageDocumentation
1185
+ */
1186
+
1187
+ /**
1188
+ * Run the `convert` command.
1189
+ *
1190
+ * @param args - The arguments after the `convert` subcommand token.
1191
+ * @param deps - Injected input readers ({@link RunDeps}).
1192
+ * @param posture - The resolved {@link PhiPosture} (governs only the opt-in unsafe excerpt on an HL7
1193
+ * parse-failure diagnostic; the converted bundle and the value-free findings are unaffected).
1194
+ * @returns A {@link RunResult}: the converted FHIR `Bundle` on `stdout` (the data channel), value-free
1195
+ * findings on `stderr` (or JSON under `--json`), and an exit code that carries the outcome: `0`
1196
+ * clean · `1` an error-severity conversion issue · `65` the HL7 input could not be parsed or is not
1197
+ * an HL7 v2 source · `66` no input · `2` usage.
1198
+ * @throws Never {@link CliError}; may propagate a truly unexpected error for the dispatcher to map to
1199
+ * `CLI_INTERNAL`.
1200
+ * @example
1201
+ * ```ts
1202
+ * import { convertCommand } from "@cosyte/cli";
1203
+ *
1204
+ * const deps = {
1205
+ * readFile: async () => new TextEncoder().encode("MSH|^~\\&|A|B|C|D|20240101||ADT^A01|1|P|2.5\r"),
1206
+ * readStdin: async () => new Uint8Array(),
1207
+ * };
1208
+ * (await convertCommand(["adt.hl7", "--to", "fhir"], deps)).exit; // => 0
1209
+ * ```
1210
+ */
1211
+ declare function convertCommand(args: string[], deps: RunDeps, posture?: PhiPosture): Promise<RunResult>;
1212
+ /**
1213
+ * Decide the conversion outcome from the library's value-free findings: whether any is
1214
+ * **error-severity** (which drives a non-zero exit: the load-bearing "a conversion error is never
1215
+ * exit 0" rule) and the value-free human report. The severity classification is
1216
+ * the library's: `@cosyte/transform` fixes each issue's severity; the CLI only reads it. Exported so
1217
+ * the exit-verdict and report logic is unit-testable with synthetic findings, independent of which HL7
1218
+ * message happens to produce an error.
1219
+ *
1220
+ * @param findings - The value-free {@link Finding}s the conversion produced.
1221
+ * @returns `hasError` (true iff any finding is error/fatal severity) and the rendered value-free
1222
+ * `report` (one line per finding + a summary line).
1223
+ * @example
1224
+ * ```ts
1225
+ * import { convertOutcome } from "@cosyte/cli";
1226
+ *
1227
+ * convertOutcome([{ code: "TRANSFORM_RESOURCE_INVALID", severity: "error", location: "PID" }])
1228
+ * .hasError; // => true
1229
+ * convertOutcome([{ code: "TRANSFORM_ELEMENT_DROPPED", severity: "information", location: "PID.13" }])
1230
+ * .hasError; // => false
1231
+ * ```
1232
+ */
1233
+ declare function convertOutcome(findings: readonly Finding[]): {
1234
+ readonly hasError: boolean;
1235
+ readonly report: string;
1236
+ };
1237
+
1238
+ /**
1239
+ * `cosyte map-codes <conceptmap|-> --code <code> [--system <uri>] [--version <v>] [--display <d>]
1240
+ * [--json] [--quiet]`
1241
+ *
1242
+ * Translate a single source coding through a **BYO FHIR R4 ConceptMap** via
1243
+ * **`@cosyte/terminology`**. The positional argument is the ConceptMap document (a file, or `-` for
1244
+ * stdin); `--system` + `--code` (and optional `--version`/`--display`) name the source coding to
1245
+ * translate. The CLI adds **no** mapping content of its own: `terminology` is content-free and
1246
+ * never fabricates a target; the CLI loads the user's map and forwards the translation faithfully.
1247
+ *
1248
+ * A ConceptMap and a terminology code are **reference data, not PHI**, so the translation result
1249
+ * (the matched target coding(s), or the value-free "unmapped" signal) is the user's explicit request
1250
+ * and goes to **stdout**. The exit code carries the outcome so it is usable as a gate: **`0`** at
1251
+ * least one match · **`1`** no mapping found (the never-fabricate `TERM_TRANSLATE_UNMAPPED` outcome) ·
1252
+ * `65` the supplied ConceptMap is not valid JSON / not a loadable ConceptMap · `66` no input · `2`
1253
+ * usage. stderr stays value-free (stable codes and counts only).
1254
+ *
1255
+ * @packageDocumentation
1256
+ */
1257
+
1258
+ /**
1259
+ * Run the `map-codes` command.
1260
+ *
1261
+ * @param args - The arguments after the `map-codes` subcommand token.
1262
+ * @param deps - Injected input readers ({@link RunDeps}); the positional argument (or `-`) is the BYO
1263
+ * ConceptMap document.
1264
+ * @returns A {@link RunResult}: the translation result on `stdout` (matched target coding(s) or the
1265
+ * value-free unmapped signal), a value-free note on `stderr` (unless `--quiet`), and an exit code
1266
+ * carrying the outcome: `0` mapped · `1` unmapped · `65` unloadable ConceptMap · `66` no input ·
1267
+ * `2` usage.
1268
+ * @throws Never {@link CliError}; may propagate a truly unexpected error for the dispatcher to map to
1269
+ * `CLI_INTERNAL`.
1270
+ * @example
1271
+ * ```ts
1272
+ * import { mapCodesCommand } from "@cosyte/cli";
1273
+ *
1274
+ * const cm = JSON.stringify({
1275
+ * resourceType: "ConceptMap",
1276
+ * group: [
1277
+ * {
1278
+ * source: "http://hl7.org/fhir/administrative-gender",
1279
+ * target: "http://terminology.hl7.org/CodeSystem/v2-0001",
1280
+ * element: [{ code: "male", target: [{ code: "M", equivalence: "equivalent" }] }],
1281
+ * },
1282
+ * ],
1283
+ * });
1284
+ * const deps = {
1285
+ * readFile: async () => new TextEncoder().encode(cm),
1286
+ * readStdin: async () => new Uint8Array(),
1287
+ * };
1288
+ * const r = await mapCodesCommand(
1289
+ * ["gender.json", "--system", "http://hl7.org/fhir/administrative-gender", "--code", "male"],
1290
+ * deps,
1291
+ * );
1292
+ * r.exit; // => 0
1293
+ * ```
1294
+ */
1295
+ declare function mapCodesCommand(args: string[], deps: RunDeps): Promise<RunResult>;
1296
+
1297
+ /**
1298
+ * `cosyte redact <file|-> [--format …]` (alias `cosyte deid …`): the command whose *job* is to strip
1299
+ * PHI, emitting a de-identified copy of the parsed model.
1300
+ *
1301
+ * **It is deliberately not implemented yet.** De-identification belongs to **`@cosyte/deid`**, which
1302
+ * is unpublished, and the wrapped parsers expose no de-id API to delegate to. A
1303
+ * built-in "minimal Safe-Harbor" pass over only the obvious PHI loci would leave PHI behind and
1304
+ * present a **false-safety impression**: the cardinal hazard `redact` exists to avoid. So this
1305
+ * command is an **honest, typed `CLI_NOT_IMPLEMENTED`** (never a fake success, never a partial scrub
1306
+ * dressed up as de-identified), gated on the de-identification seam in `core/deid.ts`.
1307
+ *
1308
+ * To keep that guarantee airtight, the command **never reads the input**: it consults
1309
+ * {@link deidStatus} first, and (while de-id is unavailable) reports the value-free reason and exits
1310
+ * `EX_UNAVAILABLE` (`69`) without ever touching the file's bytes. The command surface (positional
1311
+ * `<file|->`, `--format`) already exists so wiring `@cosyte/deid` later is additive.
1312
+ *
1313
+ * @packageDocumentation
1314
+ */
1315
+
1316
+ /**
1317
+ * Run the `redact` / `deid` command.
1318
+ *
1319
+ * @param args - The arguments after the `redact`/`deid` subcommand token.
1320
+ * @returns A {@link RunResult}. While `@cosyte/deid` is unavailable: empty `stdout`, a value-free
1321
+ * `CLI_NOT_IMPLEMENTED` diagnostic on `stderr`, and exit `EX_UNAVAILABLE` (`69`). A malformed
1322
+ * invocation (an unknown flag) is a usage error (exit `2`). The input is **never read**.
1323
+ * @example
1324
+ * ```ts
1325
+ * import { redactCommand } from "@cosyte/cli";
1326
+ *
1327
+ * const r = redactCommand(["message.hl7"]);
1328
+ * r.exit; // => 69
1329
+ * ```
1330
+ */
1331
+ declare function redactCommand(args: string[]): RunResult;
1332
+
1333
+ /**
1334
+ * `cosyte completion <bash|zsh|fish>`
1335
+ *
1336
+ * Print a shell completion script for `cosyte`, generated from the command tree, to **stdout**: the
1337
+ * user pipes it into their shell (`source <(cosyte completion bash)`) or saves it to their completions
1338
+ * directory. The script is static and value-free: it names commands, subcommand tokens, and flags,
1339
+ * never any input. An unknown or missing shell is a usage error (exit `2`), never a silent no-op.
1340
+ *
1341
+ * @packageDocumentation
1342
+ */
1343
+
1344
+ /**
1345
+ * Run the `completion` command.
1346
+ *
1347
+ * @param args - The arguments after the `completion` subcommand token; the first is the shell name.
1348
+ * @returns A {@link RunResult}: the completion script on `stdout` (exit `0`), or a value-free usage
1349
+ * error (exit `2`) when the shell is missing or unrecognised.
1350
+ * @example
1351
+ * ```ts
1352
+ * import { completionCommand } from "@cosyte/cli";
1353
+ *
1354
+ * completionCommand(["bash"]).exit; // => 0
1355
+ * completionCommand(["powershell"]).exit; // => 2
1356
+ * ```
1357
+ */
1358
+ declare function completionCommand(args: string[]): RunResult;
1359
+
1360
+ export { CLI_CODES, type CliCode, CliError, type CosyteFormat, DEID_UNAVAILABLE_REASON, DETECTABLE_FORMATS, type DeidAvailability, type DetectResult, EXIT, type ExitCode, type Finding, type FmtResult, type InputResolution, type InspectSummary, KNOWN_FORMATS, OP_SUPPORT, type Op, type ParseResult, type ParseWarning, type PhiPosture, type ResolvedInput, RunDeps, type RunResult, SHOW_VALUES, UNSAFE_EXCERPT_MAX, UNSAFE_SHOW_VALUES_FLAG, VALUE_FREE, VERSION, type Verdict, asCosyteFormat, classifyCandidates, completionCommand, convertCommand, convertOutcome, deframeMllp, deidStatus, detectFormat, detectionError, errorResult, extractPhiPosture, extractStableCode, fmtCommand, fmtFormat, formatDiagnostic, formatHl7Position, formatsSupporting, inspectCommand, inspectFormat, loadOptional, mapCodesCommand, parseCommand, parseFailureResult, parseFormat, redactCommand, resolveInput, run, supportsOp, toCliError, unsafeInputSuffix, validateCommand, validateFormat, valueFreeLocator };