moonbit-icd

    MoonBit ICD-10/ICD-11 parsing, catalog queries, delimited import, batch validation, deterministic reports, and CLI workflows.

    icd
    healthcare
    validation
    catalog
    cli
    parser
    Download zip
    Author
    Version
    0.2.3
    License
    Apache-2.0
    Last updated
    2 months ago
    Downloads
    43

    No dependencies

    #moonbit-icd

    moonbit-icd is a reusable MoonBit toolkit for structured ICD coding workflows. It covers code normalization and parsing, chapter/range resolution, catalog queries, authorized data import/export, batch validation, deterministic reports, and a small icd-check command-line interface.

    The library is designed for health-information prototypes, claims-data preprocessing, research annotation, teaching tools, and other software that needs structural coding checks. It is not a diagnostic system and does not replace jurisdiction-specific coding guidance.

    #Core capabilities

    • Strict ICD-10 category/subcategory parsing and ICD-11 stem/extension parsing.
    • Canonical normalization for user-entered codes and safe invalid-input errors.
    • ICD-10 chapter boundaries, code ranges, overlap checks, and partitioning.
    • Catalog construction with duplicate, chapter, parent, and exclusion checks.
    • Exact, prefix, title, chapter, hierarchy, exclusion, and ranked-search queries.
    • CSV/TSV import/export with quoted-field support and line/column diagnostics.
    • Batch validation with valid/unknown/invalid counts and chapter distributions.
    • Text, TSV, and JSON-like deterministic report rendering.
    • A representative, hand-authored fixture catalog used by tests and examples.

    #Quick start

    Install the MoonBit toolchain, then run the project from its module root: The repository is validated with MoonBit stable v0.10.9; v0.10.9 or newer is recommended.

    moon check --target all --deny-warn moon test --target all --deny-warn moon run cmd/main -- check I10 moon run cmd/main -- chapter J45 moon run cmd/main -- prefix A00 moon run cmd/main -- search diabetes moon run cmd/main -- batch I10,B20,bad moon run cmd/main -- stats

    The package namespace is Ycq-68798/moonbit-icd. A consumer can depend on the module through moon.mod and use the public root package APIs.

    #Library example

    ///|
    test {
    let code = parse_icd10(" a00.0 ")
    inspect(code.canonical(), content="A00.0")

    let report = validate_icd10("B20")
    debug_inspect(report.status, content="Valid")
    assert_true(format_report(report).contains("exclusion hint"))
    }

    For an application-provided catalog, construct entries with IcdEntry::new, validate it with Catalog::from_entries, and then call validate_against or validate_batch. import_entries accepts the same six-column schema emitted by export_entries:

    code,title,chapter_id,parent,excludes,note I10,Essential hypertension,IX,,,example

    #CLI

    The executable is intentionally thin and delegates to the library:

    moon run cmd/main -- check I10 moon run cmd/main -- chapter J45 moon run cmd/main -- prefix A00 moon run cmd/main -- search diabetes moon run cmd/main -- batch I10,B20,bad moon run cmd/main -- stats

    check distinguishes invalid syntax, syntactically valid codes absent from the current catalog, and catalog entries that are valid for the structural workflow. batch keeps input order so callers can correlate each result with an imported row.

    #Architecture

    AreaFilesResponsibility
    Domain modeltypes.mbt, errors.mbtPublic records, statuses, and errors
    Parsingnormalization.mbt, parser.mbtCanonical forms and ICD syntax
    Rangesranges.mbt, range_tools.mbtChapters, rank boundaries, partitions
    Catalogcatalog*.mbt, advanced_query.mbtInvariants, queries, search, fixtures
    Data pipelinedelimited_reader.mbt, delimited_writer.mbtCSV/TSV import and export
    Validationvalidate.mbt, batch_validation.mbt, validation_policy.mbtSingle and batch workflows
    Reportinganalytics.mbt, report_rendering.mbt, data_quality.mbtMetrics, audits, deterministic output
    Executablescmd/main, cmd/benchmarkCLI usage and reproducible workload

    The root package has no external dependencies. This keeps consumers free to choose their own data source and serialization boundary.

    #Data boundary and licensing

    The repository contains representative hand-authored fixtures for software behavior, not a complete official ICD release. It does not redistribute a full WHO, ICD-10-CM, or national table. Production deployments should import data that they are authorized to use and should preserve that data's jurisdiction, version, attribution, and license metadata.

    Repository source is licensed under Apache-2.0. See DATA-SOURCES.md for provenance and redistribution guidance.

    #Benchmark

    Run the deterministic benchmark workload locally:

    moon run cmd/benchmark -- --rounds 1000

    The command reports the actual rounds, workload size, status totals, and a checksum. It is paired with an external wall-clock measurement so results can be reproduced on a stated toolchain and machine; see BENCHMARKS.md.

    #Testing and CI

    Local checks matching CI are:

    moon version --all moon update moon fmt --check moon check --target all --deny-warn moon test --target all --deny-warn moon test --target native --enable-coverage --deny-warn moon info git diff --exit-code

    GitHub Actions runs the MoonBit stable installer on Ubuntu, macOS, and Windows, checks all supported backends, runs native coverage where available, and rejects formatting or generated-interface drift.

    #Contributing

    See CONTRIBUTING.md for the development loop, test expectations, and data-source requirements. Bug reports should include the smallest reproducible code, toolchain version, target backend, and command output. Never include private clinical records or other sensitive data.

    #License

    Apache-2.0. See LICENSE.

    CatalogError

    pub(all) suberror CatalogError {
    DuplicateCode(String)
    InvalidEntry(String, String)
    MissingReference(String, String)
    } derive(Eq, ToJson,
    Debug
    )

    IcdParseError

    pub(all) suberror IcdParseError {
    EmptyInput
    UnsupportedEdition(String)
    InvalidCode(String)
    } derive(Eq, ToJson,
    Debug
    )

    BatchItem

    pub struct BatchItem {
    line : Int
    input : String
    report : ValidationReport
    } derive(Eq, ToJson,
    Debug
    )

    BatchReport

    pub struct BatchReport {
    items : Array[BatchItem]
    summary : BatchSummary
    } derive(Eq, ToJson,
    Debug
    )

    BatchSummary

    pub struct BatchSummary {
    total : Int
    valid : Int
    unknown : Int
    invalid : Int
    chapters : Array[ChapterCount]
    } derive(Eq, ToJson,
    Debug
    )

    Catalog

    pub struct Catalog {
    entries : Array[IcdEntry]
    } derive(
    Debug
    )

    Catalog::all

    fn Catalog::all(self : Catalog) -> Array[IcdEntry]

    Catalog::ancestors

    fn Catalog::ancestors(self : Catalog, code : String) -> Array[IcdEntry]

    Catalog::children

    fn Catalog::children(self : Catalog, parent : String) -> Array[IcdEntry]

    Catalog::exclusions

    fn Catalog::exclusions(self : Catalog, code : String) -> Array[IcdEntry]

    Catalog::from_entries

    fn Catalog::from_entries(entries : Array[IcdEntry]) -> Catalog raise CatalogError

    Catalog::in_chapter

    fn Catalog::in_chapter(self : Catalog, chapter_id : String) -> Array[IcdEntry]

    Catalog::len

    fn Catalog::len(self : Catalog) -> Int

    Catalog::lookup

    fn Catalog::lookup(self : Catalog, code : String) -> IcdEntry?

    Catalog::prefix

    fn Catalog::prefix(self : Catalog, prefix : String) -> Array[IcdEntry]

    fn Catalog::ranked_search(self : Catalog, query : String, limit : Int) -> Array[SearchHit]

    Catalog::search_title

    fn Catalog::search_title(self : Catalog, query : String) -> Array[IcdEntry]

    CatalogAudit

    pub struct CatalogAudit {
    entries : Int
    chapter_coverage : Int
    missing_parents : Int
    missing_exclusions : Int
    duplicate_codes : Int
    invalid_codes : Int
    } derive(Eq, ToJson,
    Debug
    )

    CatalogAudit::is_healthy

    fn CatalogAudit::is_healthy(self : CatalogAudit) -> Bool

    ChapterCount

    pub struct ChapterCount {
    chapter_id : String
    total : Int
    valid : Int
    unknown : Int
    invalid : Int
    } derive(Eq, ToJson,
    Debug
    )

    CodeRange

    pub struct CodeRange {
    start : String
    end : String
    start_rank : Int
    end_rank : Int
    } derive(Eq, ToJson,
    Debug
    )

    CodeRange::contains

    fn CodeRange::contains(self : CodeRange, code : String) -> Bool

    CodeRange::new

    fn CodeRange::new(start : String, end : String) -> CodeRange raise IcdParseError

    CodeRange::overlaps

    fn CodeRange::overlaps(self : CodeRange, other : CodeRange) -> Bool

    CodeRange::partition

    fn CodeRange::partition(self : CodeRange, codes : Array[String]) -> RangePartition

    Delimiter

    pub enum Delimiter {
    Comma
    Tab
    } derive(Eq, ToJson,
    Debug
    )

    Delimiter::comma

    fn Delimiter::comma() -> Delimiter

    Delimiter::tab

    fn Delimiter::tab() -> Delimiter

    IcdChapter

    pub struct IcdChapter {
    id : String
    title : String
    start : String
    end : String
    note : String
    } derive(Eq, ToJson,
    Debug
    )

    IcdChapter::contains

    fn IcdChapter::contains(self : IcdChapter, code : IcdCode) -> Bool

    IcdCode

    pub struct IcdCode {
    edition : IcdEdition
    raw : String
    stem : String
    category : String
    subcategory : String?
    numeric : Int
    extension : String?
    } derive(Eq, ToJson,
    Debug
    )

    IcdCode::canonical

    fn IcdCode::canonical(self : IcdCode) -> String

    IcdEdition

    pub enum IcdEdition {
    ICD10
    ICD11
    } derive(Eq, ToJson,
    Debug
    )

    IcdEntry

    pub struct IcdEntry {
    code : String
    title : String
    chapter_id : String
    parent : String?
    excludes : Array[String]
    note : String
    } derive(Eq, ToJson,
    Debug
    )

    IcdEntry::new

    fn IcdEntry::new(code : String, title : String, chapter_id : String, parent : String?, excludes : Array[String], note : String) -> IcdEntry

    ImportDiagnostic

    pub struct ImportDiagnostic {
    line : Int
    column : Int
    message : String
    hint : String
    } derive(Eq, ToJson,
    Debug
    )

    ImportOptions

    pub struct ImportOptions {
    has_header : Bool
    delimiter : Delimiter
    reject_unknown_columns : Bool
    } derive(Eq, ToJson,
    Debug
    )

    ImportOptions::csv

    ImportOptions::new

    fn ImportOptions::new(has_header : Bool, delimiter : Delimiter, reject_unknown_columns : Bool) -> ImportOptions

    ImportOptions::tsv

    ImportResult

    pub struct ImportResult {
    entries : Array[IcdEntry]
    diagnostics : Array[ImportDiagnostic]
    } derive(Eq, ToJson,
    Debug
    )

    NormalizationResult

    pub struct NormalizationResult {
    accepted : Array[String]
    rejected : Array[String]
    } derive(Eq, ToJson,
    Debug
    )

    RangePartition

    pub struct RangePartition {
    inside : Array[String]
    outside : Array[String]
    invalid : Array[String]
    } derive(Eq, ToJson,
    Debug
    )

    SearchHit

    pub struct SearchHit {
    code : String
    title : String
    score : Int
    } derive(Eq, ToJson,
    Debug
    )

    ValidationIssue

    pub struct ValidationIssue {
    code : String
    message : String
    hint : String
    } derive(Eq, ToJson,
    Debug
    )

    ValidationPolicy

    pub struct ValidationPolicy {
    require_catalog_membership : Bool
    } derive(Eq, ToJson,
    Debug
    )

    ValidationPolicy::permissive

    ValidationPolicy::strict

    ValidationReport

    pub struct ValidationReport {
    input : String
    normalized : String?
    status : ValidationStatus
    chapter : IcdChapter?
    entry : IcdEntry?
    issues : Array[ValidationIssue]
    } derive(Eq, ToJson,
    Debug
    )

    ValidationStatus

    pub enum ValidationStatus {
    Valid
    Unknown
    Invalid
    } derive(Eq, ToJson,
    Debug
    )

    audit_catalog

    fn audit_catalog(catalog : Catalog) -> CatalogAudit

    audit_entries

    fn audit_entries(entries : Array[IcdEntry]) -> CatalogAudit

    bundled_catalog

    fn bundled_catalog() -> Catalog

    canonicalize_lines

    fn canonicalize_lines(text : String) -> NormalizationResult

    chapters_for_range

    fn chapters_for_range(start : String, end : String) -> Array[IcdChapter]

    children_of

    fn children_of(parent : String) -> Array[IcdEntry]

    exclusion_hints

    fn exclusion_hints(entry : IcdEntry) -> Array[IcdEntry]

    execute_cli

    fn execute_cli(args : Array[String]) -> String

    export_entries

    fn export_entries(entries : Array[IcdEntry], delimiter : Delimiter) -> String

    find_chapter

    fn find_chapter(code : IcdCode) -> IcdChapter?

    find_entry

    fn find_entry(code : String) -> IcdEntry?

    format_report

    fn format_report(report : ValidationReport) -> String

    icd10_chapters

    fn icd10_chapters() -> Array[IcdChapter]

    import_entries

    fn import_entries(text : String, options : ImportOptions) -> ImportResult

    is_valid_category

    fn is_valid_category(code : String) -> Bool

    normalize_code

    fn normalize_code(input : String) -> String

    normalize_codes

    fn normalize_codes(inputs : Array[String]) -> NormalizationResult

    parse_code

    fn parse_code(input : String, edition? : IcdEdition) -> IcdCode raise IcdParseError

    parse_icd10

    fn parse_icd10(input : String) -> IcdCode raise IcdParseError

    parse_icd11

    fn parse_icd11(input : String) -> IcdCode raise IcdParseError

    query_prefix

    fn query_prefix(prefix : String) -> Array[IcdEntry]

    render_batch_json

    fn render_batch_json(report : BatchReport) -> String

    render_batch_text

    fn render_batch_text(report : BatchReport) -> String

    render_batch_tsv

    fn render_batch_tsv(report : BatchReport) -> String

    sample_entries

    fn sample_entries() -> Array[IcdEntry]

    summarize

    fn summarize(reports : Array[ValidationReport]) -> BatchSummary

    validate_against

    fn validate_against(catalog : Catalog, input : String) -> ValidationReport

    validate_batch

    fn validate_batch(catalog : Catalog, inputs : Array[String]) -> BatchReport

    validate_icd10

    fn validate_icd10(input : String) -> ValidationReport

    validate_with_policy

    fn validate_with_policy(catalog : Catalog, input : String, policy : ValidationPolicy) -> ValidationReport