@factoidal/core 0.1.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/LICENSE +201 -0
  3. package/README.md +514 -0
  4. package/browser-wasm.js +872 -0
  5. package/browser.d.ts +514 -0
  6. package/browser.js +2276 -0
  7. package/factoidal-npm-entry.js +32609 -0
  8. package/factoidal-npm-entry.wasm.assets/code-7ac046580f1bbdda8dc6.wasm +0 -0
  9. package/factoidal-npm-entry.wasm.js +455 -0
  10. package/factoidal.js +27560 -0
  11. package/factoidal.wasm.assets/code-bbe6099bfb5b10c4c3ab.wasm +0 -0
  12. package/factoidal.wasm.js +457 -0
  13. package/fn.d.ts +519 -0
  14. package/fn.js +916 -0
  15. package/hacl-init.js +92 -0
  16. package/hacl-wasm/FStar.wasm +0 -0
  17. package/hacl-wasm/Hacl_Bignum.wasm +0 -0
  18. package/hacl-wasm/Hacl_Bignum25519_51.wasm +0 -0
  19. package/hacl-wasm/Hacl_Bignum_Base.wasm +0 -0
  20. package/hacl-wasm/Hacl_Curve25519_51.wasm +0 -0
  21. package/hacl-wasm/Hacl_Ed25519.wasm +0 -0
  22. package/hacl-wasm/Hacl_Ed25519_PrecompTable.wasm +0 -0
  23. package/hacl-wasm/Hacl_Hash_Base.wasm +0 -0
  24. package/hacl-wasm/Hacl_Hash_SHA2.wasm +0 -0
  25. package/hacl-wasm/Hacl_IntTypes_Intrinsics.wasm +0 -0
  26. package/hacl-wasm/LowStar_Endianness.wasm +0 -0
  27. package/hacl-wasm/WasmSupport.wasm +0 -0
  28. package/hacl-wasm/api.js +775 -0
  29. package/hacl-wasm/api.json +3787 -0
  30. package/hacl-wasm/layouts.json +1 -0
  31. package/hacl-wasm/loader.js +568 -0
  32. package/hacl-wasm/shell.js +12 -0
  33. package/index.d.ts +1068 -0
  34. package/index.js +237 -0
  35. package/index.mjs +85 -0
  36. package/lib/api.js +2140 -0
  37. package/lib/engine-js.js +165 -0
  38. package/lib/engine-wasm.js +300 -0
  39. package/package.json +101 -0
  40. package/rdfjs.js +540 -0
  41. package/version.json +101 -0
  42. package/wasm.d.ts +130 -0
  43. package/wasm.js +158 -0
