@the_library/public 1.0.0 → 2.0.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 (113) hide show
  1. package/README.md +201 -28
  2. package/assets/branding/pond-enterprise-logo.svg +1 -1
  3. package/dist/Book-K86JRm42.d.ts +600 -0
  4. package/dist/bookSearchService-BmFHrvsv.d.ts +300 -0
  5. package/dist/branding/index.js +1 -66
  6. package/dist/branding/index.js.map +1 -1
  7. package/dist/chunk-3XUKOVEF.js +2 -0
  8. package/dist/chunk-3XUKOVEF.js.map +1 -0
  9. package/dist/chunk-46FQHZNM.js +2 -0
  10. package/dist/chunk-46FQHZNM.js.map +1 -0
  11. package/dist/chunk-7G3BMGV2.js +2 -0
  12. package/dist/chunk-7G3BMGV2.js.map +1 -0
  13. package/dist/chunk-D4DXGA2W.js +2 -0
  14. package/dist/chunk-D4DXGA2W.js.map +1 -0
  15. package/dist/chunk-EMA2QJTW.js +2 -0
  16. package/dist/chunk-EMA2QJTW.js.map +1 -0
  17. package/dist/chunk-FN52YV7L.js +2 -0
  18. package/dist/chunk-FN52YV7L.js.map +1 -0
  19. package/dist/chunk-GWQNULP4.js +2 -0
  20. package/dist/chunk-GWQNULP4.js.map +1 -0
  21. package/dist/chunk-OELHBR4F.js +2 -0
  22. package/dist/chunk-OELHBR4F.js.map +1 -0
  23. package/dist/chunk-PV3X54EU.js +2 -0
  24. package/dist/chunk-PV3X54EU.js.map +1 -0
  25. package/dist/chunk-SD3INWZF.js +2 -0
  26. package/dist/chunk-SD3INWZF.js.map +1 -0
  27. package/dist/downloader/dl2-sw.js +1 -198
  28. package/dist/downloader/dl2-sw.js.map +1 -1
  29. package/dist/downloader/file-worker-v2.js +1 -257
  30. package/dist/downloader/file-worker-v2.js.map +1 -1
  31. package/dist/downloader/index.d.ts +18 -2
  32. package/dist/downloader/index.js +1 -537
  33. package/dist/downloader/index.js.map +1 -1
  34. package/dist/downloader/mu-worker-v2.js +1 -196
  35. package/dist/downloader/mu-worker-v2.js.map +1 -1
  36. package/dist/downloader/react.d.ts +1 -1
  37. package/dist/downloader/react.js +1 -31
  38. package/dist/downloader/react.js.map +1 -1
  39. package/dist/downloader/solid.d.ts +1 -1
  40. package/dist/downloader/solid.js +1 -18
  41. package/dist/downloader/solid.js.map +1 -1
  42. package/dist/downloader/sw.js +1 -118
  43. package/dist/downloader/sw.js.map +1 -1
  44. package/dist/downloader/vue.d.ts +1 -1
  45. package/dist/downloader/vue.js +1 -18
  46. package/dist/downloader/vue.js.map +1 -1
  47. package/dist/enriched-index-T0sDG7JR.d.ts +209 -0
  48. package/dist/global/public.global.js +68 -0
  49. package/dist/global/public.manifest.json +484 -0
  50. package/dist/level-state-DXqglpAX.d.ts +27 -0
  51. package/dist/models/astro.d.ts +4 -3
  52. package/dist/models/astro.js +1 -43
  53. package/dist/models/astro.js.map +1 -1
  54. package/dist/models/index.d.ts +449 -22
  55. package/dist/models/index.js +1 -339
  56. package/dist/models/index.js.map +1 -1
  57. package/dist/models/models.d.ts +196 -441
  58. package/dist/models/models.js +1 -45
  59. package/dist/models/patch-worker.js +1 -542
  60. package/dist/models/patch-worker.js.map +1 -1
  61. package/dist/models/react.d.ts +6 -5
  62. package/dist/models/react.js +1 -72
  63. package/dist/models/react.js.map +1 -1
  64. package/dist/models/solid.d.ts +16 -6
  65. package/dist/models/solid.js +1 -94
  66. package/dist/models/solid.js.map +1 -1
  67. package/dist/models/vue.d.ts +90 -7
  68. package/dist/models/vue.js +1 -97
  69. package/dist/models/vue.js.map +1 -1
  70. package/dist/orm-MJTHCG9E.d.ts +1003 -0
  71. package/dist/{session-vqOnyxga.d.ts → session-JudUKAV7.d.ts} +76 -74
  72. package/dist/{state-BTsp-E4v.d.ts → state-CkYavOSt.d.ts} +16 -0
  73. package/dist/{types-Dn0EFMO_.d.ts → types-B-IX3HBn.d.ts} +94 -21
  74. package/dist/{types-Xb8Ta9tZ.d.ts → types-Blyx2A7F.d.ts} +10 -36
  75. package/dist/web3/auth.d.ts +89 -0
  76. package/dist/web3/auth.js +13 -0
  77. package/dist/web3/auth.js.map +1 -0
  78. package/dist/web3/index.d.ts +1913 -126
  79. package/dist/web3/index.js +1 -1019
  80. package/dist/web3/index.js.map +1 -1
  81. package/dist/web3/network.d.ts +6 -0
  82. package/dist/web3/network.js +2 -0
  83. package/dist/web3/network.js.map +1 -0
  84. package/dist/web3/registry.d.ts +34 -9
  85. package/dist/web3/registry.js +1 -22
  86. package/dist/web3/vue.d.ts +31 -14
  87. package/dist/web3/vue.js +1 -390
  88. package/dist/web3/vue.js.map +1 -1
  89. package/package.json +23 -2
  90. package/dist/chunk-2HFOWE5R.js +0 -296
  91. package/dist/chunk-2HFOWE5R.js.map +0 -1
  92. package/dist/chunk-3L6LH2XK.js +0 -465
  93. package/dist/chunk-3L6LH2XK.js.map +0 -1
  94. package/dist/chunk-4CWVFPBN.js +0 -28
  95. package/dist/chunk-4CWVFPBN.js.map +0 -1
  96. package/dist/chunk-AGHPATVL.js +0 -65
  97. package/dist/chunk-AGHPATVL.js.map +0 -1
  98. package/dist/chunk-JDUYLUDJ.js +0 -4835
  99. package/dist/chunk-JDUYLUDJ.js.map +0 -1
  100. package/dist/chunk-OEZK7IX7.js +0 -77
  101. package/dist/chunk-OEZK7IX7.js.map +0 -1
  102. package/dist/chunk-PUYDAUCI.js +0 -2873
  103. package/dist/chunk-PUYDAUCI.js.map +0 -1
  104. package/dist/chunk-WHWMTS7D.js +0 -99
  105. package/dist/chunk-WHWMTS7D.js.map +0 -1
  106. package/dist/chunk-Y7RS6RTM.js +0 -342
  107. package/dist/chunk-Y7RS6RTM.js.map +0 -1
  108. package/dist/chunk-ZEZGI2TP.js +0 -197
  109. package/dist/chunk-ZEZGI2TP.js.map +0 -1
  110. package/dist/core-dao-core-logo-VDT2I5IW.svg +0 -33
  111. package/dist/level-state-J3pj64Tr.d.ts +0 -15
  112. package/dist/models/models_v2.global.js +0 -1
  113. package/dist/orm-BvkX0aBT.d.ts +0 -507
