/**
 * ontology/fromSkos — a customer's SKOS concept scheme (JSON-LD, already
 * parsed) becomes OUR map: `readSkos` is the pure parse, `fromSkos` joins
 * the host's sources onto it and returns an `OntologySpec` for
 * `defineOntology` — the ONE shape everything else reads.
 *
 * Pattern: reader = adapter. Two pure functions over plain JSON; no I/O, no
 *          registry, no second validation path — the result goes through
 *          `defineOntology` unchanged, which is where an id that is not
 *          identifier-safe, an alias that collides with an id, or a source
 *          nobody declared is refused.
 * Role:    Map. Nothing here infers: a concept is a node typed
 *          `skos:Concept`, its id is the last segment of its IRI, its
 *          meaning is its `definition`, else its `scopeNote`, else its
 *          `prefLabel`; `broader` is `is-a`, `related` is `related`; every
 *          other name and every label in another language is left where it
 *          was. SKOS cannot say which SOURCE holds a term or which TOOL reads
 *          it — the host binds those by hand in `SkosJoin.bind`; a term with
 *          no binding is the honest state "declared, no source holds it".
 * Emits:   N/A.
 *
 * THE OWNER'S RULING (2026-09-18): customers already have taxonomies, almost
 * always as SKOS. The library takes THEIRS in and turns it into OUR map;
 * readers are adapters, `defineOntology` stays canonical. OWL is out of
 * scope; a Turtle reader is a follow-up; serving the map back in SKOS
 * vocabulary waits for the bench.
 *
 * REFUSALS — every one an `Error` with a `code` (`ERR_SKOS_…`), the IRI(s)
 * involved and what was expected; the reader never returns a partial map:
 *   ERR_SKOS_INPUT             not a JSON-LD document, or a node that is not an object
 *   ERR_SKOS_NAMED_GRAPH       a node that is itself a named graph (`{ "@id", "@graph": [...] }`) —
 *                              its concepts would be dropped without a word; flatten the document first
 *   ERR_SKOS_UNTYPED           a node carrying SKOS properties with no `@type`
 *   ERR_SKOS_NO_CONCEPTS       no `skos:Concept` in the document
 *   ERR_SKOS_NO_LABEL          a concept with no prefLabel in the asked language
 *   ERR_SKOS_ID                an IRI whose last segment is empty
 *   ERR_SKOS_ID_COLLISION      two concepts collapsing to one id
 *   ERR_SKOS_UNKNOWN_CONCEPT   a broader/narrower/related target the document does not hold
 *   ERR_SKOS_CYCLE             a cycle in `broader` (SKOS forbids it)
 *   ERR_SKOS_SCHEME_MISSING    no id or no version, from the join or the scheme node
 *   ERR_SKOS_SCHEME_AMBIGUOUS  several scheme nodes and the join does not settle id and version
 *   ERR_SKOS_BIND_UNKNOWN_TERM a `bind` key naming a term the scheme does not hold
 */
import type { OntologyEdge, OntologyNode, OntologyNodeSource, OntologySource, OntologySpec } from './types.js';
import { type JsonLdNode } from './skosJsonLd.js';
/** A JSON-LD document, already parsed: one node, an array of nodes, or `{ "@context"?, "@graph": [...] }`. */
export type SkosInput = JsonLdNode | readonly JsonLdNode[];
export type SkosErrorCode = 'ERR_SKOS_INPUT' | 'ERR_SKOS_NAMED_GRAPH' | 'ERR_SKOS_UNTYPED' | 'ERR_SKOS_NO_CONCEPTS' | 'ERR_SKOS_NO_LABEL' | 'ERR_SKOS_ID' | 'ERR_SKOS_ID_COLLISION' | 'ERR_SKOS_UNKNOWN_CONCEPT' | 'ERR_SKOS_CYCLE' | 'ERR_SKOS_SCHEME_MISSING' | 'ERR_SKOS_SCHEME_AMBIGUOUS' | 'ERR_SKOS_BIND_UNKNOWN_TERM';
/** The one error the reader throws: a `code`, the IRI(s) involved, what was expected. */
export declare class SkosError extends Error {
    readonly code: SkosErrorCode;
    readonly iris: readonly string[];
    constructor(code: SkosErrorCode, message: string, iris?: readonly string[]);
}
/** How to read the document: which language's labels to take (default `'en'`). */
export interface ReadSkosOptions {
    readonly language?: string;
}
/** One concept as read: its IRI, its derived id, and the node it becomes (no sources — SKOS has none). */
export interface SkosConcept {
    readonly iri: string;
    readonly id: string;
    readonly prefLabel: string;
    readonly node: OntologyNode;
}
/** The pure parse: the scheme's identity when the document carries it, the concepts, the edges. */
export interface SkosScheme {
    readonly iri?: string;
    readonly id?: string;
    readonly version?: string;
    readonly language: string;
    readonly concepts: readonly SkosConcept[];
    /** `is-a` from `broader`/`narrower` (once per pair), then `related` (once per pair, ends ordered by id), then `footprint:edge` entries — each group sorted, so node order and the broader/narrower spelling never move the hash. */
    readonly edges: readonly OntologyEdge[];
}
/** What SKOS cannot say and the host binds by hand: sources, and which term is held where. */
export interface SkosJoin {
    /** The map's id — else the scheme node's last IRI segment. */
    readonly id?: string;
    /** The map's version — else the scheme node's `dcterms:modified` / `owl:versionInfo` / `schema:version`. */
    readonly version?: string;
    /** Which language's labels to take (default `'en'`). */
    readonly language?: string;
    readonly sources: Readonly<Record<string, OntologySource>>;
    /** term id → the sources holding it; a key naming a term the scheme does not hold is refused. */
    readonly bind?: Readonly<Record<string, readonly OntologyNodeSource[]>>;
}
/**
 * The pure parse: concepts (sorted by id), edges, and the scheme's identity
 * when ONE `skos:ConceptScheme` node carries it. Refuses by code; never
 * partial. Exported so a host can look before it joins, and for tests.
 */
export declare function readSkos(input: SkosInput, options?: ReadSkosOptions): SkosScheme;
/**
 * The customer's scheme joined with the host's sources → an `OntologySpec`.
 * The host calls `defineOntology(fromSkos(input, join))`: nothing is
 * validated twice, and nothing is guessed — a term the join does not bind
 * has no sources, which is the honest state.
 */
export declare function fromSkos(input: SkosInput, join: SkosJoin): OntologySpec;
