@world-engines/tmw 0.1.0-alpha.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 (120) hide show
  1. package/LICENSE +46 -0
  2. package/dist/activation.d.ts +50 -0
  3. package/dist/activation.js +113 -0
  4. package/dist/audio-presentation-projection.d.ts +23 -0
  5. package/dist/audio-presentation-projection.js +39 -0
  6. package/dist/author-scenario-source-v3.d.ts +34 -0
  7. package/dist/author-scenario-source-v3.js +1 -0
  8. package/dist/authoring-runtime.d.ts +76 -0
  9. package/dist/authoring-runtime.js +282 -0
  10. package/dist/builder-diagnostics.d.ts +3 -0
  11. package/dist/builder-diagnostics.js +8 -0
  12. package/dist/builder-node.d.ts +178 -0
  13. package/dist/builder-node.js +212 -0
  14. package/dist/builder.d.ts +32 -0
  15. package/dist/builder.js +127 -0
  16. package/dist/capability-registry.d.ts +32 -0
  17. package/dist/capability-registry.js +33 -0
  18. package/dist/compile-target-profile.d.ts +16 -0
  19. package/dist/compile-target-profile.js +70 -0
  20. package/dist/compiled-plan.d.ts +44 -0
  21. package/dist/compiled-plan.js +1 -0
  22. package/dist/compiler-compatibility-gate.d.ts +96 -0
  23. package/dist/compiler-compatibility-gate.js +609 -0
  24. package/dist/compiler-release-authority.d.ts +212 -0
  25. package/dist/compiler-release-authority.js +676 -0
  26. package/dist/compiler-stage-cache.d.ts +42 -0
  27. package/dist/compiler-stage-cache.js +100 -0
  28. package/dist/compiler-stage-registry.d.ts +48 -0
  29. package/dist/compiler-stage-registry.js +126 -0
  30. package/dist/compiler.d.ts +7 -0
  31. package/dist/compiler.js +68 -0
  32. package/dist/condition-graph.d.ts +46 -0
  33. package/dist/condition-graph.js +135 -0
  34. package/dist/diagnostics.d.ts +20 -0
  35. package/dist/diagnostics.js +20 -0
  36. package/dist/durable-intent.d.ts +29 -0
  37. package/dist/durable-intent.js +60 -0
  38. package/dist/effect-flow.d.ts +69 -0
  39. package/dist/effect-flow.js +98 -0
  40. package/dist/event-fabric.d.ts +81 -0
  41. package/dist/event-fabric.js +227 -0
  42. package/dist/event-lifecycle.d.ts +59 -0
  43. package/dist/event-lifecycle.js +161 -0
  44. package/dist/evidence.d.ts +37 -0
  45. package/dist/evidence.js +92 -0
  46. package/dist/gameplay-state.d.ts +127 -0
  47. package/dist/gameplay-state.js +214 -0
  48. package/dist/index.d.ts +66 -0
  49. package/dist/index.js +52 -0
  50. package/dist/isolated-replay.d.ts +81 -0
  51. package/dist/isolated-replay.js +316 -0
  52. package/dist/music-candidate-set.d.ts +38 -0
  53. package/dist/music-candidate-set.js +102 -0
  54. package/dist/natural-language-chunking.d.ts +10 -0
  55. package/dist/natural-language-chunking.js +62 -0
  56. package/dist/natural-language-ingestion.d.ts +14 -0
  57. package/dist/natural-language-ingestion.js +128 -0
  58. package/dist/natural-language-structured-decode.d.ts +2 -0
  59. package/dist/natural-language-structured-decode.js +69 -0
  60. package/dist/natural-language-world-types.d.ts +142 -0
  61. package/dist/natural-language-world-types.js +2 -0
  62. package/dist/neutral-source-compiler.d.ts +135 -0
  63. package/dist/neutral-source-compiler.js +608 -0
  64. package/dist/presentation-intent.d.ts +42 -0
  65. package/dist/presentation-intent.js +137 -0
  66. package/dist/recall-query-envelope.d.ts +32 -0
  67. package/dist/recall-query-envelope.js +51 -0
  68. package/dist/rewrite-compensation.d.ts +28 -0
  69. package/dist/rewrite-compensation.js +85 -0
  70. package/dist/runtime-contract.d.ts +56 -0
  71. package/dist/runtime-contract.js +96 -0
  72. package/dist/runtime-domain-capabilities.d.ts +12 -0
  73. package/dist/runtime-domain-capabilities.js +20 -0
  74. package/dist/runtime-sav.d.ts +117 -0
  75. package/dist/runtime-sav.js +356 -0
  76. package/dist/runtime-trace.d.ts +44 -0
  77. package/dist/runtime-trace.js +119 -0
  78. package/dist/runtime.d.ts +238 -0
  79. package/dist/runtime.js +1887 -0
  80. package/dist/scene-author-source.d.ts +13 -0
  81. package/dist/scene-author-source.js +25 -0
  82. package/dist/scene-state.d.ts +275 -0
  83. package/dist/scene-state.js +334 -0
  84. package/dist/scheduler.d.ts +55 -0
  85. package/dist/scheduler.js +235 -0
  86. package/dist/selector-ast.d.ts +24 -0
  87. package/dist/selector-ast.js +18 -0
  88. package/dist/semantic-verdict.d.ts +48 -0
  89. package/dist/semantic-verdict.js +101 -0
  90. package/dist/simulator.d.ts +45 -0
  91. package/dist/simulator.js +58 -0
  92. package/dist/source-canonical.d.ts +4 -0
  93. package/dist/source-canonical.js +51 -0
  94. package/dist/source-crypto.d.ts +20 -0
  95. package/dist/source-crypto.js +17 -0
  96. package/dist/source-revision.d.ts +22 -0
  97. package/dist/source-revision.js +43 -0
  98. package/dist/spatial-impact-receipt.d.ts +38 -0
  99. package/dist/spatial-impact-receipt.js +67 -0
  100. package/dist/temporal-rewrite.d.ts +59 -0
  101. package/dist/temporal-rewrite.js +214 -0
  102. package/dist/time-domains.d.ts +37 -0
  103. package/dist/time-domains.js +142 -0
  104. package/dist/timeline-revision.d.ts +28 -0
  105. package/dist/timeline-revision.js +59 -0
  106. package/dist/trigger-document-v3.d.ts +99 -0
  107. package/dist/trigger-document-v3.js +334 -0
  108. package/dist/turn-commit.d.ts +56 -0
  109. package/dist/turn-commit.js +190 -0
  110. package/dist/validator.d.ts +7 -0
  111. package/dist/validator.js +142 -0
  112. package/dist/value-graph.d.ts +98 -0
  113. package/dist/value-graph.js +318 -0
  114. package/dist/view-event-delivery.d.ts +47 -0
  115. package/dist/view-event-delivery.js +197 -0
  116. package/dist/view-interaction-manifest-v3.d.ts +60 -0
  117. package/dist/view-interaction-manifest-v3.js +198 -0
  118. package/dist/view-payload-schema.d.ts +17 -0
  119. package/dist/view-payload-schema.js +84 -0
  120. package/package.json +62 -0
