@arxo/law-types
TypeScript types for Arxo Law Core 0.1: the legal IR (CLIR), evaluation documents, diagnostics, package manifests, lockfiles, decision tables, parameter datasets, queries and the rest of the normative document model.
Types only. No runtime engine, no dependencies, one small generated runtime
module for the diagnostic-code registry. To actually run law, use
@arxo/law-engine; these are
the same types it ships, published separately so a consumer that only talks to
the engine over a wire does not have to pull 4.5 MB of WebAssembly.
Install
npm install --save-dev @arxo/law-types
Use
import type { EvaluationDocument, Diagnostic, LegalIr } from '@arxo/law-types';
function firstIssue(doc: EvaluationDocument) {
return doc.issues?.[0];
}
Where these types come from
They are generated, never hand-written. The normative JSON schemas define the shape of every document; a code generator turns them into TypeScript, and automated checks verify that the schema directory, the generator's registry, the generated files and this package's build list agree. A schema change that does not reach the types fails the build rather than shipping a lie.
Where a schema uses conditional composition (allOf / if-then) the generated
type is deliberately wide and says so in a comment. A type whose precision was
not derived must be visible, not pretend to be exact.
Diagnostic codes
import type { LawDiagnosticCode } from '@arxo/law-types/diagnostics';
import {
KNOWN_DIAGNOSTIC_CODES,
isKnownDiagnosticCode,
} from '@arxo/law-types/diagnostics';
KnownDiagnosticCode is the union of every LDC-… code collected from the two
engine implementations and from the specification prose. Four classes are
distinguished in the registry the union is built from:
- emitted — at least one implementation actually produces this code;
- documented — the specification names it, no implementation emits it yet;
- reserved — named only by a companion document; the
LDC-E8xxxrange is reserved for proposals that are not yet part of conformance.
The consumer-facing type is deliberately open:
export type LawDiagnosticCode = KnownDiagnosticCode | (string & {});
Codes are additive — the frozen 0.1 semantics grows by addition — so an engine
newer than this package will legitimately answer with a code the union has never
heard of. A closed enum would reject that answer, which would be a lie about the
engine, not a check on it. string & {} keeps editor autocompletion for the
known codes while accepting the unknown one. For the same reason
isKnownDiagnosticCode(code) === false means "not known to this package
version", never "not a real code".
Match on the code, not on the message
Engine messages are Russian, and their exact text is part of a byte-level
contract between two independent implementations of the same semantics — it
cannot be translated on one side without breaking the contract. The stable,
language-independent handle for a static diagnostic is its code:
// yes
if (diagnostic.code === 'LDC-E1104') { … }
// no — this string is a contract between two engines, not an API
if (diagnostic.message.includes('пакет')) { … }
If you are building a user-facing product, map codes to your own localized strings rather than passing engine text through. The same holds for the doc comments in the generated types: they carry the schemas' Russian prose, because the schemas are the normative source and translating them here would create a second, unchecked description.
Versioning
Independent semver per package, with the engine and the client versioned
separately. 0.x releases pin exact compatible versions of sibling packages.
License
Apache-2.0. See LICENSE and NOTICE.
Building from source
In a source checkout:
npm run build -- --public --package-out /tmp/new-law-types-package
The build copies the prepared generated types and the public diagnostic registry; it does not run Cargo or regenerate schemas.
The registry also supports historical codes retired by a recorded change.
Structural types describe document formats; their presence does not promise
that every operation producing that format is in this distribution.