@x12i/memorix-descriptors 1.4.0 → 1.4.1

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 (2) hide show
  1. package/README.md +181 -20
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -35,6 +35,32 @@ npm install @x12i/xronox
35
35
 
36
36
  Peer dependencies: `@x12i/catalox` ≥5, `@x12i/memorix-retrieval` ≥1.6, `@x12i/xronox` ≥3.9 (optional).
37
37
 
38
+ Install the retrieval peer from the **npm registry** in CI and monorepos — do not use `file:../memorix-retrieval` in `devDependencies` (causes TypeScript circular build errors with the main `"."` export).
39
+
40
+ ---
41
+
42
+ ## Package exports
43
+
44
+ The main entry re-exports the full write-side surface (mutations, seeds, reconcile, CLI helpers).
45
+
46
+ **Retrieval-safe subpaths** (module graph never imports `@x12i/memorix-retrieval`) — for `@x12i/memorix-retrieval` and other read-side consumers:
47
+
48
+ | Subpath | Symbols | Use |
49
+ |---------|---------|-----|
50
+ | `@x12i/memorix-descriptors/types` | `MemorixSliceDescriptor`, `MemorixTarget`, `MemorixInventoryPolicy`, … | Type-only imports |
51
+ | `@x12i/memorix-descriptors/catalog` | `defaultIdFieldForTarget`, `MEMORIX_INVENTORY_POLICIES_CATALOG`, … | Catalog ids |
52
+ | `@x12i/memorix-descriptors/collections/parse` | `parseMemorixCollectionName` | Last-dash collection naming |
53
+ | `@x12i/memorix-descriptors/validation/slice-shape` | `isMemorixSliceDescriptor`, `validateMemorixSliceDescriptorShape` | Slice shape validation |
54
+ | `@x12i/memorix-descriptors/validation/inventory-policy` | `DEFAULT_INVENTORY_POLICY`, `isCollectionIgnored`, … | Inventory ignore policy |
55
+
56
+ ```typescript
57
+ import type { MemorixSliceDescriptor } from "@x12i/memorix-descriptors/types";
58
+ import { defaultIdFieldForTarget } from "@x12i/memorix-descriptors/catalog";
59
+ import { parseMemorixCollectionName } from "@x12i/memorix-descriptors/collections/parse";
60
+ ```
61
+
62
+ Write-side / CLI / Metadata Studio hosts should import from `"."` or use `MemorixDescriptorAdmin`.
63
+
38
64
  ---
39
65
 
40
66
  ## Bootstrap
@@ -71,6 +97,20 @@ const admin = await createMemorixDescriptorAdminFromEnv();
71
97
  // Uses MONGO_URI + Xronox when set (for reconcile / ensureCollection)