package/rdfjs.js ADDED
@@ -0,0 +1,540 @@
1
+ // factoidal — RDF/JS data model + N-Quads token converters.
2
+ //
3
+ // Implements the RDF/JS Data Model specification
4
+ // (https://rdf.js.org/data-model-spec/): DataFactory producing
5
+ // NamedNode / BlankNode / Literal / Variable / DefaultGraph / Quad
6
+ // terms with spec-compliant `termType` / `value` / `language` /
7
+ // `datatype` and `.equals()`. Self-contained — no runtime deps.
8
+ //
9
+ // Also provides converters between RDF/JS quads and the engine's
10
+ // N-Quads token strings, which are the package's dataset interchange
11
+ // handle (the F*-extracted engine parses and serializes N-Quads; the
12
+ // converters below only tokenize/untokenize the engine's own output —
13
+ // full RDF parsing of user input always goes through the engine, per
14
+ // repo rule #4 "parsers belong in F*").
15
+ //
16
+ // Escaping mirrors the F* serializer RDF.NQuads.Serialize.escape_char
17
+ // exactly: \\ \" \n \r \t (and nothing else) are escaped on output;
18
+ // unescaping additionally accepts the full N-Triples ECHAR + UCHAR set
19
+ // (\t \b \n \r \f \" \' \\ \uXXXX \UXXXXXXXX) since engine input may
20
+ // legally contain them.
21
+
22
+ 'use strict';
23
+
24
+ const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string';
25
+ const RDF_LANGSTRING =
26
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString';
27
+
28
+ // ---------------------------------------------------------------------
29
+ // Terms
30
+ // ---------------------------------------------------------------------
31
+
32
+ class NamedNode {
33
+ constructor(iri) {
34
+ this.termType = 'NamedNode';
35
+ this.value = iri;
36
+ Object.freeze(this);
37
+ }
38
+ equals(other) {
39
+ return !!other && other.termType === 'NamedNode' &&
40
+ other.value === this.value;
41
+ }
42
+ }
43
+
44
+ class BlankNode {
45
+ constructor(label) {
46
+ this.termType = 'BlankNode';
47
+ this.value = label;
48
+ Object.freeze(this);
49
+ }
50
+ equals(other) {
51
+ return !!other && other.termType === 'BlankNode' &&
52
+ other.value === this.value;
53
+ }
54
+ }
55
+
56
+ class Literal {
57
+ constructor(value, language, datatype) {
58
+ this.termType = 'Literal';
59
+ this.value = value;
60
+ this.language = language || '';
61
+ this.datatype = datatype ||
62
+ new NamedNode(language ? RDF_LANGSTRING : XSD_STRING);
63
+ Object.freeze(this);
64
+ }
65
+ equals(other) {
66
+ return !!other && other.termType === 'Literal' &&
67
+ other.value === this.value &&
68
+ other.language === this.language &&
69
+ !!other.datatype && other.datatype.value === this.datatype.value;
70
+ }
71
+ }
72
+
73
+ class Variable {
74
+ constructor(name) {
75
+ this.termType = 'Variable';
76
+ this.value = name;
77
+ Object.freeze(this);
78
+ }
79
+ equals(other) {
80
+ return !!other && other.termType === 'Variable' &&
81
+ other.value === this.value;
82
+ }
83
+ }
84
+
85
+ class DefaultGraph {
86
+ constructor() {
87
+ this.termType = 'DefaultGraph';
88
+ this.value = '';
89
+ Object.freeze(this);
90
+ }
91
+ equals(other) {
92
+ return !!other && other.termType === 'DefaultGraph';
93
+ }
94
+ }
95
+
96
+ const DEFAULT_GRAPH = new DefaultGraph();
97
+
98
+ class Quad {
99
+ constructor(subject, predicate, object, graph) {
100
+ // Per spec, a Quad is itself a Term with termType 'Quad', value ''.
101
+ this.termType = 'Quad';
102
+ this.value = '';
103
+ this.subject = subject;
104
+ this.predicate = predicate;
105
+ this.object = object;
106
+ this.graph = graph || DEFAULT_GRAPH;
107
+ Object.freeze(this);
108
+ }
109
+ equals(other) {
110
+ return !!other &&
111
+ (other.termType === 'Quad' || other.termType === undefined) &&
112
+ this.subject.equals(other.subject) &&
113
+ this.predicate.equals(other.predicate) &&
114
+ this.object.equals(other.object) &&
115
+ this.graph.equals(other.graph);
116
+ }
117
+ }
118
+
119
+ // ---------------------------------------------------------------------
120
+ // DataFactory
121
+ // ---------------------------------------------------------------------
122
+
123
+ let blankNodeCounter = 0;
124
+
125
+ const dataFactory = {
126
+ namedNode(value) {
127
+ return new NamedNode(String(value));
128
+ },
129
+ blankNode(label) {
130
+ return new BlankNode(
131
+ label !== undefined && label !== null
132
+ ? String(label)
133
+ : 'fjs_b' + (blankNodeCounter++)
134
+ );
135
+ },
136
+ literal(value, languageOrDatatype) {
137
+ const v = String(value);
138
+ if (languageOrDatatype === undefined || languageOrDatatype === null) {
139
+ return new Literal(v, '', null);
140
+ }
141
+ if (typeof languageOrDatatype === 'string') {
142
+ return new Literal(v, languageOrDatatype, null);
143
+ }
144
+ // A NamedNode datatype.
145
+ if (languageOrDatatype.termType === 'NamedNode') {
146
+ if (languageOrDatatype.value === RDF_LANGSTRING) {
147
+ // langString without a language tag is not constructible; treat
148
+ // as plain string per the most defensive reading of the spec.
149
+ return new Literal(v, '', null);
150
+ }
151
+ return new Literal(v, '', new NamedNode(languageOrDatatype.value));
152
+ }
153
+ throw new TypeError(
154
+ 'literal: second argument must be a language string or a NamedNode'
155
+ );
156
+ },
157
+ variable(name) {
158
+ return new Variable(String(name));
159
+ },
160
+ defaultGraph() {
161
+ return DEFAULT_GRAPH;
162
+ },
163
+ quad(subject, predicate, object, graph) {
164
+ return new Quad(subject, predicate, object, graph);
165
+ },
166
+ fromTerm(original) {
167
+ if (!original || typeof original.termType !== 'string') {
168
+ throw new TypeError('fromTerm: not a term');
169
+ }
170
+ switch (original.termType) {
171
+ case 'NamedNode': return new NamedNode(original.value);
172
+ case 'BlankNode': return new BlankNode(original.value);
173
+ case 'Variable': return new Variable(original.value);
174
+ case 'DefaultGraph': return DEFAULT_GRAPH;
175
+ case 'Literal':
176
+ return new Literal(
177
+ original.value,
178
+ original.language || '',
179
+ original.language
180
+ ? null
181
+ : new NamedNode(
182
+ (original.datatype && original.datatype.value) || XSD_STRING)
183
+ );
184
+ case 'Quad': return dataFactory.fromQuad(original);
185
+ default:
186
+ throw new TypeError(`fromTerm: unknown termType '${original.termType}'`);
187
+ }
188
+ },
189
+ fromQuad(original) {
190
+ if (!original || !original.subject) {
191
+ throw new TypeError('fromQuad: not a quad');
192
+ }
193
+ return new Quad(
194
+ dataFactory.fromTerm(original.subject),
195
+ dataFactory.fromTerm(original.predicate),
196
+ dataFactory.fromTerm(original.object),
197
+ original.graph ? dataFactory.fromTerm(original.graph) : DEFAULT_GRAPH
198
+ );
199
+ },
200
+ };
201
+
202
+ // ---------------------------------------------------------------------
203
+ // SPARQL Results JSON term -> RDF/JS term
204
+ // ---------------------------------------------------------------------
205
+
206
+ /**
207
+ * Convert a SPARQL 1.1 Results JSON term object
208
+ * ({type:'uri'|'bnode'|'literal'|'typed-literal', value, 'xml:lang',
209
+ * datatype}) into an RDF/JS term.
210
+ */
211
+ function termFromSrj(t) {
212
+ if (!t || typeof t.type !== 'string') {
213
+ throw new TypeError('termFromSrj: not a results-JSON term');
214
+ }
215
+ switch (t.type) {
216
+ case 'uri':
217
+ return dataFactory.namedNode(t.value);
218
+ case 'bnode':
219
+ return dataFactory.blankNode(t.value);
220
+ case 'literal':
221
+ case 'typed-literal': {
222
+ const lang = t['xml:lang'];
223
+ if (lang) return dataFactory.literal(t.value, lang);
224
+ if (t.datatype) {
225
+ return dataFactory.literal(t.value, dataFactory.namedNode(t.datatype));
226
+ }
227
+ return dataFactory.literal(t.value);
228
+ }
229
+ case 'triple': {
230
+ // RDF 1.2 triple term in SPARQL Results JSON:
231
+ // {"type":"triple","value":{"subject":T,"predicate":T,"object":T}}
232
+ // (SPARQL_Protocol.json_term) -> an RDF/JS Quad term. Recursive:
233
+ // the object may itself be a triple term.
234
+ const v = t.value || {};
235
+ return dataFactory.quad(
236
+ termFromSrj(v.subject), termFromSrj(v.predicate), termFromSrj(v.object));
237
+ }
238
+ default:
239
+ throw new TypeError(`termFromSrj: unknown term type '${t.type}'`);
240
+ }
241
+ }
242
+
243
+ // ---------------------------------------------------------------------
244
+ // N-Quads token output (mirrors RDF.NQuads.Serialize.escape_char)
245
+ // ---------------------------------------------------------------------
246
+
247
+ function escapeLiteral(s) {
248
+ let out = '';
249
+ for (const ch of s) {
250
+ switch (ch) {
251
+ case '\\': out += '\\\\'; break;
252
+ case '"': out += '\\"'; break;
253
+ case '\n': out += '\\n'; break;
254
+ case '\r': out += '\\r'; break;
255
+ case '\t': out += '\\t'; break;
256
+ default: out += ch;
257
+ }
258
+ }
259
+ return out;
260
+ }
261
+
262
+ /** Serialize one RDF/JS term to its N-Quads token. */
263
+ function termToNQuads(term) {
264
+ switch (term.termType) {
265
+ case 'NamedNode':
266
+ return '<' + term.value + '>';
267
+ case 'BlankNode':
268
+ return '_:' + term.value;
269
+ case 'Literal': {
270
+ const body = '"' + escapeLiteral(term.value) + '"';
271
+ if (term.language) return body + '@' + term.language;
272
+ if (term.datatype && term.datatype.value !== XSD_STRING) {
273
+ return body + '^^<' + term.datatype.value + '>';
274
+ }
275
+ return body;
276
+ }
277
+ case 'DefaultGraph':
278
+ return '';
279
+ case 'Quad':
280
+ // RDF 1.2 triple term -> <<( s p o )>> (matches the engine's
281
+ // Mode_12 N-Quads serializer, so it round-trips back through the
282
+ // *12 parse path).
283
+ return '<<( ' + termToNQuads(term.subject) + ' ' +
284
+ termToNQuads(term.predicate) + ' ' +
285
+ termToNQuads(term.object) + ' )>>';
286
+ default:
287
+ throw new TypeError(
288
+ `termToNQuads: cannot serialize termType '${term.termType}'`);
289
+ }
290
+ }
291
+
292
+ /** Serialize one RDF/JS quad to an N-Quads line (with trailing " .\n"). */
293
+ function quadToNQuads(quad) {
294
+ const g = quad.graph && quad.graph.termType !== 'DefaultGraph'
295
+ ? ' ' + termToNQuads(quad.graph)
296
+ : '';
297
+ return termToNQuads(quad.subject) + ' ' +
298
+ termToNQuads(quad.predicate) + ' ' +
299
+ termToNQuads(quad.object) + g + ' .\n';
300
+ }
301
+
302
+ /** Serialize an iterable of quads to an N-Quads document. */
303
+ function quadsToNQuads(quads) {
304
+ let out = '';
305
+ for (const q of quads) out += quadToNQuads(q);
306
+ return out;
307
+ }
308
+
309
+ // ---------------------------------------------------------------------
310
+ // N-Quads token input.
311
+ //
312
+ // A line tokenizer for the engine's own N-Quads output (and canonical
313
+ // N-Quads generally): one statement per line, terms separated by
314
+ // whitespace, ECHAR/UCHAR escapes inside literals. This is a token
315
+ // reader for a machine-generated regular syntax, not a general RDF
316
+ // parser — user documents in any syntax go through the engine.
317
+ // ---------------------------------------------------------------------
318
+
319
+ const UNESCAPE_MAP = {
320
+ 't': '\t', 'b': '\b', 'n': '\n', 'r': '\r', 'f': '\f',
321
+ '"': '"', "'": "'", '\\': '\\',
322
+ };
323
+
324
+ function unescapeLiteral(s, lineNo) {
325
+ if (s.indexOf('\\') < 0) return s;
326
+ let out = '';
327
+ for (let i = 0; i < s.length; i++) {
328
+ const c = s[i];
329
+ if (c !== '\\') { out += c; continue; }
330
+ const e = s[++i];
331
+ if (e in UNESCAPE_MAP) { out += UNESCAPE_MAP[e]; continue; }
332
+ if (e === 'u') {
333
+ out += String.fromCodePoint(parseInt(s.slice(i + 1, i + 5), 16));
334
+ i += 4;
335
+ continue;
336
+ }
337
+ if (e === 'U') {
338
+ out += String.fromCodePoint(parseInt(s.slice(i + 1, i + 9), 16));
339
+ i += 8;
340
+ continue;
341
+ }
342
+ throw new SyntaxError(
343
+ `N-Quads line ${lineNo}: bad escape '\\${e}'`);
344
+ }
345
+ return out;
346
+ }
347
+
348
+ // Read one term starting at s[i]; returns [term, nextIndex].
349
+ function readTerm(s, i, lineNo, factory) {
350
+ const c = s[i];
351
+ // RDF 1.2 triple term: <<( s p o )>> -> an RDF/JS Quad term
352
+ // (termType 'Quad'). Checked BEFORE the '<' IRI case since a triple
353
+ // term also opens with '<'. This reads the engine's own Mode_12
354
+ // N-Quads serializer output (RDF.NQuads.Serialize) into RDF/JS
355
+ // objects; it is not a conformance parser (that is the F* --rdf12
356
+ // path) — same interop role the rest of this reader plays.
357
+ if (c === '<' && s[i + 1] === '<' && s[i + 2] === '(') {
358
+ let j = skipWs(s, i + 3);
359
+ const [sub, a] = readTerm(s, j, lineNo, factory); j = skipWs(s, a);
360
+ const [pred, b] = readTerm(s, j, lineNo, factory); j = skipWs(s, b);
361
+ const [obj, d] = readTerm(s, j, lineNo, factory); j = skipWs(s, d);
362
+ if (s[j] === ')' && s[j + 1] === '>' && s[j + 2] === '>') {
363
+ return [factory.quad(sub, pred, obj), j + 3];
364
+ }
365
+ throw new SyntaxError(
366
+ `N-Quads line ${lineNo}: unterminated triple term (expected ')>>')`);
367
+ }
368
+ if (c === '<') {
369
+ const end = s.indexOf('>', i + 1);
370
+ if (end < 0) throw new SyntaxError(`N-Quads line ${lineNo}: unclosed IRI`);
371
+ return [factory.namedNode(s.slice(i + 1, end)), end + 1];
372
+ }
373
+ if (c === '_' && s[i + 1] === ':') {
374
+ let j = i + 2;
375
+ while (j < s.length && !/\s/.test(s[j])) j++;
376
+ return [factory.blankNode(s.slice(i + 2, j)), j];
377
+ }
378
+ if (c === '"') {
379
+ // Scan to the closing unescaped quote.
380
+ let j = i + 1;
381
+ for (;;) {
382
+ if (j >= s.length) {
383
+ throw new SyntaxError(`N-Quads line ${lineNo}: unclosed literal`);
384
+ }
385
+ if (s[j] === '\\') { j += 2; continue; }
386
+ if (s[j] === '"') break;
387
+ j++;
388
+ }
389
+ const lex = unescapeLiteral(s.slice(i + 1, j), lineNo);
390
+ j++; // past closing quote
391
+ if (s[j] === '@') {
392
+ let k = j + 1;
393
+ while (k < s.length && !/\s/.test(s[k])) k++;
394
+ return [factory.literal(lex, s.slice(j + 1, k)), k];
395
+ }
396
+ if (s[j] === '^' && s[j + 1] === '^' && s[j + 2] === '<') {
397
+ const end = s.indexOf('>', j + 3);
398
+ if (end < 0) {
399
+ throw new SyntaxError(`N-Quads line ${lineNo}: unclosed datatype IRI`);
400
+ }
401
+ return [
402
+ factory.literal(lex, factory.namedNode(s.slice(j + 3, end))),
403
+ end + 1,
404
+ ];
405
+ }
406
+ return [factory.literal(lex), j];
407
+ }
408
+ throw new SyntaxError(
409
+ `N-Quads line ${lineNo}: unexpected character '${c}' at column ${i + 1}`);
410
+ }
411
+
412
+ function skipWs(s, i) {
413
+ while (i < s.length && (s[i] === ' ' || s[i] === '\t')) i++;
414
+ return i;
415
+ }
416
+
417
+ /**
418
+ * Tokenize one N-Quads statement line into an RDF/JS quad.
419
+ * Returns null for blank/comment lines.
420
+ */
421
+ function nquadsLineToQuad(line, lineNo, factory) {
422
+ const f = factory || dataFactory;
423
+ let i = skipWs(line, 0);
424
+ if (i >= line.length || line[i] === '#') return null;
425
+ const terms = [];
426
+ while (terms.length < 4) {
427
+ const [term, next] = readTerm(line, i, lineNo, f);
428
+ terms.push(term);
429
+ i = skipWs(line, next);
430
+ if (line[i] === '.') break;
431
+ }
432
+ if (line[i] !== '.') {
433
+ throw new SyntaxError(`N-Quads line ${lineNo}: missing terminating '.'`);
434
+ }
435
+ if (terms.length < 3) {
436
+ throw new SyntaxError(`N-Quads line ${lineNo}: fewer than 3 terms`);
437
+ }
438
+ return f.quad(terms[0], terms[1], terms[2], terms[3] || f.defaultGraph());
439
+ }
440
+
441
+ /**
442
+ * Tokenize an engine-emitted N-Quads document into RDF/JS quads.
443
+ *
444
+ * options.blankNodePrefix — prepended to every blank-node label, used
445
+ * by parse() to keep labels from separate parse calls distinct (blank
446
+ * node identity is document-scoped; the prefix is bookkeeping, the
447
+ * semantic per-document renaming lives in F*
448
+ * RDF.Dataset.Merge.rename_dataset_bnodes).
449
+ */
450
+ function nquadsToQuads(text, options) {
451
+ const opts = options || {};
452
+ const factory = opts.factory || dataFactory;
453
+ const f = opts.blankNodePrefix
454
+ ? {
455
+ ...factory,
456
+ blankNode: (label) => factory.blankNode(
457
+ label === undefined || label === null
458
+ ? undefined
459
+ : opts.blankNodePrefix + label),
460
+ }
461
+ : factory;
462
+ const quads = [];
463
+ const lines = String(text).split('\n');
464
+ for (let n = 0; n < lines.length; n++) {
465
+ const q = nquadsLineToQuad(lines[n].replace(/\r$/, ''), n + 1, f);
466
+ if (q) quads.push(q);
467
+ }
468
+ return quads;
469
+ }
470
+
471
+ // ---------------------------------------------------------------------
472
+ // Dataset — a minimal RDF/JS DatasetCore over an in-memory quad array.
473
+ // ---------------------------------------------------------------------
474
+
475
+ class Dataset {
476
+ constructor(quads) {
477
+ this._quads = [];
478
+ if (quads) for (const q of quads) this.add(q);
479
+ }
480
+ get size() {
481
+ return this._quads.length;
482
+ }
483
+ add(quad) {
484
+ if (!this.has(quad)) this._quads.push(quad);
485
+ return this;
486
+ }
487
+ delete(quad) {
488
+ const ix = this._quads.findIndex((q) => q.equals(quad));
489
+ if (ix >= 0) this._quads.splice(ix, 1);
490
+ return this;
491
+ }
492
+ has(quad) {
493
+ return this._quads.some((q) => q.equals(quad));
494
+ }
495
+ match(subject, predicate, object, graph) {
496
+ const out = new Dataset();
497
+ for (const q of this._quads) {
498
+ if (subject && !subject.equals(q.subject)) continue;
499
+ if (predicate && !predicate.equals(q.predicate)) continue;
500
+ if (object && !object.equals(q.object)) continue;
501
+ if (graph && !graph.equals(q.graph)) continue;
502
+ out._quads.push(q);
503
+ }
504
+ return out;
505
+ }
506
+ [Symbol.iterator]() {
507
+ return this._quads[Symbol.iterator]();
508
+ }
509
+ toArray() {
510
+ return this._quads.slice();
511
+ }
512
+ /** N-Quads text — the engine interchange handle. */
513
+ toNQuads() {
514
+ return quadsToNQuads(this._quads);
515
+ }
516
+ toString() {
517
+ return this.toNQuads();
518
+ }
519
+ static fromNQuads(text, options) {
520
+ return new Dataset(nquadsToQuads(text, options));
521
+ }
522
+ }
523
+
524
+ module.exports = {
525
+ dataFactory,
526
+ NamedNode,
527
+ BlankNode,
528
+ Literal,
529
+ Variable,
530
+ DefaultGraph,
531
+ Quad,
532
+ Dataset,
533
+ termFromSrj,
534
+ termToNQuads,
535
+ quadToNQuads,
536
+ quadsToNQuads,
537
+ nquadsToQuads,
538
+ XSD_STRING,
539
+ RDF_LANGSTRING,
540
+ };
package/version.json ADDED
@@ -0,0 +1,101 @@
1
+ {
2
+ "version": "0.1.0",
3
+ "gitSha": "4944fdb1cc6d5fcc7a2db2f2a1802f276aac6bee",
4
+ "builtAt": "2026-08-22T05:46:06Z",
5
+ "claims": {
6
+ "schema": "1",
7
+ "statement": "Proved sound with respect to an independent F* formalization of the W3C RDF/RDFS/OWL semantics, under the stated fragment restrictions and the trust surface recorded in docs/theorem-registry.md — never claimed as a complete formally verified implementation of RDF semantics (docs/theorem-registry.md § Calibrated claims).",
8
+ "registry": "docs/theorem-registry.md",
9
+ "trustSurface": "docs/theorem-registry.md § Trust surface",
10
+ "notes": "Each item below names the exact theorem/lemma, the F* file that carries it, and the registry section a reader can open to check the claim. This is a summary, not the full registry — read docs/theorem-registry.md for the complete rule-by-rule table, hypothesis provenance, and open findings.",
11
+ "items": [
12
+ {
13
+ "id": "rho-df-closure-decides",
14
+ "claim": "The certified six-rule core-RDFS (ρdf) closure (rdfs2/3/5/7/9/11) decides entailment exactly on fragment inputs — its simple-query answers are exactly the entailed consequences.",
15
+ "theorem": "rho_df_closure_sound, rho_df_closure_decides",
16
+ "file": "formal/fstar/RDF.Entailment.RDFS.RhoDFClosure.fst",
17
+ "registrySection": "docs/theorem-registry.md § Layer 3 — the composed regime theorem, rho_df_closure soundness/fragment-preservation rows",
18
+ "npmSurface": [
19
+ "coreRdfsClosure",
20
+ "rhoDfClosure",
21
+ "coreRdfsCheck",
22
+ "rhoDfFragmentCheck"
23
+ ],
24
+ "status": "proved"
25
+ },
26
+ {
27
+ "id": "owl-rl-licensing-truth",
28
+ "claim": "Every OWL 2 RL/RDF engine rule classified [row] emits only input triples or a licensed W3C table-row application (licensing), and every row's conclusion is model-theoretically true given its premises (truth).",
29
+ "file": "formal/fstar/OWL.RL.Spec.fst, OWL.RL.Refinement.fst, OWL.Semantics.fst",
30
+ "registrySection": "docs/theorem-registry.md § 1 (OWL 2 RL/RDF — licensing and truth, per engine rule)",
31
+ "npmSurface": [
32
+ "owlClosure",
33
+ "rdfsPlusClosure",
34
+ "tableauMaterialise",
35
+ "tableauDlInconsistent",
36
+ "owlIsConsistent",
37
+ "owlEntails"
38
+ ],
39
+ "status": "proved per-rule; see §1 table for per-row status and PARKED clash-row exceptions"
40
+ },
41
+ {
42
+ "id": "rdfs-entailment-13-rows",
43
+ "claim": "11 of 13 RDF 1.1 Semantics §9 RDFS entailment rows have a shipping engine rule with both licensing and truth proved; the remaining 2 (rdfs6, rdfs10) are proved at the spec-predicate level but the shipping engine's reflexivity over-approximation for them is correctly flagged unsound (finding RS-1), not silently shipped as sound.",
44
+ "file": "formal/fstar/RDF.Entailment.RDFS.Spec.fst, RDF.Entailment.RDFS.Refinement.fst, RDF.Entailment.RDFS.ModelTheory.fst",
45
+ "registrySection": "docs/theorem-registry.md § 2 (RDFS entailment — 13 rows)",
46
+ "status": "11/13 proved sound+true; 2/13 truth-only, engine unsoundness flagged not hidden"
47
+ },
48
+ {
49
+ "id": "sparql-rdfs-regime-exact-answer",
50
+ "claim": "The SPARQL evaluator's answer set over the ρdf closure IS the RDFS entailment regime's answer set, on fragment inputs, for ground answers (soundness + completeness, unconditional).",
51
+ "theorem": "theorem_rdfs_regime_bgp_exact_answer, theorem_rdfs_regime_ask_query_complete",
52
+ "file": "formal/fstar/SPARQL11.EntailmentRegime.RDFS.fst",
53
+ "registrySection": "docs/theorem-registry.md § 5 (SPARQL algebra refinement, the query rung) § Layer 3",
54
+ "npmSurface": [
55
+ "query (options.entail = 'RDFS')"
56
+ ],
57
+ "status": "proved, unconditional"
58
+ },
59
+ {
60
+ "id": "streaming-multichunk",
61
+ "claim": "N-Quads streaming parse over ANY list of input chunks equals a batch parse of their concatenation (stream_parse chunks == batch_parse (concat_all chunks)) — the machine-checked answer to whether chunked/streamed parsing of arbitrarily large files agrees with parsing the whole file at once.",
62
+ "theorem": "theorem_stream_eq_batch",
63
+ "file": "formal/fstar/RDF.NQuads.Streaming.fst",
64
+ "registrySection": "docs/theorem-registry.md § 7 (G4/M1 parser round-trip theorems) — Task #48/#402 MULTI-CHUNK STREAMING THEOREM, 2026-08-11",
65
+ "status": "proved"
66
+ },
67
+ {
68
+ "id": "srj-n-row",
69
+ "claim": "SPARQL Results JSON serialisation (serialise_response_json) equals the fixed SRJ shape (head/vars block, comma-joined row texts) for ANY variable list and ANY row list of ANY length N — not just the 0/1/2-row cases spot-checked before.",
70
+ "theorem": "lemma_srj_n_rows",
71
+ "file": "formal/fstar/SPARQL.Protocol.RoundTrip.fst",
72
+ "registrySection": "docs/theorem-registry.md § 7 (G4/M1 parser round-trip theorems) — G4 M4 N-ROW symbolic SRJ theorem, 2026-08-11",
73
+ "npmSurface": [
74
+ "query (SELECT, output SPARQL Results JSON)"
75
+ ],
76
+ "status": "proved"
77
+ },
78
+ {
79
+ "id": "symbolic-iri-roundtrip",
80
+ "claim": "Parsing the printed N-Triples form of a SYMBOLIC IRI term (any ASCII codepoint list of IRI-safe characters, no escapes, no controls) recovers the original term exactly — proved against the real serializer, not a transcription.",
81
+ "theorem": "lemma_term_iri_round_trip_build_string",
82
+ "file": "formal/fstar/RDF.NTriples.RoundTrip.fst",
83
+ "registrySection": "docs/theorem-registry.md § 7 (G4/M1 parser round-trip theorems) — G4 M1 SYMBOLIC IRI round-trip theorem, 2026-08-11",
84
+ "npmSurface": [
85
+ "parse",
86
+ "serialize"
87
+ ],
88
+ "status": "proved for symbolic IRIs; full well-formed-IRI coverage open (string-conversion wall, documented)"
89
+ },
90
+ {
91
+ "id": "faststring-migration-complete",
92
+ "claim": "The FastString byte-primitive migration (steps 0-6) is complete: zero assume vals in the FastString family except the one documented CharBoundary primitive (unsafe_char_of_d7ff); the equivalence corpus is IDENTICAL between native OCaml and Node (js_of_ocaml) execution.",
93
+ "measurement": "93846 pass, 962 expected-fail, 0 unexpected fail (out of 94808), verified 3 ways (fresh Node run, fresh same-source native compile, prior recorded number)",
94
+ "file": "formal/fstar/Parser.FastString.fst, Parser.FastString.Spec.fst",
95
+ "registrySection": "docs/theorem-registry.md § 7 (G4/M1 parser round-trip theorems) — FastString migration COMPLETE, steps 0-6, 2026-08-11",
96
+ "status": "complete, measured equivalent native+Node"
97
+ }
98
+ ],
99
+ "notClaimed": "A complete formally verified implementation of RDF semantics. See docs/theorem-registry.md § Trust surface for the assume-val count (~146, mostly COTTAS/HDT storage I/O per iron rule #11), the extraction-step caveat (fstar.exe --codegen OCaml is not itself re-verified), and the rdf-mt / W3C conformance suites this registry relies on as the independent runtime check. CLAUDE.md's standing qualifier applies: parser and algebra spec verified in F*; the on-disk backend carries unverified OCaml-side optimization layers being migrated back to F*."
100
+ }
101
+ }