@x12i/memorix-format 3.0.3 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -65
- package/README.md +78 -78
- package/dist/base/concept.d.ts +4 -0
- package/dist/base/concept.d.ts.map +1 -1
- package/dist/base/concept.js +5 -1
- package/dist/base/concept.js.map +1 -1
- package/dist/cli.js +36 -36
- package/dist/v2/identity.d.ts +19 -0
- package/dist/v2/identity.d.ts.map +1 -0
- package/dist/v2/identity.js +39 -0
- package/dist/v2/identity.js.map +1 -0
- package/dist/v2/index.d.ts +1 -0
- package/dist/v2/index.d.ts.map +1 -1
- package/dist/v2/index.js +1 -0
- package/dist/v2/index.js.map +1 -1
- package/docs/association-format.md +47 -47
- package/docs/memorix-format-requirements.md +54 -54
- package/docs/memorix-format.md +68 -68
- package/docs/memorix-record-v2.md +102 -101
- package/docs/memorix-workflow-format.md +126 -126
- package/docs/migrate-present-to-v2.md +49 -49
- package/examples/invalid-record.json +11 -11
- package/examples/v2/activity-events-snapshots.json +31 -31
- package/examples/v2/people-discovery.json +26 -26
- package/examples/v2/people-snapshots-employee.json +27 -27
- package/examples/v2/playbooks-knowledge.json +27 -27
- package/examples/v2/work-items-analysis.json +26 -26
- package/examples/v2/work-items-context.json +32 -32
- package/examples/v2/work-items-decisions.json +26 -26
- package/examples/v2/work-items-raw.json +37 -37
- package/examples/v2/work-items-relationships-candidate.json +38 -38
- package/examples/v2/work-items-snapshots-lifecycle.json +31 -31
- package/examples/v2/work-items-snapshots-lightweight-refs.json +34 -34
- package/examples/v2/work-items-snapshots.json +28 -28
- package/examples/v2/work-items-workflow.json +28 -28
- package/examples/valid-snapshot.json +30 -30
- package/meta/associated-conventions.json +59 -59
- package/meta/content-type-profiles.json +27 -27
- package/meta/content-types.json +80 -80
- package/meta/envelope.json +104 -104
- package/meta/inventory/managed-descriptors.json +78 -78
- package/meta/open-buckets.json +24 -24
- package/package.json +77 -77
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
# Memorix Format — Requirements (product layer)
|
|
2
|
-
|
|
3
|
-
**Package:** `@x12i/memorix-format`
|
|
4
|
-
**Depends on:** `@x12i/memorix-base-format` (fixed skeleton — do not re-state ENV/ID/DATA/SYS here).
|
|
5
|
-
|
|
6
|
-
This document covers **Memorix product** open-bucket conventions. Base envelope MUST be satisfied first (`TOOL-3`: layer checks on base).
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## Known open buckets (when present)
|
|
11
|
-
|
|
12
|
-
**BUCKET-5.**
|
|
13
|
-
|
|
14
|
-
| Bucket | MUST contain | MUST NOT contain |
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| `analytics` | Numeric rollups | The underlying list of records |
|
|
17
|
-
| `enrichment` | External / prior-system values as received | Interpreted judgments |
|
|
18
|
-
| `insights` | Judgments, scores, recommendations | Anything a reader would mistake for a stored native fact |
|
|
19
|
-
|
|
20
|
-
These names are **Memorix declarations**, not base-reserved keys. Base classifies them as open buckets.
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Associated properties
|
|
25
|
-
|
|
26
|
-
**ASSOC-1.** Keys matching Memorix association patterns (`associated…`, legacy short names, `associatedTop…`, `associated…Enrichment`, custom `associated` prefix).
|
|
27
|
-
|
|
28
|
-
**ASSOC-2.** When present, MUST be an array.
|
|
29
|
-
|
|
30
|
-
**ASSOC-3.** MUST be omitted when empty — never `[]`.
|
|
31
|
-
|
|
32
|
-
**ASSOC-5.** Items MUST be plain objects (linked payloads), not full envelopes.
|
|
33
|
-
|
|
34
|
-
**ASSOC-6.** Resolution MUST be snapshot-first (see association-format.md). Enforced by associator tooling, documented here.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Snapshot vs minimal (SCOPE)
|
|
39
|
-
|
|
40
|
-
**SCOPE-1.** Full open-bucket set SHOULD appear primarily on snapshots.
|
|
41
|
-
|
|
42
|
-
**SCOPE-2.** Non-snapshot content types MUST include `recordId` + `data`; SHOULD omit `analytics` / `insights` / most `associated*` unless opted in via ContentTypeMeta.
|
|
43
|
-
|
|
44
|
-
**SCOPE-3.** Readers MUST treat missing optional buckets as N/A, not error.
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## Validator
|
|
49
|
-
|
|
50
|
-
**TOOL-3.** `validateMemorixRecord` = `validateMemorixBaseRecord` + profile/ASSOC/SCOPE.
|
|
51
|
-
|
|
52
|
-
**TOOL-4.** `migrateMemorixRecord` / CLI `migrate` transforms legacy/transitional envelopes to the present format and SHOULD validate the result.
|
|
53
|
-
|
|
54
|
-
Built-in profiles: `snapshots`, `minimal` (`--profile=`).
|
|
1
|
+
# Memorix Format — Requirements (product layer)
|
|
2
|
+
|
|
3
|
+
**Package:** `@x12i/memorix-format`
|
|
4
|
+
**Depends on:** `@x12i/memorix-base-format` (fixed skeleton — do not re-state ENV/ID/DATA/SYS here).
|
|
5
|
+
|
|
6
|
+
This document covers **Memorix product** open-bucket conventions. Base envelope MUST be satisfied first (`TOOL-3`: layer checks on base).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Known open buckets (when present)
|
|
11
|
+
|
|
12
|
+
**BUCKET-5.**
|
|
13
|
+
|
|
14
|
+
| Bucket | MUST contain | MUST NOT contain |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `analytics` | Numeric rollups | The underlying list of records |
|
|
17
|
+
| `enrichment` | External / prior-system values as received | Interpreted judgments |
|
|
18
|
+
| `insights` | Judgments, scores, recommendations | Anything a reader would mistake for a stored native fact |
|
|
19
|
+
|
|
20
|
+
These names are **Memorix declarations**, not base-reserved keys. Base classifies them as open buckets.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Associated properties
|
|
25
|
+
|
|
26
|
+
**ASSOC-1.** Keys matching Memorix association patterns (`associated…`, legacy short names, `associatedTop…`, `associated…Enrichment`, custom `associated` prefix).
|
|
27
|
+
|
|
28
|
+
**ASSOC-2.** When present, MUST be an array.
|
|
29
|
+
|
|
30
|
+
**ASSOC-3.** MUST be omitted when empty — never `[]`.
|
|
31
|
+
|
|
32
|
+
**ASSOC-5.** Items MUST be plain objects (linked payloads), not full envelopes.
|
|
33
|
+
|
|
34
|
+
**ASSOC-6.** Resolution MUST be snapshot-first (see association-format.md). Enforced by associator tooling, documented here.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Snapshot vs minimal (SCOPE)
|
|
39
|
+
|
|
40
|
+
**SCOPE-1.** Full open-bucket set SHOULD appear primarily on snapshots.
|
|
41
|
+
|
|
42
|
+
**SCOPE-2.** Non-snapshot content types MUST include `recordId` + `data`; SHOULD omit `analytics` / `insights` / most `associated*` unless opted in via ContentTypeMeta.
|
|
43
|
+
|
|
44
|
+
**SCOPE-3.** Readers MUST treat missing optional buckets as N/A, not error.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Validator
|
|
49
|
+
|
|
50
|
+
**TOOL-3.** `validateMemorixRecord` = `validateMemorixBaseRecord` + profile/ASSOC/SCOPE.
|
|
51
|
+
|
|
52
|
+
**TOOL-4.** `migrateMemorixRecord` / CLI `migrate` transforms legacy/transitional envelopes to the present format and SHOULD validate the result.
|
|
53
|
+
|
|
54
|
+
Built-in profiles: `snapshots`, `minimal` (`--profile=`).
|
package/docs/memorix-format.md
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
# Memorix Record Format
|
|
2
|
-
|
|
3
|
-
> **Canonical SoT for new work:** [memorix-record/2](./memorix-record-v2.md) (`validateMemorixRecordV2`).
|
|
4
|
-
> **Present envelope (migration source):** documented below — still enforced by default in writer/pipeline until `MEMORIX_RECORD_FORMAT=v2`.
|
|
5
|
-
> Core present envelope helpers: [`@x12i/memorix-base-format`](https://www.npmjs.com/package/@x12i/memorix-base-format) (temporary; folding into this package).
|
|
6
|
-
> Requirements: [memorix-format-requirements.md](./memorix-format-requirements.md).
|
|
7
|
-
|
|
8
|
-
## Purpose
|
|
9
|
-
|
|
10
|
-
A Memorix record is a structured memory object: a stable envelope around domain payload, with clear separation between business data, derived analytics, external enrichment, AI insights, and cross-entity references.
|
|
11
|
-
|
|
12
|
-
**Prefer `memorix-record/2` for all new platform paths.** Present envelope remains for reading/migrating existing data.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Present envelope (migration source)
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
type MemorixRecordPresent = {
|
|
20
|
-
_id?: string;
|
|
21
|
-
recordId: string;
|
|
22
|
-
concept: {
|
|
23
|
-
_extIdentifier: { kind: string; key: string; [kindValue: string]: string };
|
|
24
|
-
title: string;
|
|
25
|
-
};
|
|
26
|
-
data: JsonObject;
|
|
27
|
-
analytics?: JsonObject;
|
|
28
|
-
enrichment?: JsonObject;
|
|
29
|
-
insights?: JsonObject;
|
|
30
|
-
// associated…?: JsonObject[]; // copied payloads — removed in V2
|
|
31
|
-
_system?: {
|
|
32
|
-
state?: "active" | "archived" | "superseded";
|
|
33
|
-
lifecycle?: Array<{ process: string; processedAt: string }>;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Migrate legacy → present: `npx memorix-format migrate`.
|
|
39
|
-
Migrate present → V2: `npx memorix-format migrate-to-v2 --object-type=… --content-type=… --data-category=…`.
|
|
40
|
-
|
|
41
|
-
Associated properties use the reserved `associated` prefix on **present** records only. See [association-format.md](./association-format.md). V2 rejects copied association roots.
|
|
42
|
-
|
|
43
|
-
Human/LLM readers SHOULD omit root `_…` and `concept._extIdentifier` by default; keep `recordId` for joins.
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Data And Associated Buckets (present)
|
|
48
|
-
|
|
49
|
-
Every piece of business data lives in **exactly one** of these buckets (plus the envelope fields above):
|
|
50
|
-
|
|
51
|
-
| Bucket | Contents |
|
|
52
|
-
|---|---|
|
|
53
|
-
| **`data`** | Native facts about the subject itself |
|
|
54
|
-
| **`analytics`** | Numeric rollups computed from other records |
|
|
55
|
-
| **`enrichment`** | External / prior-system values as received |
|
|
56
|
-
| **`insights`** | AI / judgment outputs |
|
|
57
|
-
| **`associated*`** | Copied related payloads (present only; removed in V2) |
|
|
58
|
-
|
|
59
|
-
On **memorix-record/2**, snapshot buckets are optional and **omitted when empty**. Root `associated*` may hold **lightweight refs** only (Option A — still format-valid). **Authoritative relationship storage (Gate G4)** is centralized per-category collections (Candidate C); see `@x12i/memorix-relationship-store` (archived: `.tmp/housekeeping-2026-07-23/docs/re-factoring-and-opx-agent/RELATIONSHIP-STORAGE-DECISION.md`).
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Further reading
|
|
64
|
-
|
|
65
|
-
- [memorix-record-v2.md](./memorix-record-v2.md) — Gate G2 contract
|
|
66
|
-
- [association-format.md](./association-format.md) — present association naming
|
|
67
|
-
- [memorix-workflow-format.md](./memorix-workflow-format.md) — workflow as sibling content
|
|
68
|
-
- Golden V2 examples: `examples/v2/`
|
|
1
|
+
# Memorix Record Format
|
|
2
|
+
|
|
3
|
+
> **Canonical SoT for new work:** [memorix-record/2](./memorix-record-v2.md) (`validateMemorixRecordV2`).
|
|
4
|
+
> **Present envelope (migration source):** documented below — still enforced by default in writer/pipeline until `MEMORIX_RECORD_FORMAT=v2`.
|
|
5
|
+
> Core present envelope helpers: [`@x12i/memorix-base-format`](https://www.npmjs.com/package/@x12i/memorix-base-format) (temporary; folding into this package).
|
|
6
|
+
> Requirements: [memorix-format-requirements.md](./memorix-format-requirements.md).
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
A Memorix record is a structured memory object: a stable envelope around domain payload, with clear separation between business data, derived analytics, external enrichment, AI insights, and cross-entity references.
|
|
11
|
+
|
|
12
|
+
**Prefer `memorix-record/2` for all new platform paths.** Present envelope remains for reading/migrating existing data.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Present envelope (migration source)
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
type MemorixRecordPresent = {
|
|
20
|
+
_id?: string;
|
|
21
|
+
recordId: string;
|
|
22
|
+
concept: {
|
|
23
|
+
_extIdentifier: { kind: string; key: string; [kindValue: string]: string };
|
|
24
|
+
title: string;
|
|
25
|
+
};
|
|
26
|
+
data: JsonObject;
|
|
27
|
+
analytics?: JsonObject;
|
|
28
|
+
enrichment?: JsonObject;
|
|
29
|
+
insights?: JsonObject;
|
|
30
|
+
// associated…?: JsonObject[]; // copied payloads — removed in V2
|
|
31
|
+
_system?: {
|
|
32
|
+
state?: "active" | "archived" | "superseded";
|
|
33
|
+
lifecycle?: Array<{ process: string; processedAt: string }>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Migrate legacy → present: `npx memorix-format migrate`.
|
|
39
|
+
Migrate present → V2: `npx memorix-format migrate-to-v2 --object-type=… --content-type=… --data-category=…`.
|
|
40
|
+
|
|
41
|
+
Associated properties use the reserved `associated` prefix on **present** records only. See [association-format.md](./association-format.md). V2 rejects copied association roots.
|
|
42
|
+
|
|
43
|
+
Human/LLM readers SHOULD omit root `_…` and `concept._extIdentifier` by default; keep `recordId` for joins.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Data And Associated Buckets (present)
|
|
48
|
+
|
|
49
|
+
Every piece of business data lives in **exactly one** of these buckets (plus the envelope fields above):
|
|
50
|
+
|
|
51
|
+
| Bucket | Contents |
|
|
52
|
+
|---|---|
|
|
53
|
+
| **`data`** | Native facts about the subject itself |
|
|
54
|
+
| **`analytics`** | Numeric rollups computed from other records |
|
|
55
|
+
| **`enrichment`** | External / prior-system values as received |
|
|
56
|
+
| **`insights`** | AI / judgment outputs |
|
|
57
|
+
| **`associated*`** | Copied related payloads (present only; removed in V2) |
|
|
58
|
+
|
|
59
|
+
On **memorix-record/2**, snapshot buckets are optional and **omitted when empty**. Root `associated*` may hold **lightweight refs** only (Option A — still format-valid). **Authoritative relationship storage (Gate G4)** is centralized per-category collections (Candidate C); see `@x12i/memorix-relationship-store` (archived: `.tmp/housekeeping-2026-07-23/docs/re-factoring-and-opx-agent/RELATIONSHIP-STORAGE-DECISION.md`).
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Further reading
|
|
64
|
+
|
|
65
|
+
- [memorix-record-v2.md](./memorix-record-v2.md) — Gate G2 contract
|
|
66
|
+
- [association-format.md](./association-format.md) — present association naming
|
|
67
|
+
- [memorix-workflow-format.md](./memorix-workflow-format.md) — workflow as sibling content
|
|
68
|
+
- Golden V2 examples: `examples/v2/`
|
|
@@ -1,101 +1,102 @@
|
|
|
1
|
-
# memorix-record/2
|
|
2
|
-
|
|
3
|
-
**Status:** Gate G2 contract — preferred source of truth for new platform work.
|
|
4
|
-
**Package:** `@x12i/memorix-format` (`validateMemorixRecordV2`, `migratePresentToV2`, CLI `validate-v2` / `migrate-to-v2`).
|
|
5
|
-
|
|
6
|
-
Present-tense envelope docs remain in [memorix-format.md](./memorix-format.md) for migration only.
|
|
7
|
-
Migration semantics: [migrate-present-to-v2.md](./migrate-present-to-v2.md).
|
|
8
|
-
|
|
9
|
-
## Envelope
|
|
10
|
-
|
|
11
|
-
```ts
|
|
12
|
-
type MemorixRecordV2 = {
|
|
13
|
-
format: "memorix-record/2";
|
|
14
|
-
recordId: string;
|
|
15
|
-
revision: number; // starts at 1; increments every successful mutation
|
|
16
|
-
objectType: string;
|
|
17
|
-
contentType: string;
|
|
18
|
-
dataCategory: "entity" | "event" | "knowledge";
|
|
19
|
-
concept: {
|
|
20
|
-
title: string;
|
|
21
|
-
identifiers: {
|
|
22
|
-
primary: { kind: string; value: string; issuer?: string; normalizedValue?: string };
|
|
23
|
-
alternates?: Array<...>; // omit when empty
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
data: Record<string, unknown>;
|
|
27
|
-
analytics?: Record<string, unknown>; // snapshots (and knowledge) only; omit when unused
|
|
28
|
-
enrichment?: Record<string, unknown>;
|
|
29
|
-
insights?: Record<string, unknown>;
|
|
30
|
-
// Option A — lightweight relationship refs remain FORMAT-VALID (G2).
|
|
31
|
-
// Gate G4 selected authoritative storage = central per-category collections (Candidate C).
|
|
32
|
-
// associatedPeople?: Array<{
|
|
33
|
-
// relationshipDefinitionId: string; // required
|
|
34
|
-
// recordId: string; // required
|
|
35
|
-
// relationshipId?: string; // optional — deterministically derivable
|
|
36
|
-
// }>;
|
|
37
|
-
_system: {
|
|
38
|
-
state: "active" | "archived" | "superseded";
|
|
39
|
-
createdAt: string;
|
|
40
|
-
modifiedAt: string;
|
|
41
|
-
observedAt?: string;
|
|
42
|
-
lifecycle?: Array<{ process: string; processedAt: string }>; // omit when empty
|
|
43
|
-
provenance?: Record<string, unknown>;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Locked decisions (Gate G2)
|
|
49
|
-
|
|
50
|
-
1. **Empty optional snapshot buckets are omitted** — never emit `{}`.
|
|
51
|
-
2. **Workflow is a sibling content record** (`contentType: "workflow"`), not a separate document system.
|
|
52
|
-
3. **Composition** = same `recordId` across content types; not a relationship.
|
|
53
|
-
4. **`_graphRuns` / `_jobTypeRuns` stay off the subject** — operational run ledger owns run history.
|
|
54
|
-
5. **V2 rejects copied related-record payloads.** Root `associated*` may hold **lightweight relationship refs** only: required `relationshipDefinitionId` + `recordId`; optional `relationshipId` (derivable). Without `relationshipDefinitionId` the item is not a relationship. **Option A** (direct-record lightweight `associated*` roots) remains **format-valid** for validation and migration compatibility.
|
|
55
|
-
6. **Authoritative physical relationship storage is Gate G4 Candidate C** — org-prefixed per-category `relationships` collections (`entity` / `event` / `knowledge`). Option A lightweight roots and sibling `relationships` content are **not** the selected authoritative storage model; see `@x12i/memorix-relationship-store` / `@x12i/memorix-relationships` (decision note archived under `.tmp/housekeeping-2026-07-23/docs/re-factoring-and-opx-agent/RELATIONSHIP-STORAGE-DECISION.md`).
|
|
56
|
-
7. **
|
|
57
|
-
|
|
58
|
-
## Revision vs lifecycle
|
|
59
|
-
|
|
60
|
-
| Rule | Behavior |
|
|
61
|
-
|---|---|
|
|
62
|
-
| Revision | Increments on every successful mutation |
|
|
63
|
-
| Lifecycle | Appended only for meaningful process/state events |
|
|
64
|
-
| Independence | Revision may change with no lifecycle entry |
|
|
65
|
-
| Concurrency | Stale `expectedRevision` is rejected (`checkExpectedRevision`) |
|
|
66
|
-
|
|
67
|
-
Helpers: `applySuccessfulMutation`, `nextRevision`, `checkExpectedRevision`.
|
|
68
|
-
|
|
69
|
-
## Discriminators
|
|
70
|
-
|
|
71
|
-
- Pure structural V2 validation does not invent discriminator values.
|
|
72
|
-
- Content-type **profiles** (from metadata) may declare `path`, `required`, `defaultValue`, `allowedValues`.
|
|
73
|
-
- Missing + profile default → warning `V2-DISCRIMINATOR-DEFAULT` (writers apply default).
|
|
74
|
-
- Missing + required + no default → error `V2-DISCRIMINATOR`.
|
|
75
|
-
|
|
76
|
-
## Examples
|
|
77
|
-
|
|
78
|
-
See [`examples/v2/`](../examples/v2/) — includes lifecycle, lightweight refs, analysis/decision/discovery, workflow sibling, relationships-candidate sibling.
|
|
79
|
-
|
|
80
|
-
## Migrate
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
npx memorix-format migrate-to-v2 ./present.json \
|
|
84
|
-
--object-type=work-items \
|
|
85
|
-
--content-type=snapshots \
|
|
86
|
-
--data-category=entity \
|
|
87
|
-
--issuer=opx-source
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Output includes `v2`, `extractedRelationships`, and `warnings`.
|
|
91
|
-
|
|
92
|
-
## Writer cutover flag
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
1
|
+
# memorix-record/2
|
|
2
|
+
|
|
3
|
+
**Status:** Gate G2 contract — preferred source of truth for new platform work.
|
|
4
|
+
**Package:** `@x12i/memorix-format` (`validateMemorixRecordV2`, `migratePresentToV2`, CLI `validate-v2` / `migrate-to-v2`).
|
|
5
|
+
|
|
6
|
+
Present-tense envelope docs remain in [memorix-format.md](./memorix-format.md) for migration only.
|
|
7
|
+
Migration semantics: [migrate-present-to-v2.md](./migrate-present-to-v2.md).
|
|
8
|
+
|
|
9
|
+
## Envelope
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
type MemorixRecordV2 = {
|
|
13
|
+
format: "memorix-record/2";
|
|
14
|
+
recordId: string;
|
|
15
|
+
revision: number; // starts at 1; increments every successful mutation
|
|
16
|
+
objectType: string;
|
|
17
|
+
contentType: string;
|
|
18
|
+
dataCategory: "entity" | "event" | "knowledge";
|
|
19
|
+
concept: {
|
|
20
|
+
title: string;
|
|
21
|
+
identifiers: {
|
|
22
|
+
primary: { kind: string; value: string; issuer?: string; normalizedValue?: string };
|
|
23
|
+
alternates?: Array<...>; // omit when empty
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
data: Record<string, unknown>;
|
|
27
|
+
analytics?: Record<string, unknown>; // snapshots (and knowledge) only; omit when unused
|
|
28
|
+
enrichment?: Record<string, unknown>;
|
|
29
|
+
insights?: Record<string, unknown>;
|
|
30
|
+
// Option A — lightweight relationship refs remain FORMAT-VALID (G2).
|
|
31
|
+
// Gate G4 selected authoritative storage = central per-category collections (Candidate C).
|
|
32
|
+
// associatedPeople?: Array<{
|
|
33
|
+
// relationshipDefinitionId: string; // required
|
|
34
|
+
// recordId: string; // required
|
|
35
|
+
// relationshipId?: string; // optional — deterministically derivable
|
|
36
|
+
// }>;
|
|
37
|
+
_system: {
|
|
38
|
+
state: "active" | "archived" | "superseded";
|
|
39
|
+
createdAt: string;
|
|
40
|
+
modifiedAt: string;
|
|
41
|
+
observedAt?: string;
|
|
42
|
+
lifecycle?: Array<{ process: string; processedAt: string }>; // omit when empty
|
|
43
|
+
provenance?: Record<string, unknown>;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Locked decisions (Gate G2)
|
|
49
|
+
|
|
50
|
+
1. **Empty optional snapshot buckets are omitted** — never emit `{}`.
|
|
51
|
+
2. **Workflow is a sibling content record** (`contentType: "workflow"`), not a separate document system.
|
|
52
|
+
3. **Composition** = same `recordId` across content types; not a relationship.
|
|
53
|
+
4. **`_graphRuns` / `_jobTypeRuns` stay off the subject** — operational run ledger owns run history.
|
|
54
|
+
5. **V2 rejects copied related-record payloads.** Root `associated*` may hold **lightweight relationship refs** only: required `relationshipDefinitionId` + `recordId`; optional `relationshipId` (derivable). Without `relationshipDefinitionId` the item is not a relationship. **Option A** (direct-record lightweight `associated*` roots) remains **format-valid** for validation and migration compatibility.
|
|
55
|
+
6. **Authoritative physical relationship storage is Gate G4 Candidate C** — org-prefixed per-category `relationships` collections (`entity` / `event` / `knowledge`). Option A lightweight roots and sibling `relationships` content are **not** the selected authoritative storage model; see `@x12i/memorix-relationship-store` / `@x12i/memorix-relationships` (decision note archived under `.tmp/housekeeping-2026-07-23/docs/re-factoring-and-opx-agent/RELATIONSHIP-STORAGE-DECISION.md`).
|
|
56
|
+
7. **Writers persist `memorix-record/2` exclusively.** The historical `MEMORIX_RECORD_FORMAT=v2` switch is obsolete and must not be documented as optional. Present-format docs remain for migration tooling only.
|
|
57
|
+
|
|
58
|
+
## Revision vs lifecycle
|
|
59
|
+
|
|
60
|
+
| Rule | Behavior |
|
|
61
|
+
|---|---|
|
|
62
|
+
| Revision | Increments on every successful mutation |
|
|
63
|
+
| Lifecycle | Appended only for meaningful process/state events |
|
|
64
|
+
| Independence | Revision may change with no lifecycle entry |
|
|
65
|
+
| Concurrency | Stale `expectedRevision` is rejected (`checkExpectedRevision`) |
|
|
66
|
+
|
|
67
|
+
Helpers: `applySuccessfulMutation`, `nextRevision`, `checkExpectedRevision`.
|
|
68
|
+
|
|
69
|
+
## Discriminators
|
|
70
|
+
|
|
71
|
+
- Pure structural V2 validation does not invent discriminator values.
|
|
72
|
+
- Content-type **profiles** (from metadata) may declare `path`, `required`, `defaultValue`, `allowedValues`.
|
|
73
|
+
- Missing + profile default → warning `V2-DISCRIMINATOR-DEFAULT` (writers apply default).
|
|
74
|
+
- Missing + required + no default → error `V2-DISCRIMINATOR`.
|
|
75
|
+
|
|
76
|
+
## Examples
|
|
77
|
+
|
|
78
|
+
See [`examples/v2/`](../examples/v2/) — includes lifecycle, lightweight refs, analysis/decision/discovery, workflow sibling, relationships-candidate sibling.
|
|
79
|
+
|
|
80
|
+
## Migrate
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npx memorix-format migrate-to-v2 ./present.json \
|
|
84
|
+
--object-type=work-items \
|
|
85
|
+
--content-type=snapshots \
|
|
86
|
+
--data-category=entity \
|
|
87
|
+
--issuer=opx-source
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Output includes `v2`, `extractedRelationships`, and `warnings`.
|
|
91
|
+
|
|
92
|
+
## Writer cutover flag
|
|
93
|
+
|
|
94
|
+
Obsolete. Production writers always validate and persist `memorix-record/2`. Do not set `MEMORIX_RECORD_FORMAT`.
|
|
95
|
+
|
|
96
|
+
## Subject identity
|
|
97
|
+
|
|
98
|
+
See [the subject-model contract](../../docs/subject-model-contract.md). `recordId` is never Mongo `_id`. Source identifiers are adopted as `{issuer}/{kind}/{value}`.
|
|
99
|
+
|
|
100
|
+
## Folding `@x12i/memorix-base-format`
|
|
101
|
+
|
|
102
|
+
Present base validation still depends on `@x12i/memorix-base-format`. That package becomes a temporary re-export after consumers move to `@x12i/memorix-format` / V2, then is deleted (Phase 0 deletion ledger).
|