72
98
  ```
73
99
 
100
+ ### Control plane (retrieval + descriptors)
101
+
102
+ For Explorer-like hosts that need both read and write stacks with shared `catalox`, `xronox`, and `appId`:
103
+
104
+ ```typescript
105
+ import { createMemorixControlPlaneFromEnv } from "@x12i/memorix-descriptors";
106
+
107
+ const { retrieval, descriptors } = await createMemorixControlPlaneFromEnv();
108
+ // retrieval.client — MemorixRetrievalClient (buildMemorixUnifiedInventory, fetchList, …)
109
+ // descriptors — MemorixDescriptorAdmin (mutations, reconcile, applyReconcileDraft)
110
+ ```
111
+
112
+ Uses `createMemorixRetrievalStackFromEnv` from `@x12i/memorix-retrieval` internally.
113
+
74
114
  ---
75
115
 
76
116
  ## Memorix targets
@@ -214,6 +254,37 @@ Content types live under `entityDescriptor.contentTypes` (each resolves to a Mon
214
254
 
215
255
  ---
216
256
 
257
+ ### Slice descriptors
258
+
259
+ Slice descriptors are list-catalog items with `kind: "slice"` (inventory-driven list views).
260
+
261
+ | Method | Description |
262
+ |--------|-------------|
263
+ | `createSliceDescriptor(input)` | Validate shape + snapshot refs; write to list catalog |
264
+ | `updateSliceDescriptor(sliceId, patch)` | |
265
+ | `removeSliceDescriptor(sliceId)` | |
266
+ | `validateSliceDescriptor(sliceId)` | Shape + entity/field/content-type checks |
267
+ | `previewSliceDescriptor(sliceId)` | Dry-run preview payload |
268
+
269
+ Also exported: `validateMemorixSliceDescriptorShape`, `validateSliceDescriptorAgainstSnapshot`, `buildSlicePreview` (main entry and `./validation/slice-shape` for shape-only helpers).
270
+
271
+ ---
272
+
273
+ ### Inventory policy
274
+
275
+ Ignored collections are stored in Catalox catalog `memorix-inventory-policies` (item id `default`).
276
+
277
+ | Method | Description |
278
+ |--------|-------------|
279
+ | `getInventoryPolicy()` | Load current policy |
280
+ | `updateInventoryPolicy(patch)` | Replace `ignoredCollections` |
281
+ | `ignoreCollection(input)` | Append ignored entry |
282
+ | `unignoreCollection(input)` | Remove ignored entry |
283
+
284
+ Also exported from `./validation/inventory-policy`: `DEFAULT_INVENTORY_POLICY`, `validateMemorixInventoryPolicy`, `isCollectionIgnored`, `ignoredCollectionKey`.
285
+
286
+ ---
287
+
217
288
  ### Relations
218
289
 
219
290
  Relations live on the **source** entity descriptor under `relations`.
@@ -267,19 +338,90 @@ Uses `mergeSeedItemScopeIntoUpsertData` from `@x12i/memorix-retrieval` for apply
267
338
 
268
339
  ### Mongo reconciliation
269
340
 
341
+ Uses **`buildMemorixUnifiedInventory`** from `@x12i/memorix-retrieval` (same shape as the Inventory UI). Legacy `buildMemorixCollectionInventory` is no longer used.
342
+
343
+ ```typescript
344
+ const result = await admin.reconcileDescriptorsWithMongo({
345
+ inventory: unifiedFromRetrieval, // optional — pass what Inventory already loaded
346
+ inventoryOptions: { sourceLens: "catalox-first", includeExactCounts: true },
347
+ allowCreateCollection: true, // create missing Mongo collections (native driver)
348
+ autoRegisterOrphans: true, // apply register-entity drafts for parseable orphans
349
+ skipMongo: true, // suggestions only, no Mongo side effects
350
+ });
351
+ ```
352
+
353
+ **Returns:**
354
+
355
+ ```typescript
356
+ {
357
+ inventory: MemorixUnifiedInventory;
358
+ issues: MemorixInventoryIssue[]; // same as inventory.issues
359
+ suggestions: ReconcileSuggestion[];
360
+ applied: Array<{ kind: string; detail: string }>;
361
+ }
362
+ ```
363
+
364
+ **Suggestion kinds** (aligned with unified inventory issues):
365
+
366
+ | Kind | Typical issue | Action |
367
+ |------|---------------|--------|
368
+ | `ensure-collection` | `missing-collection` | Create Mongo collection for declared content type |
369
+ | `empty-declared-collection` | `empty-declared-collection` | Informational |
370
+ | `create-descriptor-for-orphan` | `orphan-collection`, `object-missing` | Register new entity descriptor |
371
+ | `add-content-type-for-orphan` | `content-type-missing` | Add content type to existing entity |
372
+ | `fix-collection-binding` | `collection-mismatch` | Patch content type `collection` binding |
373
+ | `ignore-collection` | `unparseable-collection` | Add to inventory ignore policy |
374
+ | `unparseable-collection` | `unparseable-collection` | Informational / manual review |
375
+
376
+ Requires `MONGO_URI` and Xronox when building inventory internally (via `createMemorixDescriptorAdminFromEnv` or `createMemorixControlPlaneFromEnv`).
377
+
378
+ ---
379
+
380
+ ### Reconcile drafts & apply
381
+
382
+ Draft builders produce a **`ReconcileDescriptorDraft`** (`suggestedAction` + `draft` payload + `warnings`). Metadata Studio flow: **build draft → dry-run preview → apply**.
383
+
384
+ | Builder | `suggestedAction` |
385
+ |---------|-------------------|
386
+ | `buildDescriptorDraftFromOrphanCollection(input)` | `registerEntityDescriptor` |
387
+ | `buildAddContentTypeDraftFromCollection(input, snapshot?)` | `addContentType` |
388
+ | `buildFixCollectionBindingDraft(input, snapshot?, env?)` | `updateContentType` |
389
+ | `buildIgnoreCollectionDraft(input)` | `ignoreCollection` |
390
+
270
391
  | Method | Description |
271
392
  |--------|-------------|
272
- | `reconcileDescriptorsWithMongo()` | Uses `buildMemorixCollectionInventory` from retrieval |
393
+ | `buildReconcileDraftForSuggestion(suggestion, snapshot?, env?)` | Map a `ReconcileSuggestion` to a draft (uses builders above) |
394
+ | `applyReconcileDraft(ctx, draft, options?)` | Low-level apply (also `admin.applyReconcileDraft(draft, options?)`) |
273
395
 
274
- Returns `inventory` + `suggestions`:
396
+ Supported apply actions: `registerEntityDescriptor`, `addContentType`, `updateContentType`, `ignoreCollection`. `manualReview` drafts return `MANUAL_REVIEW_REQUIRED`.
275
397
 
276
- - `ensure-collection` — declared in descriptors, missing in Mongo
277
- - `empty-declared-collection` declared but zero documents
278
- - `create-descriptor-for-orphan` Mongo collection with no descriptor
398
+ ```typescript
399
+ const { suggestions } = await admin.reconcileDescriptorsWithMongo({ skipMongo: true });
400
+ const snapshot = await admin.loadSnapshot();
401
+ const draft = buildReconcileDraftForSuggestion(suggestions[0]!, snapshot);
402
+ const preview = await admin.applyReconcileDraft(draft!, { dryRun: true });
403
+ const applied = await admin.applyReconcileDraft(draft!, { dryRun: false });
404
+ ```
405
+
406
+ Also on admin (with snapshot-aware validation): `buildDescriptorDraftFromOrphanCollection`, `buildAddContentTypeDraftFromCollection`, `buildFixCollectionBindingDraft`, `buildIgnoreCollectionDraft`.
407
+
408
+ ---
279
409
 
280
- Descriptors in Catalox remain schema truth; orphans are **suggestions** only (`autoRegisterOrphans` not implemented).
410
+ ### Typed mutation dispatcher (optional)
281
411
 
282
- Requires `MONGO_URI` and Xronox when calling `createMemorixDescriptorAdminFromEnv`.
412
+ Single entry for hosts that route mutation requests by operation name (Explorer `POST /metadata/mutations`, CLI, CI):
413
+
414
+ ```typescript
415
+ import { executeDescriptorMutation } from "@x12i/memorix-descriptors";
416
+
417
+ const result = await executeDescriptorMutation(admin, {
418
+ operation: "addContentType",
419
+ input: { entityName: "assets", contentType: { key: "enrichment", postfix: "enrichment", collection: "assets-enrichment" } },
420
+ options: { dryRun: true },
421
+ });
422
+ ```
423
+
424
+ Dispatches to `MemorixDescriptorAdmin` methods including `applyReconcileDraft`. Unknown operations return `UNKNOWN_OPERATION`.
283
425
 
284
426
  ---
285
427
 
@@ -290,7 +432,7 @@ Binary: `memorix-descriptors` (after `npm run build`).
290
432
  | Command | Status |
291
433
  |---------|--------|
292
434
  | `validate` | ✅ |
293
- | `reconcile` | ✅ (needs Xronox / `MONGO_URI`) |
435
+ | `reconcile` | ✅ (needs Xronox / `MONGO_URI`; JSON includes `inventory`, `issues`, `suggestions`, `applied`) |
294
436
  | `graph [--format mermaid]` | ✅ |
295
437
  | `entity register --file <json> [--dry-run]` | ✅ |
296
438
  | `content-type add <entity> <key> --postfix <p> [--dry-run]` | ✅ |
@@ -301,16 +443,17 @@ Binary: `memorix-descriptors` (after `npm run build`).
301
443
  | `seed export <dir>` | ✅ |
302
444
  | `seed import <dir> [--dry-run]` | ✅ |
303
445
 
304
- **Library-only today** (use `MemorixDescriptorAdmin` directly): entity update/remove, property CRUD, content-type update/remove, list/item create/remove, relation CRUD, mapping update/remove, `ensureCollection`, etc.
305
-
306
446
  ```bash
