@cosyte/astm 0.0.17 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -180,10 +180,11 @@ declare const WARNING_CODES: {
180
180
  readonly ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT: "ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT";
181
181
  /**
182
182
  * Two escape alignments of the same bytes disagreed about a **field** boundary, the reading taken
183
- * kept it, and the escape character that reading resumes on **heads no sequence at all**, so the
184
- * boundary was bought with a byte this reading cannot read while the competing alignment is
185
- * exactly the reading that can. Every field after that point sits one place further right than the
186
- * competing alignment puts it.
183
+ * kept it, and the escape character that reading resumes on **heads no sequence this codec can
184
+ * interpret**, so the boundary was bought with bytes this reading cannot read while the competing
185
+ * alignment is exactly the reading that can. Every field after that point sits one place further
186
+ * right than the competing alignment puts it, **except on the one class named at the end of this
187
+ * entry**, where the two readings instead read the same number of fields in different places.
187
188
  *
188
189
  * **The shift is the harm, and on a result record it reaches the status slot.** Measured on the
189
190
  * canonical set, `R|1|^^^687|28.6&F&|&U/L||||F` reads **9** fields under the reading taken and
@@ -214,30 +215,230 @@ declare const WARNING_CODES: {
214
215
  * modeled *inside* a field: a Universal Test ID's four components are the LOINC-candidate slot,
215
216
  * the test name, the **coding scheme** and the **local code**, and a patient name's three are
216
217
  * last, first and middle. A gained component boundary shifts those, so a local code can be read
217
- * as a coding scheme and a given name as a middle name. Measured, and **where the earlier body is
218
- * a recognized mnemonic, reported by nothing** (only the tolerable
219
- * {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER} fires, so a gate-legal profile accepts it).
220
- * An **unrecognized** earlier body raises
221
- * {@link WARNING_CODES.ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT} there and is refused, which is the
222
- * same split this code's own exclusion takes. It is a separate, open condition rather than something this
223
- * code covers, because wiring this sink to another split is a different criterion needing its own
224
- * population measurement. The repeat role costs the **value**, which this code does not report
225
- * either.
226
- * - **The tail is weighed one construct deep.** Where the escape character the reading taken
227
- * resumes on heads a sequence this codec *recognizes*, the reading taken interprets it and the
228
- * competing alignment would leave it bare, so the bytes prefer the reading taken: under a set
229
- * naming the field separator `F`, `28.6&F&F&F&U/L` is that separator escaped, written, and
230
- * escaped again, and refusing it would be an over-refusal of a well-formed stream. Where it
231
- * heads a sequence whose body is *unrecognized*, the reading taken still consumes it while the
232
- * competing alignment would leave **two** escape characters bare, so the preference is stronger
233
- * again, and this stays silent there even though the field shift is real. That last case is the
234
- * named residue: measured, not overlooked.
218
+ * as a coding scheme and a given name as a middle name. Measured, and it used to be reported by
219
+ * nothing where the earlier body was a recognized mnemonic (only the tolerable
220
+ * {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER} fired, so a gate-legal profile accepted
221
+ * it). It is now reported by
222
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS}, a separate code on the same
223
+ * tail test wired to the component split, because wiring this sink to another split is a
224
+ * different criterion needing its own population measurement. It is still not something **this**
225
+ * code covers. The repeat role costs the **value**, which this code does not report either, and
226
+ * which {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD} reports.
227
+ * - **The tail is weighed one construct deep, and exactly one tail is excluded.** Where the escape
228
+ * character the reading taken resumes on heads a sequence this codec *recognizes*, the reading
229
+ * taken interprets a construct and leaves nothing unread: under a set naming the field separator
230
+ * `F`, `28.6&F&F&F&U/L` is that separator escaped, written, and escaped again, entirely well
231
+ * formed, and refusing it would be an over-refusal. That is the only tail on which a stream's
232
+ * escaping can be clean, which is why it is the only exclusion. Where the tail heads a sequence
233
+ * whose body is *unrecognized*, the reading taken consumes a triple it cannot read, preserved
234
+ * verbatim and never guessed at, the field shift is the same shift, and **this reports it**.
235
+ * Consuming a triple is not interpreting one.
236
+ * - **That remaining silence is a TRADE, not a claim that nothing was lost.** The gained field
237
+ * boundary is exactly as real on the excluded tail, and there it is not merely under-reported:
238
+ * it is `warnings: []`. Under the canonical set `R|1|^^^687|28.6&F&|&F&U/L||||F` reads **nine**
239
+ * fields against the competing alignment's eight and hands back a status of **`final`** with an
240
+ * empty warning list. Reporting it would refuse a stream whose escaping is working, which is
241
+ * the trade this bound makes. **Read the raw line when an escape character sits next to a
242
+ * delimiter, whether or not anything fired.**
243
+ *
244
+ * **⚠️ THE ONE CLASS WHERE NO FIELD INDEX MOVES, NAMED RATHER THAN LEFT TO BE FOUND.** Where the
245
+ * sequence past the boundary carries the **field separator itself** as its body, the reading taken
246
+ * holds that character inside an opaque atom while the competing alignment splits on it, so the
247
+ * two readings return the **same number** of fields in **different places**. Under the canonical
248
+ * set `R|1|^^^687|28.6&F&|&|&U/L||||F` reads nine fields under both, the status `F` sits in field
249
+ * 9 under both, and what differs is the units: `&|&U/L` against `&U/L`. This still fires there,
250
+ * which is over-reporting relative to the field indexes and never under-reporting, and the class
251
+ * costs no stream its disposition: that tail body is a splitting delimiter in force, so
252
+ * {@link WARNING_CODES.ASTM_RECORD_DELIMITER_SWALLOWED_BY_ESCAPE} has already refused the record.
253
+ * What holds on **every** firing tuple is that the two readings disagree and that both consume
254
+ * every byte, so neither is forced.
235
255
  *
236
256
  * **Catch it on the first read.** Emit rewrites the preserved sequences into recognized mnemonics,
237
257
  * and those bytes carry the reading that was taken unambiguously, so a second-generation read is
238
258
  * silent and is correct about its own bytes. A clean re-read is not evidence.
239
259
  */
240
260
  readonly ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS: "ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS";
261
+ /**
262
+ * Two escape alignments of the same bytes disagreed about a **repeat** boundary, the reading
263
+ * taken kept it, and the escape character that reading resumes on **heads no sequence this codec
264
+ * can interpret**. Same contested position and same tail test as
265
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS}, on a different delimiter role, and
266
+ * what it costs is a different thing, which is why it is a different code.
267
+ *
268
+ * **Nothing shifts, and that is not the same as nothing being lost.** No field-indexed slot
269
+ * moves: the units and the result status are read out of the same field numbers under either
270
+ * alignment. What this reports is that **the field is read as more repeats than the competing
271
+ * alignment gives it**, which holds wherever it fires **except on the one class named at the end
272
+ * of this entry**. What that costs depends on **which** boundary was gained, and the two cases
273
+ * are stated separately rather than folded into one claim.
274
+ *
275
+ * **Where it is the FIRST boundary in the field, a modeled slot is lost**, because a field's
276
+ * modeled value and components are taken from its **first repeat alone**. Everything past the
277
+ * boundary stays on the wire and stays in `repeats`, and leaves every modeled slot:
278
+ *
279
+ * - **A value truncates.** Under `H|F^&`, `R|1|^^^687|28.6&S&F&U/L||||F` reads the value field as
280
+ * the two repeats `28.6^` and `&U/L`, so a consumer reads `28.6^` and the rest of the value is
281
+ * gone. The competing alignment reads one repeat carrying all of it.
282
+ * - **A modeled component list is deleted rather than shifted.** The same boundary inside a
283
+ * Universal Test ID leaves the components of the first repeat only: under `H|F^&`,
284
+ * `R|1|&F&F&687|28.6|U/L||||F` reads a UTID of one component holding a decoded field separator,
285
+ * with no coding scheme and no local code, where the bytes carry `687`. A patient name loses
286
+ * its given and middle names the same way. That is the half of this condition the shift report
287
+ * could not cover, because components are modeled **inside** a field.
288
+ *
289
+ * Before this code the only warnings on those streams were **tolerable** ones
290
+ * ({@link WARNING_CODES.ASTM_NONSTANDARD_DELIMITERS} and, where the tail applies,
291
+ * {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER}), so the widest gate-legal profile plus
292
+ * `{ strict: true }` accepted a truncated value and an emptied Universal Test ID.
293
+ *
294
+ * **Where it is a LATER boundary, no modeled slot moves and this still fires.** The first repeat
295
+ * is identical under both alignments, so the value, the components and every slot taken from them
296
+ * read the same either way (`R|1|^^^687|5.0F28.6&S&F&U/L||||F` under `H|F^&` reads a value of
297
+ * `5.0` under both), and what differs is the repeat structure after the first. It fires there
298
+ * deliberately: the boundary is still one the bytes do not force and a consumer reading `repeats`
299
+ * is still reading an alignment guess. Relative to the modeled slots that is **over-reporting,
300
+ * never under-reporting**. Narrowing it to the first boundary would change which streams a
301
+ * published package refuses and wants its own measurement, so the bound is written down instead.
302
+ *
303
+ * **It is a report, not a repair.** The split is unchanged, every decoded byte is identical,
304
+ * `repeats` still carries every one of them, and the value read is the value that was always
305
+ * read. Picking the other alignment would be a different guess with no more evidence behind it,
306
+ * on a published package.
307
+ *
308
+ * **Two further deliberate bounds, both stated rather than left to be found.**
309
+ * - **Only the repeat role.** The **component** role reaches a modeled slot too, and differently:
310
+ * there the components stay in the record and move one slot along, so a local code reads as a
311
+ * coding scheme and a given name as a middle name. That is measured and is now reported by
312
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS}, a third code on the same tail
313
+ * test wired to the component split. It is still not covered **here**, because wiring a sink to
314
+ * another split is another criterion, which is why it took its own population measurement.
315
+ * - **The tail is weighed one construct deep**, exactly as for the shift report, **and exactly
316
+ * one tail is excluded.** Where the escape character the reading resumes on heads a sequence
317
+ * this codec *recognizes*, it interprets a construct and the repeats are the ones the sender
318
+ * wrote: under a set naming the repeat separator `F`, `28.6&F&F&F&U/L` is that separator
319
+ * escaped, written, and escaped again, entirely well formed, and refusing it would be an
320
+ * over-refusal. That is the only tail on which a stream's escaping can be clean, which is why it
321
+ * is the only exclusion. Where the tail heads a sequence whose body is *unrecognized*, the
322
+ * reading taken consumes a triple it cannot read, preserved verbatim and never guessed at, the
323
+ * truncation is the same truncation, and **this reports it**.
324
+ * - **That remaining silence is a TRADE, not a claim that nothing was lost.** On the excluded tail
325
+ * the gained boundary is exactly as real and it is `warnings: []`: under the canonical set
326
+ * `R|1|^^^687|28.6&S&\&S&U/L|U/L||||F` reads a value of `28.6^`, and `^U/L` leaves every
327
+ * modeled slot, with an empty warning list. Reporting it would refuse a stream whose escaping
328
+ * is working.
329
+ *
330
+ * **⚠️ THE ONE CLASS WHERE THE FIELD IS NOT READ AS MORE REPEATS, NAMED RATHER THAN LEFT TO BE
331
+ * FOUND.** Where the sequence past the boundary carries the **repeat separator itself** as its
332
+ * body, the reading taken holds that character inside an opaque atom while the competing
333
+ * alignment splits on it, so the two readings return the **same number** of repeats in
334
+ * **different places** and what differs is their contents: under the canonical set
335
+ * `28.6&F&\&\&U/L` reads two repeats under both. This still fires there, which is over-reporting
336
+ * relative to the repeat count and never under-reporting, and the class costs no stream its
337
+ * disposition: that tail body is a splitting delimiter in force, so
338
+ * {@link WARNING_CODES.ASTM_RECORD_DELIMITER_SWALLOWED_BY_ESCAPE} has already refused the record.
339
+ * What holds on **every** firing tuple is that the two readings disagree and that both consume
340
+ * every byte, so neither is forced.
341
+ *
342
+ * **Catch it on the first read.** Emit rewrites the preserved sequences into recognized
343
+ * mnemonics, and those bytes carry the reading that was taken unambiguously, so a
344
+ * second-generation read is silent and is correct about its own bytes. A clean re-read is not
345
+ * evidence.
346
+ */
347
+ readonly ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD: "ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD";
348
+ /**
349
+ * Two escape alignments of the same bytes disagreed about a **component** boundary, the reading
350
+ * taken kept it, and the escape character that reading resumes on **heads no sequence this codec
351
+ * can interpret**. Same contested position and same tail test as
352
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS} and
353
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD}, on the third and last splitting
354
+ * role, and what it costs is a third thing again, which is why it is a third code.
355
+ *
356
+ * **The components are neither shifted out of the record nor dropped from it: they MOVE one slot
357
+ * along.** A field's components are modeled *inside* it, so a gained component boundary shifts
358
+ * every component after it exactly as a gained field boundary shifts every later field, **except
359
+ * on the one class named at the end of this entry**, where the two readings instead read the same
360
+ * number of components in different places. Nothing leaves the record and nothing changes field
361
+ * number; what changes is which modeled slot each component lands in, and those slots are named
362
+ * things:
363
+ *
364
+ * - **A Universal Test ID's coding scheme and local code.** Under the canonical set,
365
+ * `R|1|&F&^&GLU^L^687|28.6|U/L||||F` reads four components, so `L` is the coding scheme and
366
+ * `687` the vendor's local code. The competing alignment reads three, so `L` is the test name
367
+ * and **`687` is the coding scheme**. A local code and a code-system selector are not the same
368
+ * thing, and a consumer routing on one of them routes on the alignment.
369
+ * - **A patient's given and middle names.** `P|1||MRN-0001||DOE&F&^&JANE^A||19700101|F` reads a
370
+ * given name of `&JANE` and a middle name of `A` under the reading taken, and under the
371
+ * competing one `A` is the **given** name with no middle name at all.
372
+ *
373
+ * Before this code the only warning on those streams was the **tolerable**
374
+ * {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER}, so the widest gate-legal profile plus
375
+ * `{ strict: true }` accepted a test identity and a patient name whose parts were decided by the
376
+ * alignment rather than by the sender.
377
+ *
378
+ * **Every gained boundary at or before the LAST MODELED COMPONENT INDEX moves a slot, not only
379
+ * the first, and that is the difference from the repeat role.** There the field is modeled out of
380
+ * its first repeat alone, so only the first gained boundary reaches a modeled slot; here the shift
381
+ * propagates from wherever the boundary sits to the end of the component list.
382
+ *
383
+ * **TWO bounds run the other way, and this fires inside both**, which is **over-reporting, never
384
+ * under-reporting**: the direction this package errs in. Both axes are swept on their own rather
385
+ * than left to the shared corpus, which holds them fixed, and neither is closed by narrowing the
386
+ * guard, because narrowing changes which streams a published package refuses and wants its own
387
+ * measurement.
388
+ *
389
+ * - **Past the last modeled component index, nothing NAMED moves.** A model reads a fixed number
390
+ * of components: a patient name three (last, first, middle), a Universal Test ID four. A
391
+ * contested boundary further right than that still shifts the components after it while every
392
+ * named slot reads byte-identically under both alignments.
393
+ * - **Inside a LATER repeat nothing modeled moves at all**, because `components` is the first
394
+ * repeat, so what changes is `repeats[n]` for that `n` alone.
395
+ *
396
+ * It fires in both because the boundary is still one the bytes do not force, and a consumer
397
+ * reading `components` or `repeats` is still reading an alignment guess.
398
+ *
399
+ * **It is a report, not a repair.** The split is unchanged, every decoded byte is identical, and
400
+ * the components read are the components that were always read. Picking the other alignment would
401
+ * be a different guess with no more evidence behind it, on a published package. **Withholding the
402
+ * moved slots is a separate question and is deliberately not answered here**, for the reason the
403
+ * shift report already gives: declining to model a slot changes an extracted value for every
404
+ * consumer of a package already on the registry.
405
+ *
406
+ * **The tail is weighed one construct deep**, exactly as for the other two, **and exactly one tail
407
+ * is excluded.** Where the escape character the reading resumes on heads a sequence this codec
408
+ * *recognizes*, it interprets a construct and the components are the ones the sender wrote: under
409
+ * a set naming the component separator `F`, `GLU&F&F&F&L` is that separator escaped, written, and
410
+ * escaped again, entirely well formed, and refusing it would be an over-refusal. That is the only
411
+ * tail on which a stream's escaping can be clean, which is why it is the only exclusion. Where the
412
+ * tail heads a sequence whose body is *unrecognized*, the reading taken consumes a triple it
413
+ * cannot read, preserved verbatim and never guessed at, the slots move exactly as far, and **this
414
+ * reports it**.
415
+ *
416
+ * **That remaining silence is a TRADE, not a claim that nothing was lost.** On the excluded tail
417
+ * the gained boundary is exactly as real and it is `warnings: []`: under the canonical set
418
+ * `&F&^&F&GLU^L^687` reads one component more than the competing alignment, so `L` is the coding
419
+ * scheme and `687` the local code under one reading and `687` the **coding scheme** under the
420
+ * other, with an empty warning list. Reporting it would refuse a stream whose escaping is
421
+ * working.
422
+ *
423
+ * **⚠️ THE ONE CLASS WHERE NO COMPONENT INDEX MOVES, NAMED RATHER THAN LEFT TO BE FOUND.** It is a
424
+ * **third** bound running the other way, and unlike the two above it is about the bytes past the
425
+ * boundary rather than about where the boundary sits. Where the sequence past it carries the
426
+ * **component separator itself** as its body, the reading taken holds that character inside an
427
+ * opaque atom while the competing alignment splits on it, so the two readings return the **same
428
+ * number** of components in **different places** and what differs is their contents: under the
429
+ * canonical set `P|1||MRN-0001||DOE&F&^&^&JANE^A||19700101|F` reads three components under both,
430
+ * with `A` the middle name under both. This still fires there, and the class costs no stream its
431
+ * disposition: that tail body is a splitting delimiter in force, so
432
+ * {@link WARNING_CODES.ASTM_RECORD_DELIMITER_SWALLOWED_BY_ESCAPE} has already refused the record.
433
+ * What holds on **every** firing tuple is that the two readings disagree and that both consume
434
+ * every byte, so neither is forced.
435
+ *
436
+ * **Catch it on the first read.** Emit rewrites the preserved sequences into recognized
437
+ * mnemonics, and those bytes carry the reading that was taken unambiguously, so a
438
+ * second-generation read is silent and is correct about its own bytes. A clean re-read is not
439
+ * evidence.
440
+ */
441
+ readonly ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS: "ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS";
241
442
  /** An escape sequence body was not one of `&F&`/`&S&`/`&R&`/`&E&`: preserved verbatim. */
242
443
  readonly ASTM_UNKNOWN_ESCAPE_SEQUENCE: "ASTM_UNKNOWN_ESCAPE_SEQUENCE";
243
444
  /**
@@ -493,15 +694,21 @@ declare function ambiguousEscapeAlignment(position: AstmPosition): AstmRecordWar
493
694
  /**
494
695
  * Build an `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS` warning. Emitted when a competing escape
495
696
  * alignment decided a **field** boundary and the escape character the reading taken resumes on
496
- * heads no sequence of its own, so every field after that point sits one place further right than
697
+ * heads no sequence this codec can interpret, so every field after that point sits one place further
698
+ * right than
497
699
  * the competing alignment puts it. On a result record that reaches the units and the **result
498
700
  * status**: a trailing status letter lands in field 9 under the reading taken and in no field at
499
- * all under the competing one.
500
- *
501
- * A profile may **not** tolerate this code. It fires alongside
502
- * {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER}, which remains tolerable and reports the
503
- * strictly weaker fact that one escape character was read as a literal, and alongside
504
- * {@link WARNING_CODES.ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT} where that also applies. The reading
701
+ * all under the competing one. **Except where the sequence past the boundary carries the field
702
+ * separator itself**, where the two readings read the same number of fields in different places and
703
+ * no field index moves; see {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS}.
704
+ *
705
+ * A profile may **not** tolerate this code. **Which tolerable escape report accompanies it depends
706
+ * on the tail**: {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER} where the tail heads no
707
+ * sequence at all, and {@link WARNING_CODES.ASTM_UNKNOWN_ESCAPE_SEQUENCE} where it heads one whose
708
+ * body is unrecognized. Both report strictly weaker facts, and wherever the escape role is a
709
+ * character distinct from the three splitting roles one of them always fires beside this code. It
710
+ * fires alongside {@link WARNING_CODES.ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT} where that also
711
+ * applies. The reading
505
712
  * is unchanged: this reports the shift, it does not repair it.
506
713
  *
507
714
  * @example
@@ -511,6 +718,70 @@ declare function ambiguousEscapeAlignment(position: AstmPosition): AstmRecordWar
511
718
  * ```
512
719
  */
513
720
  declare function alignmentShiftedFields(position: AstmPosition): AstmRecordWarning;
721
+ /**
722
+ * Build an `ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD` warning. Emitted when a competing escape
723
+ * alignment decided a **repeat** boundary and the escape character the reading taken resumes on
724
+ * heads no sequence this codec can interpret, so the field is read as more repeats than the
725
+ * competing alignment
726
+ * gives it. No field-indexed slot moves, and that is the difference from
727
+ * {@link alignmentShiftedFields}. Where the gained boundary is the **first** in the field it still
728
+ * reaches a modeled slot, because a field's modeled value and components are taken from its first
729
+ * repeat alone: everything past the boundary stays in `repeats` and leaves every modeled slot, so a
730
+ * result value truncates and a Universal Test ID or a patient name loses the components that sat
731
+ * after it. At a **later** boundary nothing modeled moves and this still fires, which is
732
+ * over-reporting relative to those slots and never under-reporting, and **where the sequence past
733
+ * the boundary carries the repeat separator itself** the two readings read the same number of
734
+ * repeats in different places, so the field is not read as more repeats at all; see
735
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD}.
736
+ *
737
+ * A profile may **not** tolerate this code. **Which tolerable escape report accompanies it depends
738
+ * on the tail**: {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER} where the tail heads no
739
+ * sequence at all, and {@link WARNING_CODES.ASTM_UNKNOWN_ESCAPE_SEQUENCE} where it heads one whose
740
+ * body is unrecognized. Both report strictly weaker facts, and wherever the escape role is a
741
+ * character distinct from the three splitting roles one of them always fires beside this code. It
742
+ * fires alongside {@link WARNING_CODES.ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT} where that also
743
+ * applies. The reading
744
+ * is unchanged: this reports the gained boundary, it does not repair it.
745
+ *
746
+ * @example
747
+ * ```ts
748
+ * import { alignmentTruncatedField } from "@cosyte/astm";
749
+ * alignmentTruncatedField({ recordIndex: 2, recordType: "R", fieldIndex: 4 });
750
+ * ```
751
+ */
752
+ declare function alignmentTruncatedField(position: AstmPosition): AstmRecordWarning;
753
+ /**
754
+ * Build an `ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS` warning. Emitted when a competing escape
755
+ * alignment decided a **component** boundary and the escape character the reading taken resumes on
756
+ * heads no sequence this codec can interpret, so every component after that point sits one place
757
+ * further right
758
+ * than the competing alignment puts it. No field number changes and nothing leaves the record, and
759
+ * that is the difference from {@link alignmentShiftedFields} and {@link alignmentTruncatedField}:
760
+ * what moves is which modeled slot each component lands in, so a Universal Test ID's coding scheme
761
+ * and local code, or a patient's given and middle names, are read out of positions the competing
762
+ * alignment does not put them in. **Every gained boundary at or before the last modeled component
763
+ * index moves those slots, not only the first**; past that index, and inside a **later repeat**,
764
+ * nothing named moves and this still fires, which is over-reporting and never under-reporting, and
765
+ * **where the sequence past the boundary carries the component separator itself** the two readings
766
+ * read the same number of components in different places, so no component index moves at all. See
767
+ * {@link WARNING_CODES.ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS}.
768
+ *
769
+ * A profile may **not** tolerate this code. **Which tolerable escape report accompanies it depends
770
+ * on the tail**: {@link WARNING_CODES.ASTM_UNPAIRED_ESCAPE_CHARACTER} where the tail heads no
771
+ * sequence at all, and {@link WARNING_CODES.ASTM_UNKNOWN_ESCAPE_SEQUENCE} where it heads one whose
772
+ * body is unrecognized. Both report strictly weaker facts, and wherever the escape role is a
773
+ * character distinct from the three splitting roles one of them always fires beside this code. It
774
+ * fires alongside {@link WARNING_CODES.ASTM_RECORD_AMBIGUOUS_ESCAPE_ALIGNMENT} where that also
775
+ * applies. The reading
776
+ * is unchanged: this reports the moved components, it does not repair them.
777
+ *
778
+ * @example
779
+ * ```ts
780
+ * import { alignmentShiftedComponents } from "@cosyte/astm";
781
+ * alignmentShiftedComponents({ recordIndex: 2, recordType: "R", fieldIndex: 3 });
782
+ * ```
783
+ */
784
+ declare function alignmentShiftedComponents(position: AstmPosition): AstmRecordWarning;
514
785
  /**
515
786
  * Build an `ASTM_RECORD_DELIMITERS_REDECLARED` warning. Emitted when a later `H`
516
787
  * record declares a delimiter set different from the one in force; the new set is
@@ -3242,11 +3513,20 @@ declare function classifyMessage(records: readonly AstmRecord[]): AstmMessageCla
3242
3513
  * readings the bytes carry.
3243
3514
  * @param onAlignmentShiftedFields - Called (with the 0-based field index) for each
3244
3515
  * contested **field** boundary the reading took while resuming on an escape
3245
- * character that heads no sequence, so every later field is one place further
3246
- * right than the competing alignment puts it. Wired only to the field split: a
3516
+ * character that heads no sequence this codec can interpret. Wired only to the field split: a
3247
3517
  * repeat or component boundary divides one field and so moves no field-indexed
3248
3518
  * slot. That is a choice and not a consequence, because components are modeled
3249
- * inside a field; see {@link ShiftedFieldsSink}.
3519
+ * inside a field. **What the boundary costs, and the one class in which nothing
3520
+ * moves index, are stated in {@link ShiftedFieldsSink} and not restated here.**
3521
+ * @param onAlignmentTruncatedField - Called (with the 0-based field index) for that
3522
+ * same condition on the **repeat** split, where no field-indexed slot moves.
3523
+ * **What the boundary costs, its two index bounds and the one class in which nothing
3524
+ * moves index are stated in {@link TruncatedFieldSink} and not restated here.**
3525
+ * @param onAlignmentShiftedComponents - Called (with the 0-based field index) for that same
3526
+ * condition on the **component** split, where no field-indexed slot moves and nothing leaves the
3527
+ * record. **What the boundary costs, its three index bounds and the one class in which nothing
3528
+ * moves index are stated in {@link ShiftedComponentsSink} and not restated here.** All three
3529
+ * splitting roles are wired now.
3250
3530
  * @returns The record's fields.
3251
3531
  * @example
3252
3532
  * ```ts
@@ -3255,7 +3535,7 @@ declare function classifyMessage(records: readonly AstmRecord[]): AstmMessageCla
3255
3535
  * fields[3].components[0]; // "28.6"
3256
3536
  * ```
3257
3537
  */
3258
- declare function tokenizeRecord(record: string, d: Delimiters, onUnknownEscape?: (fieldIndex: number) => void, onUnpairedEscape?: (fieldIndex: number) => void, onSwallowedDelimiter?: (fieldIndex: number) => void, onAmbiguousAlignment?: (fieldIndex: number) => void, onAlignmentShiftedFields?: (fieldIndex: number) => void): AstmField[];
3538
+ declare function tokenizeRecord(record: string, d: Delimiters, onUnknownEscape?: (fieldIndex: number) => void, onUnpairedEscape?: (fieldIndex: number) => void, onSwallowedDelimiter?: (fieldIndex: number) => void, onAmbiguousAlignment?: (fieldIndex: number) => void, onAlignmentShiftedFields?: (fieldIndex: number) => void, onAlignmentTruncatedField?: (fieldIndex: number) => void, onAlignmentShiftedComponents?: (fieldIndex: number) => void): AstmField[];
3259
3539
  /**
3260
3540
  * Tokenize an `H` (header) record into its fields.
3261
3541
  *
@@ -3288,9 +3568,15 @@ declare function tokenizeRecord(record: string, d: Delimiters, onUnknownEscape?:
3288
3568
  * each competing escape alignment in the data portion. The declaration is opaque,
3289
3569
  * so the characters it names literally never report here either.
3290
3570
  * @param onAlignmentShiftedFields - Called with the 0-based whole-record field index
3291
- * for each contested field boundary in the data portion whose reading resumes on
3292
- * an escape character heading no sequence. The declaration is opaque, so it never
3293
- * reports here either.
3571
+ * for each contested field boundary in the data portion whose reading resumes on an
3572
+ * escape character heading no sequence this codec can interpret. The declaration is
3573
+ * opaque, so it never reports here either.
3574
+ * @param onAlignmentTruncatedField - Called with the 0-based whole-record field index
3575
+ * for each contested **repeat** boundary in the data portion on that same tail
3576
+ * test. The declaration is opaque, so it never reports here either.
3577
+ * @param onAlignmentShiftedComponents - Called with the 0-based whole-record field index for each
3578
+ * contested **component** boundary in the data portion on that same tail test. The declaration is
3579
+ * opaque, so it never reports here either.
3294
3580
  * @returns The header's fields.
3295
3581
  * @example
3296
3582
  * ```ts
@@ -3300,7 +3586,7 @@ declare function tokenizeRecord(record: string, d: Delimiters, onUnknownEscape?:
3300
3586
  * fields[4].raw; // "sender"
3301
3587
  * ```
3302
3588
  */
3303
- declare function tokenizeHeader(record: string, d: Delimiters, onUnknownEscape?: (fieldIndex: number) => void, onUnpairedEscape?: (fieldIndex: number) => void, onSwallowedDelimiter?: (fieldIndex: number) => void, onAmbiguousAlignment?: (fieldIndex: number) => void, onAlignmentShiftedFields?: (fieldIndex: number) => void): AstmField[];
3589
+ declare function tokenizeHeader(record: string, d: Delimiters, onUnknownEscape?: (fieldIndex: number) => void, onUnpairedEscape?: (fieldIndex: number) => void, onSwallowedDelimiter?: (fieldIndex: number) => void, onAmbiguousAlignment?: (fieldIndex: number) => void, onAlignmentShiftedFields?: (fieldIndex: number) => void, onAlignmentTruncatedField?: (fieldIndex: number) => void, onAlignmentShiftedComponents?: (fieldIndex: number) => void): AstmField[];
3304
3590
  /**
3305
3591
  * The primary scalar of a field: its first repeat's first component, decoded.
3306
3592
  * Returns `undefined` for a truly empty field so callers can distinguish
@@ -3475,17 +3761,39 @@ declare class AstmParseError extends Error {
3475
3761
  * asks whether this codec's vocabulary prefers the reading taken *at* the contested
3476
3762
  * position. It says nothing about what the reading taken makes of the bytes *after*
3477
3763
  * the boundary, and that is where the two alignments really diverge: they resume
3478
- * one character apart, so they disagree about the whole tail. Where the escape
3479
- * character the reading taken resumes on heads no sequence at all, the boundary was
3480
- * bought with a byte this reading cannot read, while the competing alignment is
3764
+ * one character apart, so they disagree about the bytes past the boundary, and
3765
+ * on most tails about the whole of them. Where the escape
3766
+ * character the reading taken resumes on heads no sequence this codec can
3767
+ * **interpret** (it heads none at all, or it heads one whose body is not a recognized
3768
+ * mnemonic and is therefore preserved verbatim rather than read), the boundary was
3769
+ * bought with bytes this reading cannot read, while the competing alignment is
3481
3770
  * precisely the reading that can. On the **field** separator that gained boundary
3482
3771
  * shifts every later field one place, so a result record's units and **result
3483
3772
  * status** are read out of slots the competing alignment does not put them in, and
3484
3773
  * a status of `final` can be a consequence of the alignment rather than something
3485
3774
  * the sender wrote there. That is `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS`; see
3486
- * {@link ShiftedFieldsSink}, including the tail and the two other delimiter roles it
3487
- * deliberately stays silent on, and why neither silence is a claim that nothing was
3488
- * lost there.
3775
+ * {@link ShiftedFieldsSink}, including the one tail it deliberately stays silent on,
3776
+ * why that silence is what keeps this off conformant traffic, and why it is still not
3777
+ * a claim that nothing was lost there.
3778
+ *
3779
+ * **The same question asked on the repeat separator has a different answer, so it
3780
+ * has a code of its own.** A gained repeat boundary moves no field-indexed slot, and
3781
+ * where it is the **first** boundary in the field it still reaches a modeled slot,
3782
+ * because a field's modeled reading is taken from its first repeat alone: everything
3783
+ * past that boundary leaves the record, so a result value truncates and a Universal
3784
+ * Test ID or a patient name loses the components that sat after it. That is
3785
+ * `ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD`; see {@link TruncatedFieldSink}, including
3786
+ * what it does at a later boundary, where it fires and no modeled slot moves.
3787
+ *
3788
+ * **The same question asked on the component separator has a third answer again, and
3789
+ * so a third code.** There the components neither leave the record nor change field
3790
+ * number: they move one slot along, because components are modeled *inside* a field.
3791
+ * A Universal Test ID's coding scheme and local code, and a patient's given and middle
3792
+ * names, are then read out of positions the competing alignment does not put them in.
3793
+ * That is `ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS`; see {@link ShiftedComponentsSink},
3794
+ * including what it does inside a later repeat, where it fires and no modeled slot
3795
+ * moves. All three roles are wired now; there is no fourth, because nothing splits on
3796
+ * the escape role.
3489
3797
  *
3490
3798
  * Re-escaping (the inverse, for spec-clean emit) lives in the serializer and is
3491
3799
  * deliberately not implemented here.
@@ -3570,11 +3878,18 @@ type SwallowedDelimiterSink = () => void;
3570
3878
  type AmbiguousAlignmentSink = (segmentIndex: number) => void;
3571
3879
  /**
3572
3880
  * A callback the split calls when a competing escape alignment decided a boundary
3573
- * **and the reading taken cannot read the byte immediately past it**: the escape
3574
- * character the leftmost reading resumes on heads no escape sequence at all, so it
3575
- * is kept as a bare literal (reported separately as
3576
- * `ASTM_UNPAIRED_ESCAPE_CHARACTER`), while the competing alignment is exactly the
3577
- * reading that gives that character a job, as the close of its own triple.
3881
+ * **and the reading taken cannot read what lies immediately past it**: the escape
3882
+ * character the leftmost reading resumes on heads no sequence this codec can
3883
+ * *interpret*, while the competing alignment is exactly the reading that gives that
3884
+ * character a job, as the close of its own triple. Two tails satisfy that, and they
3885
+ * are reported alike because they cost alike:
3886
+ *
3887
+ * - **It heads no sequence at all**, so it is kept as a bare literal and reported
3888
+ * separately as `ASTM_UNPAIRED_ESCAPE_CHARACTER`.
3889
+ * - **It heads a sequence whose body is not a recognized mnemonic**, so the triple is
3890
+ * preserved verbatim, never guessed at, and reported separately as
3891
+ * `ASTM_UNKNOWN_ESCAPE_SEQUENCE`. **Consuming a triple is not interpreting one**,
3892
+ * and the boundary is bought with bytes this reading cannot read either way.
3578
3893
  *
3579
3894
  * Wired **only to the split taken on the field separator**, because that is the
3580
3895
  * whole of its claim: a gained *field* boundary shifts every later field one place,
@@ -3587,11 +3902,16 @@ type AmbiguousAlignmentSink = (segmentIndex: number) => void;
3587
3902
  * reaches nothing outside it, so it moves no **field-indexed** slot and is
3588
3903
  * deliberately outside this. **That bound is a choice, not a consequence, and the
3589
3904
  * difference matters**: components are modeled *inside* a field (a Universal Test
3590
- * ID's coding scheme and local code, a patient name's parts), so a gained component
3591
- * boundary does move a modeled slot. That is measured, unreported by anything, and
3592
- * open, not something this sink covers. The callback lets the parser surface a
3593
- * value-free `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS` warning. Optional so the split
3594
- * can be used purely.
3905
+ * ID's coding scheme and local code, a patient name's parts), so a gained repeat or
3906
+ * component boundary does reach a modeled slot. The **repeat** half of that is
3907
+ * reported by {@link TruncatedFieldSink}, on the same tail test and under its own
3908
+ * code, because what it costs is a different thing. The **component** half is
3909
+ * reported by {@link ShiftedComponentsSink}, on that same tail test and under a code of
3910
+ * its own again, because what it costs is a third thing: there the components move one
3911
+ * slot along rather than leaving the record. The
3912
+ * callback lets the parser surface a value-free
3913
+ * `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS` warning. Optional so the split can be used
3914
+ * purely.
3595
3915
  *
3596
3916
  * **It is a report, not a repair.** The split is unchanged, every decoded byte is
3597
3917
  * identical, and the status read is the status that was always read. What is new is
@@ -3606,29 +3926,230 @@ type AmbiguousAlignmentSink = (segmentIndex: number) => void;
3606
3926
  * questions are different, so neither test is widened to answer the other.
3607
3927
  *
3608
3928
  * **The tail is weighed one construct deep, and that bound is stated rather than
3609
- * left to be found.** Two tails are excluded, with the same reason: the bytes past
3610
- * the boundary prefer the reading taken.
3611
- *
3612
- * - **The escape character heads a sequence this codec recognizes.** Then the
3613
- * reading taken interprets it and leaves nothing bare, while the competing
3614
- * alignment would leave it bare. Under a set naming the field separator `F`,
3615
- * `28.6&F&F&F&U/L` is the sender escaping that separator, writing it, and
3616
- * escaping it again: entirely well formed, and refusing it is the over-refusal
3617
- * that sank the preceding candidate criterion for this family.
3618
- * - **The escape character heads a sequence whose body this codec does not
3619
- * recognize.** Then the reading taken still consumes it as a sequence and carries
3620
- * one unreadable body, while the competing alignment would leave *two* escape
3621
- * characters bare. The preference is stronger there, not weaker.
3622
- *
3623
- * What that bound leaves open is the second of those tails, where the field shift
3624
- * is real and this stays silent. It is measured and named rather than closed by
3625
- * widening the test, because widening it would report a boundary the bytes prefer.
3929
+ * left to be found.** Exactly one tail is excluded: **the escape character heads a
3930
+ * sequence this codec recognizes.** Then the reading taken interprets a construct
3931
+ * and leaves nothing unread, while the competing alignment would leave it bare.
3932
+ * Under a set naming the field separator `F`, `28.6&F&F&F&U/L` is the sender
3933
+ * escaping that separator, writing it, and escaping it again: entirely well formed,
3934
+ * and refusing it is the over-refusal that sank the preceding candidate criterion
3935
+ * for this family.
3936
+ *
3937
+ * **That exclusion is not a matter of degree, which is why it is the only one.** It
3938
+ * is the sole tail on which a stream's escaping can be clean at all: on the other
3939
+ * two the package already reports a deviation, so this report can never be the
3940
+ * reason a well-formed stream is refused. A tail comparison that instead weighs
3941
+ * which alignment the bytes *prefer* would exclude the unrecognized body too (the
3942
+ * competing alignment leaves two escape characters bare there against the reading
3943
+ * taken's one unreadable body) and it is the wrong question: these codes report a
3944
+ * **cost**, not a preference, and the cost is identical under both reported tails.
3945
+ *
3946
+ * **That silence is a TRADE, and it is not a claim that nothing was lost there.** The
3947
+ * gained field boundary is exactly as real on the excluded tail, and it can be
3948
+ * entirely silent: under the canonical set `R|1|^^^687|28.6&F&|&F&U/L||||F` reads
3949
+ * **nine** fields against the competing alignment's eight with `warnings: []`, so a
3950
+ * result status of `final` is read out of a slot the other reading does not have.
3951
+ * Reporting it would refuse a stream whose escaping is working, which is the trade
3952
+ * this bound makes. **Read the raw line when an escape character sits next to a
3953
+ * delimiter, whether or not anything fired.**
3954
+ *
3955
+ * **⚠️ THE SHIFT IS NOT UNIVERSAL OVER THE FIRING POPULATION, AND THE EXCEPTION IS
3956
+ * NAMED RATHER THAN LEFT TO BE FOUND.** Where the sequence past the boundary carries
3957
+ * the **field separator itself** as its body, the reading taken holds that character
3958
+ * inside an opaque atom while the competing alignment splits on it, so the two
3959
+ * readings return the **same number** of fields in **different places**: no field
3960
+ * index moves, and what differs is the **contents** of the fields at and after the
3961
+ * boundary. Under the canonical set `R|1|^^^687|28.6&F&|&|&U/L||||F` reads nine
3962
+ * fields under both, with the status `F` in field 9 under both, and units of `&|&U/L`
3963
+ * against `&U/L`. That class is bounded and costs no stream its disposition: the tail
3964
+ * body is then a splitting delimiter in force, so
3965
+ * `ASTM_RECORD_DELIMITER_SWALLOWED_BY_ESCAPE` has already refused the record. What
3966
+ * holds on **every** firing tuple is that the two readings disagree and that both
3967
+ * consume every byte, so neither is forced.
3626
3968
  *
3627
3969
  * @param segmentIndex - The 0-based index of the field being accumulated when the
3628
- * shifting boundary was taken. Every field after it is one place further right
3629
- * than the competing alignment puts it.
3970
+ * contested boundary was taken. Every field after it is one place further right
3971
+ * than the competing alignment puts it, **except** where the sequence past the
3972
+ * boundary carries the field separator as its body, where the two readings return
3973
+ * the same number of fields with different contents instead.
3630
3974
  */
3631
3975
  type ShiftedFieldsSink = (segmentIndex: number) => void;
3976
+ /**
3977
+ * A callback the split calls on **exactly the condition {@link ShiftedFieldsSink}
3978
+ * reports**, wired instead to the split taken on the **repeat** separator. The two
3979
+ * sinks test the same predicate, because the predicate is about the bytes and the
3980
+ * split does not know which role it is being taken on; they are separate so the
3981
+ * caller that does know can name what the gained boundary costs, which is not the
3982
+ * same thing in the two roles. Do not "simplify" them into one: the codes would then
3983
+ * have to make one claim covering both, and the claim is different.
3984
+ *
3985
+ * **What a gained repeat boundary costs, and it is not a shift.** No field-indexed
3986
+ * slot moves: the units slot and the result-status slot are read out of the same
3987
+ * field numbers under either alignment. What the report says is that **the field is
3988
+ * read as more repeats than the competing alignment gives it**, and that holds
3989
+ * wherever it fires **except on the named class below**, where the two readings read
3990
+ * the same number of repeats in different places. What it costs depends on **which**
3991
+ * boundary was gained, and the two cases are stated separately rather than folded
3992
+ * into one claim:
3993
+ *
3994
+ * - **The gained boundary is the FIRST in the field, and then a modeled slot is
3995
+ * lost.** A field's modeled value and its components are taken from its **first
3996
+ * repeat alone**, so everything past the boundary is still on the wire, still in
3997
+ * `repeats`, and gone from every modeled slot. Under a set naming the repeat
3998
+ * separator `F`, the value `28.6&S&F&U/L` reads as the two repeats `28.6^` and
3999
+ * `&U/L`, and every value extractor answers `28.6^`, while the competing alignment
4000
+ * reads one repeat carrying all of it. The same boundary inside a Universal Test ID
4001
+ * field leaves the components of the first repeat only, so a UTID whose bytes carry
4002
+ * a test code can come back as a single component holding a decoded delimiter, with
4003
+ * the coding scheme and local code read from nothing at all. A patient name loses
4004
+ * its given and middle names the same way.
4005
+ * - **The gained boundary is a LATER one, and then no modeled slot moves.** The first
4006
+ * repeat is identical under both alignments, so the value, the components and every
4007
+ * slot taken from them read the same either way; what differs is the repeat
4008
+ * structure after the first. **This still fires there, deliberately and measurably**
4009
+ * (`5.0F28.6&S&F&U/L` under that same set), because the boundary is still one the
4010
+ * bytes do not force and a consumer reading `repeats` is still reading an alignment
4011
+ * guess. Relative to the modeled slots that is **over-reporting, never
4012
+ * under-reporting**, which is the direction this package errs in. Narrowing the sink
4013
+ * to the first boundary would change which streams a published package refuses and
4014
+ * wants its own measurement, so the bound is written down instead of guessed at.
4015
+ *
4016
+ * **It is a report, not a repair.** The split is unchanged, every decoded byte is
4017
+ * identical, `repeats` still carries every one of them, and the value read is the
4018
+ * value that was always read. What is new is that the gained boundary is reported by
4019
+ * a code no profile may tolerate, where before it was covered only by tolerable ones.
4020
+ *
4021
+ * **The tail is weighed one construct deep, exactly as in {@link ShiftedFieldsSink},
4022
+ * and one tail is excluded for the same reason.** Where the escape character the
4023
+ * reading taken resumes on heads a sequence this codec **recognizes**, it interprets
4024
+ * a construct and the two repeats are the ones the sender wrote: under a set naming
4025
+ * the repeat separator `F`, `28.6&F&F&F&U/L` is that separator escaped, written, and
4026
+ * escaped again, with nothing reported at all. Refusing that is the over-refusal that
4027
+ * sank an earlier candidate criterion for this family, and that tail is the only one
4028
+ * on which a stream's escaping can be clean. Where the tail heads a sequence whose
4029
+ * body is *unrecognized*, the reading taken consumes a triple it cannot read, the
4030
+ * truncation is the same truncation, and this reports it.
4031
+ *
4032
+ * **That silence is a TRADE, and it is not a claim that nothing was lost there.** The
4033
+ * gained repeat boundary is exactly as real on the excluded tail and can be entirely
4034
+ * silent: under the canonical set `28.6&S&\&S&U/L` reads a value of `28.6^` with
4035
+ * `warnings: []`, so `^U/L` leaves every modeled slot at a boundary the bytes do not
4036
+ * force. Reporting it would refuse a stream whose escaping is working.
4037
+ *
4038
+ * **⚠️ THE TRUNCATION IS NOT UNIVERSAL OVER THE FIRING POPULATION, AND THE EXCEPTION
4039
+ * IS NAMED RATHER THAN LEFT TO BE FOUND.** Where the sequence past the boundary
4040
+ * carries the **repeat separator itself** as its body, the reading taken holds that
4041
+ * character inside an opaque atom while the competing alignment splits on it, so the
4042
+ * two readings return the **same number** of repeats in **different places**: the
4043
+ * field is not read as more repeats than the competing alignment gives it, and what
4044
+ * differs is the **contents**. Under the canonical set `28.6&F&\&\&U/L` reads two
4045
+ * repeats under both. That class is bounded and costs no stream its disposition: the
4046
+ * tail body is then a splitting delimiter in force, so
4047
+ * `ASTM_RECORD_DELIMITER_SWALLOWED_BY_ESCAPE` has already refused the record. What
4048
+ * holds on **every** firing tuple is that the two readings disagree and that both
4049
+ * consume every byte, so neither is forced.
4050
+ *
4051
+ * @param segmentIndex - The 0-based index of the repeat being accumulated when the
4052
+ * contested boundary was taken, so `0` is the boundary that ends the first repeat
4053
+ * and is the one that reaches a modeled slot. It is **not** a field index: the
4054
+ * caller splitting one field into repeats already knows which field it is in, and
4055
+ * reports that.
4056
+ */
4057
+ type TruncatedFieldSink = (segmentIndex: number) => void;
4058
+ /**
4059
+ * A callback the split calls on **exactly the condition {@link ShiftedFieldsSink}
4060
+ * reports**, wired instead to the split taken on the **component** separator. The
4061
+ * third and last of the three sinks that share that one predicate, for the reason the
4062
+ * other two share it: the predicate is about the bytes and the split does not know
4063
+ * which role it is being taken on, so the caller that does know names what the gained
4064
+ * boundary costs. Do not "simplify" the three into one: the codes would then have to
4065
+ * make one claim covering all of them, and the three claims are different.
4066
+ *
4067
+ * **What a gained component boundary costs, and it is neither of the other two.** No
4068
+ * field number changes, so nothing shifts between field-indexed slots, and nothing
4069
+ * leaves the record, so nothing truncates. Components are modeled **inside** a field,
4070
+ * so what happens is that every component after the gained boundary is one place
4071
+ * further right than the competing alignment puts it, and the slots that indexes into
4072
+ * are named things: a Universal Test ID's LOINC-candidate slot, test name, **coding
4073
+ * scheme** and **local code**; a patient name's last, first and middle. Under the
4074
+ * canonical set `&F&^&GLU^L^687` reads four components, so `L` is the coding scheme
4075
+ * and `687` the vendor's local code, while the competing alignment reads three and
4076
+ * `687` is the **coding scheme**. `DOE&F&^&JANE^A` reads a given name of `&JANE` and a
4077
+ * middle name of `A`, while the competing alignment makes `A` the **given** name with
4078
+ * no middle name at all.
4079
+ *
4080
+ * **Every gained boundary at or before the LAST MODELED COMPONENT INDEX moves a
4081
+ * modeled slot, not only the first.** That is the structural difference from
4082
+ * {@link TruncatedFieldSink}: a field is modeled out of its first repeat alone, so
4083
+ * there only the first gained boundary reaches a modeled slot, while here the shift
4084
+ * propagates from wherever the boundary sits to the end of the component list.
4085
+ *
4086
+ * **TWO bounds run the other way, and the report fires inside both, which is
4087
+ * over-reporting and never under-reporting.** Neither is an oversight and neither is
4088
+ * closed by narrowing the guard, because narrowing changes which streams a published
4089
+ * package refuses and wants its own measurement. Both axes are swept on their own
4090
+ * rather than left to the shared corpus, which holds them fixed.
4091
+ *
4092
+ * - **Past the last modeled component index, nothing NAMED moves.** A model reads a
4093
+ * fixed number of components: a patient name three (last, first, middle), a
4094
+ * Universal Test ID four. A contested boundary further right than that still shifts
4095
+ * the components after it and leaves every named slot byte-identical under both
4096
+ * alignments, and this fires there.
4097
+ * - **Inside a LATER repeat nothing modeled moves at all.** `components` is
4098
+ * `repeats[0]`, so a component boundary gained inside the second or a later repeat
4099
+ * changes only `repeats[n]` for that `n`.
4100
+ *
4101
+ * It fires in both because the boundary is still one the bytes do not force, and a
4102
+ * consumer reading `components` or `repeats` is still reading an alignment guess.
4103
+ *
4104
+ * **It is a report, not a repair.** The split is unchanged, every decoded byte is
4105
+ * identical, and the components read are the components that were always read. What is
4106
+ * new is that the moved slots are reported by a code no profile may tolerate, where
4107
+ * before they were covered only by tolerable ones. **Withholding them is a separate
4108
+ * question, deliberately not answered here**: declining to model a slot changes an
4109
+ * extracted value for every consumer of a package already on the registry.
4110
+ *
4111
+ * **The tail is weighed one construct deep, exactly as in the other two sinks, and one
4112
+ * tail is excluded for the same reason.** Where the escape character the reading taken
4113
+ * resumes on heads a sequence this codec **recognizes**, it interprets a construct and
4114
+ * the components are the ones the sender wrote: under a set naming the component
4115
+ * separator `F`, `GLU&F&F&F&L` is that separator escaped, written, and escaped again,
4116
+ * with nothing reported at all. Refusing that is the over-refusal that sank an earlier
4117
+ * candidate criterion for this family, and that tail is the only one on which a
4118
+ * stream's escaping can be clean. Where the tail heads a sequence whose body is
4119
+ * *unrecognized*, the reading taken consumes a triple it cannot read, the slots move
4120
+ * exactly as far, and this reports it.
4121
+ *
4122
+ * **That silence is a TRADE, and it is not a claim that nothing was lost there.** The
4123
+ * gained component boundary is exactly as real on the excluded tail and can be
4124
+ * entirely silent: under the canonical set `&F&^&F&GLU^L^687` reads one component more
4125
+ * than the competing alignment with `warnings: []`, so a coding scheme and a local code
4126
+ * still sit where an alignment guess put them. Reporting it would refuse a stream whose
4127
+ * escaping is working.
4128
+ *
4129
+ * **⚠️ THE MOVE IS NOT UNIVERSAL OVER THE FIRING POPULATION, AND THE EXCEPTION IS NAMED
4130
+ * RATHER THAN LEFT TO BE FOUND.** It is a **third** bound running the other way, and it
4131
+ * differs from the two above: those two fire where nothing named moves because of where
4132
+ * the boundary sits, while this one is about the bytes past it. Where the sequence past
4133
+ * the boundary carries the **component separator itself** as its body, the reading taken
4134
+ * holds that character inside an opaque atom while the competing alignment splits on it,
4135
+ * so the two readings return the **same number** of components in **different places**:
4136
+ * no component index moves, and what differs is the **contents**. Under the canonical
4137
+ * set `DOE&F&^&^&JANE^A` reads three components under both, with `A` the middle name
4138
+ * under both. That class is bounded and costs no stream its disposition: the tail body
4139
+ * is then a splitting delimiter in force, so
4140
+ * `ASTM_RECORD_DELIMITER_SWALLOWED_BY_ESCAPE` has already refused the record. What holds
4141
+ * on **every** firing tuple is that the two readings disagree and that both consume
4142
+ * every byte, so neither is forced.
4143
+ *
4144
+ * @param segmentIndex - The 0-based index of the component being accumulated when the
4145
+ * contested boundary was taken. Every component after it is one place further right
4146
+ * than the competing alignment puts it, **except** where the sequence past the
4147
+ * boundary carries the component separator as its body, where the two readings return
4148
+ * the same number of components with different contents instead. It is **not** a field
4149
+ * index, and it is **not** a repeat index: the caller splitting one repeat into
4150
+ * components already knows both, and reports the field.
4151
+ */
4152
+ type ShiftedComponentsSink = (segmentIndex: number) => void;
3632
4153
  /**
3633
4154
  * Decode the four recognized ASTM escape mnemonics in a single already-split
3634
4155
  * leaf (a component string), substituting the *active* delimiters read from the
@@ -3694,10 +4215,20 @@ declare function decodeEscapes(leaf: string, d: Delimiters, onUnknown?: UnknownE
3694
4215
  * closing escape character could instead have opened a sequence holding this
3695
4216
  * delimiter, so the boundary taken here is not the only reading of the bytes.
3696
4217
  * @param onShiftedFields - Called once per contested boundary where the escape
3697
- * character this reading resumes on heads no sequence of its own, so the boundary
3698
- * was bought with a byte the reading cannot read. Wired only by the split taken on
3699
- * the field separator: see {@link ShiftedFieldsSink} for why, and for the tail it
3700
- * deliberately does not report.
4218
+ * character this reading resumes on heads no sequence this codec can *interpret*
4219
+ * (none at all, or one whose body is not a recognized mnemonic), so the boundary
4220
+ * was bought with bytes the reading cannot read. Wired only by the split taken on
4221
+ * the field separator: see {@link ShiftedFieldsSink} for why, and for the one tail
4222
+ * it deliberately does not report.
4223
+ * @param onTruncatedField - Called on that same condition, wired only by the split
4224
+ * taken on the repeat separator, where the cost is not a shift. **What it is, its
4225
+ * two index bounds and the one class in which nothing moves index are stated in
4226
+ * {@link TruncatedFieldSink} and not restated here.**
4227
+ * @param onShiftedComponents - Called on that same condition again, wired only by the
4228
+ * split taken on the component separator, where nothing shifts between fields and
4229
+ * nothing leaves the record. **What the boundary costs, its three index bounds and
4230
+ * the one class in which nothing moves index are stated in
4231
+ * {@link ShiftedComponentsSink} and not restated here.**
3701
4232
  * @returns The raw segments, in order.
3702
4233
  * @example
3703
4234
  * ```ts
@@ -3707,7 +4238,7 @@ declare function decodeEscapes(leaf: string, d: Delimiters, onUnknown?: UnknownE
3707
4238
  * splitEscapeAware("O&Brien^John", "^", "&"); // ["O&Brien", "John"] (unpaired: literal)
3708
4239
  * ```
3709
4240
  */
3710
- declare function splitEscapeAware(text: string, delimiter: string, escape: string, onAmbiguousAlignment?: AmbiguousAlignmentSink, onShiftedFields?: ShiftedFieldsSink): string[];
4241
+ declare function splitEscapeAware(text: string, delimiter: string, escape: string, onAmbiguousAlignment?: AmbiguousAlignmentSink, onShiftedFields?: ShiftedFieldsSink, onTruncatedField?: TruncatedFieldSink, onShiftedComponents?: ShiftedComponentsSink): string[];
3711
4242
 
3712
4243
  /**
3713
4244
  * Deep-freeze helper for the immutable ASTM model.
@@ -4074,8 +4605,11 @@ declare function resolveProfileTransport(profile: AstmProfile | undefined): Astm
4074
4605
  * **A further reader landed with `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS`, and it is
4075
4606
  * the first one that reaches a MODELED SLOT rather than a boundary.** It reports
4076
4607
  * that a contested alignment decided a **field** boundary while the reading taken
4077
- * resumes on an escape character heading no sequence, so every later field sits one
4078
- * place further right than the competing alignment puts it. On a result record that
4608
+ * resumes on an escape character heading no sequence this codec can interpret, so
4609
+ * every later field sits one place further right than the competing alignment puts
4610
+ * it (**except where the sequence past the boundary carries the field separator
4611
+ * itself**, where the two readings read the same number of fields in different
4612
+ * places). On a result record that
4079
4613
  * moves the units and the **result status**: the sender's trailing letter is read out
4080
4614
  * of field 9 under the reading taken and out of no field at all under the other, so a
4081
4615
  * status of `final` can be a consequence of the alignment rather than something the
@@ -4089,6 +4623,57 @@ declare function resolveProfileTransport(profile: AstmProfile | undefined): Astm
4089
4623
  * in a value alters no boundary at all), and the case where it accompanies a shifted
4090
4624
  * field is now reported by a code no profile may re-badge.
4091
4625
  *
4626
+ * **`ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD` landed next, on the same contested
4627
+ * position and the same tail test, and it reaches a modeled slot by the other
4628
+ * route.** It reports a contested alignment deciding a **repeat** boundary. Nothing
4629
+ * shifts: no field-indexed slot moves, which is exactly why the shift report could
4630
+ * not cover it. What it reports is that the field is read as more repeats than the
4631
+ * competing alignment gives it (**except where the sequence past the boundary carries
4632
+ * the repeat separator itself**, where the two readings read the same number of
4633
+ * repeats in different places), and **where that gained boundary is the first one in
4634
+ * the field** it reaches a modeled slot, because a field's modeled value and
4635
+ * components are taken from its **first repeat alone**: everything past it stays in
4636
+ * `repeats` and leaves every modeled slot, so a result value truncates and a
4637
+ * Universal Test ID or a patient name comes back holding only the components that sat
4638
+ * before it. Until it existed the warnings on those streams were
4639
+ * `ASTM_NONSTANDARD_DELIMITERS` and `ASTM_UNPAIRED_ESCAPE_CHARACTER`, both on the list
4640
+ * below, so the widest gate-legal profile plus `{ strict: true }` accepted a truncated
4641
+ * value and an emptied test identity. **At a later boundary it fires and no modeled
4642
+ * slot moves**, which is over-reporting relative to those slots and never
4643
+ * under-reporting: measured, and stated on the code itself rather than left to be
4644
+ * found. It is safety-critical by construction and must never be admitted.
4645
+ * Re-reading the survivors against it moved no admission, and the reason is the one
4646
+ * the entry above already turns on: each of them re-badges the code it names and no
4647
+ * other, and what this condition now raises is a code no profile may name.
4648
+ *
4649
+ * **`ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS` completes the set, on the same
4650
+ * contested position and the same tail test, wired to the third and last splitting
4651
+ * role.** It reports a contested alignment deciding a **component** boundary. Nothing
4652
+ * shifts between fields and nothing leaves the record, which is why neither of the two
4653
+ * above could cover it: components are modeled **inside** a field, so every component
4654
+ * after the gained boundary is one place further right than the competing alignment
4655
+ * puts it (**except where the sequence past the boundary carries the component
4656
+ * separator itself**, where the two readings read the same number of components in
4657
+ * different places). That indexes into named slots. A Universal Test ID's four components are the
4658
+ * LOINC-candidate slot, the test name, the **coding scheme** and the **local code**, so
4659
+ * `&F&^&GLU^L^687` reads `687` as the vendor's local code under the reading taken and
4660
+ * as the **coding scheme** under the competing one; a patient name's three are last,
4661
+ * first and middle, so `DOE&F&^&JANE^A` reads `A` as the middle name under the reading
4662
+ * taken and as the **given** name under the other. Until it existed the only warning on
4663
+ * those streams was `ASTM_UNPAIRED_ESCAPE_CHARACTER`, on the list below, so the widest
4664
+ * gate-legal profile plus `{ strict: true }` accepted a test identity and a patient name
4665
+ * whose parts were decided by the alignment. **Unlike the repeat role, every gained
4666
+ * boundary at or before the last modeled component index moves those slots and not only
4667
+ * the first**, because the shift propagates to the end of the component list. **THREE
4668
+ * bounds run the other way and it fires inside all three**, which is over-reporting and
4669
+ * never under-reporting: past the last modeled index nothing NAMED moves (a name models
4670
+ * three components, a Universal Test ID four); inside a later repeat nothing modeled moves
4671
+ * at all; and on the class named above nothing moves index at all. All three axes are
4672
+ * measured on sweeps of their own rather than on the shared corpus, which holds them
4673
+ * fixed. It is safety-critical by construction and must never be
4674
+ * admitted. Re-reading the survivors against it moved no admission, for the reason the
4675
+ * two entries above already turn on.
4676
+ *
4092
4677
  * **So the ones that remain are recorded with the reading each one survives**, not
4093
4678
  * merely with the value it preserves. Each was re-derived against **every** reader of
4094
4679
  * record structure named above (this sentence deliberately names no count: it has
@@ -4147,6 +4732,17 @@ declare function resolveProfileTransport(profile: AstmProfile | undefined): Astm
4147
4732
  * time, and this entry survives it on the same narrower claim: what that reader
4148
4733
  * raises is a different code, which a profile cannot name and cannot tolerate.
4149
4734
  *
4735
+ * **A THIRD reader landed with the widened tail bound, and it is named here for the
4736
+ * same reason.** `headsInterpretableSequence` in `../common/escapes.ts` asks the
4737
+ * mnemonic test about the escape character just past a contested boundary, so an
4738
+ * **unrecognized** body there, which is exactly the condition this code reports, now
4739
+ * also decides whether `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS`,
4740
+ * `ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD` or `ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS`
4741
+ * fires. Three sinks, one predicate, and this entry survives all three on the same
4742
+ * narrower claim: none of the codes they raise may be named by a profile.
4743
+ * **Re-derive this list whenever something new starts reading record structure**: the
4744
+ * count is now three and this is the second time it has grown.
4745
+ *
4150
4746
  * **This entry used to be recorded as questionable, and what made it questionable
4151
4747
  * is now a separate code that is not on this list.** The argument above is about
4152
4748
  * the *decoded value*, and it holds. What it did not cover is that the
@@ -4174,21 +4770,35 @@ declare function resolveProfileTransport(profile: AstmProfile | undefined): Astm
4174
4770
  * decoded value, so the value is identical with or without the profile. Note what
4175
4771
  * makes this admissible is a property of the *parse*, not of the warning: reading
4176
4772
  * the character as a literal is unconditional, and tolerating the code changes
4177
- * nothing about how the record splits. No reader sees it, on the same grounds as
4178
- * the entry above: the type letter is read before any decoding, the split reader
4773
+ * nothing about how the record splits. None of the three readers named at the top of
4774
+ * this file sees it: the type letter is read before any decoding, the split reader
4179
4775
  * counts fields the escape-aware tokenizer has already finished dividing, and a
4180
- * decoded value is never cut back into records. Contrast the condition it
4776
+ * decoded value is never cut back into records. **Three later readers DO see it**, and
4777
+ * they are named below rather than left out of this bullet. Contrast the condition it
4181
4778
  * replaced, which **would** have failed part 1: reading the same character as an
4182
4779
  * unterminated sequence merged every field after it into one, and a code reporting
4183
4780
  * that would have been a report of lost values.
4184
4781
  *
4185
- * **The alignment reader is not a reader of this condition, and the distinction is
4186
- * worth stating rather than leaving to be checked.** It asks whether the character
4187
- * two positions past a sequence *is* the escape character, never whether that
4188
- * character heads a sequence of its own, which is the question this code answers.
4189
- * The two are independent in both directions, measured: `28.6&Z&|&U/L` raises this
4190
- * code and the alignment code together, and `28.6&Z&|&U&L` raises the alignment
4191
- * code with no unpaired character anywhere in it.
4782
+ * **The alignment reader is not a reader of this condition**, and that much still
4783
+ * holds: it asks whether the character two positions past a sequence *is* the escape
4784
+ * character, never whether that character heads a sequence of its own. The two are
4785
+ * independent in both directions, measured: `28.6&Z&|&U/L` raises this code and the
4786
+ * alignment code together, and `28.6&Z&|&U&L` raises the alignment code with no
4787
+ * unpaired character anywhere in it.
4788
+ *
4789
+ * **The TAIL readers are a different matter, and "no reader sees it" is
4790
+ * therefore FALSE of this entry and must not be restored.** There are three of them
4791
+ * now, one per splitting role: `ASTM_RECORD_ALIGNMENT_SHIFTED_FIELDS`,
4792
+ * `ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD` and
4793
+ * `ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS` all fire where the character at
4794
+ * `i + 4` heads no sequence this codec can interpret, and heading no sequence at all
4795
+ * is one of the two ways to satisfy that, so this code's own question is asked about
4796
+ * the character just past a contested boundary. That is a reader of the reported
4797
+ * condition, so this entry survives on the same narrower claim the unknown-sequence
4798
+ * entry above already uses, not on nothing reading it: a profile re-badges the code
4799
+ * it names and no other, and what those three readers raise is not tolerable in any
4800
+ * case. If a future reader of this condition ever produces something a profile
4801
+ * **can** tolerate, this entry stops being admissible and comes off the list.
4192
4802
  * - `ASTM_RECORD_UNINTERPRETED_QUERY_STATUS`: a request-information status carried
4193
4803
  * verbatim as a leaf field on a `Q` record; the code set is paywalled and is not
4194
4804
  * interpreted, profile or not. Classification reads whether a `Q` record is
@@ -4202,7 +4812,9 @@ declare function resolveProfileTransport(profile: AstmProfile | undefined): Astm
4202
4812
  * an unrecognized record type, a record the delimiters in force could not split, a
4203
4813
  * declaration naming one character in two roles, a delimiter an unrecognized escape
4204
4814
  * sequence kept out of the split, a boundary a competing escape alignment disagrees
4205
- * about, a bad frame checksum / sequence gap / unterminated
4815
+ * about, a field whose modeled reading stops at a boundary only one alignment has,
4816
+ * a component list only one alignment aligns that way,
4817
+ * a bad frame checksum / sequence gap / unterminated
4206
4818
  * / oversize frame, an ambiguous transport, an unexpected protocol event, or a
4207
4819
  * rejected frame: is forbidden.
4208
4820
  *
@@ -4249,6 +4861,24 @@ declare function resolveProfileTransport(profile: AstmProfile | undefined): Astm
4249
4861
  * reading `final` that the competing alignment of the same bytes puts in no field at
4250
4862
  * all.
4251
4863
  *
4864
+ * `ASTM_RECORD_ALIGNMENT_TRUNCATED_FIELD` is not on this list and must not be added
4865
+ * to it either. It reports the same contested alignment deciding a **repeat**
4866
+ * boundary, where no slot changes hands and a modeled reading is cut off instead: the
4867
+ * field is read out of its first repeat alone, so where that boundary is the first
4868
+ * one a value truncates and a Universal Test ID's coding scheme and local code are
4869
+ * read from bytes that are no longer in any modeled slot. Reporting a value that is
4870
+ * not the whole of what the sender wrote fails the first half of the two-clause test
4871
+ * outright.
4872
+ *
4873
+ * `ASTM_RECORD_ALIGNMENT_SHIFTED_COMPONENTS` is not on this list and must not be added
4874
+ * to it either. It reports the same contested alignment deciding a **component**
4875
+ * boundary, where nothing leaves the record and no field number changes, and every
4876
+ * component after it moves one slot along instead: a Universal Test ID's coding scheme
4877
+ * and local code, and a patient's given and middle names, are read out of positions the
4878
+ * competing alignment does not put them in. Reporting a code system, a vendor's local
4879
+ * code or a given name that the bytes do not unambiguously carry fails the first half of
4880
+ * the two-clause test outright.
4881
+ *
4252
4882
  * @example
4253
4883
  * ```ts
4254
4884
  * import { TOLERABLE_CODES } from "@cosyte/astm";
@@ -5593,4 +6223,4 @@ declare class AstmFrameStrictError extends Error {
5593
6223
  */
5594
6224
  declare const VERSION: string;
5595
6225
 
5596
- export { ALL_ASTM_WARNING_CODES, AMBIGUOUS_CODES, ACK as ASTM_ACK, ENQ as ASTM_ENQ, EOT as ASTM_EOT, NAK as ASTM_NAK, type AbnormalFlag, type AbnormalFlagCode, type AbnormalFlagMeaning, type AmbiguousAlignmentSink, type AmbiguousCode, type AnyAstmWarningCode, AstmAmbiguousStreamError, type AstmDate, type AstmDatePrecision, type AstmField, type AstmFrame, AstmFrameEncodeError, type AstmFrameEncodeErrorCode, type AstmFramePosition, AstmFrameStrictError, type AstmFrameWarning, type AstmFraming, type AstmLivdWarning, type AstmLtpWarning, type AstmMessage, type AstmMessageClassification, type AstmMessageKind, AstmParseError, type AstmParseOptions, type AstmPosition, type AstmProfile, AstmProfileDefinitionError, type AstmProfileProvenance, type AstmQuirkMatch, type AstmQuirkTolerance, type AstmRecord, type AstmRecordInput, type AstmRecordWarning, AstmSerializeError, type AstmSerializeErrorCode, type AstmStreamMessage, AstmStrictError, CANONICAL_DELIMITERS, type CommentInput, type CommentRecord, type ComposeFramesOptions, type DecodeAstmFramesResult, type DefineAstmProfileOptions, type DelimiterDeclarationFault, type DelimiterReadResult, type Delimiters, type DetectFramingOptions, type DetectFramingResult, FATAL_CODES, FRAME_WARNING_CODES, type FatalCode, type FrameChecksum, type FrameOptions, type FrameTerminator, type FrameWarningCode, type FramedAstmResult, type HeaderInput, type HeaderRecord, LIVD_WARNING_CODES, LTP_WARNING_CODES, type LivdAnnotation, type LivdCatalog, type LivdEntry, type LivdLookup, type LivdMapping, type LivdResult, type LivdWarningCode, type LtpAction, type LtpEvent, type LtpPhase, type LtpState, type LtpTransition, type LtpWarningCode, type ManufacturerRecord, type MessageInput, type OrderInput, type OrderRecord, type PatientInput, type PatientName, type PatientNameInput, type PatientRecord, type QueryInput, type QueryRecord, type ReferenceRange, type ReferenceRangeKind, type ResultInput, type ResultRecord, type ResultStatus, type ResultStatusCode, type ResultStatusMeaning, SAFETY_CRITICAL_CODES, type ScientificRecord, type ShiftedFieldsSink, type SwallowedDelimiterSink, TOLERABLE_CODES, type TerminatorRecord, type UniversalTestId, type UniversalTestIdProvenance, type UnknownEscapeSink, type UnpairedEscapeSink, type UnsupportedRecord, VERSION, type VerbatimInput, WARNING_CODES, type WarningCode, alignmentShiftedFields, ambiguousEscapeAlignment, ambiguousMessageKind, ambiguousValueSplit, applyAstmProfile, applyAstmProfileToWarnings, applyLivd, astmDateToLocalISO, astmProfiles, attachComments, buildAstmMessage, classifyMessage, comments, commentsFor, composeAstmFrames, computeChecksum, decodeAstmFrames, decodeEscapes, deepFreeze, defineAstmProfile, defineLivdCatalog, delimiterRoleCollision, delimiterSwallowedByEscape, delimitersRedeclared, detectFraming, encodeComponent, fieldScalar, fieldsUnseparated, frameBadChecksum, frameOversize, frameSequenceGap, frameUnterminated, getAstmProfile, getDefaultAstmProfile, hasCollidingRoles, interpretAbnormalFlag, interpretResultStatus, isNonStandard, isSafetyCriticalCode, listAstmProfiles, livdAmbiguousMapping, livdUnmappedCode, lookupLivdForRecord, ltpAmbiguousTransport, ltpFrameRejected, ltpInitialState, ltpReduce, ltpUnexpectedEvent, messages, nonStandardDelimiters, orders, orphanComment, parseAstmDate, parseAstmRecords, parseChecksumHex, parseFramedAstm, parseReferenceRange, partialTimestamp, patient, primaryCode, profileQuirkApplied, query, readDelimiterDeclaration, readDelimiters, recognizeUniversalTestId, resolveProfileTransport, results, serializeAstmRecord, serializeAstmRecords, serializeField, serializeFramedAstm, setDefaultAstmProfile, splitEscapeAware, toChecksumHex, tokenizeHeader, tokenizeRecord, undefinedAbnormalFlag, undefinedResultStatus, uninterpretedQueryStatus, unitsAbsent, unknownEscapeSequence, unknownRecordType, unpairedEscapeCharacter, unparseableReferenceRange, unreadableRedeclaration };
6226
+ export { ALL_ASTM_WARNING_CODES, AMBIGUOUS_CODES, ACK as ASTM_ACK, ENQ as ASTM_ENQ, EOT as ASTM_EOT, NAK as ASTM_NAK, type AbnormalFlag, type AbnormalFlagCode, type AbnormalFlagMeaning, type AmbiguousAlignmentSink, type AmbiguousCode, type AnyAstmWarningCode, AstmAmbiguousStreamError, type AstmDate, type AstmDatePrecision, type AstmField, type AstmFrame, AstmFrameEncodeError, type AstmFrameEncodeErrorCode, type AstmFramePosition, AstmFrameStrictError, type AstmFrameWarning, type AstmFraming, type AstmLivdWarning, type AstmLtpWarning, type AstmMessage, type AstmMessageClassification, type AstmMessageKind, AstmParseError, type AstmParseOptions, type AstmPosition, type AstmProfile, AstmProfileDefinitionError, type AstmProfileProvenance, type AstmQuirkMatch, type AstmQuirkTolerance, type AstmRecord, type AstmRecordInput, type AstmRecordWarning, AstmSerializeError, type AstmSerializeErrorCode, type AstmStreamMessage, AstmStrictError, CANONICAL_DELIMITERS, type CommentInput, type CommentRecord, type ComposeFramesOptions, type DecodeAstmFramesResult, type DefineAstmProfileOptions, type DelimiterDeclarationFault, type DelimiterReadResult, type Delimiters, type DetectFramingOptions, type DetectFramingResult, FATAL_CODES, FRAME_WARNING_CODES, type FatalCode, type FrameChecksum, type FrameOptions, type FrameTerminator, type FrameWarningCode, type FramedAstmResult, type HeaderInput, type HeaderRecord, LIVD_WARNING_CODES, LTP_WARNING_CODES, type LivdAnnotation, type LivdCatalog, type LivdEntry, type LivdLookup, type LivdMapping, type LivdResult, type LivdWarningCode, type LtpAction, type LtpEvent, type LtpPhase, type LtpState, type LtpTransition, type LtpWarningCode, type ManufacturerRecord, type MessageInput, type OrderInput, type OrderRecord, type PatientInput, type PatientName, type PatientNameInput, type PatientRecord, type QueryInput, type QueryRecord, type ReferenceRange, type ReferenceRangeKind, type ResultInput, type ResultRecord, type ResultStatus, type ResultStatusCode, type ResultStatusMeaning, SAFETY_CRITICAL_CODES, type ScientificRecord, type ShiftedComponentsSink, type ShiftedFieldsSink, type SwallowedDelimiterSink, TOLERABLE_CODES, type TerminatorRecord, type TruncatedFieldSink, type UniversalTestId, type UniversalTestIdProvenance, type UnknownEscapeSink, type UnpairedEscapeSink, type UnsupportedRecord, VERSION, type VerbatimInput, WARNING_CODES, type WarningCode, alignmentShiftedComponents, alignmentShiftedFields, alignmentTruncatedField, ambiguousEscapeAlignment, ambiguousMessageKind, ambiguousValueSplit, applyAstmProfile, applyAstmProfileToWarnings, applyLivd, astmDateToLocalISO, astmProfiles, attachComments, buildAstmMessage, classifyMessage, comments, commentsFor, composeAstmFrames, computeChecksum, decodeAstmFrames, decodeEscapes, deepFreeze, defineAstmProfile, defineLivdCatalog, delimiterRoleCollision, delimiterSwallowedByEscape, delimitersRedeclared, detectFraming, encodeComponent, fieldScalar, fieldsUnseparated, frameBadChecksum, frameOversize, frameSequenceGap, frameUnterminated, getAstmProfile, getDefaultAstmProfile, hasCollidingRoles, interpretAbnormalFlag, interpretResultStatus, isNonStandard, isSafetyCriticalCode, listAstmProfiles, livdAmbiguousMapping, livdUnmappedCode, lookupLivdForRecord, ltpAmbiguousTransport, ltpFrameRejected, ltpInitialState, ltpReduce, ltpUnexpectedEvent, messages, nonStandardDelimiters, orders, orphanComment, parseAstmDate, parseAstmRecords, parseChecksumHex, parseFramedAstm, parseReferenceRange, partialTimestamp, patient, primaryCode, profileQuirkApplied, query, readDelimiterDeclaration, readDelimiters, recognizeUniversalTestId, resolveProfileTransport, results, serializeAstmRecord, serializeAstmRecords, serializeField, serializeFramedAstm, setDefaultAstmProfile, splitEscapeAware, toChecksumHex, tokenizeHeader, tokenizeRecord, undefinedAbnormalFlag, undefinedResultStatus, uninterpretedQueryStatus, unitsAbsent, unknownEscapeSequence, unknownRecordType, unpairedEscapeCharacter, unparseableReferenceRange, unreadableRedeclaration };