@cosyte/astm 0.0.7 → 0.0.8

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.mjs CHANGED
@@ -119,7 +119,11 @@ function primaryCode(u) {
119
119
 
120
120
  // src/common/warnings.ts
121
121
  var WARNING_CODES = {
122
- /** A record's type letter is not one of the modeled types: surfaced as an unsupported record. */
122
+ /**
123
+ * A record's type letter is not one of the modeled types: surfaced as an unsupported record,
124
+ * never dropped. Treat it as a possible lost message boundary, because a header the reader did
125
+ * not recognize as one does not open a new message.
126
+ */
123
127
  ASTM_RECORD_UNKNOWN_TYPE: "ASTM_RECORD_UNKNOWN_TYPE",
124
128
  /** The header declared delimiters other than the canonical `H|\^&`: tolerated, noted. */
125
129
  ASTM_NONSTANDARD_DELIMITERS: "ASTM_NONSTANDARD_DELIMITERS",
@@ -212,7 +216,7 @@ var WARNING_CODES = {
212
216
  function unknownRecordType(position) {
213
217
  return {
214
218
  code: WARNING_CODES.ASTM_RECORD_UNKNOWN_TYPE,
215
- message: "Unrecognized record type, surfaced verbatim as an unsupported record.",
219
+ message: "Unrecognized record type, surfaced verbatim as an unsupported record. If this record was a header, message grouping did not open a new message here.",
216
220
  position
217
221
  };
218
222
  }
@@ -425,6 +429,135 @@ function classifyMessage(records) {
425
429
  return { kind, hasQuery, hasResults, hasOrders, isHostQueryRequest: kind === "host-query" };
426
430
  }
427
431
 
432
+ // src/frames/warnings.ts
433
+ var FRAME_WARNING_CODES = {
434
+ /**
435
+ * A frame's two-hex-char checksum did not match the modulo-256 sum recomputed over its bytes. The
436
+ * frame is surfaced with `trusted: false` and its text is **never merged** into a reassembled
437
+ * record (default **warn** in lenient mode, escalated to a thrown error in `strict`). Corruption is
438
+ * never silently trusted: the "checksums are routinely not validated" claim was refuted; we
439
+ * validate.
440
+ */
441
+ ASTM_FRAME_BAD_CHECKSUM: "ASTM_FRAME_BAD_CHECKSUM",
442
+ /**
443
+ * A frame's sequence number was not the expected next value (`1 → … → 7 → 0 → …`): a frame was
444
+ * possibly dropped. The stream is **never silently concatenated across the gap** as if contiguous;
445
+ * the in-progress record is tainted and not emitted as a clean reassembly.
446
+ */
447
+ ASTM_FRAME_SEQUENCE_GAP: "ASTM_FRAME_SEQUENCE_GAP",
448
+ /**
449
+ * A frame opened with `STX` but no valid terminator + checksum was found before the stream ended
450
+ * (or before the next `STX`), or a record's frames ended on an intermediate `ETB` with no final
451
+ * `ETX`. The partial bytes are surfaced flagged untrusted and **no partial record is invented**
452
+ * (warn in lenient, thrown in `strict`).
453
+ */
454
+ ASTM_FRAME_UNTERMINATED: "ASTM_FRAME_UNTERMINATED",
455
+ /**
456
+ * A frame's record text exceeded the 240-byte limit without a split. The frame is still surfaced
457
+ * (and, if its checksum validates, reassembled): the deviation is flagged, not silently dropped
458
+ * (warn in lenient, thrown in `strict`).
459
+ */
460
+ ASTM_FRAME_OVERSIZE: "ASTM_FRAME_OVERSIZE"
461
+ };
462
+ function frameBadChecksum(position) {
463
+ return {
464
+ code: FRAME_WARNING_CODES.ASTM_FRAME_BAD_CHECKSUM,
465
+ message: "Frame checksum mismatch, surfaced untrusted, never merged into a record.",
466
+ position
467
+ };
468
+ }
469
+ function frameSequenceGap(position) {
470
+ return {
471
+ code: FRAME_WARNING_CODES.ASTM_FRAME_SEQUENCE_GAP,
472
+ message: "Frame number out of sequence, possible dropped frame, never silently bridged.",
473
+ position
474
+ };
475
+ }
476
+ function frameUnterminated(position) {
477
+ return {
478
+ code: FRAME_WARNING_CODES.ASTM_FRAME_UNTERMINATED,
479
+ message: "Unterminated frame, partial bytes surfaced untrusted, no partial record invented.",
480
+ position
481
+ };
482
+ }
483
+ function frameOversize(position) {
484
+ return {
485
+ code: FRAME_WARNING_CODES.ASTM_FRAME_OVERSIZE,
486
+ message: "Frame text exceeded the 240-byte limit without a split, flagged, never dropped.",
487
+ position
488
+ };
489
+ }
490
+
491
+ // src/ltp/warnings.ts
492
+ var LTP_WARNING_CODES = {
493
+ /**
494
+ * The transport detector could not tell a framed stream from a raw (unframed) one from its leading
495
+ * byte: it was neither `STX`/`ENQ` nor a bare record letter. It **defaults to framed** and warns,
496
+ * never guessing silently into data loss; a profile override forces the mode. (cobas b121 drops
497
+ * framing over TCP; cobas 4800 / Iguana retain it, both realities exist, so an unrecognizable lead
498
+ * is defaulted, not assumed.)
499
+ */
500
+ ASTM_LTP_AMBIGUOUS_TRANSPORT: "ASTM_LTP_AMBIGUOUS_TRANSPORT",
501
+ /**
502
+ * A control event arrived in a protocol state that did not expect it: e.g. an inbound `ACK`/`NAK`
503
+ * at a receiver (which sends, never receives, those), or an `ENQ` mid-transfer. The event is
504
+ * surfaced and handled defensively (an unexpected `ACK`/`NAK` is **never** read as acceptance of
505
+ * data); it never advances the transfer as if valid.
506
+ */
507
+ ASTM_LTP_UNEXPECTED_EVENT: "ASTM_LTP_UNEXPECTED_EVENT",
508
+ /**
509
+ * The receiver rejected a received frame with a `NAK` instead of accepting it: because its
510
+ * checksum failed, it was unterminated, or its frame number was out of sequence. The frame's text
511
+ * is **never** appended to the record and the transfer does **not** advance; the receiver awaits the
512
+ * sender's retransmit. This is the protocol-level face of the frame codec's fail-safe: a bad frame
513
+ * drives retransmit, not acceptance.
514
+ */
515
+ ASTM_LTP_FRAME_REJECTED: "ASTM_LTP_FRAME_REJECTED"
516
+ };
517
+ function ltpAmbiguousTransport() {
518
+ return {
519
+ code: LTP_WARNING_CODES.ASTM_LTP_AMBIGUOUS_TRANSPORT,
520
+ message: "Leading byte was neither a frame start (STX/ENQ) nor a record letter, defaulted to framed; override with a profile to force raw."
521
+ };
522
+ }
523
+ function ltpUnexpectedEvent(frameNumber) {
524
+ return {
525
+ code: LTP_WARNING_CODES.ASTM_LTP_UNEXPECTED_EVENT,
526
+ message: "Control event arrived in a state that did not expect it, handled defensively, never read as acceptance.",
527
+ ...frameNumber !== void 0 ? { frameNumber } : {}
528
+ };
529
+ }
530
+ function ltpFrameRejected(frameNumber) {
531
+ return {
532
+ code: LTP_WARNING_CODES.ASTM_LTP_FRAME_REJECTED,
533
+ message: "Frame rejected (bad checksum, unterminated, or out of sequence), NAK sent, retransmit expected, never accepted.",
534
+ ...frameNumber !== void 0 ? { frameNumber } : {}
535
+ };
536
+ }
537
+
538
+ // src/profiles/safety.ts
539
+ var TOLERABLE_CODES = Object.freeze(
540
+ /* @__PURE__ */ new Set([
541
+ WARNING_CODES.ASTM_NONSTANDARD_DELIMITERS,
542
+ WARNING_CODES.ASTM_UNKNOWN_ESCAPE_SEQUENCE,
543
+ WARNING_CODES.ASTM_RECORD_UNINTERPRETED_QUERY_STATUS
544
+ ])
545
+ );
546
+ var ALL_WARNING_CODES = [
547
+ ...Object.values(WARNING_CODES),
548
+ ...Object.values(FRAME_WARNING_CODES),
549
+ ...Object.values(LTP_WARNING_CODES)
550
+ ];
551
+ var ALL_ASTM_WARNING_CODES = Object.freeze(
552
+ new Set(ALL_WARNING_CODES)
553
+ );
554
+ var SAFETY_CRITICAL_CODES = Object.freeze(
555
+ new Set(ALL_WARNING_CODES.filter((c) => !TOLERABLE_CODES.has(c)))
556
+ );
557
+ function isSafetyCriticalCode(code) {
558
+ return SAFETY_CRITICAL_CODES.has(code);
559
+ }
560
+
428
561
  // src/profiles/apply.ts
429
562
  function toleranceApplies(tolerance, warning) {
430
563
  if (tolerance.code !== warning.code) return false;
@@ -440,6 +573,7 @@ function toleranceApplies(tolerance, warning) {
440
573
  }
441
574
  function applyAstmProfile(profile, warning) {
442
575
  if (warning.expected === true) return warning;
576
+ if (isSafetyCriticalCode(warning.code)) return warning;
443
577
  for (const tolerance of profile.tolerate) {
444
578
  if (toleranceApplies(tolerance, warning)) {
445
579
  return profileQuirkApplied(warning, profile.name);
@@ -561,136 +695,6 @@ var AstmProfileDefinitionError = class extends Error {
561
695
  }
562
696
  };
563
697
 
564
- // src/frames/warnings.ts
565
- var FRAME_WARNING_CODES = {
566
- /**
567
- * A frame's two-hex-char checksum did not match the modulo-256 sum recomputed over its bytes. The
568
- * frame is surfaced with `trusted: false` and its text is **never merged** into a reassembled
569
- * record (default **warn** in lenient mode, escalated to a thrown error in `strict`). Corruption is
570
- * never silently trusted: the "checksums are routinely not validated" claim was refuted; we
571
- * validate.
572
- */
573
- ASTM_FRAME_BAD_CHECKSUM: "ASTM_FRAME_BAD_CHECKSUM",
574
- /**
575
- * A frame's sequence number was not the expected next value (`1 → … → 7 → 0 → …`): a frame was
576
- * possibly dropped. The stream is **never silently concatenated across the gap** as if contiguous;
577
- * the in-progress record is tainted and not emitted as a clean reassembly.
578
- */
579
- ASTM_FRAME_SEQUENCE_GAP: "ASTM_FRAME_SEQUENCE_GAP",
580
- /**
581
- * A frame opened with `STX` but no valid terminator + checksum was found before the stream ended
582
- * (or before the next `STX`), or a record's frames ended on an intermediate `ETB` with no final
583
- * `ETX`. The partial bytes are surfaced flagged untrusted and **no partial record is invented**
584
- * (warn in lenient, thrown in `strict`).
585
- */
586
- ASTM_FRAME_UNTERMINATED: "ASTM_FRAME_UNTERMINATED",
587
- /**
588
- * A frame's record text exceeded the 240-byte limit without a split. The frame is still surfaced
589
- * (and, if its checksum validates, reassembled): the deviation is flagged, not silently dropped
590
- * (warn in lenient, thrown in `strict`).
591
- */
592
- ASTM_FRAME_OVERSIZE: "ASTM_FRAME_OVERSIZE"
593
- };
594
- function frameBadChecksum(position) {
595
- return {
596
- code: FRAME_WARNING_CODES.ASTM_FRAME_BAD_CHECKSUM,
597
- message: "Frame checksum mismatch, surfaced untrusted, never merged into a record.",
598
- position
599
- };
600
- }
601
- function frameSequenceGap(position) {
602
- return {
603
- code: FRAME_WARNING_CODES.ASTM_FRAME_SEQUENCE_GAP,
604
- message: "Frame number out of sequence, possible dropped frame, never silently bridged.",
605
- position
606
- };
607
- }
608
- function frameUnterminated(position) {
609
- return {
610
- code: FRAME_WARNING_CODES.ASTM_FRAME_UNTERMINATED,
611
- message: "Unterminated frame, partial bytes surfaced untrusted, no partial record invented.",
612
- position
613
- };
614
- }
615
- function frameOversize(position) {
616
- return {
617
- code: FRAME_WARNING_CODES.ASTM_FRAME_OVERSIZE,
618
- message: "Frame text exceeded the 240-byte limit without a split, flagged, never dropped.",
619
- position
620
- };
621
- }
622
-
623
- // src/ltp/warnings.ts
624
- var LTP_WARNING_CODES = {
625
- /**
626
- * The transport detector could not tell a framed stream from a raw (unframed) one from its leading
627
- * byte: it was neither `STX`/`ENQ` nor a bare record letter. It **defaults to framed** and warns,
628
- * never guessing silently into data loss; a profile override forces the mode. (cobas b121 drops
629
- * framing over TCP; cobas 4800 / Iguana retain it, both realities exist, so an unrecognizable lead
630
- * is defaulted, not assumed.)
631
- */
632
- ASTM_LTP_AMBIGUOUS_TRANSPORT: "ASTM_LTP_AMBIGUOUS_TRANSPORT",
633
- /**
634
- * A control event arrived in a protocol state that did not expect it: e.g. an inbound `ACK`/`NAK`
635
- * at a receiver (which sends, never receives, those), or an `ENQ` mid-transfer. The event is
636
- * surfaced and handled defensively (an unexpected `ACK`/`NAK` is **never** read as acceptance of
637
- * data); it never advances the transfer as if valid.
638
- */
639
- ASTM_LTP_UNEXPECTED_EVENT: "ASTM_LTP_UNEXPECTED_EVENT",
640
- /**
641
- * The receiver rejected a received frame with a `NAK` instead of accepting it: because its
642
- * checksum failed, it was unterminated, or its frame number was out of sequence. The frame's text
643
- * is **never** appended to the record and the transfer does **not** advance; the receiver awaits the
644
- * sender's retransmit. This is the protocol-level face of the frame codec's fail-safe: a bad frame
645
- * drives retransmit, not acceptance.
646
- */
647
- ASTM_LTP_FRAME_REJECTED: "ASTM_LTP_FRAME_REJECTED"
648
- };
649
- function ltpAmbiguousTransport() {
650
- return {
651
- code: LTP_WARNING_CODES.ASTM_LTP_AMBIGUOUS_TRANSPORT,
652
- message: "Leading byte was neither a frame start (STX/ENQ) nor a record letter, defaulted to framed; override with a profile to force raw."
653
- };
654
- }
655
- function ltpUnexpectedEvent(frameNumber) {
656
- return {
657
- code: LTP_WARNING_CODES.ASTM_LTP_UNEXPECTED_EVENT,
658
- message: "Control event arrived in a state that did not expect it, handled defensively, never read as acceptance.",
659
- ...frameNumber !== void 0 ? { frameNumber } : {}
660
- };
661
- }
662
- function ltpFrameRejected(frameNumber) {
663
- return {
664
- code: LTP_WARNING_CODES.ASTM_LTP_FRAME_REJECTED,
665
- message: "Frame rejected (bad checksum, unterminated, or out of sequence), NAK sent, retransmit expected, never accepted.",
666
- ...frameNumber !== void 0 ? { frameNumber } : {}
667
- };
668
- }
669
-
670
- // src/profiles/safety.ts
671
- var TOLERABLE_CODES = Object.freeze(
672
- /* @__PURE__ */ new Set([
673
- WARNING_CODES.ASTM_RECORD_UNKNOWN_TYPE,
674
- WARNING_CODES.ASTM_NONSTANDARD_DELIMITERS,
675
- WARNING_CODES.ASTM_UNKNOWN_ESCAPE_SEQUENCE,
676
- WARNING_CODES.ASTM_RECORD_UNINTERPRETED_QUERY_STATUS
677
- ])
678
- );
679
- var ALL_WARNING_CODES = [
680
- ...Object.values(WARNING_CODES),
681
- ...Object.values(FRAME_WARNING_CODES),
682
- ...Object.values(LTP_WARNING_CODES)
683
- ];
684
- var ALL_ASTM_WARNING_CODES = Object.freeze(
685
- new Set(ALL_WARNING_CODES)
686
- );
687
- var SAFETY_CRITICAL_CODES = Object.freeze(
688
- new Set(ALL_WARNING_CODES.filter((c) => !TOLERABLE_CODES.has(c)))
689
- );
690
- function isSafetyCriticalCode(code) {
691
- return SAFETY_CRITICAL_CODES.has(code);
692
- }
693
-
694
698
  // src/profiles/validate.ts
695
699
  var KNOWN_OPTION_KEYS = [
696
700
  "name",
@@ -770,7 +774,7 @@ function validateTolerations(tolerate, profileName) {
770
774
  }
771
775
  if (isSafetyCriticalCode(t.code)) {
772
776
  throw new AstmProfileDefinitionError(
773
- `Profile '${profileName}' may not tolerate '${t.code}': it is a safety-critical warning code (a result value / flag / status / range / units, patient or comment context, message-kind ambiguity, code system, or a frame / LTP integrity warning). A profile quiets benign structural noise, never a deviation that could change a clinical reading or corrupt the wire: it can never make a bad checksum "ok" or a cancelled result read "final."`,
777
+ `Profile '${profileName}' may not tolerate '${t.code}': it is a safety-critical warning code (a result value / flag / status / range / units, patient or comment context, message-kind ambiguity, code system, an unrecognized record type, or a frame / LTP integrity warning). A profile quiets benign structural noise, never a deviation that could change a clinical reading, report a lost message boundary, or corrupt the wire: it can never make a bad checksum "ok", a cancelled result read "final", or quiet the warning that says two messages were read as one.`,
774
778
  profileName
775
779
  );
776
780
  }
@@ -2197,7 +2201,7 @@ function concatBytes3(chunks) {
2197
2201
  }
2198
2202
 
2199
2203
  // src/index.ts
2200
- var VERSION = "0.0.7";
2204
+ var VERSION = "0.0.8";
2201
2205
 
2202
2206
  export { ALL_ASTM_WARNING_CODES, AMBIGUOUS_CODES, ACK as ASTM_ACK, ENQ as ASTM_ENQ, EOT as ASTM_EOT, NAK as ASTM_NAK, AstmAmbiguousStreamError, AstmFrameEncodeError, AstmFrameStrictError, AstmParseError, AstmProfileDefinitionError, AstmSerializeError, AstmStrictError, CANONICAL_DELIMITERS, FATAL_CODES, FRAME_WARNING_CODES, LIVD_WARNING_CODES, LTP_WARNING_CODES, SAFETY_CRITICAL_CODES, TOLERABLE_CODES, VERSION, WARNING_CODES, ambiguousMessageKind, ambiguousValueSplit, applyAstmProfile, applyAstmProfileToWarnings, applyLivd, astmDateToLocalISO, astmProfiles, attachComments, buildAstmMessage, classifyMessage, comments, commentsFor, composeAstmFrames, computeChecksum, decodeAstmFrames, decodeEscapes, deepFreeze, defineAstmProfile, defineLivdCatalog, delimitersRedeclared, detectFraming, encodeComponent, fieldScalar, frameBadChecksum, frameOversize, frameSequenceGap, frameUnterminated, getAstmProfile, getDefaultAstmProfile, 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, readDelimiters, recognizeUniversalTestId, resolveProfileTransport, results, serializeAstmRecord, serializeAstmRecords, serializeField, serializeFramedAstm, setDefaultAstmProfile, splitEscapeAware, toChecksumHex, tokenizeHeader, tokenizeRecord, undefinedAbnormalFlag, undefinedResultStatus, uninterpretedQueryStatus, unitsAbsent, unknownEscapeSequence, unknownRecordType, unparseableReferenceRange, unreadableRedeclaration };
2203
2207
  //# sourceMappingURL=index.mjs.map