@@ -0,0 +1,10 @@
1
+ import type { NaturalLanguageChunk } from "./natural-language-world-types.js";
2
+ export interface NaturalLanguageChunkingOptions {
3
+ readonly maximumCharacters?: number;
4
+ readonly overlapCharacters?: number;
5
+ }
6
+ /**
7
+ * 生成覆盖全文的确定性 chunk。offset 使用 JavaScript/DOM 通用的 UTF-16 code unit,
8
+ * 且绝不切开 surrogate pair。
9
+ */
10
+ export declare function chunkNaturalLanguageSource(text: string, options?: NaturalLanguageChunkingOptions): Promise<readonly NaturalLanguageChunk[]>;
@@ -0,0 +1,62 @@
1
+ import { tmwSha256Hex } from "./runtime-trace.js";
2
+ function canonicalBoundary(text, candidate) {
3
+ if (candidate > 0 && candidate < text.length
4
+ && /[\uD800-\uDBFF]/u.test(text[candidate - 1])
5
+ && /[\uDC00-\uDFFF]/u.test(text[candidate]))
6
+ return candidate - 1;
7
+ return candidate;
8
+ }
9
+ function chooseEnd(text, start, maximum) {
10
+ const hardEnd = Math.min(text.length, start + maximum);
11
+ if (hardEnd === text.length)
12
+ return text.length;
13
+ const minimumSoftEnd = start + Math.floor(maximum / 2);
14
+ for (const separator of ["\n\n", "\n", "。", ". ", " "]) {
15
+ const found = text.lastIndexOf(separator, hardEnd - separator.length);
16
+ if (found >= minimumSoftEnd)
17
+ return canonicalBoundary(text, found + separator.length);
18
+ }
19
+ return canonicalBoundary(text, hardEnd);
20
+ }
21
+ /**
22
+ * 生成覆盖全文的确定性 chunk。offset 使用 JavaScript/DOM 通用的 UTF-16 code unit,
23
+ * 且绝不切开 surrogate pair。
24
+ */
25
+ export async function chunkNaturalLanguageSource(text, options = {}) {
26
+ if (typeof text !== "string" || text.length === 0)
27
+ throw new Error("natural_language_source_empty");
28
+ const maximum = options.maximumCharacters ?? 6_000;
29
+ const overlap = options.overlapCharacters ?? 400;
30
+ if (!Number.isSafeInteger(maximum) || maximum < 256)
31
+ throw new Error("natural_language_chunk_maximum_invalid");
32
+ if (!Number.isSafeInteger(overlap) || overlap < 0 || overlap >= maximum / 2) {
33
+ throw new Error("natural_language_chunk_overlap_invalid");
34
+ }
35
+ const chunks = [];
36
+ let start = 0;
37
+ while (start < text.length) {
38
+ const end = chooseEnd(text, start, maximum);
39
+ if (end <= start)
40
+ throw new Error("natural_language_chunk_no_progress");
41
+ const chunkText = text.slice(start, end);
42
+ chunks.push(Object.freeze({
43
+ index: chunks.length,
44
+ startOffset: start,
45
+ endOffset: end,
46
+ text: chunkText,
47
+ sha256: await tmwSha256Hex(chunkText),
48
+ }));
49
+ if (end === text.length)
50
+ break;
51
+ start = canonicalBoundary(text, Math.max(start + 1, end - overlap));
52
+ }
53
+ if (chunks[0]?.startOffset !== 0 || chunks.at(-1)?.endOffset !== text.length) {
54
+ throw new Error("natural_language_chunk_coverage_incomplete");
55
+ }
56
+ for (let index = 1; index < chunks.length; index += 1) {
57
+ if (chunks[index].startOffset > chunks[index - 1].endOffset) {
58
+ throw new Error("natural_language_chunk_coverage_gap");
59
+ }
60
+ }
61
+ return Object.freeze(chunks);
62
+ }
@@ -0,0 +1,14 @@
1
+ import { type NaturalLanguageChunkingOptions } from "./natural-language-chunking.js";
2
+ import { type TypedWorldAuthorityPort, type WorldFactExtractionPort, type WorldOperations } from "./natural-language-world-types.js";
3
+ export * from "./natural-language-world-types.js";
4
+ export { chunkNaturalLanguageSource } from "./natural-language-chunking.js";
5
+ export type { NaturalLanguageChunkingOptions } from "./natural-language-chunking.js";
6
+ export { decodeWorldFactExtractionResult } from "./natural-language-structured-decode.js";
7
+ export interface NaturalLanguageWorldOperationsOptions {
8
+ readonly authority: TypedWorldAuthorityPort;
9
+ readonly extractor: WorldFactExtractionPort;
10
+ readonly chunking?: NaturalLanguageChunkingOptions;
11
+ readonly maximumConcurrentExtractions?: number;
12
+ readonly clock?: () => number;
13
+ }
14
+ export declare function createNaturalLanguageWorldOperations(options: NaturalLanguageWorldOperationsOptions): WorldOperations;
@@ -0,0 +1,128 @@
1
+ import { canonicalTmwJson, requireTmwIdentifier, requireTmwSha256, tmwSha256Hex } from "./runtime-trace.js";
2
+ import { chunkNaturalLanguageSource } from "./natural-language-chunking.js";
3
+ import { decodeWorldFactExtractionResult } from "./natural-language-structured-decode.js";
4
+ import { WORLD_FACT_EXTRACTION_REQUEST_SCHEMA, WORLD_FACT_EXTRACTION_RESULT_SCHEMA, } from "./natural-language-world-types.js";
5
+ export * from "./natural-language-world-types.js";
6
+ export { chunkNaturalLanguageSource } from "./natural-language-chunking.js";
7
+ export { decodeWorldFactExtractionResult } from "./natural-language-structured-decode.js";
8
+ function canonicalText(value, code, maximum) {
9
+ if (typeof value !== "string" || value.length === 0 || value.length > maximum || value.trim() !== value || value.normalize("NFC") !== value)
10
+ throw new Error(code);
11
+ return value;
12
+ }
13
+ function sourceText(value) {
14
+ if (typeof value !== "string" || value.length === 0 || value.length > 10_000_000 || value.normalize("NFC") !== value || value.includes("\0"))
15
+ throw new Error("natural_language_source_invalid");
16
+ return value;
17
+ }
18
+ async function factIdentity(scopeId, fact) {
19
+ return tmwSha256Hex(canonicalTmwJson({ scopeId, kind: fact.kind, subject: fact.subject, predicate: fact.predicate, object: fact.object, qualifiers: fact.qualifiers }));
20
+ }
21
+ function orderProvenance(values) {
22
+ const unique = new Map(values.map((value) => [canonicalTmwJson(value), value]));
23
+ return Object.freeze([...unique.values()].sort((left, right) => left.startOffset - right.startOffset || left.endOffset - right.endOffset || left.chunkIndex - right.chunkIndex));
24
+ }
25
+ function renderedObject(fact) {
26
+ if (fact.object.type === "entity")
27
+ return fact.object.value.label;
28
+ if (fact.object.type === "json")
29
+ return canonicalTmwJson(fact.object.value);
30
+ return String(fact.object.value);
31
+ }
32
+ async function extractDocument(source, sourceSha256, extractor, chunking, maximumConcurrentExtractions) {
33
+ const chunks = await chunkNaturalLanguageSource(source.text, chunking);
34
+ const extractedByChunk = new Array(chunks.length);
35
+ const concurrency = Math.min(chunks.length, maximumConcurrentExtractions ?? 4);
36
+ let cursor = 0;
37
+ await Promise.all(Array.from({ length: concurrency }, async () => {
38
+ while (cursor < chunks.length) {
39
+ const index = cursor;
40
+ cursor += 1;
41
+ const chunk = chunks[index];
42
+ extractedByChunk[index] = { chunk, facts: decodeWorldFactExtractionResult(await extractor.extract(Object.freeze({
43
+ schema: WORLD_FACT_EXTRACTION_REQUEST_SCHEMA,
44
+ source: Object.freeze({ scopeId: source.scopeId, sourceId: source.sourceId, sourceRevision: source.sourceRevision, sourceSha256 }),
45
+ chunk, outputSchema: WORLD_FACT_EXTRACTION_RESULT_SCHEMA,
46
+ })), chunk) };
47
+ }
48
+ }));
49
+ const byId = new Map();
50
+ for (const { chunk, facts } of extractedByChunk)
51
+ for (const candidate of facts) {
52
+ const core = Object.freeze({ kind: candidate.kind, subject: candidate.subject, predicate: candidate.predicate, object: candidate.object, qualifiers: candidate.qualifiers });
53
+ const factId = await factIdentity(source.scopeId, core);
54
+ const provenance = Object.freeze({
55
+ sourceId: source.sourceId, sourceRevision: source.sourceRevision, sourceSha256,
56
+ chunkIndex: chunk.index, chunkSha256: chunk.sha256,
57
+ startOffset: chunk.startOffset + candidate.evidence.startOffset,
58
+ endOffset: chunk.startOffset + candidate.evidence.endOffset, quote: candidate.evidence.quote,
59
+ });
60
+ const previous = byId.get(factId);
61
+ byId.set(factId, Object.freeze({ factId, scopeId: source.scopeId, ...core,
62
+ confidence: Math.max(previous?.confidence ?? 0, candidate.confidence),
63
+ provenance: orderProvenance([...(previous?.provenance ?? []), provenance]),
64
+ }));
65
+ }
66
+ return Object.freeze({ chunks: chunks.length, facts: Object.freeze([...byId.values()].sort((a, b) => a.factId.localeCompare(b.factId))) });
67
+ }
68
+ const graphEntityId = (scopeId, sourceEntityId) => `${scopeId}:${sourceEntityId}`;
69
+ function buildLadybugBatch(input) {
70
+ const entities = new Map();
71
+ const ensureEntity = (id, label) => {
72
+ const graphId = graphEntityId(input.source.scopeId, id);
73
+ if (!entities.has(graphId))
74
+ entities.set(graphId, { id: graphId, label, facts: [] });
75
+ return entities.get(graphId);
76
+ };
77
+ const relations = [];
78
+ for (const fact of input.facts) {
79
+ ensureEntity(fact.subject.id, fact.subject.label).facts.push(fact);
80
+ if (fact.kind === "relation" && fact.object.type === "entity") {
81
+ const destination = ensureEntity(fact.object.value.id, fact.object.value.label);
82
+ relations.push(Object.freeze({ src: graphEntityId(input.source.scopeId, fact.subject.id), dst: destination.id, kind: fact.predicate, props: Object.freeze({ scopeId: fact.scopeId, factId: fact.factId, qualifiers: fact.qualifiers, confidence: fact.confidence, provenance: fact.provenance }) }));
83
+ }
84
+ }
85
+ return Object.freeze({
86
+ schemaVersion: 1, batchId: input.batchId,
87
+ source: Object.freeze({ sourceId: input.source.sourceId, ...(input.source.sourcePath === undefined ? {} : { sourcePath: input.source.sourcePath }), contentSha256: input.sourceSha256, extractedAtMs: input.extractedAtMs, extractor: Object.freeze({ harness: input.extractor.harness, ...(input.extractor.model === undefined ? {} : { model: input.extractor.model }), contractVersion: input.extractor.contractVersion }) }),
88
+ entities: Object.freeze([...entities.values()].sort((a, b) => a.id.localeCompare(b.id)).map((entity) => Object.freeze({ id: entity.id, kind: "world_entity", scopeId: input.source.scopeId, text: [entity.label, ...entity.facts.map((fact) => `${fact.predicate}: ${renderedObject(fact)}`)].join("\n"), props: Object.freeze({ scopeId: input.source.scopeId, sourceEntityId: entity.id.slice(input.source.scopeId.length + 1), label: entity.label, facts: entity.facts }) }))),
89
+ relations: Object.freeze(relations.sort((a, b) => `${a.src}\0${a.dst}\0${a.kind}`.localeCompare(`${b.src}\0${b.dst}\0${b.kind}`))),
90
+ });
91
+ }
92
+ export function createNaturalLanguageWorldOperations(options) {
93
+ canonicalText(options.extractor.harness, "world_fact_extractor_harness_invalid", 512);
94
+ canonicalText(options.extractor.contractVersion, "world_fact_extractor_contract_invalid", 512);
95
+ if (options.extractor.model !== undefined)
96
+ canonicalText(options.extractor.model, "world_fact_extractor_model_invalid", 512);
97
+ if (options.maximumConcurrentExtractions !== undefined && (!Number.isSafeInteger(options.maximumConcurrentExtractions) || options.maximumConcurrentExtractions < 1 || options.maximumConcurrentExtractions > 16))
98
+ throw new Error("world_fact_extraction_concurrency_invalid");
99
+ return Object.freeze({
100
+ async commit(sourceInput) {
101
+ const source = Object.freeze({ scopeId: requireTmwIdentifier(sourceInput.scopeId, "world_fact_scope_id"), sourceId: requireTmwIdentifier(sourceInput.sourceId, "world_fact_source_id"), sourceRevision: requireTmwIdentifier(sourceInput.sourceRevision, "world_fact_source_revision"), text: sourceText(sourceInput.text), ...(sourceInput.sourcePath === undefined ? {} : { sourcePath: canonicalText(sourceInput.sourcePath, "world_fact_source_path_invalid", 4_096) }), mediaType: sourceInput.mediaType ?? "text/plain" });
102
+ if (source.mediaType !== "text/plain" && source.mediaType !== "text/markdown")
103
+ throw new Error("natural_language_media_type_invalid");
104
+ const sourceSha256 = requireTmwSha256(await tmwSha256Hex(source.text), "world_fact_source_sha256");
105
+ const extracted = await extractDocument(source, sourceSha256, options.extractor, options.chunking, options.maximumConcurrentExtractions);
106
+ const batchId = await tmwSha256Hex(canonicalTmwJson({ schemaVersion: 1, scopeId: source.scopeId, sourceId: source.sourceId, sourceRevision: source.sourceRevision, sourceSha256, harness: options.extractor.harness, model: options.extractor.model ?? null, contractVersion: options.extractor.contractVersion }));
107
+ const extractedAtMs = (options.clock ?? Date.now)();
108
+ if (!Number.isSafeInteger(extractedAtMs) || extractedAtMs < 0)
109
+ throw new Error("world_fact_extracted_at_invalid");
110
+ const result = await options.authority.commit(buildLadybugBatch({ source, sourceSha256, extractedAtMs, extractor: options.extractor, batchId, facts: extracted.facts }));
111
+ return Object.freeze({ status: result.status, version: result.version, batchId, sourceSha256, chunkCount: extracted.chunks, factCount: extracted.facts.length });
112
+ },
113
+ async read(input) {
114
+ return options.authority.read({ scopeId: requireTmwIdentifier(input.scopeId, "world_fact_scope_id"), factId: requireTmwSha256(input.factId, "world_fact_id") });
115
+ },
116
+ async resolve(input) {
117
+ const limit = input.limit ?? 8;
118
+ const minimumRelevance = input.minimumRelevance ?? 0.55;
119
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
120
+ throw new Error("world_fact_recall_limit_invalid");
121
+ if (!Number.isFinite(minimumRelevance) || minimumRelevance < 0 || minimumRelevance > 1)
122
+ throw new Error("world_fact_recall_minimum_relevance_invalid");
123
+ const scopeId = requireTmwIdentifier(input.scopeId, "world_fact_scope_id");
124
+ const hits = await options.authority.resolve({ scopeId, query: canonicalText(input.query, "world_fact_query_invalid", 8_192), mode: "semantic", limit, minimumRelevance });
125
+ return Object.freeze(hits.filter((hit) => hit.fact.scopeId === scopeId && hit.relevance >= minimumRelevance && hit.channels.includes("semantic")).sort((left, right) => right.relevance - left.relevance).slice(0, limit));
126
+ },
127
+ });
128
+ }
@@ -0,0 +1,2 @@
1
+ import { type ExtractedWorldFact, type NaturalLanguageChunk } from "./natural-language-world-types.js";
2
+ export declare function decodeWorldFactExtractionResult(value: unknown, chunk: NaturalLanguageChunk): readonly ExtractedWorldFact[];
@@ -0,0 +1,69 @@
1
+ import { canonicalTmwJsonValue, requireTmwIdentifier } from "./runtime-trace.js";
2
+ import { WORLD_FACT_EXTRACTION_RESULT_SCHEMA } from "./natural-language-world-types.js";
3
+ function record(value, code) {
4
+ if (typeof value !== "object" || value === null || Array.isArray(value) || (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null))
5
+ throw new Error(code);
6
+ return value;
7
+ }
8
+ function exactKeys(value, keys, code) {
9
+ const actual = Object.keys(value).sort();
10
+ const expected = [...keys].sort();
11
+ if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index]))
12
+ throw new Error(code);
13
+ }
14
+ function text(value, code, maximum = 4_096) {
15
+ if (typeof value !== "string" || value.length === 0 || value.length > maximum || value.trim() !== value || value.normalize("NFC") !== value)
16
+ throw new Error(code);
17
+ return value;
18
+ }
19
+ function decodeEntity(value, code) {
20
+ const input = record(value, code);
21
+ exactKeys(input, ["id", "label"], code);
22
+ return Object.freeze({ id: requireTmwIdentifier(text(input.id, code), code), label: text(input.label, code) });
23
+ }
24
+ function decodeValue(value) {
25
+ const input = record(value, "world_fact_object_invalid");
26
+ exactKeys(input, ["type", "value"], "world_fact_object_shape_invalid");
27
+ switch (input.type) {
28
+ case "string": return Object.freeze({ type: "string", value: text(input.value, "world_fact_string_invalid", 32_768) });
29
+ case "number":
30
+ if (typeof input.value !== "number" || !Number.isFinite(input.value))
31
+ throw new Error("world_fact_number_invalid");
32
+ return Object.freeze({ type: "number", value: Object.is(input.value, -0) ? 0 : input.value });
33
+ case "boolean":
34
+ if (typeof input.value !== "boolean")
35
+ throw new Error("world_fact_boolean_invalid");
36
+ return Object.freeze({ type: "boolean", value: input.value });
37
+ case "entity": return Object.freeze({ type: "entity", value: decodeEntity(input.value, "world_fact_entity_object_invalid") });
38
+ case "json": return Object.freeze({ type: "json", value: canonicalTmwJsonValue(input.value, "world_fact_json") });
39
+ default: throw new Error("world_fact_object_type_invalid");
40
+ }
41
+ }
42
+ export function decodeWorldFactExtractionResult(value, chunk) {
43
+ const input = record(value, "world_fact_extraction_result_invalid");
44
+ exactKeys(input, ["schema", "facts"], "world_fact_extraction_result_shape_invalid");
45
+ if (input.schema !== WORLD_FACT_EXTRACTION_RESULT_SCHEMA || !Array.isArray(input.facts))
46
+ throw new Error("world_fact_extraction_result_schema_invalid");
47
+ return Object.freeze(input.facts.map((item, index) => {
48
+ const fact = record(item, `world_fact_${index}_invalid`);
49
+ exactKeys(fact, ["kind", "subject", "predicate", "object", "qualifiers", "confidence", "evidence"], `world_fact_${index}_shape_invalid`);
50
+ if (fact.kind !== "entity" && fact.kind !== "attribute" && fact.kind !== "relation" && fact.kind !== "event")
51
+ throw new Error(`world_fact_${index}_kind_invalid`);
52
+ if (typeof fact.confidence !== "number" || !Number.isFinite(fact.confidence) || fact.confidence < 0 || fact.confidence > 1)
53
+ throw new Error(`world_fact_${index}_confidence_invalid`);
54
+ const evidence = record(fact.evidence, `world_fact_${index}_evidence_invalid`);
55
+ exactKeys(evidence, ["startOffset", "endOffset", "quote"], `world_fact_${index}_evidence_shape_invalid`);
56
+ if (!Number.isSafeInteger(evidence.startOffset) || !Number.isSafeInteger(evidence.endOffset))
57
+ throw new Error(`world_fact_${index}_evidence_offset_invalid`);
58
+ const startOffset = evidence.startOffset;
59
+ const endOffset = evidence.endOffset;
60
+ if (startOffset < 0 || endOffset <= startOffset || endOffset > chunk.text.length)
61
+ throw new Error(`world_fact_${index}_evidence_range_invalid`);
62
+ if (typeof evidence.quote !== "string" || chunk.text.slice(startOffset, endOffset) !== evidence.quote)
63
+ throw new Error(`world_fact_${index}_evidence_quote_mismatch`);
64
+ const qualifiersValue = canonicalTmwJsonValue(fact.qualifiers, `world_fact_${index}_qualifiers`);
65
+ if (typeof qualifiersValue !== "object" || qualifiersValue === null || Array.isArray(qualifiersValue))
66
+ throw new Error(`world_fact_${index}_qualifiers_invalid`);
67
+ return Object.freeze({ kind: fact.kind, subject: decodeEntity(fact.subject, `world_fact_${index}_subject_invalid`), predicate: requireTmwIdentifier(text(fact.predicate, `world_fact_${index}_predicate_invalid`), `world_fact_${index}_predicate`), object: decodeValue(fact.object), qualifiers: qualifiersValue, confidence: fact.confidence, evidence: Object.freeze({ startOffset, endOffset, quote: evidence.quote }) });
68
+ }));
69
+ }
@@ -0,0 +1,142 @@
1
+ import type { TmwJsonValue } from "./runtime-contract.js";
2
+ import type { LadybugExtractionBatch } from "@world-engines/protocol-ts";
3
+ export type { LadybugExtractionBatch } from "@world-engines/protocol-ts";
4
+ export declare const WORLD_FACT_EXTRACTION_REQUEST_SCHEMA: "tmw-world-fact-extraction-request.v1";
5
+ export declare const WORLD_FACT_EXTRACTION_RESULT_SCHEMA: "tmw-world-fact-extraction-result.v1";
6
+ export type WorldFactKind = "entity" | "attribute" | "relation" | "event";
7
+ export type WorldFactValue = Readonly<{
8
+ type: "string";
9
+ value: string;
10
+ }> | Readonly<{
11
+ type: "number";
12
+ value: number;
13
+ }> | Readonly<{
14
+ type: "boolean";
15
+ value: boolean;
16
+ }> | Readonly<{
17
+ type: "entity";
18
+ value: Readonly<{
19
+ id: string;
20
+ label: string;
21
+ }>;
22
+ }> | Readonly<{
23
+ type: "json";
24
+ value: TmwJsonValue;
25
+ }>;
26
+ export interface NaturalLanguageSource {
27
+ readonly scopeId: string;
28
+ readonly sourceId: string;
29
+ readonly sourcePath?: string;
30
+ readonly sourceRevision: string;
31
+ readonly text: string;
32
+ readonly mediaType?: "text/plain" | "text/markdown";
33
+ }
34
+ export interface NaturalLanguageChunk {
35
+ readonly index: number;
36
+ readonly startOffset: number;
37
+ readonly endOffset: number;
38
+ readonly text: string;
39
+ readonly sha256: string;
40
+ }
41
+ export interface ExtractedWorldFact {
42
+ readonly kind: WorldFactKind;
43
+ readonly subject: Readonly<{
44
+ id: string;
45
+ label: string;
46
+ }>;
47
+ readonly predicate: string;
48
+ readonly object: WorldFactValue;
49
+ readonly qualifiers: Readonly<Record<string, TmwJsonValue>>;
50
+ readonly confidence: number;
51
+ readonly evidence: Readonly<{
52
+ startOffset: number;
53
+ endOffset: number;
54
+ quote: string;
55
+ }>;
56
+ }
57
+ export interface WorldFactProvenance {
58
+ readonly sourceId: string;
59
+ readonly sourceRevision: string;
60
+ readonly sourceSha256: string;
61
+ readonly chunkIndex: number;
62
+ readonly chunkSha256: string;
63
+ readonly startOffset: number;
64
+ readonly endOffset: number;
65
+ readonly quote: string;
66
+ }
67
+ export interface WorldFactRecord {
68
+ readonly factId: string;
69
+ readonly scopeId: string;
70
+ readonly kind: WorldFactKind;
71
+ readonly subject: Readonly<{
72
+ id: string;
73
+ label: string;
74
+ }>;
75
+ readonly predicate: string;
76
+ readonly object: WorldFactValue;
77
+ readonly qualifiers: Readonly<Record<string, TmwJsonValue>>;
78
+ readonly confidence: number;
79
+ readonly provenance: readonly WorldFactProvenance[];
80
+ }
81
+ export interface WorldFactExtractionRequest {
82
+ readonly schema: typeof WORLD_FACT_EXTRACTION_REQUEST_SCHEMA;
83
+ readonly source: Readonly<{
84
+ scopeId: string;
85
+ sourceId: string;
86
+ sourceRevision: string;
87
+ sourceSha256: string;
88
+ }>;
89
+ readonly chunk: NaturalLanguageChunk;
90
+ readonly outputSchema: typeof WORLD_FACT_EXTRACTION_RESULT_SCHEMA;
91
+ }
92
+ export interface WorldFactExtractionPort {
93
+ readonly harness: string;
94
+ readonly model?: string;
95
+ readonly contractVersion: string;
96
+ /** 必须调用真实用户 harness/LLM;返回值会按 closed schema 严格解码。 */
97
+ extract(request: WorldFactExtractionRequest): Promise<unknown>;
98
+ }
99
+ export interface WorldFactCommitReceipt {
100
+ readonly status: "committed" | "already_committed";
101
+ readonly version: string;
102
+ readonly batchId: string;
103
+ readonly sourceSha256: string;
104
+ readonly chunkCount: number;
105
+ readonly factCount: number;
106
+ }
107
+ export interface WorldFactRecallHit {
108
+ readonly fact: WorldFactRecord;
109
+ readonly relevance: number;
110
+ readonly channels: readonly ("keyword" | "semantic")[];
111
+ }
112
+ /** 只能由 ProjectHost 在 writer lease 内以 typedworld_apply 实现;Ladybug projection/cache 不是 authority。 */
113
+ export interface TypedWorldAuthorityPort {
114
+ commit(batch: LadybugExtractionBatch): Promise<Readonly<{
115
+ status: "committed" | "already_committed";
116
+ version: string;
117
+ }>>;
118
+ read(input: Readonly<{
119
+ scopeId: string;
120
+ factId: string;
121
+ }>): Promise<WorldFactRecord | null>;
122
+ resolve(input: Readonly<{
123
+ scopeId: string;
124
+ query: string;
125
+ mode: "semantic";
126
+ limit: number;
127
+ minimumRelevance: number;
128
+ }>): Promise<readonly WorldFactRecallHit[]>;
129
+ }
130
+ export interface WorldOperations {
131
+ commit(source: NaturalLanguageSource): Promise<WorldFactCommitReceipt>;
132
+ read(input: Readonly<{
133
+ scopeId: string;
134
+ factId: string;
135
+ }>): Promise<WorldFactRecord | null>;
136
+ resolve(input: Readonly<{
137
+ scopeId: string;
138
+ query: string;
139
+ limit?: number;
140
+ minimumRelevance?: number;
141
+ }>): Promise<readonly WorldFactRecallHit[]>;
142
+ }
@@ -0,0 +1,2 @@
1
+ export const WORLD_FACT_EXTRACTION_REQUEST_SCHEMA = "tmw-world-fact-extraction-request.v1";
2
+ export const WORLD_FACT_EXTRACTION_RESULT_SCHEMA = "tmw-world-fact-extraction-result.v1";
@@ -0,0 +1,135 @@
1
+ import { type CompileTargetProfile } from "./compile-target-profile.js";
2
+ import { type CompilerStageCache } from "./compiler-stage-cache.js";
3
+ import { type CompilerStage, type CompilerStageRegistry } from "./compiler-stage-registry.js";
4
+ import { type TmwDiagnostic } from "./diagnostics.js";
5
+ import { type TriggerConditionNodeV3, type TriggerDocumentV3, type TriggerEdgeV3, type TriggerEffectNodeV3, type TriggerEventNodeV3, type TriggerPresentationNodeV3 } from "./trigger-document-v3.js";
6
+ import { type PlaneGenerationV1 } from "@world-engines/spatial-authoring/plane-generation";
7
+ import { type ProceduralWorldV1 } from "@world-engines/spatial-authoring/procedural-city";
8
+ import { type RoadGenerationV1 } from "@world-engines/spatial-authoring/road-generation";
9
+ import { type SpatialTemplateConfigurationV1 } from "@world-engines/spatial-authoring/spatial-templates";
10
+ export declare const NEUTRAL_SOURCE_COMPILER_RECEIPT_SCHEMA_VERSION: 1;
11
+ export declare const TMW_TRIGGER_SEMANTICS_STAGE_VERSION: "3";
12
+ export declare const NEUTRAL_SPATIAL_WORLD_STAGE_VERSION: "1";
13
+ export declare const NEUTRAL_SPATIAL_WORLD_STAGE_ID: "neutral.spatial-world";
14
+ export declare const CURRENT_NEUTRAL_COMPILER_STAGE_VERSIONS: readonly (Readonly<{
15
+ stage_id: "neutral.metadata";
16
+ stage_version: "1";
17
+ }> | Readonly<{
18
+ stage_id: "neutral.logical-graph";
19
+ stage_version: "1";
20
+ }> | Readonly<{
21
+ stage_id: "tmw.trigger-semantics";
22
+ stage_version: "3";
23
+ }> | Readonly<{
24
+ stage_id: "neutral.layout";
25
+ stage_version: "1";
26
+ }> | Readonly<{
27
+ stage_id: "neutral.view-project";
28
+ stage_version: "1";
29
+ }> | Readonly<{
30
+ stage_id: "neutral.resource-refs";
31
+ stage_version: "1";
32
+ }> | Readonly<{
33
+ stage_id: "neutral.prompt-retrieval";
34
+ stage_version: "1";
35
+ }>)[];
36
+ /** 空间发布 profile 必须显式绑定新 stage,旧七阶段 profile 保持可重放。 */
37
+ export declare const SPATIAL_NEUTRAL_COMPILER_STAGE_VERSIONS: readonly (Readonly<{
38
+ stage_id: "neutral.metadata";
39
+ stage_version: "1";
40
+ }> | Readonly<{
41
+ stage_id: "neutral.logical-graph";
42
+ stage_version: "1";
43
+ }> | Readonly<{
44
+ stage_id: "tmw.trigger-semantics";
45
+ stage_version: "3";
46
+ }> | Readonly<{
47
+ stage_id: "neutral.layout";
48
+ stage_version: "1";
49
+ }> | Readonly<{
50
+ stage_id: "neutral.view-project";
51
+ stage_version: "1";
52
+ }> | Readonly<{
53
+ stage_id: "neutral.resource-refs";
54
+ stage_version: "1";
55
+ }> | Readonly<{
56
+ stage_id: "neutral.prompt-retrieval";
57
+ stage_version: "1";
58
+ }> | Readonly<{
59
+ stage_id: "neutral.spatial-world";
60
+ stage_version: "1";
61
+ }>)[];
62
+ export interface NeutralSourceDerivedObject {
63
+ readonly stage_id: string;
64
+ readonly stage_version: string;
65
+ readonly media_type: "application/octet-stream";
66
+ readonly bytes: Uint8Array;
67
+ readonly byte_length: number;
68
+ readonly sha256: string;
69
+ }
70
+ export interface NeutralSourceCompilerStageReceipt {
71
+ readonly stage_id: string;
72
+ readonly stage_version: string;
73
+ readonly cache_key: string;
74
+ readonly content_cache_key: string;
75
+ readonly input_sections: readonly Readonly<{
76
+ section_key: string;
77
+ sha256: string;
78
+ }>[];
79
+ readonly dependency_outputs: readonly Readonly<{
80
+ stage_id: string;
81
+ sha256: string;
82
+ }>[];
83
+ readonly output_byte_length: number;
84
+ readonly output_sha256: string;
85
+ }
86
+ export interface NeutralSourceCompilerReceiptCore {
87
+ readonly receipt_schema_version: typeof NEUTRAL_SOURCE_COMPILER_RECEIPT_SCHEMA_VERSION;
88
+ readonly scenario_id: string;
89
+ readonly source_manifest_sha256: string;
90
+ readonly compiler_release: string;
91
+ readonly target_profile_sha256: string;
92
+ readonly stages: readonly NeutralSourceCompilerStageReceipt[];
93
+ readonly derived_objects_sha256: string;
94
+ }
95
+ export interface NeutralSourceCompilerReceipt extends NeutralSourceCompilerReceiptCore {
96
+ readonly receipt_sha256: string;
97
+ }
98
+ export type CompileNeutralScenarioSourceOutcome = {
99
+ readonly ok: true;
100
+ readonly derived_objects: readonly NeutralSourceDerivedObject[];
101
+ readonly receipt: NeutralSourceCompilerReceipt;
102
+ readonly diagnostics: readonly TmwDiagnostic[];
103
+ } | {
104
+ readonly ok: false;
105
+ readonly diagnostics: readonly TmwDiagnostic[];
106
+ };
107
+ export interface NeutralTriggerSemantics {
108
+ readonly value_graph?: import("./value-graph.js").TmwValueGraphV1;
109
+ readonly events: readonly TriggerEventNodeV3[];
110
+ readonly conditions: readonly TriggerConditionNodeV3[];
111
+ readonly effects: readonly TriggerEffectNodeV3[];
112
+ readonly presentations: readonly TriggerPresentationNodeV3[];
113
+ readonly edges: readonly TriggerEdgeV3[];
114
+ }
115
+ export interface NeutralCompiledSpatialBase {
116
+ readonly generation: PlaneGenerationV1;
117
+ readonly procedural: ProceduralWorldV1;
118
+ /** 缺席时严格保留 procedural-world-v1 的既有道路语义。 */
119
+ readonly roadGeneration?: RoadGenerationV1;
120
+ /** 仅 active template snapshot;作者 templateLibrary 不进入 Player 产物。 */
121
+ readonly templates?: SpatialTemplateConfigurationV1;
122
+ readonly baseDigest: string;
123
+ readonly controlledActorId?: string;
124
+ }
125
+ export type NeutralSpatialWorldUnsupportedReason = "topology_missing" | "topology_not_plane" | "generation_missing" | "procedural_missing";
126
+ export interface NeutralSpatialWorldUnsupported {
127
+ readonly player_programmatic_supported: false;
128
+ readonly reason: NeutralSpatialWorldUnsupportedReason;
129
+ }
130
+ export declare function createNeutralSpatialWorldCompilerStage(): CompilerStage;
131
+ export declare function neutralTriggerSemanticsFromDocument(document: TriggerDocumentV3): NeutralTriggerSemantics;
132
+ export declare function materializeTmw3TriggerDocument(value: unknown): Promise<TriggerDocumentV3>;
133
+ export declare function compileNeutralScenarioSource(input: unknown, targetProfile: CompileTargetProfile, registry: CompilerStageRegistry, cache: CompilerStageCache): Promise<CompileNeutralScenarioSourceOutcome>;
134
+ export declare function canonicalNeutralSourceCompilerReceiptBytes(receipt: NeutralSourceCompilerReceipt): Uint8Array;
135
+ export declare function buildCurrentTmw3NeutralCompilerStageRegistry(profile?: CompileTargetProfile): CompilerStageRegistry;