307
447
  npx memorix-descriptors validate
448
+ npx memorix-descriptors reconcile --allow-create-collection --auto-register-orphans
308
449
  npx memorix-descriptors graph --format mermaid
309
450
  npx memorix-descriptors entity register --file ./new-entity.json --dry-run
310
451
  npx memorix-descriptors seed export ./catalox-seeds/inputs
311
452
  npx memorix-descriptors seed import ./catalox-seeds/inputs --dry-run
312
453
  ```
313
454
 
455
+ **Library-only today** (use `MemorixDescriptorAdmin` directly): entity update/remove, property CRUD, content-type update/remove, list/item/slice create/remove, relation CRUD, mapping update/remove, inventory policy, `ensureCollection`, reconcile draft builders, `applyReconcileDraft`, `executeDescriptorMutation`, etc.
456
+
314
457
  ---
315
458
 
316
459
  ## Explorer / host integration
@@ -318,27 +461,38 @@ npx memorix-descriptors seed import ./catalox-seeds/inputs --dry-run
318
461
  | UI surface | API |
319
462
  |------------|-----|
320
463
  | Entity graph canvas | `getDescriptorGraph`, `reconcileDescriptorsWithMongo` |
464
+ | Inventory / Metadata Studio reconcile | `buildMemorixUnifiedInventory` (retrieval) + `reconcileDescriptorsWithMongo`, `buildReconcileDraftForSuggestion`, `applyReconcileDraft` |
321
465
  | Add entity wizard | `registerEntityDescriptor` |
322
466
  | Column / field editor | `addProperty`, `updateListDescriptor` |
323
467
  | Detail layout editor | `updateItemDescriptor` |
468
+ | Slice editor | `createSliceDescriptor`, `validateSliceDescriptor`, `previewSliceDescriptor` |
324
469
  | Collection health | `reconcileDescriptorsWithMongo` |
470
+ | Ignore collection | `ignoreCollection`, `buildIgnoreCollectionDraft` |
325
471
  | Mapping editor | `registerMapping` |
326
472
  | Knowledge tab | Filter entities where `target === "knowledge"` |
473
+ | Generic mutation HTTP | `executeDescriptorMutation` (optional) |
327
474
 
328
- Hosts should **read** via `@x12i/memorix-retrieval` and **write** only through this package.
475
+ Hosts should **read** via `@x12i/memorix-retrieval` and **write** only through this package. Pass pre-built `MemorixUnifiedInventory` into reconcile when the Inventory UI already loaded it.
329
476
 
330
477
  ---
331
478
 
332
479
  ## Validation utilities (exported)
333
480
 
481
+ ### Main entry (`"."`)
482
+
334
483
  Re-exported / extended validators (aligned with retrieval rules, plus `knowledge` target):
335
484
 
336
485
  - `validateMemorixEntityDescriptor`, `validateMemorixListDescriptor`, `validateMemorixEntityListDescriptor`, `validateMemorixItemDescriptor`
486
+ - `validateMemorixSliceDescriptorShape`, `validateSliceDescriptorAgainstSnapshot`, `buildSlicePreview`, `isMemorixSliceDescriptor`
487
+ - `validateMemorixInventoryPolicy`, `validateIgnoredCollectionEntry`, `isCollectionIgnored`, `DEFAULT_INVENTORY_POLICY`
337
488
  - `validatePropertyDescriptor`, `assertListFieldsHumanReadable`
338
489
  - `defaultListDescriptorId`, `defaultItemDescriptorId`, `singularizeEntityName`, `isKebabCase`
490
+ - `parseMemorixCollectionName`, `defaultIdFieldForTarget`
339
491
  - `DescriptorValidationError`
340
492
 
341
- ---
493
+ ### Retrieval-safe subpaths
494
+
495
+ See [Package exports](#package-exports). Subpath entry modules do not import `@x12i/memorix-retrieval` (avoids TS5055 cycles when retrieval depends on descriptors).
342
496
 
343
497
  ## Environment variables
344
498
 
@@ -352,6 +506,7 @@ See [`.env.example`](.env.example).
352
506
  | `MONGO_URI` | Xronox for reconcile / `ensureCollection` |
353
507
  | `MEMORIX_ENTITIES_DB`, `MEMORIX_EVENTS_DB`, `MEMORIX_KNOWLEDGE_DB` | DB names |
354
508
  | `MEMORIX_*_COLLECTION_<ENTITY>` | Per-entity collection overrides |
509
+ | `MEMORIX_ENSURE_DESCRIPTOR_CATALOGS=1` | Auto-create descriptor catalogs on `createMemorixDescriptorAdminFromEnv` / control plane bootstrap |
355
510
  | `FIRESTORE_LIVE_TESTS=1` | Enable live integration tests |
356
511
 
357
512
  ---
@@ -364,7 +519,9 @@ npm run test:live # integration tests (reads .env, needs FIRESTORE_LIVE_TESTS=1)
364
519
  npm run test:all # both
365
520
  ```