@@ -0,0 +1,1003 @@
1
+ /**
2
+ * Local-only, non-EVM operations (analytics, local state).
3
+ * EVM-bound mutations use `PatchOperation` from `@the_library/db_schemas`
4
+ * (re-exported in `binary.ts`) — do not add EVM operation variants here.
5
+ */
6
+ declare enum ActionTypes {
7
+ Visit = 0,
8
+ VisitPart = 1,
9
+ Download = 2,
10
+ Rate = 3,
11
+ RatePart = 4,
12
+ Share = 5,
13
+ SharePart = 6
14
+ }
15
+ declare enum WorkerCommands {
16
+ Init = "init",// Initial load: fetch sidecars + local patches
17
+ SavePatches = "savePatches",
18
+ GetRecord = "getRecord",// LRU on-demand re-hydration (SPEC §2.5)
19
+ LoadLanguage = "loadLanguage"
20
+ }
21
+ declare enum Rating {
22
+ None = 0,
23
+ New = 1,
24
+ Keep = 2,
25
+ Trash = 3,
26
+ Shared = 4
27
+ }
28
+ declare enum WorkerEvent {
29
+ WorkerReady = "workerready",
30
+ WorkerLoadingError = "workerLoadingError",
31
+ DownloadStarted = "downloadStarted",
32
+ DownloadFinished = "downloadFinished",
33
+ DownloadError = "downloadError",
34
+ LevelUpdated = "levelUpdated"
35
+ }
36
+ declare enum DownloadState {
37
+ Unknown = 0,
38
+ Pending = 1,
39
+ InProgress = 2,
40
+ Done = 3,
41
+ Error = 4
42
+ }
43
+ /** Sidecar type byte in the DPM1 wire header (SPEC §4.1). */
44
+ declare enum SidecarType {
45
+ Slim = 0,
46
+ Extended = 1,
47
+ Provenance = 2
48
+ }
49
+
50
+ declare enum PatchOperation {
51
+ EditPropertyString = 1,
52
+ EditPropertyNumber = 2,
53
+ EditInstanceFieldString = 3,
54
+ EditInstanceFieldNumber = 4,
55
+ EditRelation = 5,
56
+ CreateRecord = 7,
57
+ AddInstance = 8,
58
+ MergeProposal = 9,
59
+ DeleteBridge = 10
60
+ }
61
+ declare enum PatchAction {
62
+ Remove = 0,
63
+ Add = 1
64
+ }
65
+ interface BasePatch {
66
+ operation: PatchOperation;
67
+ objectType: number;
68
+ objectId: bigint;
69
+ langId: number;
70
+ }
71
+ interface EditPropertyNumberObj extends BasePatch {
72
+ operation: PatchOperation.EditPropertyNumber;
73
+ propertyId: number;
74
+ value: number;
75
+ /**
76
+ * 2-bit origin code: 0=unset, 1=AI, 2=human, 3=consensus (see orm.ts's
77
+ * Config.defaultProvenance). Optional because a patch decoded from a
78
+ * pre-provenance on-chain word (WIRE_FORMAT_LEGACY, or any WIDE-format word
79
+ * written before this field existed) has no genuine value to report —
80
+ * those decode with `provenance` absent, not fabricated as 0. A WIDE-format
81
+ * word encoded by the current packPatch always carries an explicit value
82
+ * (0 if the author didn't set one).
83
+ */
84
+ provenance?: number;
85
+ }
86
+ interface EditPropertyStringObj extends BasePatch {
87
+ operation: PatchOperation.EditPropertyString;
88
+ propertyId: number;
89
+ value: string;
90
+ /** See EditPropertyNumberObj.provenance. */
91
+ provenance?: number;
92
+ }
93
+ interface EditInstanceFieldNumberObj extends BasePatch {
94
+ operation: PatchOperation.EditInstanceFieldNumber;
95
+ instanceIndex: number;
96
+ propertyId: number;
97
+ value: number;
98
+ }
99
+ interface EditInstanceFieldStringObj extends BasePatch {
100
+ operation: PatchOperation.EditInstanceFieldString;
101
+ instanceIndex: number;
102
+ propertyId: number;
103
+ value: string;
104
+ }
105
+ interface EditRelationObj extends BasePatch {
106
+ operation: PatchOperation.EditRelation;
107
+ relationId: number;
108
+ action: PatchAction;
109
+ targetId: bigint;
110
+ }
111
+ interface CreateRecordObj extends BasePatch {
112
+ operation: PatchOperation.CreateRecord;
113
+ objectType: number;
114
+ objectId: bigint;
115
+ langId: number;
116
+ }
117
+ interface AddInstanceObj extends BasePatch {
118
+ operation: PatchOperation.AddInstance;
119
+ objectType: number;
120
+ objectId: bigint;
121
+ langId: number;
122
+ instanceIndex: number;
123
+ }
124
+ interface MergeProposalObj extends BasePatch {
125
+ operation: PatchOperation.MergeProposal;
126
+ original: string;
127
+ destSystem: string;
128
+ relationType: 'equivalentWith' | 'childOf' | 'parentOf';
129
+ targetId: number | string;
130
+ confidence: number;
131
+ }
132
+ interface DeleteBridgeObj extends BasePatch {
133
+ operation: PatchOperation.DeleteBridge;
134
+ original: string;
135
+ destinationSystem: string;
136
+ bridgeTypeToDelete: 'equivalentWith' | 'childOf' | 'parentOf';
137
+ targetTagId: number | bigint | string;
138
+ }
139
+ type AnyPatch = EditPropertyNumberObj | EditPropertyStringObj | EditInstanceFieldNumberObj | EditInstanceFieldStringObj | EditRelationObj | CreateRecordObj | AddInstanceObj | MergeProposalObj | DeleteBridgeObj;
140
+ declare enum ActionOperation {
141
+ Download = 6,
142
+ Visit = 11,
143
+ Rate = 12,
144
+ RatePart = 13,
145
+ Share = 14,
146
+ SharePart = 15
147
+ }
148
+ declare const isActionOperation: (op: number) => op is ActionOperation;
149
+ interface BaseActionPatch {
150
+ operation: ActionOperation;
151
+ objectType: number;
152
+ objectId: bigint;
153
+ ts: number;
154
+ }
155
+ interface VisitActionObj extends BaseActionPatch {
156
+ operation: ActionOperation.Visit;
157
+ }
158
+ interface DownloadActionObj extends BaseActionPatch {
159
+ operation: ActionOperation.Download;
160
+ }
161
+ interface RateActionObj extends BaseActionPatch {
162
+ operation: ActionOperation.Rate;
163
+ rate: number;
164
+ }
165
+ interface RatePartActionObj extends BaseActionPatch {
166
+ operation: ActionOperation.RatePart;
167
+ part: number;
168
+ rate: number;
169
+ }
170
+ interface ShareActionObj extends BaseActionPatch {
171
+ operation: ActionOperation.Share;
172
+ socialMediaId: number;
173
+ }
174
+ interface SharePartActionObj extends BaseActionPatch {
175
+ operation: ActionOperation.SharePart;
176
+ part: number;
177
+ socialMediaId: number;
178
+ }
179
+ type AnyActionPatch = VisitActionObj | DownloadActionObj | RateActionObj | RatePartActionObj | ShareActionObj | SharePartActionObj;
180
+ interface EnumLayout {
181
+ bits: number;
182
+ values: string[];
183
+ }
184
+ interface PropLayout {
185
+ name: string;
186
+ type: 'string' | 'number' | 'boolean' | 'enum';
187
+ bits: number;
188
+ enum?: string;
189
+ }
190
+ interface VersionEntry {
191
+ hash: string;
192
+ enums: Record<string, EnumLayout>;
193
+ props: Record<number, PropLayout>;
194
+ instanceFields: Record<number, number[]>;
195
+ }
196
+ interface VersionsFile {
197
+ current: number;
198
+ versions: Record<number, VersionEntry>;
199
+ }
200
+ interface VersionLayout {
201
+ hash: string;
202
+ enums: Record<string, EnumLayout>;
203
+ props: Record<number, PropLayout>;
204
+ instanceFields: Record<number, number[]>;
205
+ }
206
+ interface EvmPayload {
207
+ version: number;
208
+ patches: bigint[];
209
+ textIndex: number[];
210
+ textData: string[];
211
+ }
212
+ declare const LANG_ID_ENCODE: Record<string, number>;
213
+ declare const LANG_ID_DECODE: Record<number, string>;
214
+
215
+ /**
216
+ * Merges all version delta entries up to and including `version`.
217
+ *
218
+ * WARNING: COUPLING CONTRACT
219
+ * \`resolveLayout\` relies on \`computeVersionDelta\` emitting the FULL \`instanceFields\`
220
+ * array for any model that changed. It blindly overwrites the merged layout with the
221
+ * delta entry's array (\`merged.instanceFields[ot] = [...fields]\`). If future
222
+ * optimizations shrink \`versions.json\` by emitting only newly added fields, this
223
+ * function will silently corrupt the field layout by deleting historical fields.
224
+ */
225
+ declare function resolveLayout(version: number, versionsFile: VersionsFile): VersionLayout;
226
+ declare function packPatch(patch: AnyPatch, layout: VersionLayout): bigint;
227
+ declare function unpackPatch(packed: bigint, layout: VersionLayout): AnyPatch;
228
+ declare function packActionPatch(patch: AnyActionPatch): bigint;
229
+ declare function unpackActionPatch(packed: bigint): AnyActionPatch;
230
+ declare function patchToEvm(patches: (AnyPatch | AnyActionPatch)[], layout: VersionLayout, version: number): EvmPayload;
231
+ declare function evmToPatch(payload: EvmPayload, versionsFile: VersionsFile): (AnyPatch | AnyActionPatch)[];
232
+
233
+ type Lang = string;
234
+ type uid = bigint;
235
+ /**
236
+ * Canonical bigint<->string boundary for wireIds crossing a surface that
237
+ * can't carry bigint natively — JSON (`JSON.stringify` throws on bigint) and
238
+ * IndexedDB keys (bigint isn't a valid IDB key type). Every such boundary
239
+ * should use these two primitives via its own explicit typed transform
240
+ * function, not a generic JSON reviver/replacer or an inline `.toString()` —
241
+ * see optmized-uid/11-wireId-64bits-refactor.md §3 for why a generic reviver
242
+ * breaks on arrays like `authorIds` (a reviver sees the array index as the
243
+ * key, never the field name).
244
+ */
245
+ declare const toJsonId: (id: uid) => string;
246
+ declare const fromJsonId: (s: string) => uid;
247
+ interface RecordIdentityCluster {
248
+ sfcuid: string;
249
+ native: string;
250
+ aliases: string[];
251
+ wireId: uid;
252
+ }
253
+ /**
254
+ * Key used in per-language value maps when a value is language-agnostic
255
+ * (patches with langId 0).
256
+ */
257
+ declare const LANG_AGNOSTIC: Lang;
258
+ /**
259
+ * One embedded instance (e.g. a PDF variant of a Book). Keys are the
260
+ * instanceField names from the schema; `isDefault` is appended by the
261
+ * sidecar writer and is not an instanceField.
262
+ */
263
+ type InstanceData = Record<string, string | number | boolean | null>;
264
+ /**
265
+ * V2 in-memory ORM tuple. All value maps are per-language (perLang defaults
266
+ * to true in the V2 schema); language-agnostic values use LANG_AGNOSTIC ("").
267
+ */
268
+ type CommonOrmJson = [
269
+ uid,
270
+ Map<number, Set<uid>>,
271
+ Map<number, Set<uid>>,
272
+ Map<number, Map<Lang, number>>,
273
+ Map<number, Map<Lang, boolean>>,
274
+ Map<number, Map<Lang, string>>,
275
+ Map<Lang, InstanceData[]>
276
+ ];
277
+ /**
278
+ * True JSON-text-safe serialization of CommonOrmJson — every uid slot is
279
+ * decimal-string-encoded (the toJsonId convention above) since bigint isn't
280
+ * JSON-serializable. This is what `Orm.toJSON()` emits, and therefore what
281
+ * `JSON.stringify(someRecord)` actually produces (JSON.stringify calls a
282
+ * `toJSON` method before applying any replacer). It is NOT a
283
+ * structured-clone/postMessage format — `CommonOrmJson` itself already
284
+ * survives structured clone natively (bigint is structured-clone-safe), so
285
+ * there's no separate bigint-native "serialized" form needed for that case.
286
+ */
287
+ type SerializedCommonOrmJson = [
288
+ string,
289
+ Array<[number, Array<string>]>,
290
+ Array<[number, Array<string>]>,
291
+ Array<[number, Array<[Lang, number]>]>,
292
+ Array<[number, Array<[Lang, boolean]>]>,
293
+ Array<[number, Array<[Lang, string]>]>,
294
+ Array<[Lang, InstanceData[]]>
295
+ ];
296
+ type PropertyType = 'string' | 'number' | 'boolean' | 'enum';
297
+ interface BaseLocalOp {
298
+ ts: number;
299
+ action: ActionTypes;
300
+ objectType: number;
301
+ objectId: uid;
302
+ }
303
+ interface RateOp extends BaseLocalOp {
304
+ rate: Rating;
305
+ }
306
+ interface PartOp extends BaseLocalOp {
307
+ part: number;
308
+ }
309
+ interface RatePartOp extends PartOp {
310
+ rate: Rating;
311
+ }
312
+ interface ShareOp extends BaseLocalOp {
313
+ socialMediaId: number;
314
+ }
315
+ interface SharePartOp extends PartOp {
316
+ socialMediaId: number;
317
+ }
318
+ type LocalOp = RateOp | RatePartOp | PartOp | ShareOp | SharePartOp | BaseLocalOp;
319
+ /**
320
+ * Anything the patcher queue can hold: EVM-bound V2 patches (`AnyPatch`,
321
+ * discriminated by `operation`) or local analytics ops (discriminated by `action`).
322
+ * Local delivery metadata is never encoded into a wire patch.
323
+ */
324
+ type QueueItem = (AnyPatch | LocalOp) & {
325
+ eventId?: string;
326
+ sourceStream?: string;
327
+ provenance?: number;
328
+ };
329
+ declare const isEvmPatch: (item: QueueItem) => item is AnyPatch;
330
+ type SidecarUrls = {
331
+ objectType: number;
332
+ lang: Lang;
333
+ slimUrl?: string;
334
+ extendedUrl?: string;
335
+ provUrl?: string;
336
+ aiUrl?: string;
337
+ };
338
+ type InitPayload = {
339
+ cmd: WorkerCommands.Init;
340
+ payload: {
341
+ /** Flattened sidecar URLs for all selected languages. */
342
+ sidecars: Array<SidecarUrls>;
343
+ selectedLangs: Lang[];
344
+ };
345
+ };
346
+ type SavePatchesPayload = {
347
+ cmd: WorkerCommands.SavePatches;
348
+ payload: {
349
+ username: string;
350
+ patches: Array<QueueItem>;
351
+ };
352
+ };
353
+ type GetRecordPayload = {
354
+ cmd: WorkerCommands.GetRecord;
355
+ payload: {
356
+ objectType: number;
357
+ id: uid;
358
+ creatorUsername?: string;
359
+ };
360
+ };
361
+ type LoadLanguagePayload = {
362
+ cmd: WorkerCommands.LoadLanguage;
363
+ payload: {
364
+ lang: Lang;
365
+ sidecars: Array<SidecarUrls>;
366
+ };
367
+ };
368
+ type WorkerPayload = InitPayload | SavePatchesPayload | GetRecordPayload | LoadLanguagePayload;
369
+ interface IThread {
370
+ sendRequest(payload: WorkerPayload, transferables?: Array<any>): Promise<any>;
371
+ }
372
+ type StatSummary = {
373
+ visits: Array<number>;
374
+ rating: Rating;
375
+ socialMediaId: Array<number>;
376
+ downloads: Array<number>;
377
+ parts: {
378
+ [partId: string]: {
379
+ rating: Rating;
380
+ socialMediaId: Array<number>;
381
+ visits: Array<number>;
382
+ };
383
+ };
384
+ };
385
+ interface BookData {
386
+ fileId: string;
387
+ parsed: boolean;
388
+ author: string;
389
+ title: string;
390
+ dimensions: Array<{
391
+ width: number;
392
+ height: number;
393
+ } | null>;
394
+ }
395
+ interface FileRecord {
396
+ id: string;
397
+ creationTime: number;
398
+ sizeKb: number;
399
+ content: Uint8Array;
400
+ local: boolean;
401
+ }
402
+ declare enum BridgeRelation {
403
+ EquivalentWith = 0,
404
+ ChildOf = 1,
405
+ ParentOf = 2
406
+ }
407
+ interface BridgeLink {
408
+ id: number | string;
409
+ confidence: number;
410
+ }
411
+ interface BridgeSystemConversions {
412
+ equivalentWith?: BridgeLink[];
413
+ childOf?: BridgeLink[];
414
+ parentOf?: BridgeLink[];
415
+ }
416
+ interface BridgeDefinition {
417
+ original: string;
418
+ conversions?: Record<string, BridgeSystemConversions>;
419
+ }
420
+
421
+ /**
422
+ * V2 model definition — the shape of the enriched JSON files in
423
+ * `@the_library/db_schemas/generated-src/*.json` (frozen numeric IDs).
424
+ */
425
+ interface SchemaProp {
426
+ name: string;
427
+ type: PropertyType;
428
+ source: 'slim' | 'extended';
429
+ propId: number;
430
+ enum?: string;
431
+ bits?: number;
432
+ nullable?: boolean;
433
+ }
434
+ interface SchemaInstanceField {
435
+ name: string;
436
+ type: PropertyType;
437
+ propId: number;
438
+ enum?: string;
439
+ bits?: number;
440
+ nullable?: boolean;
441
+ identityComponent?: boolean;
442
+ source?: 'slim' | 'extended';
443
+ }
444
+ interface SchemaRelation {
445
+ name: string;
446
+ targetType: string;
447
+ direction: 'has' | 'in';
448
+ cardinality: '1to1' | '1toN';
449
+ inverted: string;
450
+ relationId: number;
451
+ }
452
+ /**
453
+ * Cols field name for a `has`-relation tail. The `authors` relation keeps its
454
+ * historical `authorIds` name for back-compat; every other relation uses its
455
+ * schema name directly (e.g. Tag.tags, Tag.books). Single source of truth for
456
+ * both the codegen (schemaGenerator.ts, which emits `${relationColName(rel)}`
457
+ * as the ExtendedCols field name) and the runtime reader (orm.ts's
458
+ * mergeExtended, which must look up that same field name on the incoming cols
459
+ * object) — they must never drift apart.
460
+ */
461
+ declare const relationColName: (rel: SchemaRelation) => string;
462
+ interface SchemaIndex {
463
+ name: string;
464
+ keys: string[];
465
+ linkToUidStrategy?: boolean;
466
+ classifier?: {
467
+ type: 'prefix';
468
+ separator: string;
469
+ fallback: string;
470
+ customMappings?: Record<string, string>;
471
+ };
472
+ }
473
+ interface ModelDefinition {
474
+ name: string;
475
+ typePrefix: string;
476
+ objectId: number;
477
+ multipleInstances: boolean;
478
+ uidStrategy?: string | string[];
479
+ instanceUidStrategy?: string | string[];
480
+ isPrivate?: boolean;
481
+ standardPks?: Record<string, string>;
482
+ props: SchemaProp[];
483
+ instanceFields: SchemaInstanceField[];
484
+ relations: SchemaRelation[];
485
+ indexes?: SchemaIndex[];
486
+ }
487
+ declare class SchemaRegistry {
488
+ private static instance;
489
+ private schemas;
490
+ private byName;
491
+ private constructor();
492
+ static getInstance(): SchemaRegistry;
493
+ register(schema: ModelDefinition): void;
494
+ get(id: number): ModelDefinition;
495
+ /** Lookup by model name (relation targetType resolution). */
496
+ getByName(name: string): ModelDefinition | undefined;
497
+ clear(): void;
498
+ }
499
+ declare const Registry: SchemaRegistry;
500
+
501
+ /**
502
+ * Replay/baking metadata: real per-language "was this actually set" state,
503
+ * carried alongside the corpus's flattened display values so both the corpus
504
+ * baker (`@the_library/corpus-builder`) and worker/browser LRU rehydration
505
+ * (`orm.ts`'s `mergeProv`, `reconstructRecord.ts`) can reuse the exact same
506
+ * fallback-resolution rules the live ORM already implements for setters/
507
+ * getters (`resolveLangValue` in orm.ts), instead of each reimplementing an
508
+ * approximation of it.
509
+ *
510
+ * BACKGROUND — why this exists at all (2026-09-08, findings #5/#6 in
511
+ * reviews/2026-09-07/assessment.md, and the follow-up probe documented in
512
+ * reviews/2026-09-07/implementation-p1-5-through-p1-6.md):
513
+ *
514
+ * The published corpus (`BookInput`/`TagInput`/`PersonInput`, see
515
+ * generated-src/*.ts) stores exactly ONE flattened value per property per
516
+ * per-language corpus build (e.g. `book.title` in the `fra` corpus is a
517
+ * single string). The corpus baker (`apply-patches-plain.ts`) runs
518
+ * incrementally: each build call receives only the patches accumulated since
519
+ * the last build (`data/patches.jsonl` is truncated after every successful
520
+ * publish — see apps/book-manager/CLAUDE.md's "Publishing the models_v2
521
+ * corpus" section), plus the PREVIOUS build's already-flattened output as its
522
+ * starting point. That flattened single value is fundamentally ambiguous:
523
+ * given `book.title === 'Arbre'` for the `fra` build, there is no way to tell
524
+ * whether "Arbre" is a genuine, deliberately-authored French title, or
525
+ * whether it is itself a fallback value that leaked in from an English edit
526
+ * because French had never been set yet. The same ambiguity applies to
527
+ * `false`/`0`/`""`: a nullable field's `""` might mean "explicitly cleared"
528
+ * or "never set"; a non-nullable boolean/number's `false`/`0` is completely
529
+ * indistinguishable from "never set" once flattened.
530
+ *
531
+ * A first fix attempt tried to paper over this with a heuristic (checking
532
+ * whether the flattened value was "nullable and non-empty" before allowing a
533
+ * fallback edit to overwrite it). That heuristic could not protect
534
+ * non-nullable fields (`safe`, `deleted`, every `QualityScore`) at all, and
535
+ * could not tell a real translation from a previously-baked fallback either
536
+ * — see the git history of apply-patches-plain.ts around that date for what
537
+ * NOT to reintroduce.
538
+ *
539
+ * The actual fix: export the ORM's REAL internal per-(propId, lang) storage
540
+ * (`Orm._stringValues`/`_numberValues`/`_boolValues`, via `Orm.propertySlots()`)
541
+ * as a small, JSON-serializable side-channel, persist it in the corpus's
542
+ * existing binary "prov" sidecar tier (see serializer.ts's
543
+ * `commonSerializeProv`/`commonDeserializeProv` and this file's
544
+ * `REPLAY_METADATA_COLUMNS`), and restore it into a real headless `Orm`
545
+ * instance before each incremental bake (`apply-patches-plain.ts`). Because
546
+ * `Map.has(lang)` is a real presence check independent of the stored value,
547
+ * `false`/`0`/`""` are now indistinguishable from nothing ONLY when they
548
+ * really are nothing — solving both the cross-language-overwrite bug and the
549
+ * non-nullable-field blind spot structurally, not via a guess.
550
+ *
551
+ * Compatibility limit (documented in implementation-p1-5-through-p1-6.md):
552
+ * a corpus built BEFORE this change has no slots at all. The first time such
553
+ * a record is baked under the new code (`apply-patches-plain.ts`'s
554
+ * `!fresh.has(rec)` bootstrap branch), every one of its current non-null
555
+ * flattened values is conservatively treated as an explicit slot for the
556
+ * CURRENT build's language — including any prior English-fallback-into-French
557
+ * corruption from before this fix existed. This stops the bug from
558
+ * recurring; it cannot retroactively repair history that's already wrong.
559
+ * Only a rebuild from the original patch log (not the already-flattened
560
+ * corpus) can recover genuinely lost translation intent.
561
+ */
562
+ type PropertySlots = Array<[number, Array<[Lang, string | number | boolean]>]>;
563
+ /**
564
+ * Sidecar column names (as written into the binary "prov" tier — see
565
+ * `serializer.ts`) vs. the in-memory field names used on plain
566
+ * `BookInput`/`TagInput`/`PersonInput` objects while baking. Deliberately
567
+ * DOUBLE-underscored on the wire (`__propertySlots`/`__instanceRemaps`) to
568
+ * keep them visually distinct from the existing single-underscore `_prov`/
569
+ * `_createSeq` bookkeeping fields these plain objects already carry
570
+ * informally (neither of those is declared in the generated `BookInput`
571
+ * etc. interfaces either — this follows the same, pre-existing convention).
572
+ *
573
+ * These are genuinely NEW named columns in the prov sidecar's binary format,
574
+ * not a new sidecar file/tier and not a `SIDECAR_FORMAT_VERSION` bump: the
575
+ * sidecar column format is self-describing (each column writes its own type
576
+ * byte + name string ahead of its data — see enriched-index.ts's
577
+ * `writeSidecar`/`parseSidecar`), so an old reader parsing a new sidecar
578
+ * still parses these columns without error (it just won't know what to do
579
+ * with the data), and a new reader parsing an old sidecar (without these
580
+ * columns) simply sees them as absent — see `commonDeserializeProv`'s
581
+ * `REPLAY_METADATA_COLUMNS` branch in serializer.ts.
582
+ */
583
+ declare const PROPERTY_SLOTS_COLUMN = "__propertySlots";
584
+ declare const INSTANCE_REMAPS_COLUMN = "__instanceRemaps";
585
+ /** [sidecar column name, in-memory field name] pairs — see the doc comment above. */
586
+ declare const REPLAY_METADATA_COLUMNS: readonly [readonly ["__propertySlots", "_propertySlots"], readonly ["__instanceRemaps", "_instanceRemaps"]];
587
+ /** Base properties (propId 0-7) plus a schema's own `props`, keyed by propId
588
+ * so a schema can override a base entry if it ever needs to (Map dedup keeps
589
+ * the last write per propId — schema.props is spread after baseProperties). */
590
+ declare function scalarProperties(schema: ModelDefinition): SchemaProp[];
591
+
592
+ declare enum LifecycleStatus {
593
+ Provisional = 0,
594
+ Submitted = 1,
595
+ CommunityPending = 2,
596
+ Canonical = 3
597
+ }
598
+
599
+ /** Called after every StatsStore change (a local action, or restored rows added). */
600
+ declare const subscribeStats: (listener: () => void) => (() => void);
601
+ declare const PopulateStatsStore: (operations: Array<LocalOp>) => void;
602
+ declare const DownloadsByType: (objectType: number) => Array<uid>;
603
+ declare const VisitsByType: (objectType: number) => Array<uid>;
604
+ declare const FavoritesByTypes: (objectType: number) => Array<{
605
+ id: uid;
606
+ nbVisits: number;
607
+ rating: Rating;
608
+ }>;
609
+ declare class Stats {
610
+ private objectId;
611
+ protected objectType: number;
612
+ constructor(objectId: uid, objectType: number);
613
+ favoriteParts(): Array<{
614
+ partId: number;
615
+ nbVisits: number;
616
+ rating: Rating;
617
+ }>;
618
+ check(): void;
619
+ visit(): void;
620
+ download(): void;
621
+ get rating(): Rating;
622
+ set rating(rating: Rating);
623
+ share(socialMediaId: number): void;
624
+ ratePart(partId: number, rating: Rating): void;
625
+ visitPart(partId: number): void;
626
+ }
627
+
628
+ interface UidFactory {
629
+ next(): Promise<{
630
+ wireId: bigint;
631
+ }>;
632
+ isUserCreated(wireId: bigint): boolean;
633
+ }
634
+ /**
635
+ * Bit 63 is the user-created scope flag (see optmized-uid/11-wireId-64bits-refactor.md §0).
636
+ * scope(1) + random(63). 0 = canonical, 1 = user-created.
637
+ */
638
+ declare function isUserCreated(wireId: bigint | number | string): boolean;
639
+ declare class CryptoRandomUidFactory implements UidFactory {
640
+ next(): Promise<{
641
+ wireId: bigint;
642
+ }>;
643
+ isUserCreated(wireId: bigint): boolean;
644
+ }
645
+ declare function loadOrInitUidFactory(db: IDBDatabase): Promise<UidFactory>;
646
+
647
+ declare const Config: {
648
+ readonly userLang: Lang;
649
+ readonly commonLang: Lang;
650
+ readonly defaultProvenance: number | undefined;
651
+ readonly loadAiSidecars: boolean;
652
+ };
653
+ declare function setDefaultLanguage(lang: Lang): void;
654
+ declare function setDefaultProvenance(provenance: number): void;
655
+ declare function setLoadAiSidecars(enabled: boolean): void;
656
+ declare const PROVENANCE_UNSET = 0;
657
+ declare const PROVENANCE_AI = 1;
658
+ declare const PROVENANCE_MANUAL_LOCAL = 2;
659
+ declare const PROVENANCE_CONSENSUS = 3;
660
+ declare const TITLE_PROP = 0;
661
+ declare const DESCRIPTION_PROP = 1;
662
+ declare const ORIGINAL_LANG_PROP = 2;
663
+ declare const AGE_GRADE_BAND_PROP = 3;
664
+ declare const PREVIEW_TX_ID_PROP = 4;
665
+ declare const SAFE_PROP = 5;
666
+ declare const DELETED_PROP = 6;
667
+ declare const LIFECYCLE_STATUS_PROP = 7;
668
+
669
+ /** Decimal-string-encodes every uid — see SerializedCommonOrmJson's own doc comment for why. */
670
+ declare function serializeMapOfSets(map: Map<number, Set<uid>>): Array<[number, Array<string>]>;
671
+ declare function serializeMapOfMaps<V>(mapOfMaps: Map<number, Map<Lang, V>>): Array<[number, Array<[Lang, V]>]>;
672
+ declare const inflateOrmJson: (v2: SerializedCommonOrmJson) => CommonOrmJson;
673
+ interface DeepCollectOptions {
674
+ /** Include deleted/unsafe records — both as final result items and as
675
+ * pass-through nodes during traversal. Default false: a deleted/unsafe
676
+ * node discovered via the hierarchy or a bridge is a dead end (neither
677
+ * its own contributions nor anything beyond it is included). The
678
+ * query's own starting record is exempt from this — it is always
679
+ * processed regardless of its own deleted/safe flags, since the caller
680
+ * explicitly chose it. */
681
+ includeDeleted?: boolean;
682
+ /** Which BridgeRelation types to follow when expanding across bridges.
683
+ * Default [EquivalentWith, ParentOf] — "broader absorbs narrower", the
684
+ * same rule the has-direction hierarchy relation already follows.
685
+ * ChildOf points to something BROADER than the caller and is excluded
686
+ * by default (following it would balloon every leaf query to include
687
+ * an entire foreign classification system) — pass it explicitly to
688
+ * opt in. Pass [] to disable bridge-following entirely. */
689
+ bridgeTypes?: BridgeRelation[];
690
+ }
691
+ declare class Orm extends Stats {
692
+ /** Persisted delivery boundary already included by worker reconstruction. */
693
+ hydratedThrough: number;
694
+ readonly _id: uid;
695
+ protected _boolValues: Map<number, Map<string, boolean>>;
696
+ protected _stringValues: Map<number, Map<string, string>>;
697
+ protected _numberValues: Map<number, Map<string, number>>;
698
+ protected _has: Map<number, Set<bigint>>;
699
+ protected _in: Map<number, Set<bigint>>;
700
+ /** lang -> instance array (BookInstanceData structs, not ORM objects). */
701
+ protected _instances: Map<string, InstanceData[]>;
702
+ /** lang -> propId -> provenance code (2-bit: unset/AI/human/consensus). */
703
+ protected _provenance: Map<string, Map<number, number>>;
704
+ protected _aiResults: Map<string, Map<string, Map<string, Set<{
705
+ ts: number;
706
+ value: any;
707
+ format: string;
708
+ }>>>>;
709
+ /** Bridges to other taxonomy systems */
710
+ bridges?: BridgeDefinition;
711
+ schema: ModelDefinition;
712
+ /**
713
+ * Safe relation accessor for generated model getters. For each relation ID:
714
+ * - If the target record is resident in the LRU cache, it is loaded and included.
715
+ * - If the target record is missing (never loaded, evicted, or a stale sidecar
716
+ * reference), a detailed console warning is emitted and the ID is skipped.
717
+ * The application never crashes from an unresolved relation.
718
+ *
719
+ * Warning format:
720
+ * [ORM] Tag with Id=123 and name="General" has a relationship not met:
721
+ * tags to Id=4718593. With id=4718593 not defined.
722
+ *
723
+ * @param owner The record that owns the relation (used for the log message).
724
+ * @param ids The set of target IDs stored in the relation.
725
+ * @param checker `ModelClass.Has` — returns true when the record is in cache.
726
+ * @param loader `ModelClass.Load` — retrieves the record from cache.
727
+ * @param relationName Human-readable relation name, e.g. `"tags"` or `"inTags"`.
728
+ */
729
+ protected static _safeRelation<T>(owner: Orm, ids: uid[], checker: (id: uid) => boolean, loader: (id: uid) => T, relationName: string): T[];
730
+ static createNewRequest(id: uid): CommonOrmJson;
731
+ static createNewRecord<T extends Orm>(this: {
732
+ new (json: any, creatorUsername?: string): T;
733
+ type: number;
734
+ }, uidFactory: UidFactory, creatorUsername: string): Promise<T>;
735
+ protected _creatorUsername?: string;
736
+ get creatorUsername(): string;
737
+ constructor(objectType: number, json: CommonOrmJson | SerializedCommonOrmJson, creatorUsername?: string);
738
+ /**
739
+ * `(user:objectId:langId:originalIndex) -> realIndex` pairs, produced by
740
+ * `patchContext.ts`'s `resolveAddInstanceConflict` whenever an incoming
741
+ * `AddInstance` collides with an index another author/device already
742
+ * populated with a genuinely different edition (different `downloadTxId`
743
+ * etc. — see `areInstancesEqual`). Kept as a plain array of tuples, not a
744
+ * `Map`, purely so it round-trips through `JSON.stringify`/`JSON.parse`
745
+ * unchanged for persistence (a `Map` doesn't survive that). Persisted two
746
+ * ways, both consumed the same way:
747
+ * - Live app: `patchContext.ts`'s `InstanceRemapStore` (backed by an
748
+ * IndexedDB `instanceRemaps` object store — see
749
+ * apps/book-manager/specifications/done/record_creation_flow_v2.md
750
+ * §3.3) durably remembers a remap so a device's LATER patches
751
+ * addressed to the old index get silently redirected.
752
+ * - Corpus baking / worker rehydration: this field itself is the
753
+ * durable copy, serialized into the `__instanceRemaps` sidecar column
754
+ * (see propertySlots.ts) so a remap made during one incremental
755
+ * corpus build survives into the next one, even though
756
+ * `data/patches.jsonl` (the source patches) is cleared after every
757
+ * build. Without this, a field-only edit in a LATER build that still
758
+ * referenced the pre-remap index would silently corrupt whichever
759
+ * edition now legitimately occupies that slot — this is exactly what
760
+ * reviews/2026-09-07/implementation-p1-5-through-p1-6.md's "a remap
761
+ * was lost after binary bake/reload" regression test guards against.
762
+ * - `patchContext.ts`'s remap lookup checks BOTH sources (live
763
+ * `instanceRemapStore` first, then this field) so a corpus-restored
764
+ * mapping can inform live replay when local IndexedDB has none yet.
765
+ */
766
+ instanceRemaps: Array<[string, number]>;
767
+ /**
768
+ * Export the REAL per-(propId, lang) storage — not resolved/flattened
769
+ * values — as a JSON-serializable array. This is the read side of the
770
+ * property-slots mechanism documented in propertySlots.ts: it lets a
771
+ * caller (the corpus baker, or worker rehydration via `mergeProv`)
772
+ * persist "which languages actually have an explicit value for this
773
+ * property" across a serialize/deserialize round trip, so a later
774
+ * `restorePropertySlots()` call can reconstruct a record whose
775
+ * `resolveLangValue`-based fallback behaves identically to a record that
776
+ * was never detached at all.
777
+ */
778
+ propertySlots(): PropertySlots;
779
+ /**
780
+ * Restore real per-language property state (the inverse of
781
+ * `propertySlots()`), for a headless/detached `Orm` instance that has no
782
+ * other way to acquire it (the corpus baker constructs one from scratch
783
+ * for every record it bakes — see apply-patches-plain.ts).
784
+ *
785
+ * `scope` exists because the corpus baker's restore is asymmetric: for
786
+ * the language it is CURRENTLY building (e.g. baking the `fra` corpus),
787
+ * the persisted `fra` slots must be treated as the complete, authoritative
788
+ * truth for that language — anything not explicitly there really is
789
+ * unset. But OTHER languages' slots (e.g. `eng`) are only useful as
790
+ * fallback data if `fra` turns out to have nothing at all for a given
791
+ * property; they must not silently overwrite anything already restored
792
+ * for the target language. `scope === undefined` is the simpler
793
+ * unscoped case (restoring a complete detached snapshot with no
794
+ * asymmetry, e.g. worker rehydration in `mergeProv`) and clears
795
+ * everything first. With a `scope`, only that language's existing slots
796
+ * are cleared before restoring (so a stale `fra` value from a PRIOR
797
+ * build doesn't linger if bootstrapping fresh state), and the
798
+ * `!values.get(id)?.has(lang)` check on the fallback path guarantees an
799
+ * already-restored `scope` value is never clobbered by another
800
+ * language's slot processed later in the same `slots` array.
801
+ *
802
+ * Why this can't be approximated by checking whether the corpus's
803
+ * flattened value is falsy/empty: see propertySlots.ts's module doc —
804
+ * `false`/`0`/`""` are legitimate explicit values that a heuristic
805
+ * cannot tell apart from "never set". Only replaying the real slots data
806
+ * (a genuine Map keyed by language) preserves that distinction.
807
+ */
808
+ restorePropertySlots(slots: PropertySlots, scope?: Lang): void;
809
+ /** Complete worker hydration state; unlike toJSON, includes auxiliary tiers. */
810
+ snapshot(): {
811
+ json: SerializedCommonOrmJson;
812
+ instanceRemaps: [string, number][];
813
+ patchOrder: number;
814
+ provenance: Map<string, Map<number, number>>;
815
+ bridges: BridgeDefinition | undefined;
816
+ ai: Map<string, Map<string, Map<string, Set<{
817
+ ts: number;
818
+ value: any;
819
+ format: string;
820
+ }>>>>;
821
+ };
822
+ /** Replace materialized state in place so existing UI references remain valid. */
823
+ replaceSnapshot(state: ReturnType<Orm['snapshot']>): void;
824
+ restoreSnapshot(state: ReturnType<Orm['snapshot']>): void;
825
+ toJSON(): SerializedCommonOrmJson;
826
+ /** Raw cross-language view: company -> model -> lang -> results. */
827
+ getAiResultsAllLangs(): Map<string, Map<string, Map<Lang, Set<{
828
+ ts: number;
829
+ value: any;
830
+ format: string;
831
+ }>>>>;
832
+ /** Per-language view: company -> model -> results, resolved for `lang`
833
+ * (falls back to the session's default language when omitted/null). */
834
+ getAiResults(lang?: Lang | null): Map<string, Map<string, Set<{
835
+ ts: number;
836
+ value: any;
837
+ format: string;
838
+ }>>>;
839
+ /** AI results are per-language: the same record can carry a different assessment per translation. */
840
+ attachAiResult(company: string, modelName: string, lang: Lang, result: any): void;
841
+ get id(): uid;
842
+ protected langOf(langId: number): Lang;
843
+ protected langIdOf(lang?: Lang): number;
844
+ getLoadedLanguages(): Lang[];
845
+ /**
846
+ * Get the uidStrategy array defined in this model's schema.
847
+ * Used to determine which classification systems are supported.
848
+ */
849
+ protected getUidStrategies(): string[];
850
+ /**
851
+ * Detect which classification system (uidStrategy) this record belongs to.
852
+ * Works by checking which notation/classification fields are populated.
853
+ *
854
+ * Field name mapping uses a convention: "lcc" -> "lccNotation" or special
855
+ * names like "lcc" -> "locCallNumber" for Book. The mapping is determined
856
+ * by the MODEL_CLASSIFICATION_FIELD_MAP in classification-utils.
857
+ *
858
+ * @param fieldMap Optional override mapping of strategy -> field name
859
+ * @returns The detected strategy, or 'unclassified' if none found
860
+ */
861
+ getClassificationType(fieldMap?: Record<string, string>): string;
862
+ /**
863
+ * Get the default field name mapping for this model's classification systems.
864
+ * Override in subclasses or provide via fieldMap parameter if needed.
865
+ *
866
+ * Default convention: strategy "X" maps to field "xNotation" (e.g., "lcc" -> "lccNotation")
867
+ */
868
+ protected getDefaultClassificationFieldMap(): Record<string, string>;
869
+ get title(): string;
870
+ set title(value: string);
871
+ getTitle(lang: Lang): string;
872
+ setTitle(value: string, lang: Lang): void;
873
+ get description(): string;
874
+ set description(value: string);
875
+ getDescription(lang: Lang): string;
876
+ setDescription(value: string, lang: Lang): void;
877
+ get originalLang(): string;
878
+ set originalLang(value: string);
879
+ getOriginalLang(lang: Lang): string;
880
+ setOriginalLang(value: string, lang: Lang): void;
881
+ get ageGradeBand(): number;
882
+ set ageGradeBand(value: number);
883
+ get previewTxId(): string;
884
+ set previewTxId(value: string);
885
+ get safe(): boolean;
886
+ set safe(value: boolean);
887
+ get deleted(): boolean;
888
+ set deleted(value: boolean);
889
+ get lifecycleStatus(): LifecycleStatus;
890
+ set lifecycleStatus(value: LifecycleStatus);
891
+ protected dispatchString(propertyId: number, value: string, lang?: Lang): void;
892
+ protected dispatchNumber(propertyId: number, value: number, lang?: Lang): void;
893
+ protected dispatchRelation(relationId: number, action: PatchAction, targetId: uid): void;
894
+ /**
895
+ * Raw in-memory relation mutation: no patch is emitted. Used by the
896
+ * generic inverse propagation in patch() and by generated in-side
897
+ * relation helpers. Idempotent (Set semantics).
898
+ */
899
+ protected applyRelationRaw(direction: 'has' | 'in', relationId: number, action: PatchAction, targetId: uid, effects?: boolean): void;
900
+ /**
901
+ * Bulk-restores the inverse (`in`) edges implied by this record's forward
902
+ * (`has`) relations onto their target records. The sidecar serializes only
903
+ * the `has` direction (§3.7.1); `mergeExtended` fills `_has`, but the inverse
904
+ * side (`Person.authorOf`, `Tag.inTags`, …) stays empty until this runs.
905
+ *
906
+ * No patch emitted, no reactivity fired (bulk boot path). Idempotent (Set
907
+ * add). Targets must already be materialized — call after a full
908
+ * `hydrateAll` pass (see `rebuildInverseRelations`).
909
+ */
910
+ restoreInverses(): void;
911
+ /**
912
+ * Looks up an existing child of the `has`-side relation `relationId`
913
+ * whose title (base prop 0) matches `title` after trim + case-fold.
914
+ * Children not materialized in the LRU are skipped — same tolerance as
915
+ * `_safeRelation`. Returns null when no materialized child matches.
916
+ */
917
+ findChildByTitle(relationId: number, title: string): Orm | null;
918
+ /**
919
+ * Re-hydrates any children of `relationId` evicted from the LRU cache.
920
+ * Without this, `findChildByTitle` silently skips evicted-but-real
921
+ * children (it can only see what's resident), so `getOrCreateChildByTitle`
922
+ * would mint a duplicate instead of finding the existing match — the
923
+ * eviction-driven dup-tag bug. A no-op if the target class was never
924
+ * registered (registerModelClass runs at generated-module load) or
925
+ * nothing is actually missing.
926
+ */
927
+ private hydrateChildren;
928
+ /**
929
+ * Find-or-create keyed on child title, scoped to this parent. The
930
+ * relation Set already guarantees a child id can only appear once; this
931
+ * extends the uniqueness to titles: if a child titled `title` already
932
+ * exists in `relationId`, it is returned untouched and nothing is
933
+ * created or linked. Otherwise `create` mints the record, its title is
934
+ * set and it is linked to this parent. Titles may still repeat under
935
+ * OTHER parents (e.g. many taxonomy branches each own a "General") —
936
+ * that is deliberate; uniqueness is per parent, not global.
937
+ */
938
+ getOrCreateChildByTitle<T extends Orm>(relationId: number, title: string, create: () => Promise<T>): Promise<T>;
939
+ /**
940
+ * Generic recursive collector for any "has"/"in" relation, declaratively
941
+ * driven by the schema — no model needs its own copy of this logic (it
942
+ * used to be hand-rolled three separate times in apps/book-manager:
943
+ * topic-actions.ts's collectTopicDownloadTxIds, TopicTree.tsx's
944
+ * countBooksRecursive, ClassificationTree.tsx's countBooks).
945
+ */
946
+ getBridgedRelationIdsSync(relationId: number, direction: 'has' | 'in', visitedBridges?: Set<string>): Array<uid>;
947
+ /**
948
+ * Walks two axes from `this`, unioning `relationName`'s targets at every
949
+ * node reached on either axis, recursively:
950
+ * - the has-direction self-referential hierarchy relation (e.g.
951
+ * Tag.tags) — UNLESS relationName itself IS that self-referential
952
+ * relation's in-direction counterpart (e.g. Tag.inTags), in which
953
+ * case structural expansion ascends via that relation instead of
954
+ * descending via the has side;
955
+ * - this.bridges (cross-classification-system links), following only
956
+ * the BridgeRelation types in opts.bridgeTypes and resolving each
957
+ * link's id against this record's OWN model type (bridges carry no
958
+ * target-type field — the data model only supports same-type links,
959
+ * e.g. Tag-to-Tag — a non-numeric or unresolvable id is skipped, not
960
+ * thrown, since it may be an external standard's notation with no
961
+ * local record backing it).
962
+ *
963
+ * One visited-node Set spans both axes, so any cycle — pure hierarchy,
964
+ * pure bridge, or mixed — terminates and each node contributes once.
965
+ * See bridgeDeepRelations.test.ts for the full behavioral spec this
966
+ * implements.
967
+ */
968
+ collectDeepIds(relationName: string, opts?: DeepCollectOptions): Promise<uid[]>;
969
+ /**
970
+ * Applies a V2 patch to the in-memory state. Triggers reactivity.
971
+ */
972
+ patch(patch: AnyPatch, _isMine?: boolean, effects?: boolean): void;
973
+ protected applyInstancePatch(p: EditInstanceFieldStringObj | EditInstanceFieldNumberObj): void;
974
+ protected getPropType(propId: number): 'string' | 'number' | 'boolean';
975
+ /**
976
+ * Resolve stored values without adding a UI default for an absent
977
+ * string. `getProp` (below) exists for live UI code, which wants an
978
+ * absent string coerced to `''` for convenient rendering. The corpus
979
+ * baker needs the RAW resolved value — including a genuine `undefined`
980
+ * when nothing at all applies — so it can tell "this property resolved
981
+ * to a value" apart from "this property has no applicable slot yet" when
982
+ * deciding whether an edit actually changed anything (see
983
+ * apply-patches-plain.ts's `applied++` bookkeeping, which compares this
984
+ * against the corpus's previous flattened value).
985
+ */
986
+ resolvedPropertyValue(propId: number, lang: Lang): any;
987
+ getProp(propId: number, lang?: Lang): any;
988
+ /** Direct state write — no patch emitted (used by merge methods). */
989
+ protected setRaw(propId: number, value: any, lang?: Lang): void;
990
+ getInstancesData(lang?: Lang): InstanceData[];
991
+ getDefaultInstanceData(lang?: Lang): InstanceData | undefined;
992
+ /** Direct state write — no patch emitted (used by mergeExtended/mergeSlim). */
993
+ setInstancesRaw(lang: Lang, instances: InstanceData[]): void;
994
+ growInstances(lang: Lang, toIndex: number): void;
995
+ addInstance(lang?: Lang): number;
996
+ getProvenance(propId: number, lang?: Lang): number;
997
+ setProvenanceRaw(lang: Lang, propId: number, value: number): void;
998
+ mergeSlim(cols: any, index: number, lang?: Lang): void;
999
+ mergeExtended(cols: any, index: number, lang?: Lang): void;
1000
+ mergeProv(cols: any, index: number, lang?: Lang): void;
1001
+ }
1002
+
1003
+ export { Registry as $, type AnyActionPatch as A, type BridgeDefinition as B, type CommonOrmJson as C, type DeepCollectOptions as D, type EvmPayload as E, type FileRecord as F, type GetRecordPayload as G, type StatSummary as H, type InstanceData as I, BridgeRelation as J, type BridgeLink as K, type Lang as L, type BridgeSystemConversions as M, type SchemaProp as N, Orm as O, type PropertyType as P, type QueueItem as Q, type RecordIdentityCluster as R, SidecarType as S, type SchemaInstanceField as T, type SchemaRelation as U, type VersionsFile as V, WorkerCommands as W, relationColName as X, type SchemaIndex as Y, type ModelDefinition as Z, SchemaRegistry as _, type SidecarUrls as a, type PropertySlots as a$, PatchOperation as a0, PatchAction as a1, packPatch as a2, unpackPatch as a3, resolveLayout as a4, patchToEvm as a5, evmToPatch as a6, LANG_ID_ENCODE as a7, LANG_ID_DECODE as a8, ActionOperation as a9, VisitsByType as aA, FavoritesByTypes as aB, Stats as aC, type UidFactory as aD, isUserCreated as aE, CryptoRandomUidFactory as aF, loadOrInitUidFactory as aG, LifecycleStatus as aH, Config as aI, setDefaultLanguage as aJ, setDefaultProvenance as aK, setLoadAiSidecars as aL, PROVENANCE_UNSET as aM, PROVENANCE_AI as aN, PROVENANCE_MANUAL_LOCAL as aO, PROVENANCE_CONSENSUS as aP, TITLE_PROP as aQ, DESCRIPTION_PROP as aR, ORIGINAL_LANG_PROP as aS, AGE_GRADE_BAND_PROP as aT, PREVIEW_TX_ID_PROP as aU, SAFE_PROP as aV, DELETED_PROP as aW, LIFECYCLE_STATUS_PROP as aX, serializeMapOfSets as aY, serializeMapOfMaps as aZ, inflateOrmJson as a_, isActionOperation as aa, packActionPatch as ab, unpackActionPatch as ac, type BasePatch as ad, type EditPropertyStringObj as ae, type EditPropertyNumberObj as af, type EditInstanceFieldStringObj as ag, type EditInstanceFieldNumberObj as ah, type EditRelationObj as ai, type CreateRecordObj as aj, type AddInstanceObj as ak, type MergeProposalObj as al, type DeleteBridgeObj as am, type VersionEntry as an, type EnumLayout as ao, type PropLayout as ap, type BaseActionPatch as aq, type VisitActionObj as ar, type DownloadActionObj as as, type RateActionObj as at, type RatePartActionObj as au, type ShareActionObj as av, type SharePartActionObj as aw, subscribeStats as ax, PopulateStatsStore as ay, DownloadsByType as az, type SerializedCommonOrmJson as b, PROPERTY_SLOTS_COLUMN as b0, INSTANCE_REMAPS_COLUMN as b1, REPLAY_METADATA_COLUMNS as b2, scalarProperties as b3, type VersionLayout as c, type IThread as d, type LocalOp as e, type AnyPatch as f, type BookData as g, ActionTypes as h, Rating as i, WorkerEvent as j, DownloadState as k, fromJsonId as l, LANG_AGNOSTIC as m, type BaseLocalOp as n, type RateOp as o, type PartOp as p, type RatePartOp as q, type ShareOp as r, type SharePartOp as s, toJsonId as t, type uid as u, isEvmPatch as v, type InitPayload as w, type SavePatchesPayload as x, type LoadLanguagePayload as y, type WorkerPayload as z };