@factoidal/core 0.18.0 → 0.20.0

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/index.d.ts CHANGED
@@ -27,8 +27,11 @@ export interface BlankNode {
27
27
  export interface Literal {
28
28
  termType: 'Literal';
29
29
  value: string;
30
- /** Language tag ('' when none). */
30
+ /** Language tag, lowercase ('' when none). */
31
31
  language: string;
32
+ /** Base direction of a directional language-tagged string (RDF 1.2):
33
+ * 'ltr' or 'rtl'; '' when none. RDF/JS Data Model, Literal.direction. */
34
+ direction: '' | 'ltr' | 'rtl';
32
35
  /** Datatype IRI term (xsd:string for plain literals). */
33
36
  datatype: NamedNode;
34
37
  equals(other: Term | null | undefined): boolean;
@@ -96,6 +99,7 @@ export type FactoidalErrorCode =
96
99
  | 'term.invalid-iri'
97
100
  | 'term.invalid-langtag'
98
101
  | 'term.invalid'
102
+ | 'literal.value'
99
103
  | 'query.syntax'
100
104
  | 'query.failed'
101
105
  | 'update.syntax'
@@ -233,6 +237,10 @@ export interface FormatCapability {
233
237
  write12: boolean;
234
238
  /** 'core' when both engines serve it; 'full' when only the full engine does. */
235
239
  engine: 'core' | 'full';
240
+ /** The registered media types (W3C registration; empty for a row with none). syntaxFor() reads the same table. */
241
+ mediaTypes: string[];
242
+ /** The registered file extensions, with the leading dot ('.ttl'). */
243
+ extensions: string[];
236
244
  }
237
245
 
238
246
  /**
@@ -280,11 +288,31 @@ export class Dataset implements Iterable<Quad> {
280
288
  toString(formatOrOptions?: WriteFormat | WriteOptions): string;
281
289
  toNQuads(): string;
282
290
  clone(): Dataset;
283
- /** RDF/JS DatasetCore (https://rdf.js.org/dataset-spec/); match and has use the engine indexes. */
284
- has(quad: Quad): boolean;
291
+ /**
292
+ * RDF/JS DatasetCore (https://rdf.js.org/dataset-spec/); match and has use
293
+ * the engine indexes. `{match: 'value'}`: a literal object matches every
294
+ * object literal that is the same term or has the same value (sameValue());
295
+ * the other positions match by term.
296
+ */
297
+ has(quad: Quad, options?: MatchOptions): boolean;
285
298
  add(quad: Quad): this;
286
- delete(quad: Quad): this;
287
- match(subject?: Term | null, predicate?: Term | null, object?: Term | null, graph?: Term | null): Dataset;
299
+ /** With `{match: 'value'}`: remove every quad of the same subject, predicate
300
+ * and graph whose object has the same value as the quad's literal object. */
301
+ delete(quad: Quad, options?: MatchOptions): this;
302
+ match(subject?: Term | null, predicate?: Term | null, object?: Term | null, graph?: Term | null,
303
+ options?: MatchOptions): Dataset;
304
+ /**
305
+ * The items of the RDF list (rdf:first/rdf:rest) at `head`, in order
306
+ * (https://github.com/danbri/factoidal/issues/1051 item 6). `rdf:nil` is
307
+ * the empty list. A list that is not well formed (a node with no or with two
308
+ * rdf:first or rdf:rest, or a cycle) is a FactoidalError, code `op.failed`.
309
+ * `graph`: omitted, null or the DefaultGraph for the default graph.
310
+ */
311
+ listItems(head: Term, graph?: Term | null): Term[];
312
+ /** The members rdf:_1, rdf:_2, ... of `node`, sorted by n, and its kind (rdf:Bag, rdf:Seq, rdf:Alt) from its rdf:type. */
313
+ containerItems(node: Term, graph?: Term | null): { kind: NamedNode | null; items: Array<{ ordinal: number; term: Term }> };
314
+ /** Add a new RDF list of `items` on fresh blank nodes; answers its head (rdf:nil for no items). */
315
+ addList(items: Iterable<Term>, graph?: Term | null): Term;
288
316
  toArray(): Quad[];
289
317
  [Symbol.iterator](): Iterator<Quad>;
290
318
  dispose(): void;
@@ -377,6 +405,12 @@ export interface ParseOptions {
377
405
  * with one diagnostic of class 'too-many-errors'. Default: no limit.
378
406
  */
379
407
  maxErrors?: number;
408
+ /**
409
+ * Read JSON-LD as JSON-LD-star (`@triple`, `@reifies`, `@annotation` as
410
+ * RDF 1.2 triple terms and reifiers), as `jsonldToRdf` does. Format
411
+ * 'jsonld' only (given or inferred); not with `lenient`. Default: false.
412
+ */
413
+ rdfstar?: boolean;
380
414
  }
381
415
 
382
416
  export interface QueryOptions extends DatasetQueryOptions {
@@ -532,17 +566,24 @@ export function canonicalize(
532
566
  export function graphs(dataset: Dataset): Array<[name: NamedNode | BlankNode, graph: Dataset]>;
533
567
 
534
568
  /**
535
- * The RDFC-1.0 canonical hash of a single graph: the SHA-256 of its
536
- * canonical N-Quads document, as 64 lowercase hexadecimal digits (RDF
537
- * Dataset Canonicalization 1.0, section 4.4 note 2). The engine computes
538
- * the canonical form and the digest. Every quad's graph component is
539
- * dropped first, so isomorphic graphs (including under blank-node
540
- * relabeling) give the same hash whatever graph name they were extracted
541
- * from. Typically called with one entry of graphs()'s output. For the
542
- * canonical text, use canonicalize(). Rejects when the input holds an
543
- * RDF 1.2 triple term or the section 4.4 call budget is exceeded.
569
+ * The RDFC-1.0 canonical hash of a dataset: the SHA-256, as 64 lowercase
570
+ * hexadecimal digits, of the canonical N-Quads document that canonicalize()
571
+ * answers (RDF Dataset Canonicalization 1.0, section 4.4 note 2), graph names
572
+ * included. The engine computes the canonical form and the digest. Since
573
+ * 0.20.0; 0.17.0 to 0.19.x dropped every graph name first, so datasets that
574
+ * differ only in their graph names got the same hash. To hash a graph
575
+ * whatever its name (for example one entry of graphs()), use
576
+ * canonicalHash(asDefaultGraph(g)). Rejects when the input holds an RDF 1.2
577
+ * triple term or the section 4.4 call budget is exceeded.
578
+ */
579
+ export function canonicalHash(dataset: Dataset): Promise<string>;
580
+
581
+ /**
582
+ * A new Dataset with the triples of every graph of `dataset`, all in the
583
+ * default graph (the engine's union of the graphs). With one entry of
584
+ * graphs(), it is that graph without its name. Dispose of it when done.
544
585
  */
545
- export function canonicalHash(datasetOrGraph: Dataset): Promise<string>;
586
+ export function asDefaultGraph(dataset: Dataset): Dataset;
546
587
 
547
588
  /**
548
589
  * Whether two datasets are isomorphic (RDF 1.1 Concepts 3.6 and 4; blank
@@ -558,9 +599,137 @@ export function fromQuads(quads: Iterable<Quad>): Promise<Dataset>;
558
599
  /** Load the engine. Afterwards the N-Quads text functions of `@factoidal/core/rdfjs` work. */
559
600
  export function ready(): Promise<void>;
560
601
 
602
+ // ---------------------------------------------------------------------
603
+ // Literal values (https://github.com/danbri/factoidal/issues/1051 items 1-3).
604
+ // Synchronous after the engine is loaded (`await ready()` or any other call);
605
+ // before that they throw a FactoidalError. The engine decides everything
606
+ // (formal/lean4/L4Factoidal/RDF/LiteralValue.lean). API.md "Literal values".
607
+ // ---------------------------------------------------------------------
608
+
609
+ /**
610
+ * The value of a literal, as JSON-safe data. A number that a JavaScript
611
+ * number may not hold exactly is a decimal string; `number` is present only
612
+ * when the value is exactly a binary64 value. Integer components are numbers
613
+ * when |n| <= 2^53 - 1, else decimal strings.
614
+ */
615
+ export type LiteralValueData =
616
+ | { kind: 'string' | 'anyURI'; string: string }
617
+ | { kind: 'boolean'; boolean: boolean }
618
+ | { kind: 'decimal'; decimal: string; integer: boolean; number?: number }
619
+ | { kind: 'float' | 'double'; decimal?: string; number: number;
620
+ negativeZero?: true; special?: 'NaN' | 'INF' | '-INF' }
621
+ | { kind: 'duration'; months: number | string; seconds: string }
622
+ | { kind: 'dateTime' | 'time' | 'date' | 'gYearMonth' | 'gYear' | 'gMonthDay' | 'gDay' | 'gMonth';
623
+ year?: number | string; month?: number; day?: number; hour?: number;
624
+ minute?: number; second?: string; timezoneOffset?: number }
625
+ | { kind: 'hexBinary' | 'base64Binary'; hex: string }
626
+ | { kind: 'QName' | 'NOTATION'; prefix: string; localName: string }
627
+ | { kind: 'list'; items: LiteralValueData[] }
628
+ | { kind: 'langString'; string: string; language: string; direction?: 'ltr' | 'rtl' };
629
+
630
+ export interface LiteralValueResult {
631
+ /** The datatype IRI. */
632
+ datatype: string;
633
+ /** false: the engine has no lexical space for this datatype. */
634
+ recognized: boolean;
635
+ /** The lexical form is in the lexical space (null when not recognized). */
636
+ valid: boolean | null;
637
+ /** Present for a valid literal of a datatype with a value model. */
638
+ value?: LiteralValueData;
639
+ /** The canonical lexical form (XSD 1.1 Part 2 section 2.3.1), when known. */
640
+ canonical?: string;
641
+ }
642
+
643
+ /** The XSD lexical-to-value mapping of a literal (RDF 1.1 Semantics section 7: no whiteSpace processing). */
644
+ export function literalValue(term: Literal): LiteralValueResult;
645
+
646
+ /** Whether the lexical form is in the datatype's lexical space; null when the engine has no lexical space for the datatype. */
647
+ export function isValidLiteral(term: Literal): boolean | null;
648
+
649
+ /** The literal with the canonical form of its value; null when it is not valid or has no canonical mapping. */
650
+ export function canonicalLiteral(term: Literal): Literal | null;
651
+
652
+ /**
653
+ * The literal of a JavaScript value. With no datatype the engine's table
654
+ * chooses: boolean xsd:boolean, string xsd:string, bigint xsd:integer, a safe
655
+ * integer Number xsd:integer, any other Number xsd:double, Date xsd:dateTime
656
+ * (UTC). `datatype` (an IRI, a NamedNode, or an XSD local name such as 'int')
657
+ * names the datatype; the value must be in its value space, else a
658
+ * FactoidalError with code 'literal.value'.
659
+ */
660
+ export function literalFromValue(
661
+ value: boolean | number | bigint | string | Date,
662
+ options?: { datatype?: string | NamedNode }
663
+ ): Literal;
664
+
561
665
  /** The engine's name tables: format names, entailment regimes, query outputs, pack syntaxes. */
562
666
  export function engineTables(): Promise<Record<string, unknown>>;
563
667
 
668
+ /**
669
+ * How Dataset.has, match and delete compare the object position
670
+ * (https://github.com/danbri/factoidal/issues/1052). 'term' (the default):
671
+ * RDF term equality. 'value': a literal object matches by value (sameValue()).
672
+ */
673
+ export interface MatchOptions {
674
+ match?: 'term' | 'value';
675
+ }
676
+
677
+ /**
678
+ * SPARQL 1.1 `=` on two RDF terms (sections 17.3 and 17.4.1.7), decided by the
679
+ * engine: `true` the same value (`"01"^^xsd:integer` and `"1.0"^^xsd:decimal`),
680
+ * `false` different values, `null` incomparable (the operator's type error:
681
+ * two different literals of an unknown datatype, an ill-typed literal and
682
+ * another literal, `xsd:integer` and `xsd:boolean`). `"NaN"^^xsd:double` is
683
+ * not the same value as itself. A term is an RDF/JS term or an N-Triples term
684
+ * string. Synchronous: the engine must be loaded (`await ready()`).
685
+ */
686
+ export function sameValue(a: Term | string, b: Term | string): boolean | null;
687
+
688
+ /**
689
+ * The syntax of a document by its file name (or IRI path; the query and the
690
+ * fragment are ignored) and its media type, from the engine's table of the
691
+ * W3C registrations (https://github.com/danbri/factoidal/issues/1053): Turtle
692
+ * `text/turtle` `.ttl`, N-Triples `application/n-triples` `.nt`, N-Quads
693
+ * `application/n-quads` `.nq`, TriG `application/trig` `.trig`, RDF/XML
694
+ * `application/rdf+xml` `.rdf`, JSON-LD `application/ld+json` `.jsonld`. The
695
+ * media type wins when it is given (its parameters are ignored); an unknown
696
+ * media type does not fall back to the name. Answers a `name` of formats(),
697
+ * or `null`. Synchronous: the engine must be loaded (`await ready()`).
698
+ */
699
+ export function syntaxFor(what: string | { fileName?: string; mediaType?: string }): string | null;
700
+
701
+ /**
702
+ * An IRI as a namespace and a local name: the local name is the longest
703
+ * suffix that is an XML NCName (what an RDF/XML QName can carry), `''` when
704
+ * there is none; `namespace + localName` is the IRI
705
+ * (https://github.com/danbri/factoidal/issues/1051 item 4). Synchronous.
706
+ */
707
+ export function splitIri(iri: string | NamedNode): { namespace: string; localName: string };
708
+
709
+ /** Is the text an XML NCName (Namespaces in XML 1.0, production [4])? A prefix label check. Synchronous. */
710
+ export function isNCName(text: string): boolean;
711
+
712
+ /** One row of the engine's vocabulary table. A term IRI is `namespace + term`. */
713
+ export interface VocabularyRow {
714
+ prefix: string;
715
+ namespace: string;
716
+ /** Local names; empty for a namespace whose vocabulary is not in the engine table. */
717
+ terms: string[];
718
+ }
719
+
720
+ /**
721
+ * The engine's vocabulary table (https://github.com/danbri/factoidal/issues/1051
722
+ * item 5): rdf, rdfs, xsd and owl with their terms; foaf, dcterms, dc and
723
+ * schema as namespaces only. The prefixes are those of the Turtle writer. Synchronous.
724
+ */
725
+ export function vocabularies(): VocabularyRow[];
726
+
727
+ /** The container membership property `rdf:_n` (n >= 1). Synchronous. */
728
+ export function memberIri(n: number): NamedNode;
729
+
730
+ /** The `n` of `rdf:_n` (no leading zero, n >= 1), or `null` for any other IRI. Synchronous. */
731
+ export function memberOrdinal(iri: string | NamedNode): number | null;
732
+
564
733
  /** A SHACL validation-report term (see shaclValidate). */
565
734
  export interface ShaclValidateResult {
566
735
  conforms: boolean;
@@ -755,7 +924,14 @@ export interface EvidenceRecord {
755
924
  outside?: OutsideSetting[];
756
925
  }
757
926
 
758
- /** The value on a wire. */
927
+ /**
928
+ * The value on a wire. After a node, `graph` is a value of the node's
929
+ * `wireOut`: a Dataset for the graph wires, text for String (a writer), the
930
+ * rows for Table (SELECT), a boolean for Answer (ASK), `[canonical, sha256]`
931
+ * for String × String (rdfcStage), the report object for ValidationReport,
932
+ * the explain result for ExplainGraphResult. Since 0.20.0; before, a node
933
+ * whose output was not a Dataset left its input on the wire.
934
+ */
759
935
  export interface Wire<G = unknown> {
760
936
  graph: G;
761
937
  evidence: EvidenceRecord[];
@@ -780,7 +956,12 @@ export interface FactoidalNode {
780
956
  readonly wireOut: string;
781
957
  readonly runnable: boolean;
782
958
  readonly bound: boolean;
783
- /** The settings as given (passed to the package function that runs the stage). */
959
+ /**
960
+ * The node's own copy of the settings as given (passed to the package
961
+ * function that runs the stage): frozen at every depth, a Dataset cloned,
962
+ * taken when node() checked them. A later change to the caller's objects
963
+ * does not reach the node; a change to a Dataset here makes run() refuse.
964
+ */
784
965
  readonly params: Readonly<Record<string, unknown>>;
785
966
  /** The settings as sent to the engine: JSON values, a Dataset as {$nquads}. */
786
967
  readonly settingsWire: Readonly<Record<string, unknown>>;
@@ -873,8 +1054,11 @@ export function pipe(...nodes: Array<FactoidalNode | Pipeline>): Pipeline;
873
1054
  * Run a node or pipeline on `input` (a Wire, or the graph: text for a
874
1055
  * reader, else a Dataset or data input). Rejects before any node runs when
875
1056
  * a node's stage has status 'missing' (unless `options.unchecked`) or has
876
- * no package function, or when the engine's check finds the pipeline not
877
- * well typed (unless `options.unchecked`; then `proved` is false).
1057
+ * no package function, when the engine's check finds the pipeline not
1058
+ * well typed (unless `options.unchecked`; then `proved` is false), or when a
1059
+ * node's settings changed after node() checked them. Rejects with code
1060
+ * 'op.failed' when a node's runner gives a value that is not of the node's
1061
+ * `wireOut` (see Wire).
878
1062
  */
879
1063
  export function run(pipeline: FactoidalNode | Pipeline, input: unknown, options?: RunOptions): Promise<RunResult>;
880
1064
 
@@ -1188,6 +1372,8 @@ export interface Sbm11Store {
1188
1372
  /** the generation CURRENT names, or "" when the source is a generation */
1189
1373
  generation: string;
1190
1374
  terms: number;
1375
+ /** how the engine checks reads; undefined from a wasm module built before the Merkle check */
1376
+ verify: 'merkle' | 'none' | undefined;
1191
1377
  query(sparql: string, options?: { base?: string; sparql12?: boolean; reference?: boolean }): Sbm11Answer;
1192
1378
  /** the resources the reader read, when its reader records them (lwsSbm11Reader) */
1193
1379
  readonly evidence: Sbm11ReadEvidence[] | undefined;
@@ -1195,8 +1381,11 @@ export interface Sbm11Store {
1195
1381
  }
1196
1382
 
1197
1383
  /** Open an SBM11 generation (https://github.com/danbri/factoidal/issues/1009).
1198
- * Node: `source` is a directory unless a reader is given or registered. */
1199
- export function openSbm11(source: string, options?: { reader?: Sbm11Reader }): Promise<Sbm11Store>;
1384
+ * Node: `source` is a directory unless a reader is given or registered.
1385
+ * `verify` (default 'merkle'): the engine checks every byte it decodes against
1386
+ * the manifest's Merkle roots and refuses a changed file with its name;
1387
+ * 'none' checks lengths only. */
1388
+ export function openSbm11(source: string, options?: { reader?: Sbm11Reader; verify?: 'merkle' | 'none' }): Promise<Sbm11Store>;
1200
1389
 
1201
1390
  /** Serve `source` with `reader`; `null` removes it. */
1202
1391
  export function registerSbm11Source(source: string, reader: Sbm11Reader | null): void;
@@ -1676,6 +1865,8 @@ export function capabilities(): Promise<{
1676
1865
  store: boolean;
1677
1866
  /** The deltaLog* functions (deltaLogEncode, deltaLogDecode, deltaLogMerge). */
1678
1867
  deltaLog: boolean;
1868
+ /** ops literalValue and literalFromValue (issue 1051). */
1869
+ literalValues: boolean;
1679
1870
  /** 'full': the whole library is in the wasm module. */
1680
1871
  profile: 'full' | string;
1681
1872
  /** The dispatch ABI version string of the loaded wasm module. */
@@ -1759,10 +1950,18 @@ declare const _default: {
1759
1950
  canonicalize: typeof canonicalize;
1760
1951
  graphs: typeof graphs;
1761
1952
  canonicalHash: typeof canonicalHash;
1953
+ asDefaultGraph: typeof asDefaultGraph;
1762
1954
  isomorphic: typeof isomorphic;
1763
1955
  fromQuads: typeof fromQuads;
1764
1956
  ready: typeof ready;
1765
1957
  engineTables: typeof engineTables;
1958
+ sameValue: typeof sameValue;
1959
+ syntaxFor: typeof syntaxFor;
1960
+ splitIri: typeof splitIri;
1961
+ isNCName: typeof isNCName;
1962
+ vocabularies: typeof vocabularies;
1963
+ memberIri: typeof memberIri;
1964
+ memberOrdinal: typeof memberOrdinal;
1766
1965
  shaclValidate: typeof shaclValidate;
1767
1966
  shexValidate: typeof shexValidate;
1768
1967
  owlClosure: typeof owlClosure;
@@ -1818,6 +2017,10 @@ declare const _default: {
1818
2017
  FactoidalError: typeof FactoidalError;
1819
2018
  dataFactory: DataFactory;
1820
2019
  queryRaw: typeof queryRaw;
2020
+ literalValue: typeof literalValue;
2021
+ isValidLiteral: typeof isValidLiteral;
2022
+ canonicalLiteral: typeof canonicalLiteral;
2023
+ literalFromValue: typeof literalFromValue;
1821
2024
  version: string;
1822
2025
  engine: string;
1823
2026
  };
package/index.mjs CHANGED
@@ -55,10 +55,24 @@ export const serialize = api.serialize;
55
55
  export const canonicalize = api.canonicalize;
56
56
  export const graphs = api.graphs;
57
57
  export const canonicalHash = api.canonicalHash;
58
+ export const asDefaultGraph = api.asDefaultGraph;
58
59
  export const isomorphic = api.isomorphic;
59
60
  export const fromQuads = api.fromQuads;
61
+ // Literal values (https://github.com/danbri/factoidal/issues/1051): synchronous
62
+ // after the engine is loaded.
63
+ export const literalValue = api.literalValue;
64
+ export const isValidLiteral = api.isValidLiteral;
65
+ export const canonicalLiteral = api.canonicalLiteral;
66
+ export const literalFromValue = api.literalFromValue;
60
67
  export const ready = api.ready;
61
68
  export const engineTables = api.engineTables;
69
+ export const sameValue = api.sameValue;
70
+ export const syntaxFor = api.syntaxFor;
71
+ export const splitIri = api.splitIri;
72
+ export const isNCName = api.isNCName;
73
+ export const vocabularies = api.vocabularies;
74
+ export const memberIri = api.memberIri;
75
+ export const memberOrdinal = api.memberOrdinal;
62
76
  export const openDataset = api.openDataset;
63
77
  export const closure = api.closure;
64
78
  export const formats = api.formats;
@@ -37,7 +37,7 @@
37
37
  // bytes change.
38
38
 
39
39
  // Stamped by formal/lean4/Wasm/build-wasm.sh step 9 -- do not hand-edit.
40
- const WASM_VERSION = "925f357453db";
40
+ const WASM_VERSION = "43c334ec5335";
41
41
 
42
42
  import createModule from './l4factoidal.mjs';
43
43
 
Binary file
@@ -2,17 +2,17 @@
2
2
  "engine": "lean4",
3
3
  "note": "The Lean 4 (L4Factoidal) engine build provenance and claims: the only engine of @factoidal/core since 0.9.0 (issue 713). This committed file is a placeholder. tools/fetch-builds.sh --set web (through tools/stamp-l4-version.mjs) writes the provenance members from the danbri/factoidal-builds release that built the wasm; formal/lean4/Wasm/build-wasm.sh step 9 writes them for a local build. Do not commit a stamped copy.",
4
4
  "stamped": true,
5
- "release": "danbri/factoidal-builds build-788ee43aec79-web",
6
- "releaseRun": "https://github.com/danbri/factoidal-builds/actions/runs/40457275423",
7
- "gitSha": "788ee43aec79c4d29592c5e82cc7ab350f0d05dd",
8
- "builtAt": "2026-10-27T06:36:59Z",
5
+ "release": "danbri/factoidal-builds build-0c9a222bdb25-web",
6
+ "releaseRun": "https://github.com/danbri/factoidal-builds/actions/runs/40662145237",
7
+ "gitSha": "0c9a222bdb25ff70456611d3fbc87a41902d8324",
8
+ "builtAt": "2026-10-28T09:52:07Z",
9
9
  "leanToolchain": "leanprover/lean4:v4.33.1",
10
10
  "emscripten": "6.0.8",
11
11
  "abiVersion": "1",
12
12
  "engineVersion": "l4factoidal-wasm 0.2.0 (dispatch: RDF parse/serialize, SPARQL query+update, RDFS/OWL-RL closures, RDFC-1.0, CL/IKL)",
13
13
  "version": "l4factoidal-wasm 0.2.0 (dispatch: RDF parse/serialize, SPARQL query+update, RDFS/OWL-RL closures, RDFC-1.0, CL/IKL)",
14
- "wasmSha256": "925f357453dbb71d087bef70fd428b054999756d7c967a806403d3d8ee875a57",
15
- "wasmBytes": 17565361,
14
+ "wasmSha256": "43c334ec53357cd40339f693d303bda3e422ac92e94ad335cb6b0e83ec4eafbd",
15
+ "wasmBytes": 17958911,
16
16
  "claims": {
17
17
  "source": "formal/lean4 (L4Factoidal): no sorry, no user axioms, no native_decide; W3C behaviour pinned by build-time #guard",
18
18
  "suitesAtBuildSha": "see docs/test-results and formal/lean4/PORT_NOTES.md at gitSha"