366
521
 
367
- Live tests: Firestore connectivity, validate deployed graph, load smoke entity (`MEMORIX_SMOKE_ENTITY`, default `assets`), catalog listing, graph, collection resolve, dry-run `addProperty`. Reconcile live test requires `MONGO_URI`.
522
+ Live tests: Firestore connectivity, validate deployed graph, load smoke entity (`MEMORIX_SMOKE_ENTITY`, default `assets`), catalog listing, graph, collection resolve, dry-run `addProperty`. Reconcile live test requires `MONGO_URI` and asserts `MemorixUnifiedInventory` shape (`rows`, `issues`, `generatedAt`).
523
+
524
+ CI (`validate-descriptor-seeds` workflow) runs `npm ci`, installs `@x12i/memorix-retrieval` from npm for the peer dependency, then `npm run build`.
368
525
 
369
526
  ---
370
527
 
@@ -374,19 +531,23 @@ Live tests: Firestore connectivity, validate deployed graph, load smoke entity (
374
531
 
375
532
  | Area | Coverage |
376
533
  |------|----------|
377
- | Bootstrap | `createMemorixDescriptorAdmin`, `createMemorixDescriptorAdminFromEnv` |
534
+ | Bootstrap | `createMemorixDescriptorAdmin`, `createMemorixDescriptorAdminFromEnv`, `createMemorixControlPlaneFromEnv` |
535
+ | Package exports | Retrieval-safe subpaths (`/types`, `/catalog`, `/collections/parse`, `/validation/slice-shape`, `/validation/inventory-policy`) |
378
536
  | Entity lifecycle | Register (atomic list+item), update, soft/hard remove |
379
537
  | Content types | Add, update, remove with referential guards |
380
538
  | Collections | Resolve, ensure (inventory), rename **plan** |
381
539
  | Properties | Add, update, remove with list/item cascade |
382
540
  | List / item descriptors | Full CRUD + set default list/item |
541
+ | Slice descriptors | CRUD, validate, preview |
542
+ | Inventory policy | Ignore / unignore collections in Catalox |
383
543
  | Relations | Add, update, remove with list/item cascade |
384
544
  | Mappings | CRUD + cross-validation (`memorix-completion-mappings`) |
385
545
  | Integrity engine | Full-graph validation, dangling refs, forbidden patterns |
386
546
  | Descriptor graph | Build + Mermaid export |
387
547
  | Seeds | Export/import/manifest; compatible with retrieval inputs layout |
388
- | Reconcile | Inventory + suggestions; `autoRegisterOrphans`, `allowCreateCollection` (native Mongo `createCollection`) |
389
- | Dry-run | All mutations |
548
+ | Reconcile | Unified inventory + issues + extended suggestions; `applyReconcileDraft`; `autoRegisterOrphans`, `allowCreateCollection` |
549
+ | Mutation dispatcher | `executeDescriptorMutation` (optional) |
550
+ | Dry-run | All mutations + reconcile apply |
390
551
  | Targets | `entity`, `event`, `knowledge` in types and entity validation |
391
552
  | Transactions | `executeCataloxWrites` — compensating rollback on mid-batch Catalox failure; `rollbackPlan` on success |
392
553
  | Audit | JSONL via `MEMORIX_DESCRIPTORS_AUDIT_LOG` or per-mutation `reason` |
@@ -427,15 +588,15 @@ Live tests: Firestore connectivity, validate deployed graph, load smoke entity (
427
588
  |-------|--------|--------|
428
589
  | **1** | Bootstrap, validation, entity/content/property CRUD, seeds, dry-run | ✅ Done |
429
590
  | **2** | List/item/relation CRUD, cascades, graph | ✅ Done |
430
- | **3** | Mappings catalog, Mongo reconcile | ✅ Done |
431
- | **4** | Knowledge target across ecosystem | Descriptors + retrieval inventory/graph |
432
- | **5** | Rename/migrate, audit, rollback, CLI parity, CI seeds | ✅ Done (impact-report CLI optional) |
591
+ | **3** | Mappings catalog, Mongo reconcile (unified inventory) | ✅ Done |
592
+ | **4** | Knowledge target, slice descriptors, inventory policy, subpath exports | Done |
593
+ | **5** | Rename/migrate, audit, rollback, CLI parity, CI seeds, reconcile apply | ✅ Done (impact-report CLI optional) |
433
594
 
434
595
  ---
435
596
 
436
597
  ## Related packages
437
598
 
438
- - **@x12i/memorix-retrieval** — read/composition layer (discover, fetchList, fetchItem, collection inventory)
599
+ - **@x12i/memorix-retrieval** — read/composition layer (discover, fetchList, fetchItem, **`buildMemorixUnifiedInventory`**)
439
600
  - **@x12i/catalox** — descriptor storage and native catalog APIs
440
601
  - **@x12i/memorix-completion** — Memorix payload document writes (not descriptors)
441
602
  - **@x12i/xronox** — optional Mongo inventory for reconcile and `ensureCollection`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x12i/memorix-descriptors",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Manage Memorix entity, list, and item descriptors in Catalox",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",