/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * Weight-package resolution. * * The `@mailwoman/neural-weights-` packages ship the `model.onnx` + `tokenizer.model` files * declared in their `files` array. At install time npm bundles those files alongside the * package.json; at runtime we locate them by resolving the package.json then walking sideways. * * Local development gotcha: the weights packages in the monorepo carry only metadata (package.json * * - README.md + model-card.json). The actual binary files are produced by Phase 2 training and copied * in at publish time. To run the neural classifier locally without publishing, either: * * 1. Pass explicit `modelPath` + `tokenizerPath` to `loadFromWeights`, or * 2. Symlink the dev model files into the weights package directory — see * `scripts/link-dev-weights.ts` in each weights package. * * The resolver checks for both files and throws a single actionable error when neither is findable, * naming all the paths it tried. */ import type { AnchorSpanMode } from "./anchor-inference.ts"; import { PlacetypeCensusResolver } from "./placetype-census.ts"; /** * The user-level npm-prefix cache the CLI weights guard installs into (`mailwoman parse --download-weights`, plan 3). * Laid out by `npm install --prefix`, so a cached package dir sits at * `/node_modules/@mailwoman/neural-weights-` and resolves sibling artifacts exactly like an installed * package. */ export declare function weightsCacheDir(): string; /** * The data-root weights overlay: `$MAILWOMAN_DATA_ROOT/weights//`, laid out with the SHIPPED filenames. * * A dev checkout carries no `model.onnx` — the binaries are not in git — so the workspace package always resolves and * is always empty, and before this probe existed that was terminal. Measured on a git worktree: the engine could not be * built at all. * * The layout is the shipped one deliberately, so {@link resolveFromPackageDir} needs no branch for it. What populates * the directory is a dev concern (`release.config.json` names the artifacts); this package knows only the CONVENTION, * because it ships to npm and must not carry a recipe consumers cannot use. */ export declare function weightsOverlayRoot(): string; /** * The overlay directory for one locale — the same path the dev linkers write, via the same helper. */ export declare function weightsOverlayDir(locale: string): string; /** * The weights package for a locale tag, normalized to the all-lowercase BCP-47 package convention. */ export declare function weightsPackageName(locale?: string): string; /** * The package directory a weights CACHE root holds for a locale — `/node_modules/@mailwoman/neural-weights- * `. * * THE ONE PLACE THAT LAYOUT IS SPELLED OUT (2026-08-06 triage). Hand-assembling a `node_modules/...` path is normally * the smell that says a package should have been located with `import.meta.resolve` or an exports subpath; this is the * one site in the tree where it is the correct answer, and it earns that by being the inverse of a resolution rather * than a substitute for one. The directory does not exist yet at the moment the layout is needed — `mailwoman parse * --download-weights` runs `npm install --prefix `, and an eval harness lays a CANDIDATE bundle out with * `scripts/stage-weights-cache.ts` — so there is nothing for a resolver to resolve. `import.meta.resolve` would also * answer from THIS module's graph (the monorepo), which is precisely the bundle the candidate is being graded against. * * Ten call sites across seven files had re-typed the literal (the promotion gate, the gauntlet harness, * `stage-weights-cache.ts`, and four test files); they now call this, so the day npm's prefix layout or the package * scope changes, one line moves. The one file that still spells it out is `neural/test/weights-cache.test.ts`, on * purpose — it is the ORACLE for this layout, and a fixture built with this helper could not fail when this helper is * wrong. * * Not `existsSync`-checked: callers want the path they are about to WRITE as often as one they mean to read. * {@linkcode resolveWeights} probes it for the two binaries before trusting it. */ export declare function weightsCachePackageDir(cacheRoot: string, locale?: string): string; export interface ResolveWeightsOpts { /** * BCP-47-ish locale tag, e.g. "en-us" or "fr-fr". Used to pick the weights package. */ locale?: string; /** * Explicit model.onnx path; takes precedence over package auto-resolve. */ modelPath?: string; /** * Explicit tokenizer.model path; takes precedence over package auto-resolve. */ tokenizerPath?: string; /** * Explicit `model-card.json` path (for the label vocab) on the explicit model+tokenizer path. When omitted, falls * back to a `model-card.json` co-located with `modelPath`. Without a card, labels default to `STAGE2_BIO_LABELS` — * which silently mis-decodes a STAGE3 (33-label) model into empty/garbage parses. Pass this (or co-locate the card) * when evaluating a custom STAGE3 checkpoint via explicit paths. */ modelCardPath?: string; /** * The BASE package's `model-card.json`, when this package declares `mailwoman.baseWeights` and the base is * resolvable. * * An overlay card describes the OVERLAY (its version, its own artifacts) while the vocabulary belongs to the shared * base model — so fields that describe the MODEL must fall back here rather than being copied per overlay, which is * the duplication that goes stale on the first retrain. */ baseModelCardPath?: string; /** * Serving tier (#718 D1). `"server"` (default) = anchor + gazetteer channels; `"pocket"` = anchor-only (skip the * gazetteer lexicon even when shipped). Selects which soft-feature sibling artifacts {@link resolveWeights} surfaces — * the loader feeds only the resolved channels. */ tier?: "server" | "pocket"; /** * Override the user-level weights cache root probed after package resolution fails (plan 3 guard). Defaults to * {@link weightsCacheDir}. Primarily a test seam. */ cacheRoot?: string; /** * Override the data-root weights overlay root probed when the package carries no binaries. Defaults to * {@link weightsOverlayRoot}. Primarily a test seam. */ overlayRoot?: string; } /** * Which directory an artifact was resolved from. * * Named rather than inferred from the path, because the four are indistinguishable by shape — every one of them is a * directory holding the same fixed filenames, which is what lets {@link resolveFromPackageDir} serve them all. */ export declare const WeightsOrigin: { /** * A path the caller supplied outright. */ readonly Explicit: "explicit"; /** * The resolved weights package's own directory. */ readonly Package: "package"; /** * The BASE package, reached through `mailwoman.baseWeights` — an overlay sharing the base model rather than shipping * its own copy. */ readonly Base: "base"; /** * The data-root overlay ({@link weightsOverlayRoot}) — a dev checkout whose package carries no binaries. */ readonly Overlay: "overlay"; /** * The user-level weights cache written by `mailwoman parse --download-weights`. */ readonly Cache: "cache"; }; export type WeightsOrigin = (typeof WeightsOrigin)[keyof typeof WeightsOrigin]; /** * One artifact's resolution outcome. `path: null` with `origin: null` is ABSENCE — the artifact was looked for and not * found — and is reported rather than omitted, because an omitted entry cannot be told apart from a field this build * never had. */ export interface WeightsArtifactReport { name: string; path: string | null; origin: WeightsOrigin | null; } export interface ResolvedWeights { modelPath: string; tokenizerPath: string; /** * Path to `model-card.json` for the resolved model. On the package path, the card co-located in the package dir. On * the explicit path, `opts.modelCardPath` or a card co-located with `modelPath`. `undefined` only when no card is * found. Read by `loadFromWeights` to thread the trained label vocabulary into the classifier — see * {@link readLabelsFromModelCard}. */ modelCardPath?: string; /** * The BASE package's `model-card.json`, when this package declares `mailwoman.baseWeights` and the base is * resolvable. * * An overlay card describes the OVERLAY (its version, its own artifacts) while the vocabulary belongs to the shared * base model — so fields that describe the MODEL must fall back here rather than being copied per overlay, which is * the duplication that goes stale on the first retrain. */ baseModelCardPath?: string; /** * Path to `crf-transitions.json` alongside the resolved model. `undefined` when the file doesn't exist (pre-v0.6.0 * bundles or CE-only training). */ crfTransitionsPath?: string; /** * Path to `semi-crf-transitions.json` alongside the resolved model — the #727 stage-2 segment-transition grammar the * span head's k-best decode consumes. `undefined` on a pre-v3 bundle (no span head). Read by `loadFromWeights` to * expose {@link NeuralAddressClassifier.spanGrammar} for the phase-4c name-evidence rerank. */ semiCRFTransitionsPath?: string; /** * Path to the postcode→anchor source shipped beside the resolved model (#718 D1) — the soft-feed `loadFromWeights` * reads to feed the anchor channel without a callsite change. Prefer the compact PCB1 binary (`postcode-.bin`, * decoded via `PostcodeBinaryResolver.toAnchorLookup()`), else a JSON anchor lookup (`anchor-lookup.json`, parsed via * `parseAnchorLookup`). `undefined` when the package ships neither (a plain/pre-#718 bundle) — the loader then runs * anchor-OFF. The `binary` flag tells the loader which parser to use. */ anchorLookupPath?: { path: string; binary: boolean; }; /** * Path to the gazetteer-anchor lexicon (`anchor-lexicon-v1.json`, #464) shipped beside the resolved model. * `undefined` when the package doesn't ship it, OR when `opts.tier === "pocket"` (pocket is anchor-only — the * gazetteer channel is deliberately skipped). Read by the `loadFromWeights` soft-feed via `parseGazetteerLexicon`. */ gazetteerLexiconPath?: string; /** * Path to the country-surface lexicon (`country-surface-lexicon-v1.json`, #1104) shipped beside the resolved model. * `undefined` when the package doesn't ship it, OR when `opts.tier === "pocket"` (anchor-only). Read by the * `loadFromWeights` soft-feed via `parseCountryLexicon`. */ countryLexiconPath?: string; /** * Street-type evidence lexicon sibling (Option-A bundle, Phase 2). The GENERATION comes from the card's * `requires.street_type.lexicon` (#1510); a card that names none falls back to `street-type-lexicon-v3.json` with a * warning. Server tier only; ships at the promote whose model requires the bundle channels. */ streetTypeLexiconPath?: string; /** * Locality-surface evidence lexicon sibling (Option-A bundle). Card-declared generation, same contract as * {@link ResolvedWeights.streetTypeLexiconPath}; legacy fallback `locality-surface-lexicon-v6.json`. */ localitySurfaceLexiconPath?: string; /** * Path to the per-locale FST gazetteer (`fst-.bin`) shipped beside the resolved model. `undefined` when the * package doesn't ship one (e.g. en-nz — byte-stable). PATH ONLY: `neural` deliberately carries no * `@mailwoman/resolver-wof-sqlite` dependency (the FST prior consumes a structural `FSTMatcherLike`), so * deserialization happens in the caller's layer — `loadFromWeights` surfaces the path on the classifier * ({@link NeuralAddressClassifier.fstPath}) and the mailwoman runtime pipeline auto-loads it from there. */ fstPath?: string; /** * Path to the locale-GENERAL street-morphology FST (`fst-street-morphology.bin`) shipped beside the resolved model — * the #1315 street-context gate's signal source, serialized at build time (`mailwoman gazetteer build * street-morphology`) instead of rebuilt from the libpostal dictionaries per process. `undefined` when the package * doesn't ship it (the runtime pipeline then falls back to the data-root staging artifact or a per-process dictionary * build). PATH ONLY, same posture as {@link ResolvedWeights.fstPath}: deserialization happens in the caller's layer. * Unlike the per-locale FST it may also resolve from the `baseWeights` package (the artifact is identical across * locales, so a data-only overlay need not ship its own copy). */ streetMorphologyPath?: string; /** * Path to the placetype-pair index (`pair-index-.bin`, PIX1 format, placetype-pair-prior arc) shipped beside the * resolved model. `undefined` when the package doesn't ship one. COUNTRY-SPECIFIC BY DESIGN — see * {@link resolvePairIndexSibling}: unlike the model/tokenizer/model-card, this artifact never falls back to a * `baseWeights` package (a shared base ships no locale-specific pairs to offer; en-us has none, en-gb ships its own * locally). Read by `loadFromWeights` to construct a `PairIndexResolver` for the `placetypePair` prior default. */ pairIndexPath?: string; /** * "explicit" if both paths came from opts; "package:" if located via {@link resolvePackageDirectory}. */ source: string; /** * The weights PACKAGE directory this resolution came from — `undefined` only for the fully-explicit * (`modelPath`+`tokenizerPath`) path, which has no package. * * Every other field is a resolved artifact path, which cannot answer "what was this package supposed to ship?" — an * absent artifact simply leaves its field `undefined`, and absence is exactly the question the anchor-presence guards * ask ({@link readDeclaredArtifactFile}, `harness.ts`'s grading-environment assertion). Note it is NOT * `dirname(modelPath)`: under `mailwoman.baseWeights` an overlay's model resolves from the BASE package while its * data siblings and its own card stay local. */ packageDir?: string; /** * Every known sibling artifact, with where it came from — or `null` on both fields when it did not resolve. * * Load-bearing rather than diagnostic. Only `model.onnx` and `tokenizer.model` make resolution fail; the other ~11 * artifacts degrade to `undefined` by design, so a checkout that finds the two binaries parses successfully with no * lexicons, no FST and no pair index — scoring worse, and silently. That silence is affordable only while the * binaries and the siblings travel together, which the data-root overlay rung stopped guaranteeing. The report is * what `mailwoman doctor` renders so "which half do I have" answers at the artifact level. * * The list is FIXED: every known artifact appears every time, so the denominator does not move with the answer. */ artifacts: WeightsArtifactReport[]; } export declare function resolveWeights(opts: ResolveWeightsOpts): ResolvedWeights; /** * The evidence-bundle lexicon families, and the LEGACY filename each resolved by before the card named its own (#1510). * * WHY THIS EXISTS. `resolveWeights` used to probe two literal filenames — `street-type-lexicon-v3.json` and * `locality-surface-lexicon-v6.json` — while both the shipped v4.0.1 recipe and the v4.2.0 candidate TRAIN against * locality-surface **v7** (`/data/gazetteer/locality-surface-lexicon-v7.json`). Serving therefore fed the channel a * DIFFERENT lexicon generation than training painted, and nothing said so: the v6 file exists, the channel loads, the * parse works. The Run B gate had to stage v7's CONTENT under the v6 FILENAME to score the candidate faithfully — a * workaround that only exists because the filename, not the card, was the contract. * * The contract is now the card: `requires..lexicon` NAMES the artifact the model trained against, and * {@linkcode resolveEvidenceLexicon} resolves that. The legacy filenames stay as the back-compat answer for a card that * declares no version — every bundle published before 2026-08-06 — and taking that path warns once. */ export declare const EVIDENCE_LEXICON_FAMILIES: { readonly street_type: { readonly prefix: "street-type-lexicon-v"; readonly legacy: "street-type-lexicon-v3.json"; }; readonly locality_surface: { readonly prefix: "locality-surface-lexicon-v"; readonly legacy: "locality-surface-lexicon-v6.json"; }; }; export type EvidenceLexiconChannel = keyof typeof EVIDENCE_LEXICON_FAMILIES; /** * A train/serve lexicon MISMATCH (#1510): the card names one generation of an evidence lexicon and the weights package * ships a different one. Thrown at LOAD time, from {@linkcode resolveWeights}, naming BOTH versions — the whole point is * that this can never again be a silent downgrade. */ export declare class LexiconVersionMismatchError extends Error { constructor(message: string); } /** * Locate the PCN1 placetype census for `country` — `placetype-census-.bin`, the artifact `mailwoman gazetteer * census` builds (`neural/placetype-census.ts` owns both ends of the format). * * WHY THIS ONE DOES NOT TAKE A `packageDir`, unlike every other resolver in this file. The census is a BUILD-LOCAL * artifact: it lives under `$MAILWOMAN_DATA_ROOT/wof/`, exactly where `fst-street-morphology.bin` and the pair-index * probe outputs live, and it ships in NO weights tarball. That is a deliberate deferral, not an oversight. The * 2026-08-04 wiring assessment ruled that the census gets no decode wiring until a calibration rung measures a δ (the * header's `delta` field is optional and every shipped artifact omits it), and until something at runtime READS it, * adding 137–165 KB per locale to a published package buys nothing. When a calibration rung earns that cost, this * function grows a package-sibling probe ahead of the data-root one — the same shape as * {@link resolveAnchorLookupSibling}'s binary-then-JSON ladder. * * What the artifact is FOR, today: OBSERVABILITY. `PlacetypeCensusResolver` answers "does this parent have children of * this KIND at all, and how much more often than the country at large" (presence + lift; within-parent share is ~100% * everywhere, so a share-proportional consumer would read a constant). The pair prior probes it alongside each parent * candidate and records what it found on the parse trace (`TracePrior` of kind `placetypeCensus`) — nothing else. The * calibration rung's job is to read those traces and decide whether a δ is worth shipping. * * What the NEXT rung needs, so nobody mistakes this for a finished mechanism: the census is SPAN-BLIND (the D-C4 * ceiling). A node asserts something about a PARENT SURFACE, never about where a child span starts or ends, so census * evidence alone cannot tell "East Acton" the place from "East Acton" opening a venue name — it fails the same * venue-confound board that pinned window mode at a 52.1% false-positive rate and forced the pair prior's segment * default. Composition with span evidence (the parent-span probe chain this rides, plus whatever span-boundary signal * the calibration rung finds) is the open design question, not a δ sweep. * * `undefined` when the file is absent — the caller then wires no census and the feature is entirely inert, with no * warning: an absent build-local artifact is the NORMAL state for every consumer who never ran the build command. */ export declare function resolvePlacetypeCensusPath(country: string): string | undefined; /** * Read the census for `country` into a {@link PlacetypeCensusResolver}, or `undefined` when there is nothing to read * (see {@link resolvePlacetypeCensusPath} for what this artifact is, why it is build-local, and what the next rung * needs). `explicitPath` overrides the data-root lookup — a harness that built a census to a scratch directory. * * Degrade rules, deliberately asymmetric: an ABSENT artifact is silent, because not having built one is the normal * state for everyone who never ran `mailwoman gazetteer census`, and a warning there would fire for every user of the * library. A present-but-unreadable file, or one whose header names a different country than the locale being parsed, * is LOUD — those are build mistakes, and the country one in particular would otherwise have a census describing the * wrong country's hierarchy quietly riding the trace a calibration rung reads. */ export declare function loadPlacetypeCensus(country: string, explicitPath?: string): PlacetypeCensusResolver | undefined; /** * Read the `labels` array from a `model-card.json` file. Returns `undefined` when the file is missing, unreadable, * malformed, or has no `labels` field — callers should fall back to their compile-time default in that case (the loader * contract: the JS-side default tracks the most recent shipped stage, so a card without `labels` is always a pre-v0.4.0 * card whose label vocab matches that default by construction). * * Validates shape: must be a non-empty array of strings. Throws on a present-but-malformed `labels` field — a card that * emits e.g. `labels: 21` rather than `labels: [...]` is a corrupted artifact and should be loud, not silently * re-defaulted. */ export declare function readLabelsFromModelCard(modelCardPath: string | undefined): readonly string[] | undefined; /** * The structured `requires` block of a `model-card.json` (#718) — the declared SHIP-CONFIG the model was trained * against. The ProductionScorer reads this and FAILS CLOSED when a declared channel isn't actually fed (silent OOD is * the #566/#685 trap). Each channel is optional; a missing channel means "not declared" (treated as not-required). */ export interface RequiredChannels { /** * Postcode-anchor channel (#239/#240). `span_mode` declares WHICH substrings the runtime should look up — omit (or * `alnum-run`) for every model trained before 2026-08-05, `shaped` for a model trained against a lookup with * letter-bearing keys (see `neural/anchor-inference.ts`'s `AnchorSpanMode`). Declaring `shaped` on a model that never * saw those keys changes the encoder's input for nothing; declaring `alnum-run` on one that did leaves its GB/NL * postcodes unanchored. */ anchor?: { required: boolean; span_mode?: AnchorSpanMode; }; /** * Gazetteer-anchor channel (#464). */ gazetteer?: { required: boolean; }; /** * Country-lexicon channel (#1104). */ country?: { required: boolean; }; /** * Address-system conventions (#511 Tier A). `mode` mirrors `ParseOpts.addressSystemConventions`. */ conventions?: { required: boolean; mode?: "auto" | string; }; /** * Punctuation-gap span bridge (v4.4.0 corrective). */ bridge?: { required: boolean; }; /** * Near-postcode gazetteer choreography (#464, v0.9.13). */ suppress_gazetteer_near_postcode?: boolean; /** * Street-type evidence channel (Option-A bundle, Phase 3). `lexicon` NAMES the artifact generation the model trained * against — see {@linkcode EVIDENCE_LEXICON_FAMILIES}. */ street_type?: { required: boolean; lexicon?: string; }; /** * Locality-surface evidence channel (Option-A bundle, Phase 3). `lexicon` NAMES the artifact generation the model * trained against — see {@linkcode EVIDENCE_LEXICON_FAMILIES}. */ locality_surface?: { required: boolean; lexicon?: string; }; } /** * The `files` keys under which a weights card names its postcode→anchor artifact: the compact PCB1 binary first * (`postcode-.bin`), then the legacy JSON lookup. */ export declare const ANCHOR_ARTIFACT_CARD_KEYS: readonly ["postcode_anchor", "anchor_lookup"]; /** * An artifact a package's own model-card DECLARES it ships, and whether it is actually there. */ export interface DeclaredArtifact { /** * The `files` key that named it (`postcode_anchor`). */ key: string; /** * The declared filename, verbatim from the card (`postcode-us.bin`). */ file: string; /** * `packageDir`-relative resolution of {@link DeclaredArtifact.file}. */ path: string; present: boolean; } /** * What a weights package's OWN `model-card.json` declares it ships under `files`, for one family of keys. * * The card's `files` block is the package's manifest of intent, and it is the only per-package statement of what SHOULD * be on disk — `requires` describes the trained ENCODER, which is a different claim and is shared across every overlay * that inherits the base model. Conflating the two is the #1516 defect: en-gb's card declares * `requires.anchor.required: true` (a true statement about the encoder) while deliberately shipping no * `postcode-gb.bin` under the #1476 mitigation, so a guard keyed on `requires` alone calls a supported configuration * broken, and — because the old warning fired once per PROCESS and named no package — the operator reads that as the * PRIMARY locale's bin being missing. * * Reads the package's own card only, never the `baseWeights` fallback: an overlay that ships no card of its own is * making no claim about its files, and inheriting the base's manifest would attribute `postcode-us.bin` to it. * * @returns `undefined` when the package has no card, the card has no `files` block, or none of `keys` appears there — * all three meaning "this package declares no such artifact", which is a legal posture, not a fault. */ export declare function readDeclaredArtifactFile(packageDir: string | undefined, keys?: readonly string[]): DeclaredArtifact | undefined; /** * A soft-feed channel `loadFromWeights` can find declared-but-unfed. */ export type UnfedChannel = "anchor" | "gazetteer" | "country" | "street_type" | "locality_surface"; /** * Build the loud-degrade warner for one weights package (#718 D1) — the Node mirror of neural-web's * `warnOnUnfedTrainedChannels`. A card that declares a channel REQUIRED, paired with a package that didn't ship (or * could not parse) its data, runs that channel OFF. Structural fallback (the parse still works), loud console (a * silently anchor-OFF anchor-trained model is the #566/#685 OOD crater this exists to surface). * * BOUND TO A PACKAGE, and deduped per (channel, package) — it was once per channel per PROCESS until #1516. One process * routinely loads several packages (the gauntlet grades six locale overlays), so channel-only dedupe meant the first * degraded package spoke and every later one was suppressed, while the line named no package at all. Both halves * produced the same wrong reading: an operator whose `postcode-us.bin` was present and feeding, watching a different * overlay degrade, was told "no postcode-.bin found in the weights package". * * @param weightsPackage How to identify the package in the message — locale plus resolved directory. */ export declare function unfedChannelWarner(weightsPackage: string): (channel: UnfedChannel, detail: string) => void; /** * Why an unfed anchor channel is worth a warning for THIS package, or `undefined` when it is not. * * The condition the #1516 fix turns on, in one place because it is the whole substance of the fix. The old test was * `requires.anchor.required && nothing loaded`, and `requires` describes the trained ENCODER — shared by every overlay * that inherits the base model. So the en-gb overlay, which ships no `postcode-gb.bin` on purpose under the #1476 * mitigation, warned on every load; the line named no package and fired once per PROCESS, so an operator whose * `postcode-us.bin` was present and feeding read it as the primary locale's binary having gone missing. * * Declared-and-missing is a broken package and stays loud. Declared-nothing is a supported posture and is silent — * `buildGauntletDeps` asserts the presence a GRADING run needs, which is the only place that knows whether this * particular run needs GB anchors. */ export declare function unfedAnchorDetail(packageDir: string | undefined): string | undefined; /** * Read the structured `requires` block from a `model-card.json` (#718). DEFENSIVE: returns `undefined` when the card is * absent, unreadable, or has no `requires` field (callers then INFER the required channels from the ONNX graph — see * `inferRequiredChannelsFromInputs`). Throws ONLY when the field is PRESENT but corrupt (not an object, or a channel * entry with a non-boolean `required`) — a malformed declared contract is a loud artifact bug, not a silent * re-default. */ export declare function readRequiredChannels(modelCardPath: string | undefined): RequiredChannels | undefined; /** * Back-compat inference of the required soft-feature channels from an ONNX model's declared input names (#718). A model * that exports `anchor_features` / `gazetteer_features` declared those channels mandatory at train time — feeding zeros * is the channel-off identity, but a model TRAINED with the channel is OOD when scored without it. Cards without a * `requires` block (every pre-#718 bundle) route through here so the fail-closed guard still protects them. * Conventions/bridge are NOT graph-observable (no dedicated input), so they're left undeclared here — only the card * declares them. */ export declare function inferRequiredChannelsFromInputs(inputNames: readonly string[]): RequiredChannels; /** * One tag's certified capability under a (tier × address-system) cell of the capability manifest (#718/#719). * `maskOffF1` is the model's measured per-tag exact-match F1 with the conventions mask OFF; `maskOnF1` is the same with * the mask ON — recorded ONLY for tags some codex `forbiddenTags` row suppresses, because that's the only place the * loader's delta-gate consults it. */ export interface TagCapability { /** * Measured per-tag F1 (percent) with the conventions mask OFF — the model's real capability. */ maskOffF1: number; /** * Measured per-tag F1 (percent) with the mask ON. Present only for codex-forbidden tags. */ maskOnF1?: number; } /** * The `capabilities` block of a `model-card.json` (#718/#719): per serving TIER (`server` = anchor+gazetteer; `pocket` * = anchor-only) × per codex address-system × per tag, the model's certified per-tag capability. The `createScorer` * loader reads this to FAIL CLOSED when a conventions mask would forbid a tag the model is certified to emit — the * structural fix that makes the D2/#719 bug-class (a mask destroying a demonstrated capability) impossible. * * Shape: `capabilities[tier][system][tag] = { maskOffF1, maskOnF1? }`. A `$comment` provenance key may sit alongside * the tier keys and is ignored by readers. */ export type CapabilityManifest = Record>>; /** * Read the `capabilities` block from a `model-card.json` (#718/#719). DEFENSIVE, mirroring `readRequiredChannels`: * returns `undefined` when the card is absent, unreadable, or has no `capabilities` field (a pre-#718 card → the * loader's delta-gate is skipped, back-compat). Throws ONLY when the field is PRESENT but not an object — a corrupt * declared contract is a loud artifact bug, not a silent skip. Tier/system/tag sub-shapes are read leniently (a * malformed cell simply yields no capability claim — `undefined` from `lookupTagCapability`). */ export declare function readCapabilityManifest(modelCardPath: string | undefined): CapabilityManifest | undefined; /** * Resolve `capabilities[tier][system][tag]` to a `TagCapability`, returning `undefined` for any missing/malformed cell * (a tag the model is NOT certified for — the loader treats that as legal: the model can't emit it, so a mask can't * destroy it). Skips the `$comment` provenance key. */ export declare function lookupTagCapability(manifest: CapabilityManifest | undefined, tier: string, system: string, tag: string): TagCapability | undefined; export interface CRFTransitions { transitions: number[][]; startTransitions: number[]; endTransitions: number[]; } /** * Read learned CRF transition parameters from `crf-transitions.json`. Returns `undefined` when the file is missing or * malformed — callers fall back to the structural BIO mask only. */ export declare function readCRFTransitions(crfPath: string | undefined): CRFTransitions | undefined; //# sourceMappingURL=weights.d.ts.map