@neocompose/cli 0.40.0 → 0.41.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.
package/dist/neo.mjs CHANGED
@@ -19441,7 +19441,7 @@ var init_project_schema_contract_generated = __esm({
19441
19441
  "../packages/neoscript-language/src/project-schema-contract.generated.ts"() {
19442
19442
  "use strict";
19443
19443
  PROJECT_SCHEMA_MANIFEST_FORMAT_VERSION = 4;
19444
- PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "4.0";
19444
+ PROJECT_SCHEMA_MANIFEST_CONTRACT_VERSION = "4.1";
19445
19445
  PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
19446
19446
  NEO_PROJECT_SOURCE_RECORD_CONTRACT = {
19447
19447
  "recordFields": {
@@ -19459,6 +19459,7 @@ var init_project_schema_contract_generated = __esm({
19459
19459
  "system",
19460
19460
  "storage",
19461
19461
  "storageKey",
19462
+ "distribution",
19462
19463
  "minValue",
19463
19464
  "maxValue",
19464
19465
  "decimalPoints",
@@ -19657,6 +19658,10 @@ var init_project_schema_contract_generated = __esm({
19657
19658
  "Visible",
19658
19659
  "Hidden"
19659
19660
  ],
19661
+ "NeoSubtreeDistribution": [
19662
+ "Sparse",
19663
+ "Packed"
19664
+ ],
19660
19665
  "NeoStringFormat": [
19661
19666
  "Localized",
19662
19667
  "Plain"
@@ -23829,6 +23834,7 @@ function fieldsForAnnotation(name, context, environment) {
23829
23834
  }
23830
23835
  if (name === "settings") return settingsFields(context);
23831
23836
  if (name === "storage") return storageFields(context);
23837
+ if (name === "distribution") return distributionFields(context);
23832
23838
  if (name === "relations") return relationFields(context, environment);
23833
23839
  if (name === "system") {
23834
23840
  return context.kind === "class" || context.kind === "schema" || context.kind === "member" ? markerFields("NeoSystemAttribute") : null;
@@ -23901,6 +23907,12 @@ function settingsFields(context) {
23901
23907
  )
23902
23908
  );
23903
23909
  }
23910
+ function distributionFields(context) {
23911
+ if (context.kind === "member" || context.kind === "type") {
23912
+ return [{ name: "kind", type: "NeoSubtreeDistribution" }];
23913
+ }
23914
+ return null;
23915
+ }
23904
23916
  function storageFields(context) {
23905
23917
  if (context.kind === "class") {
23906
23918
  return [{ name: "allowed", type: "NeoAllowedStorage" }];
@@ -29447,7 +29459,7 @@ function projectDeclarationAnnotationNames(declaration) {
29447
29459
  ];
29448
29460
  }
29449
29461
  function projectMemberAnnotationNames(member) {
29450
- const names = ["id", "settings", "storage"];
29462
+ const names = ["id", "settings", "storage", "distribution"];
29451
29463
  if (member?.type.name === "List") names.push("index", "column");
29452
29464
  return names;
29453
29465
  }
@@ -31044,6 +31056,8 @@ function annotationSignatureParameters(name) {
31044
31056
  return ["named settings"];
31045
31057
  case "storage":
31046
31058
  return ["StorageKind allowed"];
31059
+ case "distribution":
31060
+ return ["NeoSubtreeDistribution kind"];
31047
31061
  case "relations":
31048
31062
  return ["relation descriptors"];
31049
31063
  case "incomplete":
@@ -35728,6 +35742,7 @@ var init_document_contracts = __esm({
35728
35742
  "system",
35729
35743
  "storage",
35730
35744
  "storageKey",
35745
+ "distribution",
35731
35746
  "minValue",
35732
35747
  "maxValue",
35733
35748
  "decimalPoints",
@@ -37029,6 +37044,11 @@ function memberFromDocument(record3, members, owners, classNames, context) {
37029
37044
  // user-authored unless its own document explicitly marks it as system.
37030
37045
  system: systemFromDocument(data.system, record3, "system"),
37031
37046
  storage: normalizedStorage(field("storage", null), record3),
37047
+ // Read from the row's own document rather than through `field(...)`: an
37048
+ // override that declares no distribution inherits, and resolving the
37049
+ // chain here would emit the ancestor's explicit choice back into the
37050
+ // override's source as phantom drift (P76 §2).
37051
+ distribution: normalizedDistribution(data.distribution, record3),
37032
37052
  storageKey: normalizedStorageKey(field("storageKey", null), record3)
37033
37053
  };
37034
37054
  const primitiveKind = SIMPLE_MEMBER_KIND_BY_KIND.get(kind);
@@ -37378,6 +37398,9 @@ function memberToDocumentFields(member, baseData3) {
37378
37398
  } else if (isOverride && baseData3?.storage === 0) {
37379
37399
  fields.storage = 0;
37380
37400
  }
37401
+ if (member.distribution !== null) {
37402
+ fields.distribution = MEMBER_DISTRIBUTION.indexOf(member.distribution);
37403
+ }
37381
37404
  if (member.storageKey !== null) fields.storageKey = member.storageKey;
37382
37405
  if (member.kind === "int" || member.kind === "float") {
37383
37406
  if (member.min !== null) fields.minValue = member.min;
@@ -38134,6 +38157,10 @@ function normalizedStorage(value, record3) {
38134
38157
  const storage = ordinalValue(value ?? 0, MEMBER_STORAGE, record3, "storage");
38135
38158
  return storage === "inherit" ? null : storage;
38136
38159
  }
38160
+ function normalizedDistribution(value, record3) {
38161
+ if (value === void 0 || value === null) return null;
38162
+ return ordinalValue(value, MEMBER_DISTRIBUTION, record3, "distribution");
38163
+ }
38137
38164
  function normalizedStorageKey(value, record3) {
38138
38165
  if (value === void 0 || value === null || value === "") {
38139
38166
  return null;
@@ -38258,7 +38285,7 @@ function invalidDocument(record3, path, message) {
38258
38285
  `${record3.recordKind}:${record3.recordId}.${path} ${message}.`
38259
38286
  );
38260
38287
  }
38261
- var MEMBER_KIND, MEMBER_MODIFIERS, MEMBER_ACCESS, MEMBER_STORAGE, STRING_FORMAT, MEMBER_SEARCH_BY, MEMBER_SELECTION, FUNCTION_DISPATCH, FUNCTION_BODY, MEMBER_PAYLOAD, DICTIONARY_KEY, LIST_KIND, LIST_INDEX, COLUMN_VISIBILITY, COLUMN_PIN, COLUMN_OVERFLOW, GENERIC_BINDING, TYPE_KIND_BY_MEMBER_KIND, SIMPLE_MEMBER_KIND_BY_KIND, MEMBER_KIND_BY_KIND, TYPE_MEMBER_KIND_BY_KIND, MEMBER_IDENTITY_FIELDS, INHERITED_MEMBER_ORDINAL_FIELDS, CHAIN_RESOLVED_OPTIONAL_MEMBER_FIELDS;
38288
+ var MEMBER_KIND, MEMBER_MODIFIERS, MEMBER_ACCESS, MEMBER_STORAGE, MEMBER_DISTRIBUTION, STRING_FORMAT, MEMBER_SEARCH_BY, MEMBER_SELECTION, FUNCTION_DISPATCH, FUNCTION_BODY, MEMBER_PAYLOAD, DICTIONARY_KEY, LIST_KIND, LIST_INDEX, COLUMN_VISIBILITY, COLUMN_PIN, COLUMN_OVERFLOW, GENERIC_BINDING, TYPE_KIND_BY_MEMBER_KIND, SIMPLE_MEMBER_KIND_BY_KIND, MEMBER_KIND_BY_KIND, TYPE_MEMBER_KIND_BY_KIND, MEMBER_IDENTITY_FIELDS, INHERITED_MEMBER_ORDINAL_FIELDS, CHAIN_RESOLVED_OPTIONAL_MEMBER_FIELDS;
38262
38289
  var init_codecs = __esm({
38263
38290
  "src/project-manifest/record-adapters/codecs.ts"() {
38264
38291
  "use strict";
@@ -38297,6 +38324,7 @@ var init_codecs = __esm({
38297
38324
  MEMBER_MODIFIERS = ["virtual", "sealed", "abstract", "static"];
38298
38325
  MEMBER_ACCESS = ["public", "protected", "private"];
38299
38326
  MEMBER_STORAGE = ["inherit", "immutable", "save", "session"];
38327
+ MEMBER_DISTRIBUTION = ["sparse", "packed"];
38300
38328
  STRING_FORMAT = ["localized", "plain"];
38301
38329
  MEMBER_SEARCH_BY = ["none", "memberKey"];
38302
38330
  MEMBER_SELECTION = ["single", "multi"];
@@ -40675,6 +40703,13 @@ function assertMember2(value, path) {
40675
40703
  }
40676
40704
  assertSystem(member.system, `${path}.system`);
40677
40705
  nullableStorage(member.storage, `${path}.storage`);
40706
+ nullableDistribution(member.distribution, `${path}.distribution`);
40707
+ if (member.distribution !== null && (member.kind === "computed" || member.kind === "function" || member.kind === "scriptFunction")) {
40708
+ invalid(
40709
+ `${path}.distribution`,
40710
+ "a value-less member has no stored value to distribute."
40711
+ );
40712
+ }
40678
40713
  nullableNonEmptyString(member.storageKey, `${path}.storageKey`);
40679
40714
  if (member.isReadOnly === true) {
40680
40715
  if (owner.kind !== "classMember" && owner.kind !== "sharedClassMember") {
@@ -40738,6 +40773,12 @@ function assertMember2(value, path) {
40738
40773
  );
40739
40774
  arrayOf(member.indexes, `${path}.indexes`, assertListIndex);
40740
40775
  arrayOf(member.columns, `${path}.columns`, assertListColumn);
40776
+ if (member.distribution === "packed" && member.listKind === "unordered") {
40777
+ invalid(
40778
+ `${path}.distribution`,
40779
+ "cannot be packed while listKind is unordered: an unordered list's membership is the set of live rows carrying its id, so its entries occupy no position inside a parent row to be packed into."
40780
+ );
40781
+ }
40741
40782
  if (member.isReadOnly === true && Array.isArray(member.indexes) && member.indexes.length > 0) {
40742
40783
  invalid(`${path}.indexes`, "must be empty on a read-only member.");
40743
40784
  }
@@ -41823,6 +41864,10 @@ function nullableStorage(value, path) {
41823
41864
  if (value === null) return;
41824
41865
  stringIn(value, /* @__PURE__ */ new Set(["immutable", "save", "session"]), path);
41825
41866
  }
41867
+ function nullableDistribution(value, path) {
41868
+ if (value === null) return;
41869
+ stringIn(value, /* @__PURE__ */ new Set(["sparse", "packed"]), path);
41870
+ }
41826
41871
  function stringIn(value, allowed, path) {
41827
41872
  const result = stringAt(value, path);
41828
41873
  if (!allowed.has(result)) {
@@ -42065,7 +42110,8 @@ var init_validate = __esm({
42065
42110
  "overrideOf",
42066
42111
  "system",
42067
42112
  "storage",
42068
- "storageKey"
42113
+ "storageKey",
42114
+ "distribution"
42069
42115
  ];
42070
42116
  MEMBER_KEYS_BY_KIND = {
42071
42117
  null: [],
@@ -42669,6 +42715,148 @@ var init_member_storage = __esm({
42669
42715
  }
42670
42716
  });
42671
42717
 
42718
+ // ../src/models/members/member-kind-enum.ts
42719
+ var MemberKind;
42720
+ var init_member_kind_enum = __esm({
42721
+ "../src/models/members/member-kind-enum.ts"() {
42722
+ "use strict";
42723
+ MemberKind = /* @__PURE__ */ ((MemberKind16) => {
42724
+ MemberKind16[MemberKind16["Null"] = 0] = "Null";
42725
+ MemberKind16[MemberKind16["Bool"] = 1] = "Bool";
42726
+ MemberKind16[MemberKind16["Int"] = 2] = "Int";
42727
+ MemberKind16[MemberKind16["String"] = 3] = "String";
42728
+ MemberKind16[MemberKind16["Float"] = 4] = "Float";
42729
+ MemberKind16[MemberKind16["Dictionary"] = 5] = "Dictionary";
42730
+ MemberKind16[MemberKind16["List"] = 6] = "List";
42731
+ MemberKind16[MemberKind16["Class"] = 7] = "Class";
42732
+ MemberKind16[MemberKind16["Enum"] = 8] = "Enum";
42733
+ MemberKind16[MemberKind16["Lookup"] = 9] = "Lookup";
42734
+ MemberKind16[MemberKind16["NSProperty"] = 10] = "NSProperty";
42735
+ MemberKind16[MemberKind16["Sprite"] = 11] = "Sprite";
42736
+ MemberKind16[MemberKind16["Audio"] = 12] = "Audio";
42737
+ MemberKind16[MemberKind16["Function"] = 13] = "Function";
42738
+ MemberKind16[MemberKind16["Vector2"] = 14] = "Vector2";
42739
+ MemberKind16[MemberKind16["Vector2Int"] = 15] = "Vector2Int";
42740
+ MemberKind16[MemberKind16["Vector3"] = 16] = "Vector3";
42741
+ MemberKind16[MemberKind16["Vector3Int"] = 17] = "Vector3Int";
42742
+ MemberKind16[MemberKind16["DialogueLookup"] = 18] = "DialogueLookup";
42743
+ MemberKind16[MemberKind16["Color"] = 19] = "Color";
42744
+ MemberKind16[MemberKind16["Decimal"] = 20] = "Decimal";
42745
+ MemberKind16[MemberKind16["Generic"] = 21] = "Generic";
42746
+ MemberKind16[MemberKind16["Interface"] = 22] = "Interface";
42747
+ MemberKind16[MemberKind16["NSFunction"] = 23] = "NSFunction";
42748
+ MemberKind16[MemberKind16["FunctionRef"] = 24] = "FunctionRef";
42749
+ MemberKind16[MemberKind16["NSDelegate"] = 25] = "NSDelegate";
42750
+ MemberKind16[MemberKind16["NSAction"] = 26] = "NSAction";
42751
+ MemberKind16[MemberKind16["Variant"] = 27] = "Variant";
42752
+ return MemberKind16;
42753
+ })(MemberKind || {});
42754
+ }
42755
+ });
42756
+
42757
+ // ../src/models/members/member-subtree-distribution.ts
42758
+ function isNeoSubtreeDistributionKind(value) {
42759
+ return value === 0 /* Sparse */ || value === 1 /* Packed */;
42760
+ }
42761
+ function sparse(growth) {
42762
+ return { distribution: 0 /* Sparse */, growth };
42763
+ }
42764
+ function resolveAutomatic(kind, settings) {
42765
+ const rule = AUTOMATIC_MEMBER_DISTRIBUTION[kind];
42766
+ if (rule === 1 /* Packed */) return PACKED;
42767
+ if (rule === "valueLess") return void 0;
42768
+ if (rule === "openSlot") {
42769
+ throw new Error(
42770
+ `automaticMemberDistribution: MemberKind.Generic has no automatic distribution. Substitute the concrete binding member first and pass its kind and settings.`
42771
+ );
42772
+ }
42773
+ if (rule === "stringFormat") {
42774
+ return settings.format === 1 /* Plain */ ? sparse("unboundedText") : PACKED;
42775
+ }
42776
+ if (rule === "selectionCardinality") {
42777
+ return settings.selection === 1 /* Multi */ ? sparse("selectionCount") : PACKED;
42778
+ }
42779
+ return sparse(rule.sparse);
42780
+ }
42781
+ function automaticMemberDistribution(kind, settings) {
42782
+ return resolveAutomatic(kind, settings)?.distribution;
42783
+ }
42784
+ function memberKindSupportsDistribution(kind) {
42785
+ return AUTOMATIC_MEMBER_DISTRIBUTION[kind] !== "valueLess";
42786
+ }
42787
+ var AUTOMATIC_MEMBER_DISTRIBUTION, PACKED;
42788
+ var init_member_subtree_distribution = __esm({
42789
+ "../src/models/members/member-subtree-distribution.ts"() {
42790
+ "use strict";
42791
+ init_member_kind_enum();
42792
+ AUTOMATIC_MEMBER_DISTRIBUTION = {
42793
+ /** A stored null has no growth axis. */
42794
+ [0 /* Null */]: 1 /* Packed */,
42795
+ /** Fixed scalar. */
42796
+ [1 /* Bool */]: 1 /* Packed */,
42797
+ /** Fixed scalar. */
42798
+ [2 /* Int */]: 1 /* Packed */,
42799
+ /**
42800
+ * A localized value stores one localized-text id; plain text is unbounded.
42801
+ * The per-locale bodies stay on their own records under either arm.
42802
+ */
42803
+ [3 /* String */]: "stringFormat",
42804
+ /** Fixed scalar. */
42805
+ [4 /* Float */]: 1 /* Packed */,
42806
+ /** Entry count grows with content. */
42807
+ [5 /* Dictionary */]: { sparse: "entryCount" },
42808
+ /** Entry count grows with content. */
42809
+ [6 /* List */]: { sparse: "entryCount" },
42810
+ /** Schema and authored child count can grow. */
42811
+ [7 /* Class */]: { sparse: "authoredChildren" },
42812
+ /** The enum declaration bounds the selected option ids; enum edits recheck encoded size. */
42813
+ [8 /* Enum */]: 1 /* Packed */,
42814
+ /** Single selection stores at most one value id; multi-selection follows collection size. */
42815
+ [9 /* Lookup */]: "selectionCardinality",
42816
+ /** Computed property, no stored value. */
42817
+ [10 /* NSProperty */]: "valueLess",
42818
+ /** Fixed `fileId` and `sliceIndex` shape. */
42819
+ [11 /* Sprite */]: 1 /* Packed */,
42820
+ /** Fixed one-file-id shape. */
42821
+ [12 /* Audio */]: 1 /* Packed */,
42822
+ /** Declaration only, no stored value. */
42823
+ [13 /* Function */]: "valueLess",
42824
+ /** Fixed two-number shape. */
42825
+ [14 /* Vector2 */]: 1 /* Packed */,
42826
+ /** Fixed two-integer shape. */
42827
+ [15 /* Vector2Int */]: 1 /* Packed */,
42828
+ /** Fixed three-number shape. */
42829
+ [16 /* Vector3 */]: 1 /* Packed */,
42830
+ /** Fixed three-integer shape. */
42831
+ [17 /* Vector3Int */]: 1 /* Packed */,
42832
+ /** Single selection stores at most one dialogue id. */
42833
+ [18 /* DialogueLookup */]: "selectionCardinality",
42834
+ /** Fixed four-channel shape. */
42835
+ [19 /* Color */]: 1 /* Packed */,
42836
+ /** Exact decimals are arbitrary-length strings. */
42837
+ [20 /* Decimal */]: { sparse: "unboundedText" },
42838
+ /** The open slot has no automatic shape; an explicit member-chain choice still wins. */
42839
+ [21 /* Generic */]: "openSlot",
42840
+ /** Type information only; not a persistable member record kind. */
42841
+ [22 /* Interface */]: "valueLess",
42842
+ /** Declaration only, no stored value. */
42843
+ [23 /* NSFunction */]: "valueLess",
42844
+ /** Fixed one-member-id shape. */
42845
+ [24 /* FunctionRef */]: 1 /* Packed */,
42846
+ /** A closure can carry unbounded code and captures. */
42847
+ [25 /* NSDelegate */]: { sparse: "closureBody" },
42848
+ /** Listener count grows with content. */
42849
+ [26 /* NSAction */]: { sparse: "listenerCount" },
42850
+ /** Fixed class, variant, and optional bound-row ids. */
42851
+ [27 /* Variant */]: 1 /* Packed */
42852
+ };
42853
+ PACKED = {
42854
+ distribution: 1 /* Packed */,
42855
+ growth: null
42856
+ };
42857
+ }
42858
+ });
42859
+
42672
42860
  // ../src/models/core/world-system-kinds.generated.ts
42673
42861
  function isNeoWorldSystemClassKind(value) {
42674
42862
  if (typeof value !== "string") return false;
@@ -44435,45 +44623,6 @@ var init_classes = __esm({
44435
44623
  }
44436
44624
  });
44437
44625
 
44438
- // ../src/models/members/member-kind-enum.ts
44439
- var MemberKind;
44440
- var init_member_kind_enum = __esm({
44441
- "../src/models/members/member-kind-enum.ts"() {
44442
- "use strict";
44443
- MemberKind = /* @__PURE__ */ ((MemberKind16) => {
44444
- MemberKind16[MemberKind16["Null"] = 0] = "Null";
44445
- MemberKind16[MemberKind16["Bool"] = 1] = "Bool";
44446
- MemberKind16[MemberKind16["Int"] = 2] = "Int";
44447
- MemberKind16[MemberKind16["String"] = 3] = "String";
44448
- MemberKind16[MemberKind16["Float"] = 4] = "Float";
44449
- MemberKind16[MemberKind16["Dictionary"] = 5] = "Dictionary";
44450
- MemberKind16[MemberKind16["List"] = 6] = "List";
44451
- MemberKind16[MemberKind16["Class"] = 7] = "Class";
44452
- MemberKind16[MemberKind16["Enum"] = 8] = "Enum";
44453
- MemberKind16[MemberKind16["Lookup"] = 9] = "Lookup";
44454
- MemberKind16[MemberKind16["NSProperty"] = 10] = "NSProperty";
44455
- MemberKind16[MemberKind16["Sprite"] = 11] = "Sprite";
44456
- MemberKind16[MemberKind16["Audio"] = 12] = "Audio";
44457
- MemberKind16[MemberKind16["Function"] = 13] = "Function";
44458
- MemberKind16[MemberKind16["Vector2"] = 14] = "Vector2";
44459
- MemberKind16[MemberKind16["Vector2Int"] = 15] = "Vector2Int";
44460
- MemberKind16[MemberKind16["Vector3"] = 16] = "Vector3";
44461
- MemberKind16[MemberKind16["Vector3Int"] = 17] = "Vector3Int";
44462
- MemberKind16[MemberKind16["DialogueLookup"] = 18] = "DialogueLookup";
44463
- MemberKind16[MemberKind16["Color"] = 19] = "Color";
44464
- MemberKind16[MemberKind16["Decimal"] = 20] = "Decimal";
44465
- MemberKind16[MemberKind16["Generic"] = 21] = "Generic";
44466
- MemberKind16[MemberKind16["Interface"] = 22] = "Interface";
44467
- MemberKind16[MemberKind16["NSFunction"] = 23] = "NSFunction";
44468
- MemberKind16[MemberKind16["FunctionRef"] = 24] = "FunctionRef";
44469
- MemberKind16[MemberKind16["NSDelegate"] = 25] = "NSDelegate";
44470
- MemberKind16[MemberKind16["NSAction"] = 26] = "NSAction";
44471
- MemberKind16[MemberKind16["Variant"] = 27] = "Variant";
44472
- return MemberKind16;
44473
- })(MemberKind || {});
44474
- }
44475
- });
44476
-
44477
44626
  // ../src/models/members/structured-leaf-fields.ts
44478
44627
  function isStructuredLeafKind(kind) {
44479
44628
  return Object.prototype.hasOwnProperty.call(STRUCTURED_LEAF_FIELDS, kind);
@@ -45322,6 +45471,12 @@ function hasValidStorageField(v, allowNull) {
45322
45471
  if (typeof v.kind !== "number") return false;
45323
45472
  return memberKindSupportsStorage(v.kind);
45324
45473
  }
45474
+ function hasValidDistributionField(v) {
45475
+ if (v.distribution === void 0) return true;
45476
+ if (!isNeoSubtreeDistributionKind(v.distribution)) return false;
45477
+ if (typeof v.kind !== "number") return false;
45478
+ return memberKindSupportsDistribution(v.kind);
45479
+ }
45325
45480
  function isMemberBase(value) {
45326
45481
  const v = value;
45327
45482
  if (v?.kind === 22 /* Interface */) return false;
@@ -45345,6 +45500,7 @@ function isMemberBase(value) {
45345
45500
  return false;
45346
45501
  }
45347
45502
  if (!hasValidStorageField(v, true)) return false;
45503
+ if (!hasValidDistributionField(v)) return false;
45348
45504
  const storageKey = getField(value, "storageKey");
45349
45505
  if (storageKey !== void 0 && storageKey !== null && typeof storageKey !== "string")
45350
45506
  return false;
@@ -45443,6 +45599,7 @@ function isMemberOverrideBase(value) {
45443
45599
  return false;
45444
45600
  }
45445
45601
  if (!hasValidStorageField(v, false)) return false;
45602
+ if (!hasValidDistributionField(v)) return false;
45446
45603
  if (v.defaultValue !== void 0 && v.defaultValue !== null && !isMemberValueBase(v.defaultValue)) {
45447
45604
  return false;
45448
45605
  }
@@ -45686,6 +45843,7 @@ var init_member_kinds = __esm({
45686
45843
  init_classes();
45687
45844
  init_member_kind_enum();
45688
45845
  init_member_storage();
45846
+ init_member_subtree_distribution();
45689
45847
  init_structured_leaf_fields();
45690
45848
  init_member_kind_enum();
45691
45849
  FunctionArgumentReservedNames = /* @__PURE__ */ new Set([
@@ -46280,6 +46438,7 @@ var init_world_system_classes_generated = __esm({
46280
46438
  "../src/models/classes/world-system-classes.generated.ts"() {
46281
46439
  "use strict";
46282
46440
  init_member_storage();
46441
+ init_member_subtree_distribution();
46283
46442
  init_classes();
46284
46443
  init_member_kinds();
46285
46444
  WORLD_GRID_CHILDREN_MEMBER_ID = "system_98578ba3-a70e-4397-9283-996a898d44c8";
@@ -46373,6 +46532,7 @@ var init_world_system_classes_generated = __esm({
46373
46532
  memberKind: "string",
46374
46533
  defaultValue: "",
46375
46534
  format: 1 /* Plain */,
46535
+ distribution: 1 /* Packed */,
46376
46536
  requirement: 1 /* Required */,
46377
46537
  schemaKey: "Name"
46378
46538
  }
@@ -46389,6 +46549,7 @@ var init_world_system_classes_generated = __esm({
46389
46549
  memberKind: "string",
46390
46550
  defaultValue: "",
46391
46551
  format: 1 /* Plain */,
46552
+ distribution: 1 /* Packed */,
46392
46553
  requirement: 1 /* Required */,
46393
46554
  schemaKey: "Name"
46394
46555
  },
@@ -46421,6 +46582,7 @@ var init_world_system_classes_generated = __esm({
46421
46582
  memberKind: "string",
46422
46583
  defaultValue: "",
46423
46584
  format: 1 /* Plain */,
46585
+ distribution: 1 /* Packed */,
46424
46586
  requirement: 1 /* Required */,
46425
46587
  schemaKey: "Name"
46426
46588
  },
@@ -46453,6 +46615,7 @@ var init_world_system_classes_generated = __esm({
46453
46615
  memberKind: "string",
46454
46616
  defaultValue: "",
46455
46617
  format: 1 /* Plain */,
46618
+ distribution: 1 /* Packed */,
46456
46619
  requirement: 1 /* Required */,
46457
46620
  schemaKey: "Name"
46458
46621
  },
@@ -46483,6 +46646,7 @@ var init_world_system_classes_generated = __esm({
46483
46646
  memberKind: "string",
46484
46647
  defaultValue: "",
46485
46648
  format: 1 /* Plain */,
46649
+ distribution: 1 /* Packed */,
46486
46650
  requirement: 1 /* Required */,
46487
46651
  schemaKey: "Name"
46488
46652
  },
@@ -46570,6 +46734,7 @@ var init_world_system_classes_generated = __esm({
46570
46734
  memberKind: "string",
46571
46735
  defaultValue: "",
46572
46736
  format: 1 /* Plain */,
46737
+ distribution: 1 /* Packed */,
46573
46738
  requirement: 1 /* Required */,
46574
46739
  schemaKey: "Name"
46575
46740
  },
@@ -47332,6 +47497,7 @@ var init_world_system_classes_generated = __esm({
47332
47497
  memberKind: "string",
47333
47498
  defaultInitializerCode: "clipKey",
47334
47499
  format: 1 /* Plain */,
47500
+ distribution: 1 /* Packed */,
47335
47501
  requirement: 1 /* Required */,
47336
47502
  schemaKey: "ClipKey"
47337
47503
  }
@@ -48172,6 +48338,11 @@ function substituteMember(member, env, members, preResolvedMember) {
48172
48338
  } else {
48173
48339
  delete substituted.storageKey;
48174
48340
  }
48341
+ if (resolved.distribution !== void 0) {
48342
+ substituted.distribution = resolved.distribution;
48343
+ } else {
48344
+ delete substituted.distribution;
48345
+ }
48175
48346
  if (resolved.modifier !== void 0) {
48176
48347
  substituted.modifier = resolved.modifier;
48177
48348
  } else {
@@ -48719,10 +48890,31 @@ function pickInstanceProvenance(source) {
48719
48890
  ...source.instanceVariantRowValueId === void 0 ? {} : { instanceVariantRowValueId: source.instanceVariantRowValueId }
48720
48891
  };
48721
48892
  }
48893
+ function canonicalInstanceProvenanceViolation(value) {
48894
+ const constructorArgs = "constructorArgs" in value ? value.constructorArgs : void 0;
48895
+ const constructorId = "instanceConstructorId" in value ? value.instanceConstructorId : void 0;
48896
+ const variantId = "instanceVariantId" in value ? value.instanceVariantId : void 0;
48897
+ if (constructorArgs !== void 0 && constructorId === void 0 && typeof variantId !== "string") {
48898
+ return "constructor-args-without-stamp";
48899
+ }
48900
+ if (typeof constructorId === "string" && constructorArgs === void 0) {
48901
+ return "named-constructor-without-args";
48902
+ }
48903
+ if (constructorId === null && constructorArgs !== void 0 && typeof constructorArgs === "object" && constructorArgs !== null && !Array.isArray(constructorArgs) && Object.keys(constructorArgs).length > 0) {
48904
+ return "implicit-constructor-with-args";
48905
+ }
48906
+ if ("instanceVariantRowValueId" in value && typeof value.instanceVariantRowValueId === "string" && typeof variantId !== "string") {
48907
+ return "variant-row-without-variant";
48908
+ }
48909
+ return null;
48910
+ }
48722
48911
  function isVirtualInstanceRootShape(value) {
48723
48912
  if (value.instanceConstructorId !== void 0) return true;
48724
48913
  return typeof value.instanceVariantId === "string";
48725
48914
  }
48915
+ function isCollapseStampedInstanceRoot(value) {
48916
+ return isLiteralValueContent(value) && isVirtualInstanceRootShape(value);
48917
+ }
48726
48918
  function carriesCompleteConstructionRecipe(value) {
48727
48919
  if (!isVirtualInstanceRootShape(value)) return false;
48728
48920
  if (value.instanceConstructorId === null) return true;
@@ -49359,6 +49551,463 @@ var init_read_only_members = __esm({
49359
49551
  }
49360
49552
  });
49361
49553
 
49554
+ // ../src/models/members/member-value-id.ts
49555
+ function derivedMemberValueId(memberId) {
49556
+ return inSystemRecordNamespaceOf(
49557
+ memberId,
49558
+ v5_default(withoutSystemRecordIdPrefix(memberId), NEO_MEMBER_VALUE_NAMESPACE)
49559
+ );
49560
+ }
49561
+ function virtualValueId(instanceRootId, sourceIdentity3) {
49562
+ return inSystemRecordNamespaceOf(
49563
+ instanceRootId,
49564
+ v5_default(
49565
+ `${withoutSystemRecordIdPrefix(instanceRootId)}:${sourceIdentity3}`,
49566
+ NEO_VIRTUAL_VALUE_NAMESPACE
49567
+ )
49568
+ );
49569
+ }
49570
+ function pendingVirtualValueId(pendingInstanceRootId, sourceIdentity3) {
49571
+ return `${PENDING_VIRTUAL_VALUE_PREFIX}${encodeURIComponent(pendingInstanceRootId)}:${encodeURIComponent(sourceIdentity3)}`;
49572
+ }
49573
+ function pendingVirtualValueIdentity(token) {
49574
+ if (!token.startsWith(PENDING_VIRTUAL_VALUE_PREFIX)) return null;
49575
+ const payload = token.slice(PENDING_VIRTUAL_VALUE_PREFIX.length);
49576
+ const separator = payload.indexOf(":");
49577
+ if (separator < 0) return null;
49578
+ return {
49579
+ instanceRootId: decodeURIComponent(payload.slice(0, separator)),
49580
+ sourceIdentity: decodeURIComponent(payload.slice(separator + 1))
49581
+ };
49582
+ }
49583
+ function pendingMemberValueId(pendingMemberId) {
49584
+ return `${PENDING_MEMBER_VALUE_PREFIX}${encodeURIComponent(pendingMemberId)}`;
49585
+ }
49586
+ function pendingMemberValueMemberId(token) {
49587
+ if (!token.startsWith(PENDING_MEMBER_VALUE_PREFIX)) return null;
49588
+ return decodeURIComponent(token.slice(PENDING_MEMBER_VALUE_PREFIX.length));
49589
+ }
49590
+ var NEO_MEMBER_VALUE_NAMESPACE, NEO_VIRTUAL_VALUE_NAMESPACE, PENDING_VIRTUAL_VALUE_PREFIX, PENDING_MEMBER_VALUE_PREFIX;
49591
+ var init_member_value_id = __esm({
49592
+ "../src/models/members/member-value-id.ts"() {
49593
+ "use strict";
49594
+ init_dist_node();
49595
+ init_system_record_id();
49596
+ NEO_MEMBER_VALUE_NAMESPACE = "7f2b9c14-58d6-5a07-b3e1-4c9d0a6f8b25";
49597
+ NEO_VIRTUAL_VALUE_NAMESPACE = "3e8ca0b3-e3f1-5d5f-bf2f-6ab5ee3896d0";
49598
+ PENDING_VIRTUAL_VALUE_PREFIX = "__pending__:virtual-value:";
49599
+ PENDING_MEMBER_VALUE_PREFIX = "__pending__:member-value:";
49600
+ }
49601
+ });
49602
+
49603
+ // ../src/models/members/packed-value-encoding.ts
49604
+ function isPackedValueEnvelope(value) {
49605
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
49606
+ return false;
49607
+ }
49608
+ return Object.hasOwn(value, PACKED_VALUE_ENTRY_KEY);
49609
+ }
49610
+ function rowCarriesPackedValueContent(content) {
49611
+ if (containerHoldsPackedEntry(content.value)) return true;
49612
+ return containerHoldsPackedEntry(content.constructorArgs);
49613
+ }
49614
+ function expandPackedValueRows(rows) {
49615
+ let firstPacked = -1;
49616
+ for (let index = 0; index < rows.length; index += 1) {
49617
+ const row = rows[index];
49618
+ if (row === void 0 || !rowCarriesPackedValueContent(row)) continue;
49619
+ firstPacked = index;
49620
+ break;
49621
+ }
49622
+ if (firstPacked < 0) return rows;
49623
+ const expanded = rows.slice(0, firstPacked);
49624
+ for (let index = firstPacked; index < rows.length; index += 1) {
49625
+ const row = rows[index];
49626
+ if (row === void 0) continue;
49627
+ const decoded = decodePackedValueRow(row);
49628
+ expanded.push(decoded.row, ...decoded.children);
49629
+ }
49630
+ return expanded;
49631
+ }
49632
+ function expandPackedDocumentValues(document) {
49633
+ const stored = document.values;
49634
+ const expanded = expandPackedValueRows(stored);
49635
+ if (expanded === stored) return document;
49636
+ return { ...document, values: expanded };
49637
+ }
49638
+ function decodePackedValueRow(row) {
49639
+ if (!rowCarriesPackedValueContent(row)) {
49640
+ return { row, children: NO_CHILDREN, packedChildIdsByParentId: NO_EDGES };
49641
+ }
49642
+ const state = {
49643
+ edges: /* @__PURE__ */ new Map(),
49644
+ seenIds: /* @__PURE__ */ new Set([row.id]),
49645
+ projectId: row.projectId,
49646
+ mapKey: row.mapKey
49647
+ };
49648
+ const children = [];
49649
+ const scope = {
49650
+ state,
49651
+ ownerId: row.id,
49652
+ ownerLabel: `value "${row.id}"`,
49653
+ constructionRootId: isCollapseStampedInstanceRoot(row) ? row.id : null
49654
+ };
49655
+ const value = decodeContentField(row.value, "value", scope, children);
49656
+ const constructorArgs = decodeContentField(
49657
+ isLiteralValueContent(row) ? row.constructorArgs : void 0,
49658
+ "constructorArgs",
49659
+ scope,
49660
+ children
49661
+ );
49662
+ return {
49663
+ row: withDecodedContent(row, value, constructorArgs),
49664
+ children,
49665
+ packedChildIdsByParentId: state.edges
49666
+ };
49667
+ }
49668
+ function encodePackedValueRow(args) {
49669
+ const scope = {
49670
+ parent: args.parent,
49671
+ rowsById: args.rowsById,
49672
+ packedChildIdsByParentId: args.packedChildIdsByParentId,
49673
+ ownerId: args.parent.id,
49674
+ ownerLabel: `value "${args.parent.id}"`,
49675
+ constructionRootId: isCollapseStampedInstanceRoot(args.parent) ? args.parent.id : null
49676
+ };
49677
+ const pending = pendingPackedChildIds(scope);
49678
+ if (pending === null) return args.parent;
49679
+ const value = encodeContentField(args.parent.value, pending, scope);
49680
+ const constructorArgs = encodeContentField(
49681
+ isLiteralValueContent(args.parent) ? args.parent.constructorArgs : void 0,
49682
+ pending,
49683
+ scope
49684
+ );
49685
+ assertEveryChildPlaced(pending, scope);
49686
+ return withDecodedContent(args.parent, value, constructorArgs);
49687
+ }
49688
+ function canonicalPackedChildId(args) {
49689
+ if (args.constructionRootId === null) return null;
49690
+ if (typeof args.sourceValueId !== "string") return null;
49691
+ if (args.sourceValueId.length === 0) return null;
49692
+ return virtualValueId(args.constructionRootId, args.sourceValueId);
49693
+ }
49694
+ function decodeContentField(container, field, scope, children) {
49695
+ if (!containerHoldsPackedEntry(container)) return null;
49696
+ if (Array.isArray(container)) {
49697
+ return {
49698
+ content: container.map(
49699
+ (entry, index) => isPackedValueEnvelope(entry) ? decodeEnvelope(entry, `${field}[${index}]`, scope, children) : entry
49700
+ )
49701
+ };
49702
+ }
49703
+ const decoded = {};
49704
+ for (const [key, entry] of Object.entries(
49705
+ container
49706
+ )) {
49707
+ decoded[key] = isPackedValueEnvelope(entry) ? decodeEnvelope(
49708
+ entry,
49709
+ `${field}[${JSON.stringify(key)}]`,
49710
+ scope,
49711
+ children
49712
+ ) : entry;
49713
+ }
49714
+ return { content: decoded };
49715
+ }
49716
+ function decodeEnvelope(envelope, position, scope, children) {
49717
+ const label = `Packed value entry at ${scope.ownerLabel}.${position}`;
49718
+ const entry = envelope[PACKED_VALUE_ENTRY_KEY];
49719
+ assertDecodableEntry(entry, label);
49720
+ const id2 = packedEntryLogicalId(entry, label, scope.constructionRootId);
49721
+ if (scope.state.seenIds.has(id2)) {
49722
+ throw new PackedValueEncodingError(
49723
+ `${label} resolves to id "${id2}", which another row in the same packed payload already claims.`
49724
+ );
49725
+ }
49726
+ scope.state.seenIds.add(id2);
49727
+ registerEdge(scope.state.edges, scope.ownerId, id2);
49728
+ const childScope = {
49729
+ state: scope.state,
49730
+ ownerId: id2,
49731
+ ownerLabel: `packed value "${id2}"`,
49732
+ constructionRootId: isCollapseStampedInstanceRoot(entry) ? id2 : scope.constructionRootId
49733
+ };
49734
+ const nested = [];
49735
+ children.push(logicalChildRow(entry, id2, childScope, nested));
49736
+ children.push(...nested);
49737
+ return id2;
49738
+ }
49739
+ function logicalChildRow(entry, id2, scope, children) {
49740
+ const rowFields = {
49741
+ id: id2,
49742
+ projectId: scope.state.projectId,
49743
+ createdAt: entry.createdAt,
49744
+ updatedAt: entry.updatedAt,
49745
+ ...scope.state.mapKey === void 0 ? {} : { mapKey: scope.state.mapKey },
49746
+ ...entry.genericBindings === void 0 ? {} : { genericBindings: entry.genericBindings },
49747
+ ...entry.sourceValueId === void 0 ? {} : { sourceValueId: entry.sourceValueId }
49748
+ };
49749
+ if (isInitValueContent(entry)) return { ...rowFields, init: entry.init };
49750
+ const value = decodeContentField(entry.value, "value", scope, children);
49751
+ const constructorArgs = decodeContentField(
49752
+ entry.constructorArgs,
49753
+ "constructorArgs",
49754
+ scope,
49755
+ children
49756
+ );
49757
+ return {
49758
+ ...rowFields,
49759
+ ...literalContent(entry, value, constructorArgs)
49760
+ };
49761
+ }
49762
+ function packedEntryLogicalId(entry, label, constructionRootId) {
49763
+ const canonical = canonicalPackedChildId({
49764
+ constructionRootId,
49765
+ sourceValueId: entry.sourceValueId
49766
+ });
49767
+ const stored = entry.id;
49768
+ if (stored === void 0) {
49769
+ if (canonical === null) {
49770
+ throw new PackedValueEncodingError(
49771
+ `${label} stores no "id" and its position derives none: only a deterministic child of an enclosing construction root, stamped with a "sourceValueId", may omit its logical id.`
49772
+ );
49773
+ }
49774
+ return canonical;
49775
+ }
49776
+ if (typeof stored !== "string" || stored.length === 0) {
49777
+ throw new PackedValueEncodingError(
49778
+ `${label} stores an "id" that is not a non-empty string.`
49779
+ );
49780
+ }
49781
+ if (stored === canonical) {
49782
+ throw new PackedValueEncodingError(
49783
+ `${label} stores id "${stored}", which its position already derives; a derivable id must be omitted rather than repeated.`
49784
+ );
49785
+ }
49786
+ return stored;
49787
+ }
49788
+ function assertDecodableEntry(entry, label) {
49789
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
49790
+ throw new PackedValueEncodingError(`${label} is not an object.`);
49791
+ }
49792
+ for (const field of PACKED_ENTRY_FORBIDDEN_FIELDS) {
49793
+ if (!Object.hasOwn(entry, field)) continue;
49794
+ throw new PackedValueEncodingError(
49795
+ `${label} stores "${field}", which decoding derives from its owning row.`
49796
+ );
49797
+ }
49798
+ if (!("createdAt" in entry) || typeof entry.createdAt !== "number") {
49799
+ throw new PackedValueEncodingError(
49800
+ `${label} stores no numeric "createdAt".`
49801
+ );
49802
+ }
49803
+ if (!("updatedAt" in entry) || typeof entry.updatedAt !== "number") {
49804
+ throw new PackedValueEncodingError(
49805
+ `${label} stores no numeric "updatedAt".`
49806
+ );
49807
+ }
49808
+ const hasValue = Object.hasOwn(entry, "value");
49809
+ const hasInit = Object.hasOwn(entry, "init");
49810
+ if (hasValue && hasInit) {
49811
+ throw new PackedValueEncodingError(
49812
+ `${label} stores both "value" and "init"; a value container holds exactly one.`
49813
+ );
49814
+ }
49815
+ if (!hasValue && !hasInit) {
49816
+ throw new PackedValueEncodingError(
49817
+ `${label} stores neither "value" nor "init"; a value container holds exactly one.`
49818
+ );
49819
+ }
49820
+ if (hasInit && !isInitValueContent(entry)) {
49821
+ throw new PackedValueEncodingError(
49822
+ `${label} stores an "init" that is not a valid initializer body.`
49823
+ );
49824
+ }
49825
+ if (hasValue && !isLiteralValueContent(entry)) {
49826
+ throw new PackedValueEncodingError(
49827
+ `${label} stores a "value" whose class or construction stamp is malformed.`
49828
+ );
49829
+ }
49830
+ }
49831
+ function pendingPackedChildIds(scope) {
49832
+ const childIds = scope.packedChildIdsByParentId.get(scope.ownerId);
49833
+ if (childIds === void 0 || childIds.length === 0) return null;
49834
+ return new Set(childIds);
49835
+ }
49836
+ function assertEveryChildPlaced(pending, scope) {
49837
+ if (pending.size === 0) return;
49838
+ const [missing] = [...pending];
49839
+ throw new PackedValueEncodingError(
49840
+ `Cannot pack child "${missing}" into ${scope.ownerLabel}: no stored position of that row holds its id.`
49841
+ );
49842
+ }
49843
+ function encodeContentField(container, pending, scope) {
49844
+ if (Array.isArray(container)) {
49845
+ let changed2 = false;
49846
+ const encoded2 = container.map((entry, index) => {
49847
+ if (typeof entry !== "string" || !pending.has(entry)) return entry;
49848
+ changed2 = true;
49849
+ return encodeEnvelope(entry, `[${index}]`, pending, scope);
49850
+ });
49851
+ return changed2 ? { content: encoded2 } : null;
49852
+ }
49853
+ if (typeof container !== "object" || container === null) return null;
49854
+ let changed = false;
49855
+ const encoded = {};
49856
+ for (const [key, entry] of Object.entries(
49857
+ container
49858
+ )) {
49859
+ if (typeof entry !== "string" || !pending.has(entry)) {
49860
+ encoded[key] = entry;
49861
+ continue;
49862
+ }
49863
+ changed = true;
49864
+ encoded[key] = encodeEnvelope(
49865
+ entry,
49866
+ `[${JSON.stringify(key)}]`,
49867
+ pending,
49868
+ scope
49869
+ );
49870
+ }
49871
+ return changed ? { content: encoded } : null;
49872
+ }
49873
+ function encodeEnvelope(childId, position, pending, scope) {
49874
+ pending.delete(childId);
49875
+ const child = scope.rowsById.get(childId);
49876
+ if (child === void 0) {
49877
+ throw new PackedValueEncodingError(
49878
+ `Cannot pack child "${childId}" into ${scope.ownerLabel}: its logical row was not supplied.`
49879
+ );
49880
+ }
49881
+ if (child.projectId !== scope.parent.projectId) {
49882
+ throw new PackedValueEncodingError(
49883
+ `Cannot pack child "${childId}" into ${scope.ownerLabel}: it belongs to project "${child.projectId}" rather than "${scope.parent.projectId}".`
49884
+ );
49885
+ }
49886
+ if (child.containerId !== void 0) {
49887
+ throw new PackedValueEncodingError(
49888
+ `Cannot pack child "${childId}" into ${scope.ownerLabel}: it is an entry of unordered list "${child.containerId}", whose membership is the set of live rows and cannot survive without one.`
49889
+ );
49890
+ }
49891
+ if (child.mapKey !== scope.parent.mapKey) {
49892
+ throw new PackedValueEncodingError(
49893
+ `Cannot pack child "${childId}" into ${scope.ownerLabel}: it is stamped for storage partition "${child.mapKey ?? "main"}" rather than its parent's "${scope.parent.mapKey ?? "main"}".`
49894
+ );
49895
+ }
49896
+ const childScope = {
49897
+ ...scope,
49898
+ ownerId: childId,
49899
+ ownerLabel: `packed value "${childId}"`,
49900
+ constructionRootId: isCollapseStampedInstanceRoot(child) ? childId : scope.constructionRootId
49901
+ };
49902
+ const childPending = pendingPackedChildIds(childScope);
49903
+ const canonical = canonicalPackedChildId({
49904
+ constructionRootId: scope.constructionRootId,
49905
+ sourceValueId: child.sourceValueId
49906
+ });
49907
+ const storedId = canonical === childId ? void 0 : childId;
49908
+ if (childPending === null)
49909
+ return {
49910
+ [PACKED_VALUE_ENTRY_KEY]: packedEntry(child, null, null, storedId)
49911
+ };
49912
+ const value = encodeContentField(child.value, childPending, childScope);
49913
+ const constructorArgs = encodeContentField(
49914
+ isLiteralValueContent(child) ? child.constructorArgs : void 0,
49915
+ childPending,
49916
+ childScope
49917
+ );
49918
+ assertEveryChildPlaced(childPending, childScope);
49919
+ return {
49920
+ [PACKED_VALUE_ENTRY_KEY]: packedEntry(
49921
+ child,
49922
+ value,
49923
+ constructorArgs,
49924
+ storedId
49925
+ )
49926
+ };
49927
+ }
49928
+ function packedEntry(child, value, constructorArgs, storedId) {
49929
+ const identity2 = storedId === void 0 ? {} : { id: storedId };
49930
+ const trailer = {
49931
+ ...child.genericBindings === void 0 ? {} : { genericBindings: child.genericBindings },
49932
+ ...child.sourceValueId === void 0 ? {} : { sourceValueId: child.sourceValueId },
49933
+ createdAt: child.createdAt,
49934
+ updatedAt: child.updatedAt
49935
+ };
49936
+ if (isInitValueContent(child)) {
49937
+ return { ...identity2, init: child.init, ...trailer };
49938
+ }
49939
+ return {
49940
+ ...identity2,
49941
+ ...literalContent(child, value, constructorArgs),
49942
+ ...trailer
49943
+ };
49944
+ }
49945
+ function literalContent(content, value, constructorArgs) {
49946
+ if (!isLiteralValueContent(content)) {
49947
+ throw new PackedValueEncodingError(
49948
+ `Value container has no literal "value" to encode.`
49949
+ );
49950
+ }
49951
+ const provenance = pickInstanceProvenance(content);
49952
+ return {
49953
+ value: value === null ? content.value : value.content,
49954
+ ...Object.hasOwn(content, "classId") ? { classId: content.classId } : {},
49955
+ ...provenance,
49956
+ ...constructorArgs === null ? {} : { constructorArgs: asConstructorArgs(constructorArgs.content) }
49957
+ };
49958
+ }
49959
+ function withDecodedContent(row, value, constructorArgs) {
49960
+ if (value === null && constructorArgs === null) return row;
49961
+ return { ...row, ...literalContent(row, value, constructorArgs) };
49962
+ }
49963
+ function asConstructorArgs(content) {
49964
+ if (content === null) return null;
49965
+ if (typeof content !== "object" || Array.isArray(content)) {
49966
+ throw new PackedValueEncodingError(
49967
+ `Value container stores "constructorArgs" that is not a record.`
49968
+ );
49969
+ }
49970
+ return content;
49971
+ }
49972
+ function containerHoldsPackedEntry(container) {
49973
+ if (Array.isArray(container)) {
49974
+ return container.some((entry) => isPackedValueEnvelope(entry));
49975
+ }
49976
+ if (typeof container !== "object" || container === null) return false;
49977
+ for (const entry of Object.values(container)) {
49978
+ if (isPackedValueEnvelope(entry)) return true;
49979
+ }
49980
+ return false;
49981
+ }
49982
+ function registerEdge(edges, ownerId, childId) {
49983
+ const existing = edges.get(ownerId);
49984
+ if (existing === void 0) edges.set(ownerId, [childId]);
49985
+ else existing.push(childId);
49986
+ }
49987
+ var PACKED_VALUE_ENTRY_KEY, PackedValueEncodingError, NO_CHILDREN, NO_EDGES, PACKED_ENTRY_FORBIDDEN_FIELDS;
49988
+ var init_packed_value_encoding = __esm({
49989
+ "../src/models/members/packed-value-encoding.ts"() {
49990
+ "use strict";
49991
+ init_instance_provenance();
49992
+ init_member_kinds();
49993
+ init_member_value_id();
49994
+ PACKED_VALUE_ENTRY_KEY = "~packed";
49995
+ PackedValueEncodingError = class extends Error {
49996
+ constructor(message) {
49997
+ super(message);
49998
+ this.name = "PackedValueEncodingError";
49999
+ }
50000
+ };
50001
+ NO_CHILDREN = [];
50002
+ NO_EDGES = /* @__PURE__ */ new Map();
50003
+ PACKED_ENTRY_FORBIDDEN_FIELDS = [
50004
+ "projectId",
50005
+ "containerId",
50006
+ "mapKey"
50007
+ ];
50008
+ }
50009
+ });
50010
+
49362
50011
  // ../src/models/members/member-kinds-db-response.ts
49363
50012
  var init_member_kinds_db_response = __esm({
49364
50013
  "../src/models/members/member-kinds-db-response.ts"() {
@@ -51808,6 +52457,45 @@ var init_enum_reference_sites = __esm({
51808
52457
  }
51809
52458
  });
51810
52459
 
52460
+ // ../src/models/members/effective-distribution.ts
52461
+ function declaredMemberDistribution(memberId, members) {
52462
+ return walkExtendsMemberChain(memberId, members, (a) => {
52463
+ const distribution = a.distribution;
52464
+ return isNeoSubtreeDistributionKind(distribution) ? distribution : void 0;
52465
+ });
52466
+ }
52467
+ function concreteMember(member, members, env) {
52468
+ const resolved = resolveMember2(member, members);
52469
+ if (env === void 0) return resolved;
52470
+ return substituteMember(member, env, members, resolved);
52471
+ }
52472
+ function distributionSettings(concrete) {
52473
+ return {
52474
+ format: isLocalizedStringMember(concrete) ? 0 /* Localized */ : 1 /* Plain */,
52475
+ selection: isMultiSelectionMember(concrete) ? 1 /* Multi */ : 0 /* Single */
52476
+ };
52477
+ }
52478
+ function effectiveMemberDistribution(member, members, env) {
52479
+ const concrete = concreteMember(member, members, env);
52480
+ if (isNeoSubtreeDistributionKind(concrete.distribution)) {
52481
+ return concrete.distribution;
52482
+ }
52483
+ if (concrete.kind === 21 /* Generic */) return void 0;
52484
+ return automaticMemberDistribution(
52485
+ concrete.kind,
52486
+ distributionSettings(concrete)
52487
+ );
52488
+ }
52489
+ var init_effective_distribution = __esm({
52490
+ "../src/models/members/effective-distribution.ts"() {
52491
+ "use strict";
52492
+ init_member_kinds();
52493
+ init_member_subtree_distribution();
52494
+ init_inheritance();
52495
+ init_generics();
52496
+ }
52497
+ });
52498
+
51811
52499
  // ../src/models/members/list-indexes.ts
51812
52500
  function validateListIndexDefinitions(ctx, listMember) {
51813
52501
  const errors = [];
@@ -51945,11 +52633,30 @@ function resolveListIndexDefinitions(ctx, listMember) {
51945
52633
  };
51946
52634
  });
51947
52635
  }
52636
+ function validateListDistribution(ctx, member) {
52637
+ if (declaredMemberDistribution(member.id, ctx.members) !== 1 /* Packed */) {
52638
+ return [];
52639
+ }
52640
+ try {
52641
+ const resolved = resolveMember2(member, ctx.members);
52642
+ if (!isMemberListBase(resolved)) return [];
52643
+ if (listKindOf(resolved) !== 1 /* Unordered */) return [];
52644
+ } catch {
52645
+ return [];
52646
+ }
52647
+ return [
52648
+ {
52649
+ memberId: member.id,
52650
+ message: `List "${member.name}" (${member.id}) cannot select a packed distribution while its listKind is unordered: an unordered list's membership is the set of live rows carrying its id, so its entries occupy no position inside a parent row to be packed into.`
52651
+ }
52652
+ ];
52653
+ }
51948
52654
  function validateDocumentListIndexes(ctx) {
51949
52655
  const errors = [];
51950
52656
  for (const member of ctx.members) {
51951
52657
  if (member.kind !== 6 /* List */) continue;
51952
52658
  errors.push(...validateListIndexDefinitions(ctx, member));
52659
+ errors.push(...validateListDistribution(ctx, member));
51953
52660
  if (!isMemberOverrideMarker(member)) continue;
51954
52661
  if (getField(member, "indexes") !== void 0) {
51955
52662
  errors.push({
@@ -52073,6 +52780,8 @@ var init_list_indexes = __esm({
52073
52780
  "../src/models/members/list-indexes.ts"() {
52074
52781
  "use strict";
52075
52782
  init_member_kinds();
52783
+ init_effective_distribution();
52784
+ init_member_subtree_distribution();
52076
52785
  init_core();
52077
52786
  init_generics();
52078
52787
  init_inheritance();
@@ -52469,7 +53178,7 @@ function isStringArray(value) {
52469
53178
  if (!Array.isArray(value)) return false;
52470
53179
  return value.every(isString);
52471
53180
  }
52472
- var ProjectVersionBumpKind, ProjectRecordKind, ProjectVersionTransactionOperation;
53181
+ var ProjectVersionBumpKind, ProjectRecordKind, ProjectVersionTransactionOperation, ProjectVersionRecordOperation;
52473
53182
  var init_project_version_types = __esm({
52474
53183
  "../src/models/project/project-version-types.ts"() {
52475
53184
  "use strict";
@@ -52517,6 +53226,11 @@ var init_project_version_types = __esm({
52517
53226
  CompactBaseline: "compact-baseline",
52518
53227
  Migration: "migration"
52519
53228
  };
53229
+ ProjectVersionRecordOperation = {
53230
+ Create: "create",
53231
+ Update: "update",
53232
+ Delete: "delete"
53233
+ };
52520
53234
  }
52521
53235
  });
52522
53236
 
@@ -52562,63 +53276,16 @@ var init_delete_member_response = __esm({
52562
53276
  }
52563
53277
  });
52564
53278
 
52565
- // ../src/models/members/member-value-id.ts
52566
- function derivedMemberValueId(memberId) {
52567
- return inSystemRecordNamespaceOf(
52568
- memberId,
52569
- v5_default(withoutSystemRecordIdPrefix(memberId), NEO_MEMBER_VALUE_NAMESPACE)
52570
- );
52571
- }
52572
- function virtualValueId(instanceRootId, sourceIdentity3) {
52573
- return inSystemRecordNamespaceOf(
52574
- instanceRootId,
52575
- v5_default(
52576
- `${withoutSystemRecordIdPrefix(instanceRootId)}:${sourceIdentity3}`,
52577
- NEO_VIRTUAL_VALUE_NAMESPACE
52578
- )
52579
- );
52580
- }
52581
- function pendingVirtualValueId(pendingInstanceRootId, sourceIdentity3) {
52582
- return `${PENDING_VIRTUAL_VALUE_PREFIX}${encodeURIComponent(pendingInstanceRootId)}:${encodeURIComponent(sourceIdentity3)}`;
52583
- }
52584
- function pendingVirtualValueIdentity(token) {
52585
- if (!token.startsWith(PENDING_VIRTUAL_VALUE_PREFIX)) return null;
52586
- const payload = token.slice(PENDING_VIRTUAL_VALUE_PREFIX.length);
52587
- const separator = payload.indexOf(":");
52588
- if (separator < 0) return null;
52589
- return {
52590
- instanceRootId: decodeURIComponent(payload.slice(0, separator)),
52591
- sourceIdentity: decodeURIComponent(payload.slice(separator + 1))
52592
- };
52593
- }
52594
- function pendingMemberValueId(pendingMemberId) {
52595
- return `${PENDING_MEMBER_VALUE_PREFIX}${encodeURIComponent(pendingMemberId)}`;
52596
- }
52597
- function pendingMemberValueMemberId(token) {
52598
- if (!token.startsWith(PENDING_MEMBER_VALUE_PREFIX)) return null;
52599
- return decodeURIComponent(token.slice(PENDING_MEMBER_VALUE_PREFIX.length));
52600
- }
52601
- var NEO_MEMBER_VALUE_NAMESPACE, NEO_VIRTUAL_VALUE_NAMESPACE, PENDING_VIRTUAL_VALUE_PREFIX, PENDING_MEMBER_VALUE_PREFIX;
52602
- var init_member_value_id = __esm({
52603
- "../src/models/members/member-value-id.ts"() {
52604
- "use strict";
52605
- init_dist_node();
52606
- init_system_record_id();
52607
- NEO_MEMBER_VALUE_NAMESPACE = "7f2b9c14-58d6-5a07-b3e1-4c9d0a6f8b25";
52608
- NEO_VIRTUAL_VALUE_NAMESPACE = "3e8ca0b3-e3f1-5d5f-bf2f-6ab5ee3896d0";
52609
- PENDING_VIRTUAL_VALUE_PREFIX = "__pending__:virtual-value:";
52610
- PENDING_MEMBER_VALUE_PREFIX = "__pending__:member-value:";
52611
- }
52612
- });
52613
-
52614
53279
  // ../src/models/members/index.ts
52615
53280
  var init_members = __esm({
52616
53281
  "../src/models/members/index.ts"() {
52617
53282
  "use strict";
52618
53283
  init_member_storage();
53284
+ init_member_subtree_distribution();
52619
53285
  init_read_only_members();
52620
53286
  init_member_kinds();
52621
53287
  init_structured_leaf_fields();
53288
+ init_packed_value_encoding();
52622
53289
  init_member_kinds_db_response();
52623
53290
  init_unordered_list_membership();
52624
53291
  init_storage_partitions();
@@ -52626,6 +53293,7 @@ var init_members = __esm({
52626
53293
  init_enum_reference_sites();
52627
53294
  init_list_indexes();
52628
53295
  init_effective_storage();
53296
+ init_effective_distribution();
52629
53297
  init_effective_member_docs();
52630
53298
  init_value_responses();
52631
53299
  init_edit_member_props();
@@ -53422,6 +54090,10 @@ function emitMember(context, member, enclosingClassId) {
53422
54090
  ...member.storageKey ? [`key: ${quote(member.storageKey)}`] : []
53423
54091
  ].join(", ")})`
53424
54092
  ] : [],
54093
+ // Only an explicitly stored field is emitted. The automatic result of
54094
+ // P76 §1 is never materialized into source, so a member that omits the
54095
+ // annotation round-trips as an omission.
54096
+ ...member.distribution ? [`@distribution(kind: .${enumCase(member.distribution)})`] : [],
53425
54097
  ...memberSettings(context, member),
53426
54098
  ...listAnnotations(member),
53427
54099
  ...member.system ? [systemAnnotation2(member.system)] : []
@@ -60416,6 +61088,7 @@ function projectSchemaJsonValue(value) {
60416
61088
  }
60417
61089
  function memberCommon(context, ownerClass, declaration, id2, owner, base) {
60418
61090
  const storage = annotation(declaration.annotations, "storage");
61091
+ const distribution = annotation(declaration.annotations, "distribution");
60419
61092
  const inheritedId = declaration.modifiers.includes("override") || declaration.modifiers.includes("sealed") ? inheritedMemberId(context, ownerClass, declaration.name) : null;
60420
61093
  return {
60421
61094
  id: id2,
@@ -60440,9 +61113,30 @@ function memberCommon(context, ownerClass, declaration, id2, owner, base) {
60440
61113
  overrideOf: inheritedId,
60441
61114
  system: systemMetadata(declaration.annotations),
60442
61115
  storage: storage ? storageValue(storage, "allowed") : declaration.modifiers.includes("readonly") ? base !== void 0 ? base.storage : inheritedId !== null && resolvedMemberStorage(context, inheritedId) === "immutable" ? "immutable" : null : null,
61116
+ distribution: distribution ? distributionValue(distribution, ownerClass, declaration) : null,
60443
61117
  storageKey: storage ? stringArgument(storage, "key") : null
60444
61118
  };
60445
61119
  }
61120
+ function distributionValue(value, ownerClass, declaration) {
61121
+ const site = `${ownerClass.name}.${declaration.name}`;
61122
+ if (declaration.kind !== "field") {
61123
+ throw new Error(
61124
+ `@distribution on ${site} is not allowed: a ${declaration.kind} owns no stored value to distribute.`
61125
+ );
61126
+ }
61127
+ const kind = contextualEnumArgument(value, "kind");
61128
+ if (kind === null) {
61129
+ throw new Error(
61130
+ `@distribution on ${site} requires a kind argument, such as @distribution(kind: .Packed).`
61131
+ );
61132
+ }
61133
+ const normalized = kind.toLowerCase();
61134
+ if (normalized === "sparse") return "sparse";
61135
+ if (normalized === "packed") return "packed";
61136
+ throw new Error(
61137
+ `@distribution on ${site} has unknown kind ".${kind}". Valid kinds are .Sparse and .Packed.`
61138
+ );
61139
+ }
60446
61140
  function resolvedMemberStorage(context, memberId, visited = /* @__PURE__ */ new Set()) {
60447
61141
  if (visited.has(memberId)) return null;
60448
61142
  visited.add(memberId);
@@ -63179,9 +63873,39 @@ var init_constructor_parameter_settlement = __esm({
63179
63873
  });
63180
63874
 
63181
63875
  // src/project-source/stored-value-placements.ts
63876
+ function storedValueRowsByIdV4(records2) {
63877
+ const stored = /* @__PURE__ */ new Map();
63878
+ let packed = false;
63879
+ for (const record3 of records2) {
63880
+ if (record3.deleted === true) continue;
63881
+ if (record3.recordKind !== "value") continue;
63882
+ if (!isObjectRecord2(record3.data)) continue;
63883
+ stored.set(record3.recordId, record3.data);
63884
+ packed ||= rowCarriesPackedValueContent(record3.data);
63885
+ }
63886
+ if (!packed) return stored;
63887
+ const logical = /* @__PURE__ */ new Map();
63888
+ for (const [valueId, row] of stored) {
63889
+ if (!rowCarriesPackedValueContent(row)) {
63890
+ logical.set(valueId, row);
63891
+ continue;
63892
+ }
63893
+ if (!isMemberValue(row)) {
63894
+ throw new PackedValueEncodingError(
63895
+ `Stored value row "${valueId}" packs a child but is not a well-formed value row, so its packed payload cannot be expanded.`
63896
+ );
63897
+ }
63898
+ const decoded = decodePackedValueRow(row);
63899
+ logical.set(valueId, { ...decoded.row });
63900
+ for (const child of decoded.children) {
63901
+ logical.set(child.id, { ...child });
63902
+ }
63903
+ }
63904
+ return logical;
63905
+ }
63182
63906
  function buildStoredValuePlacementIndexV4(records2) {
63183
63907
  const live = [...records2].filter((record3) => record3.deleted !== true);
63184
- const values = /* @__PURE__ */ new Map();
63908
+ const values = storedValueRowsByIdV4(live);
63185
63909
  const classes = [];
63186
63910
  const members = [];
63187
63911
  const memberDataById = /* @__PURE__ */ new Map();
@@ -63189,9 +63913,8 @@ function buildStoredValuePlacementIndexV4(records2) {
63189
63913
  const variantTargetClassByRootValueId = /* @__PURE__ */ new Map();
63190
63914
  for (const record3 of live) {
63191
63915
  if (!isObjectRecord2(record3.data)) continue;
63192
- if (record3.recordKind === "value") {
63193
- values.set(record3.recordId, record3.data);
63194
- } else if (record3.recordKind === "class") {
63916
+ if (record3.recordKind === "value") continue;
63917
+ if (record3.recordKind === "class") {
63195
63918
  classes.push({
63196
63919
  id: record3.recordId,
63197
63920
  ...isStringRecord3(record3.data.schema) ? { schema: record3.data.schema } : {},
@@ -63399,11 +64122,7 @@ function rootValuePathsByValueId(records2, storedPlacements) {
63399
64122
  function rootValueTargetsByPath(records2, storedPlacements) {
63400
64123
  const allRecords = [...records2];
63401
64124
  const paths = rootValuePathsByValueId(allRecords, storedPlacements);
63402
- const values = new Map(
63403
- allRecords.flatMap(
63404
- (record3) => !record3.deleted && record3.recordKind === "value" && isObjectRecord3(record3.data) ? [[record3.recordId, record3.data]] : []
63405
- )
63406
- );
64125
+ const values = storedValueRowsByIdV4(allRecords);
63407
64126
  const targets = /* @__PURE__ */ new Map();
63408
64127
  for (const [valueId, path] of paths) {
63409
64128
  const classId = values.get(valueId)?.classId;
@@ -66387,6 +67106,186 @@ function resolveOwnerMembersForValues(document, targetValueIds, additionalRoots,
66387
67106
  }
66388
67107
  return resolved;
66389
67108
  }
67109
+ function isStringListValue(value) {
67110
+ if (!Array.isArray(value)) return false;
67111
+ return value.every((entry) => typeof entry === "string");
67112
+ }
67113
+ function findOwningMembersForValues(document, valueIds, additionalRoots, traversalExtension) {
67114
+ const owners = /* @__PURE__ */ new Map();
67115
+ if (valueIds.size === 0) return owners;
67116
+ const membersById2 = new Map(
67117
+ document.members.map((member) => [member.id, member])
67118
+ );
67119
+ const valuesById = new Map(document.values.map((value) => [value.id, value]));
67120
+ const rowsByContainerId = /* @__PURE__ */ new Map();
67121
+ for (const value of document.values) {
67122
+ if (typeof value.containerId !== "string") continue;
67123
+ const rows = rowsByContainerId.get(value.containerId);
67124
+ if (rows === void 0) {
67125
+ rowsByContainerId.set(value.containerId, [value]);
67126
+ } else {
67127
+ rows.push(value);
67128
+ }
67129
+ }
67130
+ const queue = [];
67131
+ const enqueueClassInstanceChildren = (args) => {
67132
+ const merged = mergeStoredInstanceSchema(
67133
+ args.effectiveClassId,
67134
+ document.classes,
67135
+ document.members
67136
+ );
67137
+ const env = resolveInstanceEnv(
67138
+ args.effectiveClassId,
67139
+ args.member.classArguments,
67140
+ document.classes
67141
+ );
67142
+ for (const entry of merged) {
67143
+ const childValueId = args.record[entry.schemaKey];
67144
+ if (childValueId === void 0) continue;
67145
+ const childMember = membersById2.get(entry.memberId);
67146
+ if (childMember === void 0) continue;
67147
+ queue.push({
67148
+ member: substituteMember(childMember, env, document.members),
67149
+ memberRecordId: childMember.id,
67150
+ id: childValueId,
67151
+ parentValueId: args.parentValueId,
67152
+ // Descending through `Overrides` opens an override graph, and every
67153
+ // row below it stays inside one (D10).
67154
+ insideAnimationOverrideGraph: args.insideAnimationOverrideGraph || entersAnimationOverrideGraph(childMember.id)
67155
+ });
67156
+ }
67157
+ };
67158
+ for (const root of additionalRoots ?? []) {
67159
+ const memberRecordId = getField(root.member, "id");
67160
+ queue.push({
67161
+ member: root.member,
67162
+ memberRecordId: typeof memberRecordId === "string" ? memberRecordId : `semantic:${root.valueId}`,
67163
+ id: root.valueId,
67164
+ insideAnimationOverrideGraph: root.position.insideAnimationOverrideGraph,
67165
+ // A caller-supplied root is a root: it is reached from the caller's own
67166
+ // context, not from a parent row this walk visited.
67167
+ parentValueId: null
67168
+ });
67169
+ }
67170
+ for (const member of document.members) {
67171
+ if (member.valueId !== void 0) {
67172
+ queue.push({
67173
+ member,
67174
+ memberRecordId: member.id,
67175
+ id: member.valueId,
67176
+ // A member-rooted row has no ancestry to have descended through (D10).
67177
+ insideAnimationOverrideGraph: false,
67178
+ parentValueId: null
67179
+ });
67180
+ }
67181
+ const defaultValue = member.defaultValue;
67182
+ if (defaultValue == null) continue;
67183
+ if (!isMemberClassBase(member)) continue;
67184
+ if (!isRecordValue(defaultValue.value)) continue;
67185
+ enqueueClassInstanceChildren({
67186
+ member,
67187
+ record: defaultValue.value,
67188
+ effectiveClassId: defaultValue.classId ?? member.classId,
67189
+ // A declaration default is never itself an override graph (D10).
67190
+ insideAnimationOverrideGraph: false,
67191
+ // The default graph hangs off the MEMBER record, so its children have no
67192
+ // owning value row (P76: they stay physically sparse).
67193
+ parentValueId: null
67194
+ });
67195
+ }
67196
+ const visited = /* @__PURE__ */ new Set();
67197
+ for (let cursor = 0; cursor < queue.length; cursor += 1) {
67198
+ const current = queue[cursor];
67199
+ if (current === void 0) continue;
67200
+ const visitKey = `${current.memberRecordId}:${current.id}`;
67201
+ if (visited.has(visitKey)) continue;
67202
+ visited.add(visitKey);
67203
+ const placement = {
67204
+ member: current.member,
67205
+ position: {
67206
+ insideAnimationOverrideGraph: current.insideAnimationOverrideGraph
67207
+ },
67208
+ parentValueId: current.parentValueId
67209
+ };
67210
+ if (valueIds.has(current.id) && !owners.has(current.id)) {
67211
+ owners.set(current.id, placement);
67212
+ if (owners.size === valueIds.size) return owners;
67213
+ }
67214
+ for (const root of traversalExtension?.({
67215
+ valueId: current.id,
67216
+ placement
67217
+ }) ?? []) {
67218
+ const memberRecordId = getField(root.member, "id");
67219
+ queue.push({
67220
+ member: root.member,
67221
+ memberRecordId: typeof memberRecordId === "string" ? memberRecordId : `semantic:${root.valueId}`,
67222
+ id: root.valueId,
67223
+ insideAnimationOverrideGraph: root.position.insideAnimationOverrideGraph,
67224
+ // A semantic root discovered from this visit is a child of this row —
67225
+ // a settled constructor argument is owned by the row that constructed
67226
+ // it, exactly as a body field is.
67227
+ parentValueId: current.id
67228
+ });
67229
+ }
67230
+ const storedValue = valuesById.get(current.id);
67231
+ if (storedValue === void 0) continue;
67232
+ if (isMemberClassBase(current.member)) {
67233
+ if (!isRecordValue(storedValue.value)) continue;
67234
+ enqueueClassInstanceChildren({
67235
+ member: current.member,
67236
+ record: storedValue.value,
67237
+ effectiveClassId: storedValue.classId ?? current.member.classId,
67238
+ insideAnimationOverrideGraph: current.insideAnimationOverrideGraph,
67239
+ parentValueId: storedValue.id
67240
+ });
67241
+ continue;
67242
+ }
67243
+ if (isMemberDictionaryBase(current.member)) {
67244
+ if (!isRecordValue(storedValue.value)) continue;
67245
+ const entryMemberRecord = membersById2.get(current.member.entryMemberId);
67246
+ if (entryMemberRecord === void 0) continue;
67247
+ const entryMember = substituteMember(
67248
+ entryMemberRecord,
67249
+ envFromStamp(storedValue.genericBindings),
67250
+ document.members
67251
+ );
67252
+ for (const childValueId of Object.values(storedValue.value)) {
67253
+ queue.push({
67254
+ member: entryMember,
67255
+ memberRecordId: entryMemberRecord.id,
67256
+ id: childValueId,
67257
+ // An entry inherits its collection's position: a Dictionary is not
67258
+ // itself a way into an override graph.
67259
+ insideAnimationOverrideGraph: current.insideAnimationOverrideGraph,
67260
+ parentValueId: storedValue.id
67261
+ });
67262
+ }
67263
+ continue;
67264
+ }
67265
+ if (isMemberListBase(current.member)) {
67266
+ const entryMemberRecord = membersById2.get(current.member.entryMemberId);
67267
+ if (entryMemberRecord === void 0) continue;
67268
+ const entryMember = substituteMember(
67269
+ entryMemberRecord,
67270
+ envFromStamp(storedValue.genericBindings),
67271
+ document.members
67272
+ );
67273
+ const childValueIds = listKindOf(current.member) === 1 /* Unordered */ ? (rowsByContainerId.get(storedValue.id) ?? []).map((row) => row.id) : isStringListValue(storedValue.value) ? storedValue.value : [];
67274
+ for (const childValueId of childValueIds) {
67275
+ queue.push({
67276
+ member: entryMember,
67277
+ memberRecordId: entryMemberRecord.id,
67278
+ id: childValueId,
67279
+ // An entry inherits its collection's position: a List is not itself
67280
+ // a way into an override graph.
67281
+ insideAnimationOverrideGraph: current.insideAnimationOverrideGraph,
67282
+ parentValueId: storedValue.id
67283
+ });
67284
+ }
67285
+ }
67286
+ }
67287
+ return owners;
67288
+ }
66390
67289
  var init_value_row_owner_members = __esm({
66391
67290
  "../src/database/value-row-owner-members.ts"() {
66392
67291
  "use strict";
@@ -66488,6 +67387,59 @@ function resolveSemanticOwnerMembersForValues(document, targetValueIds, addition
66488
67387
  }
66489
67388
  return result;
66490
67389
  }
67390
+ function findSemanticOwnerPlacementsForValues(document, targetValueIds, additionalRoots) {
67391
+ const result = /* @__PURE__ */ new Map();
67392
+ if (targetValueIds.size === 0) return result;
67393
+ const directPlacements = findOwningMembersForValues(
67394
+ document,
67395
+ targetValueIds,
67396
+ additionalRoots
67397
+ );
67398
+ if (directPlacements.size === targetValueIds.size) return directPlacements;
67399
+ const graph = new MaterializedValueGraphContext(document);
67400
+ const allValueIds = new Set(graph.valuesById.keys());
67401
+ const semanticRootIds = /* @__PURE__ */ new Set();
67402
+ const bodyPlacements = findOwningMembersForValues(
67403
+ document,
67404
+ allValueIds,
67405
+ additionalRoots
67406
+ );
67407
+ const placements = findOwningMembersForValues(
67408
+ document,
67409
+ allValueIds,
67410
+ additionalRoots,
67411
+ ({ valueId: ownerValueId, placement: ownerPlacement }) => {
67412
+ const roots = [];
67413
+ for (const edge of graph.edgesByOwnerValueId.get(ownerValueId) ?? []) {
67414
+ if (graph.referenceCountByTargetValueId.get(edge.targetValueId) !== 1) {
67415
+ continue;
67416
+ }
67417
+ if (bodyPlacements.has(edge.targetValueId)) continue;
67418
+ if (semanticRootIds.has(edge.targetValueId)) continue;
67419
+ const member = graph.constructorArgumentOwnerMember(edge);
67420
+ if (member === void 0) continue;
67421
+ const memberId = getField(member, "id");
67422
+ semanticRootIds.add(edge.targetValueId);
67423
+ roots.push({
67424
+ member,
67425
+ valueId: edge.targetValueId,
67426
+ position: {
67427
+ insideAnimationOverrideGraph: ownerPlacement.position.insideAnimationOverrideGraph || typeof memberId === "string" && entersAnimationOverrideGraph(memberId)
67428
+ }
67429
+ });
67430
+ }
67431
+ return roots;
67432
+ }
67433
+ );
67434
+ for (const [valueId, placement] of bodyPlacements) {
67435
+ placements.set(valueId, placement);
67436
+ }
67437
+ for (const valueId of targetValueIds) {
67438
+ const placement = placements.get(valueId);
67439
+ if (placement !== void 0) result.set(valueId, placement);
67440
+ }
67441
+ return result;
67442
+ }
66491
67443
  function createTypedValueNormalizer(rows, document, childrenByContainerId, parameterTypesForRow, memberById2, memberTypeInfo, genericEnvironmentForRow) {
66492
67444
  const visiting = /* @__PURE__ */ new Set();
66493
67445
  const normalizeLiteral = (value) => {
@@ -68320,7 +69272,8 @@ var init_project2 = __esm({
68320
69272
  function isCatchableNeoScriptRuntimeError(error) {
68321
69273
  return error instanceof NSGetterRuntimeError && !(error instanceof UncompiledInitializerRuntimeError) && !(error instanceof NonCatchableNSGetterRuntimeError);
68322
69274
  }
68323
- function makeEvaluatorLookups(members, values, options = {}) {
69275
+ function makeEvaluatorLookups(members, storedValues, options = {}) {
69276
+ const values = expandPackedValueRows(storedValues);
68324
69277
  const attrMap = /* @__PURE__ */ new Map();
68325
69278
  for (const a of members) attrMap.set(a.id, a);
68326
69279
  const valMap = /* @__PURE__ */ new Map();
@@ -69149,7 +70102,7 @@ function withEvaluationRuntime(ctx, writes) {
69149
70102
  ctx.__runtimeSessionValues
69150
70103
  );
69151
70104
  const referencesAlreadyRemapped = ctx.__valueOverlay !== void 0 && ctx.__runtimeReferenceRemap !== void 0;
69152
- const remap = (value) => referencesAlreadyRemapped ? value : remapRuntimeReferences(
70105
+ const remap2 = (value) => referencesAlreadyRemapped ? value : remapRuntimeReferences(
69153
70106
  value,
69154
70107
  overlay,
69155
70108
  referenceRemap,
@@ -69157,11 +70110,11 @@ function withEvaluationRuntime(ctx, writes) {
69157
70110
  );
69158
70111
  return {
69159
70112
  ...ctx,
69160
- thisValue: remap(ctx.thisValue),
69161
- rootValue: remap(ctx.rootValue),
70113
+ thisValue: remap2(ctx.thisValue),
70114
+ rootValue: remap2(ctx.rootValue),
69162
70115
  dialogueContext: ctx.dialogueContext === void 0 || ctx.dialogueContext === null ? ctx.dialogueContext : {
69163
- primary: remap(ctx.dialogueContext.primary),
69164
- trigger: remap(ctx.dialogueContext.trigger)
70116
+ primary: remap2(ctx.dialogueContext.primary),
70117
+ trigger: remap2(ctx.dialogueContext.trigger)
69165
70118
  },
69166
70119
  __runtimeSessionValues: runtimeSessionValues,
69167
70120
  __saveStaticBindings: ctx.__saveStaticBindings ?? staticBindingMap(ctx.saveStaticBindings),
@@ -77156,6 +78109,7 @@ var init_evaluateNSGetter = __esm({
77156
78109
  init_src();
77157
78110
  init_decimal();
77158
78111
  init_members();
78112
+ init_packed_value_encoding();
77159
78113
  init_core();
77160
78114
  init_member_storage_key();
77161
78115
  init_project2();
@@ -78091,12 +79045,6 @@ function resolveVirtualInstanceGraph(args) {
78091
79045
  };
78092
79046
  rowsById.set(effectiveId, effective);
78093
79047
  locationsById.set(effectiveId, location3);
78094
- if (effectiveId !== indexed.virtualId) {
78095
- locationsById.set(indexed.virtualId, {
78096
- ...location3,
78097
- id: indexed.virtualId
78098
- });
78099
- }
78100
79048
  locationsByPath.set(pathKey, location3);
78101
79049
  visiting.delete(pathKey);
78102
79050
  return location3;
@@ -78150,10 +79098,9 @@ function reportFrameResolutionDisagreement(args) {
78150
79098
  );
78151
79099
  }
78152
79100
  function resolvedStoredInstanceRows(args) {
78153
- const rows = new Map(args.document.values.map((row) => [row.id, row]));
78154
- const materializedIndex = buildVirtualInstanceMaterializedIndex({
78155
- document: args.document
78156
- });
79101
+ const document = expandPackedDocumentValues(args.document);
79102
+ const rows = new Map(document.values.map((row) => [row.id, row]));
79103
+ const materializedIndex = buildVirtualInstanceMaterializedIndex({ document });
78157
79104
  const queue = [{ root: args.instanceRoot, member: args.rootMember }];
78158
79105
  const resolvedRootIds = /* @__PURE__ */ new Set();
78159
79106
  const resolvedFrameByValueId = /* @__PURE__ */ new Map();
@@ -78162,12 +79109,12 @@ function resolvedStoredInstanceRows(args) {
78162
79109
  if (next === void 0 || resolvedRootIds.has(next.root.id)) continue;
78163
79110
  resolvedRootIds.add(next.root.id);
78164
79111
  const expanded = expandStoredInstance({
78165
- document: args.document,
79112
+ document,
78166
79113
  instanceRoot: next.root,
78167
79114
  rootMember: next.member
78168
79115
  });
78169
79116
  const graph = resolveVirtualInstanceGraph({
78170
- document: args.document,
79117
+ document,
78171
79118
  instanceRoot: next.root,
78172
79119
  rootMember: next.member,
78173
79120
  expandedRoot: expanded.root,
@@ -78829,12 +79776,12 @@ function sparsifyConstructedInstance(args) {
78829
79776
  ) ?? virtualId
78830
79777
  );
78831
79778
  }
78832
- const remap = (value) => {
79779
+ const remap2 = (value) => {
78833
79780
  if (typeof value === "string") return nextIdById.get(value) ?? value;
78834
- if (Array.isArray(value)) return value.map(remap);
79781
+ if (Array.isArray(value)) return value.map(remap2);
78835
79782
  if (typeof value !== "object" || value === null) return value;
78836
79783
  return Object.fromEntries(
78837
- Object.entries(value).map(([key, entry]) => [key, remap(entry)])
79784
+ Object.entries(value).map(([key, entry]) => [key, remap2(entry)])
78838
79785
  );
78839
79786
  };
78840
79787
  const rewrite = (row) => {
@@ -78842,9 +79789,9 @@ function sparsifyConstructedInstance(args) {
78842
79789
  return {
78843
79790
  ...literal2,
78844
79791
  id: nextIdById.get(row.id) ?? row.id,
78845
- value: remap(updatedValueById.get(row.id) ?? literal2.value),
79792
+ value: remap2(updatedValueById.get(row.id) ?? literal2.value),
78846
79793
  ...literal2.constructorArgs === void 0 ? {} : {
78847
- constructorArgs: remap(literal2.constructorArgs)
79794
+ constructorArgs: remap2(literal2.constructorArgs)
78848
79795
  },
78849
79796
  ...typeof row.containerId === "string" ? { containerId: nextIdById.get(row.containerId) ?? row.containerId } : {}
78850
79797
  };
@@ -79699,6 +80646,7 @@ var init_virtual_instance_values = __esm({
79699
80646
  init_classes();
79700
80647
  init_members();
79701
80648
  init_member_value_id();
80649
+ init_packed_value_encoding();
79702
80650
  init_stored_value_placement_index();
79703
80651
  init_instance_provenance();
79704
80652
  init_unordered_list_membership();
@@ -80432,6 +81380,16 @@ var init_projectRecordBuckets = __esm({
80432
81380
  });
80433
81381
 
80434
81382
  // ../src/database/project-record-migrations.ts
81383
+ function migrateValueDataV1ToV2(data) {
81384
+ if (typeof data !== "object" || data === null) return data;
81385
+ const value = Reflect.get(data, "value");
81386
+ if (typeof value !== "object" || value === null) return data;
81387
+ if (!Object.hasOwn(value, PACKED_VALUE_ENTRY_KEY)) return data;
81388
+ const id2 = Reflect.get(data, "id");
81389
+ throw new Error(
81390
+ `Value "${typeof id2 === "string" ? id2 : "<unknown>"}" is stamped data schema version 1 but its body already carries a "${PACKED_VALUE_ENTRY_KEY}" envelope; only version 2 may pack a subtree.`
81391
+ );
81392
+ }
80435
81393
  function migrateProjectRecordData(args) {
80436
81394
  const currentVersion = CURRENT_PROJECT_RECORD_DATA_SCHEMA_VERSION[args.recordKind];
80437
81395
  if (args.dataSchemaVersion > currentVersion) {
@@ -80455,11 +81413,26 @@ var CURRENT_PROJECT_RECORD_DATA_SCHEMA_VERSION, PROJECT_RECORD_DATA_MIGRATIONS;
80455
81413
  var init_project_record_migrations = __esm({
80456
81414
  "../src/database/project-record-migrations.ts"() {
80457
81415
  "use strict";
81416
+ init_packed_value_encoding();
80458
81417
  init_project2();
80459
81418
  CURRENT_PROJECT_RECORD_DATA_SCHEMA_VERSION = {
80460
81419
  [ProjectRecordKind.Project]: 1,
80461
81420
  [ProjectRecordKind.Member]: 6,
80462
- [ProjectRecordKind.Value]: 1,
81421
+ /**
81422
+ * 2 — P76 §3.1. A value body may carry `~packed` envelopes, so a v1 reader
81423
+ * would hand a packed child's envelope to an evaluator as if it were the
81424
+ * child's value, and an external reader has to fail closed on v2 (spec
81425
+ * §"Goals": "old readers fail closed").
81426
+ *
81427
+ * The 1 -> 2 rung below is load-bearing rather than optional. The P76
81428
+ * migrations are themselves ordinary writers: they read a value's base
81429
+ * record through {@link migrateProjectRecordData} before they can write it.
81430
+ * Bumping this with an empty ladder makes every stored v1 value unreadable
81431
+ * by the very sweep that is supposed to advance it, which is circular. The
81432
+ * rung breaks that circle, and retires with the migration once the corpus
81433
+ * carries no v1 value.
81434
+ */
81435
+ [ProjectRecordKind.Value]: 2,
80463
81436
  [ProjectRecordKind.Class]: 2,
80464
81437
  [ProjectRecordKind.Constructor]: 1,
80465
81438
  [ProjectRecordKind.Variant]: 1,
@@ -80482,7 +81455,7 @@ var init_project_record_migrations = __esm({
80482
81455
  PROJECT_RECORD_DATA_MIGRATIONS = {
80483
81456
  [ProjectRecordKind.Project]: {},
80484
81457
  [ProjectRecordKind.Member]: {},
80485
- [ProjectRecordKind.Value]: {},
81458
+ [ProjectRecordKind.Value]: { 1: migrateValueDataV1ToV2 },
80486
81459
  [ProjectRecordKind.Class]: {},
80487
81460
  [ProjectRecordKind.Constructor]: {},
80488
81461
  [ProjectRecordKind.Variant]: {},
@@ -80511,7 +81484,9 @@ __export(project_document_read_exports, {
80511
81484
  DOCUMENT_MANIFEST_PAGE_SIZE: () => DOCUMENT_MANIFEST_PAGE_SIZE,
80512
81485
  DOCUMENT_SNAPSHOT_FETCH_CHUNK_SIZE: () => DOCUMENT_SNAPSHOT_FETCH_CHUNK_SIZE,
80513
81486
  DOCUMENT_SNAPSHOT_FETCH_CONCURRENCY: () => DOCUMENT_SNAPSHOT_FETCH_CONCURRENCY,
81487
+ appendProjectRecordToBuckets: () => appendProjectRecordToBuckets,
80514
81488
  assembleProjectDocumentRaw: () => assembleProjectDocumentRaw,
81489
+ emptyProjectRecordBuckets: () => emptyProjectRecordBuckets,
80515
81490
  fetchProjectDocumentPartitionRecords: () => fetchProjectDocumentPartitionRecords,
80516
81491
  fetchProjectDocumentRawChunked: () => fetchProjectDocumentRawChunked,
80517
81492
  fetchProjectDocumentSnapshots: () => fetchProjectDocumentSnapshots,
@@ -80522,7 +81497,8 @@ __export(project_document_read_exports, {
80522
81497
  readProjectDocumentContentHashHeads: () => readProjectDocumentContentHashHeads,
80523
81498
  readProjectDocumentManifestPageRecords: () => readProjectDocumentManifestPageRecords,
80524
81499
  readProjectDocumentManifestRecords: () => readProjectDocumentManifestRecords,
80525
- readProjectDocumentRevisionMarker: () => readProjectDocumentRevisionMarker
81500
+ readProjectDocumentRevisionMarker: () => readProjectDocumentRevisionMarker,
81501
+ readStoredMembersField: () => readStoredMembersField
80526
81502
  });
80527
81503
  async function fetchProjectDocumentRawChunked(runner, options = {}) {
80528
81504
  const mapKeys = options.mapKeys ?? [
@@ -80847,29 +81823,7 @@ function readProjectDocumentSnapshotBatch(value, requestedIds) {
80847
81823
  });
80848
81824
  }
80849
81825
  function assembleProjectDocumentRaw(args) {
80850
- const buckets = {
80851
- project: null,
80852
- members: [],
80853
- classes: [],
80854
- constructors: [],
80855
- variants: [],
80856
- variantFolders: [],
80857
- internalRecordRelations: [],
80858
- values: [],
80859
- enums: [],
80860
- interfaces: [],
80861
- dialogueRecords: [],
80862
- dialogueNodes: [],
80863
- dialogueGroups: [],
80864
- priorityGroups: [],
80865
- projectFiles: [],
80866
- textureTemplates: [],
80867
- audioClipTemplates: [],
80868
- localizationConfig: null,
80869
- localizationStatuses: [],
80870
- localizedTexts: [],
80871
- migrations: []
80872
- };
81826
+ const buckets = emptyProjectRecordBuckets();
80873
81827
  const contentHashHeads = [];
80874
81828
  const sortedRecords = [...args.records].sort((left, right) => {
80875
81829
  const kind = left.recordKind.localeCompare(right.recordKind);
@@ -80898,7 +81852,7 @@ function assembleProjectDocumentRaw(args) {
80898
81852
  `Convex project document manifest references deleted snapshot "${snapshot.id}" for live record "${record3.recordId}".`
80899
81853
  );
80900
81854
  }
80901
- appendBucketRecord(buckets, record3.recordKind, snapshot.data);
81855
+ appendProjectRecordToBuckets(buckets, record3.recordKind, snapshot.data);
80902
81856
  contentHashHeads.push({
80903
81857
  recordKind: record3.recordKind,
80904
81858
  recordId: record3.recordId,
@@ -80944,7 +81898,32 @@ function assembleProjectDocumentRaw(args) {
80944
81898
  }
80945
81899
  return document;
80946
81900
  }
80947
- function appendBucketRecord(buckets, recordKind, data) {
81901
+ function emptyProjectRecordBuckets() {
81902
+ return {
81903
+ project: null,
81904
+ members: [],
81905
+ classes: [],
81906
+ constructors: [],
81907
+ variants: [],
81908
+ variantFolders: [],
81909
+ internalRecordRelations: [],
81910
+ values: [],
81911
+ enums: [],
81912
+ interfaces: [],
81913
+ dialogueRecords: [],
81914
+ dialogueNodes: [],
81915
+ dialogueGroups: [],
81916
+ priorityGroups: [],
81917
+ projectFiles: [],
81918
+ textureTemplates: [],
81919
+ audioClipTemplates: [],
81920
+ localizationConfig: null,
81921
+ localizationStatuses: [],
81922
+ localizedTexts: [],
81923
+ migrations: []
81924
+ };
81925
+ }
81926
+ function appendProjectRecordToBuckets(buckets, recordKind, data) {
80948
81927
  const bucket = PROJECT_RECORD_BUCKETS[recordKind];
80949
81928
  if (bucket === "project") {
80950
81929
  if (buckets.project !== null) {
@@ -80966,6 +81945,11 @@ function appendBucketRecord(buckets, recordKind, data) {
80966
81945
  }
80967
81946
  buckets[bucket].push(data);
80968
81947
  }
81948
+ function projectDocumentValueBuckets(rows) {
81949
+ const expanded = expandPackedValueRows(rows);
81950
+ if (expanded === rows) return { values: rows };
81951
+ return { values: [...expanded], physicalValues: rows };
81952
+ }
80969
81953
  function readProjectDocument(value, options = {}) {
80970
81954
  if (!isObject4(value)) {
80971
81955
  throw new Error("Convex project document query returned a non-object.");
@@ -80975,6 +81959,9 @@ function readProjectDocument(value, options = {}) {
80975
81959
  "localizationConfig",
80976
81960
  isProjectLocalizationConfig
80977
81961
  ) : readField(value, "localizationConfig", isProjectLocalizationConfig);
81962
+ const valueBuckets = projectDocumentValueBuckets(
81963
+ readArrayField(value, "values", isMemberValue)
81964
+ );
80978
81965
  return {
80979
81966
  version: readField(value, "version", isProjectVersion),
80980
81967
  versions: readArrayField(value, "versions", isProjectVersion),
@@ -80990,12 +81977,8 @@ function readProjectDocument(value, options = {}) {
80990
81977
  isProjectReleaseChannel
80991
81978
  ),
80992
81979
  project: readField(value, "project", isProject),
80993
- // Stored override rows are intentionally sparse. Narrow with the canonical
80994
- // storage union at this wire boundary while preserving the document's
80995
- // member collection type.
80996
- members: readArrayField(
81980
+ members: readStoredMembersField(
80997
81981
  value,
80998
- "members",
80999
81982
  options.members === "authored-or-compiled" ? isAnyMemberAuthoredOrCompiled : isAnyMember
81000
81983
  ),
81001
81984
  classes: readArrayField(value, "classes", isNeoSchemaClass),
@@ -81015,7 +81998,13 @@ function readProjectDocument(value, options = {}) {
81015
81998
  "internalRecordRelations",
81016
81999
  isInternalRecordRelation
81017
82000
  ),
81018
- values: readArrayField(value, "values", isMemberValue),
82001
+ // P76: a document is a READ model, so its `values` bucket is the logical
82002
+ // row set — packed parents holding plain child-id strings, packed children
82003
+ // as rows of their own. The physical form stays in the record stream this
82004
+ // document was built from, which is what the CLI's merge base and CAS
82005
+ // compare; nothing round-trips a document bucket back into storage.
82006
+ values: valueBuckets.values,
82007
+ ...valueBuckets.physicalValues === void 0 ? {} : { physicalValues: valueBuckets.physicalValues },
81019
82008
  enums: readArrayField(
81020
82009
  value,
81021
82010
  "enums",
@@ -81110,6 +82099,13 @@ function readOptionalArrayField(source, key, isValid) {
81110
82099
  if (!Object.prototype.hasOwnProperty.call(source, key)) return [];
81111
82100
  return readArrayField(source, key, isValid);
81112
82101
  }
82102
+ function readStoredMembersField(source, isValid = isAnyMember) {
82103
+ return readArrayField(
82104
+ source,
82105
+ "members",
82106
+ isValid
82107
+ );
82108
+ }
81113
82109
  function isObject4(value) {
81114
82110
  if (typeof value !== "object") return false;
81115
82111
  return value !== null;
@@ -81136,6 +82132,7 @@ var init_project_document_read = __esm({
81136
82132
  "use strict";
81137
82133
  init_project2();
81138
82134
  init_members();
82135
+ init_packed_value_encoding();
81139
82136
  init_classes();
81140
82137
  init_constructors2();
81141
82138
  init_variants2();
@@ -86547,322 +87544,53 @@ var init_animation_clips = __esm({
86547
87544
  }
86548
87545
  });
86549
87546
 
86550
- // ../src/database/headless-virtual-instance-lookups.ts
86551
- function headlessVirtualInstanceLookups(document, options = {}) {
86552
- const members = document.members;
86553
- const values = document.values;
86554
- const indexed = makeEvaluatorLookups(
86555
- members,
86556
- values,
86557
- options.includeValueGraphIndexes === true ? {
86558
- includeValueGraphIndexes: true,
86559
- constructorInitializerDocument: {
86560
- classes: document.classes,
86561
- members,
86562
- values
86563
- }
86564
- } : {}
86565
- );
86566
- const virtual = createHeadlessVirtualInstanceResolver({
86567
- document: {
86568
- ...document,
86569
- ...options.initializerCompiler === void 0 ? {} : { initializerCompiler: options.initializerCompiler }
86570
- },
86571
- // A thunk: the resolver resolves nested reads through the lookups being
86572
- // built around it.
86573
- resolverLookups: () => lookups
86574
- });
86575
- const lookups = {
86576
- ...indexed,
86577
- // Raw first, then virtual: a materialized row always wins over the
86578
- // expansion that would otherwise answer for it.
86579
- valueById: (id2) => indexed.valueById(id2) ?? virtual.valueById(id2),
86580
- rowForValueReference: (value) => indexed.rowForValueReference(value) ?? virtual.rowForValueReference(value),
86581
- virtualInstanceRowsForValue: (receiverValueId) => virtual.virtualInstanceRowsForValue(receiverValueId),
86582
- // Stored-construction replay evaluates `ToVariant`, and production's
86583
- // variant-constructed placements collapse through exactly this path.
86584
- resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument({
86585
- document,
86586
- resolverLookups: lookups,
86587
- ...args
86588
- }),
86589
- // A write to a virtual key must MATERIALIZE it (a pin row at the
86590
- // deterministic virtual id plus the sparse spine); the planner needs the
86591
- // owning graph, not just its rows.
86592
- virtualInstanceGraphForValue: (valueId) => virtual.virtualInstanceGraphForValue(valueId)
86593
- };
86594
- return lookups;
86595
- }
86596
- var init_headless_virtual_instance_lookups = __esm({
86597
- "../src/database/headless-virtual-instance-lookups.ts"() {
86598
- "use strict";
86599
- init_virtual_instance_values();
86600
- init_neoscript_evaluator();
86601
- }
86602
- });
86603
-
86604
- // src/evaluator-lookups.ts
86605
- function cliEvaluatorLookups(document, options = {}) {
86606
- return cliEvaluatorRuntime(document, options).databaseVM;
86607
- }
86608
- function cliEvaluatorRuntime(document, options = {}) {
86609
- const initializerCompiler = isPulledInitializerCompilationDocumentV4(document) ? pulledInitializerCompilerV4(document) : void 0;
86610
- const databaseVM = headlessVirtualInstanceLookups(document, {
86611
- ...options,
86612
- ...initializerCompiler === void 0 ? {} : { initializerCompiler }
86613
- });
86614
- return {
86615
- databaseVM,
86616
- ...initializerCompiler === void 0 ? {} : { initializerCompiler }
86617
- };
86618
- }
86619
- function cliEvaluatorReceiverValue(lookups, valueId) {
86620
- if (typeof valueId !== "string") return null;
86621
- return lookups.valueById(valueId)?.value ?? null;
87547
+ // ../src/database/canonical-json.ts
87548
+ function canonicalJsonStringify(value) {
87549
+ return JSON.stringify(toCanonicalJsonValue(value));
86622
87550
  }
86623
- var init_evaluator_lookups = __esm({
86624
- "src/evaluator-lookups.ts"() {
86625
- "use strict";
86626
- init_headless_virtual_instance_lookups();
86627
- init_initializer_replay();
86628
- }
86629
- });
86630
-
86631
- // src/project-source/materialized-construction-cache.ts
86632
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
86633
- import { createHash as createHash3 } from "node:crypto";
86634
- import { dirname as dirname2, join as join3 } from "node:path";
86635
- function createMaterializedConstructionExpressionsV1(args) {
86636
- const warm = args.useBuildCaches ? readMaterializedConstructionBuildCacheV2(args.root, args.state) : null;
86637
- const emitted = /* @__PURE__ */ new Map();
86638
- const overrideKeys = /* @__PURE__ */ new Map();
86639
- let emitters;
86640
- return {
86641
- get(valueId) {
86642
- const cached = warm?.expressions.get(valueId);
86643
- if (cached !== void 0) return cached;
86644
- if (emitted.has(valueId)) return emitted.get(valueId);
86645
- emitters ??= storedConstructionEmitters(args.state, args.manifest);
86646
- const expression = emitters.construction(valueId);
86647
- emitted.set(valueId, expression);
86648
- return expression;
86649
- },
86650
- overrideSchemaKeys(valueId) {
86651
- const cached = warm?.overrideKeys.get(valueId);
86652
- if (cached !== void 0) return cached;
86653
- if (overrideKeys.has(valueId)) return overrideKeys.get(valueId);
86654
- emitters ??= storedConstructionEmitters(args.state, args.manifest);
86655
- const keys = emitters.overrideSchemaKeys(valueId);
86656
- overrideKeys.set(valueId, keys);
86657
- return keys;
86658
- }
86659
- };
87551
+ function canonicallyEqual2(left, right) {
87552
+ return canonicalJsonStringify(left) === canonicalJsonStringify(right);
86660
87553
  }
86661
- function storedConstructionEmitters(state, manifest) {
86662
- const records2 = /* @__PURE__ */ new Map();
86663
- const candidateRoots = /* @__PURE__ */ new Set();
86664
- for (const record3 of Object.values(state.records)) {
86665
- records2.set(`${record3.recordKind}:${record3.recordId}`, {
86666
- recordKind: record3.recordKind,
86667
- recordId: record3.recordId,
86668
- contentHash: record3.contentHash,
86669
- deleted: false,
86670
- data: record3.data
86671
- });
86672
- if (record3.recordKind !== "value") continue;
86673
- if (!isObjectRecord2(record3.data)) continue;
86674
- if (!isObjectRecord2(record3.data.value)) continue;
86675
- const constructorArgs = record3.data.constructorArgs;
86676
- const hasInstanceProvenance = carriesStoredInstanceProvenance(record3.data);
86677
- if (constructorArgs !== void 0 && constructorArgs !== null && !hasInstanceProvenance) {
86678
- continue;
86679
- }
86680
- candidateRoots.add(record3.recordId);
86681
- }
86682
- const document = readPulledProjectDocumentV4(records2);
86683
- const owners = resolveOwnerMembersForValues(document, candidateRoots);
86684
- const storedPlacements = buildStoredValuePlacementIndexV4(records2.values());
86685
- const membersById2 = new Map(
86686
- document.members.map((member) => [member.id, member])
86687
- );
86688
- for (const valueId of candidateRoots) {
86689
- if (owners.has(valueId)) continue;
86690
- const memberId = storedPlacements.placementByChildValueId.get(valueId)?.memberId;
86691
- const member = memberId === null || memberId === void 0 ? void 0 : membersById2.get(memberId);
86692
- if (member !== void 0) owners.set(valueId, member);
86693
- }
86694
- const probe = createStoredConstructionProbeV4(records2, manifest);
86695
- let parents;
86696
- const parentByChildId = () => parents ??= storedValueParentIndex(records2, storedPlacements);
86697
- const root = (valueId) => {
86698
- const member = owners.get(valueId);
86699
- return member === void 0 ? void 0 : {
86700
- member,
86701
- valueId
86702
- };
86703
- };
86704
- const probedRootIds = /* @__PURE__ */ new Set();
86705
- const probeRootOnce = (rootValueId, ownedRoot) => {
86706
- if (probedRootIds.has(rootValueId)) {
86707
- return /* @__PURE__ */ new Set();
86708
- }
86709
- probedRootIds.add(rootValueId);
86710
- return probe.overrideKeys(ownedRoot);
86711
- };
86712
- return {
86713
- construction(valueId) {
86714
- const ownedRoot = root(valueId);
86715
- if (ownedRoot === void 0) return void 0;
86716
- return probe.construction(ownedRoot);
86717
- },
86718
- overrideSchemaKeys(valueId) {
86719
- const recorded = probe.overrideKeysOf(valueId);
86720
- if (recorded !== void 0) return recorded;
86721
- const ownedRoot = root(valueId);
86722
- if (ownedRoot !== void 0) return probeRootOnce(valueId, ownedRoot);
86723
- const ancestor = nearestOwnedAncestor(valueId, parentByChildId(), owners);
86724
- if (ancestor === null) return void 0;
86725
- const ancestorRoot = root(ancestor);
86726
- if (ancestorRoot === void 0) return void 0;
86727
- if (probedRootIds.has(ancestor)) return void 0;
86728
- probeRootOnce(ancestor, ancestorRoot);
86729
- return probe.overrideKeysOf(valueId);
87554
+ function toCanonicalJsonValue(value) {
87555
+ if (value === null) return null;
87556
+ if (value === void 0) return void 0;
87557
+ if (value instanceof Date) return value.toISOString();
87558
+ if (typeof value === "string") return value;
87559
+ if (typeof value === "boolean") return value;
87560
+ if (typeof value === "number") {
87561
+ if (!Number.isFinite(value)) {
87562
+ throw new Error("Cannot canonicalize a non-finite number.");
86730
87563
  }
86731
- };
86732
- }
86733
- function storedValueParentIndex(records2, placements) {
86734
- const parents = /* @__PURE__ */ new Map();
86735
- const valueIds = /* @__PURE__ */ new Set();
86736
- for (const record3 of records2.values()) {
86737
- if (record3.recordKind === "value") valueIds.add(record3.recordId);
87564
+ return value;
86738
87565
  }
86739
- for (const record3 of records2.values()) {
86740
- if (record3.recordKind !== "value") continue;
86741
- if (!isObjectRecord2(record3.data)) continue;
86742
- const containerId = record3.data.containerId;
86743
- if (typeof containerId === "string" && valueIds.has(containerId)) {
86744
- parents.set(record3.recordId, containerId);
86745
- }
86746
- const body = record3.data.value;
86747
- if (Array.isArray(body)) {
86748
- for (const entry of body) {
86749
- if (typeof entry === "string" && valueIds.has(entry)) {
86750
- parents.set(entry, record3.recordId);
86751
- }
86752
- }
86753
- continue;
86754
- }
86755
- if (!isObjectRecord2(body)) continue;
86756
- for (const child of Object.values(body)) {
86757
- if (typeof child === "string" && valueIds.has(child)) {
86758
- parents.set(child, record3.recordId);
86759
- }
86760
- }
87566
+ if (typeof value === "bigint") {
87567
+ throw new Error("Cannot canonicalize bigint values.");
86761
87568
  }
86762
- for (const edge of placements.placementByChildValueId.values()) {
86763
- if (edge.source !== "constructor") continue;
86764
- if (!parents.has(edge.childValueId)) {
86765
- parents.set(edge.childValueId, edge.parentValueId);
86766
- }
87569
+ if (typeof value === "symbol") {
87570
+ throw new Error("Cannot canonicalize symbol values.");
86767
87571
  }
86768
- return parents;
86769
- }
86770
- function nearestOwnedAncestor(valueId, parents, owners) {
86771
- const seen = /* @__PURE__ */ new Set([valueId]);
86772
- let cursor = parents.get(valueId);
86773
- while (cursor !== void 0 && !seen.has(cursor)) {
86774
- if (owners.has(cursor)) return cursor;
86775
- seen.add(cursor);
86776
- cursor = parents.get(cursor);
87572
+ if (typeof value === "function") {
87573
+ throw new Error("Cannot canonicalize function values.");
86777
87574
  }
86778
- return null;
86779
- }
86780
- function carriesStoredInstanceProvenance(value) {
86781
- return isVirtualInstanceRootShape(value);
86782
- }
86783
- function readMaterializedConstructionBuildCacheV2(root, state) {
86784
- try {
86785
- const parsed = JSON.parse(
86786
- readFileSync3(
86787
- join3(root, MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH),
86788
- "utf8"
86789
- )
86790
- );
86791
- if (parsed === null || typeof parsed !== "object") return null;
86792
- const cache = parsed;
86793
- if (cache.revision !== MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION || cache.stateFingerprint !== materializedConstructionStateFingerprint(state) || cache.expressions === null || typeof cache.expressions !== "object" || Array.isArray(cache.expressions)) {
86794
- return null;
86795
- }
86796
- const expressions = /* @__PURE__ */ new Map();
86797
- for (const [valueId, expression] of Object.entries(cache.expressions)) {
86798
- if (typeof expression !== "string") return null;
86799
- expressions.set(valueId, expression);
86800
- }
86801
- const overrideKeys = /* @__PURE__ */ new Map();
86802
- if (cache.overrideKeys !== void 0) {
86803
- if (cache.overrideKeys === null || typeof cache.overrideKeys !== "object" || Array.isArray(cache.overrideKeys)) {
86804
- return null;
86805
- }
86806
- for (const [valueId, keys] of Object.entries(cache.overrideKeys)) {
86807
- if (!Array.isArray(keys) || keys.some((key) => typeof key !== "string")) {
86808
- return null;
86809
- }
86810
- overrideKeys.set(valueId, new Set(keys));
86811
- }
86812
- }
86813
- return { expressions, overrideKeys };
86814
- } catch {
86815
- return null;
87575
+ if (Array.isArray(value)) {
87576
+ return value.map((item) => {
87577
+ const canonicalItem = toCanonicalJsonValue(item);
87578
+ if (canonicalItem === void 0) return null;
87579
+ return canonicalItem;
87580
+ });
86816
87581
  }
86817
- }
86818
- function writeMaterializedConstructionBuildCacheV2(root, state, cache) {
86819
- const file = join3(root, MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH);
86820
- mkdirSync3(dirname2(file), { recursive: true });
86821
- const temporary = `${file}.${process.pid}.tmp`;
86822
- writeFileSync3(
86823
- temporary,
86824
- `${JSON.stringify({
86825
- revision: MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION,
86826
- stateFingerprint: materializedConstructionStateFingerprint(state),
86827
- expressions: Object.fromEntries(
86828
- [...cache.expressions].sort(
86829
- ([left], [right]) => left.localeCompare(right)
86830
- )
86831
- ),
86832
- overrideKeys: Object.fromEntries(
86833
- [...cache.overrideKeys ?? /* @__PURE__ */ new Map()].sort(([left], [right]) => left.localeCompare(right)).map(([valueId, keys]) => [valueId, [...keys].sort()])
86834
- )
86835
- })}
86836
- `,
86837
- "utf8"
86838
- );
86839
- renameSync(temporary, file);
86840
- }
86841
- function materializedConstructionStateFingerprint(state) {
86842
- const hash = createHash3("sha256");
86843
- hash.update(String(MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION));
86844
- for (const [key, record3] of Object.entries(state.records).sort(
86845
- ([left], [right]) => left.localeCompare(right)
86846
- )) {
86847
- hash.update("\0");
86848
- hash.update(key);
86849
- hash.update("\0");
86850
- hash.update(record3.contentHash);
87582
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
87583
+ const canonicalObject = {};
87584
+ for (const [key, entryValue] of entries) {
87585
+ const canonicalValue = toCanonicalJsonValue(entryValue);
87586
+ if (canonicalValue === void 0) continue;
87587
+ canonicalObject[key] = canonicalValue;
86851
87588
  }
86852
- return hash.digest("hex");
87589
+ return canonicalObject;
86853
87590
  }
86854
- var MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH, MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION;
86855
- var init_materialized_construction_cache = __esm({
86856
- "src/project-source/materialized-construction-cache.ts"() {
87591
+ var init_canonical_json = __esm({
87592
+ "../src/database/canonical-json.ts"() {
86857
87593
  "use strict";
86858
- init_projection();
86859
- init_initializer_replay();
86860
- init_value_row_owner_members();
86861
- init_instance_provenance();
86862
- init_value_sources();
86863
- init_stored_value_placements();
86864
- MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH = ".neo/build/materialized-constructions-v1.json";
86865
- MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION = 2;
86866
87594
  }
86867
87595
  });
86868
87596
 
@@ -87049,6 +87777,22 @@ function collectVariantGraphValueIds(args) {
87049
87777
  }
87050
87778
  return collected;
87051
87779
  }
87780
+ function withVariantPlacementRoots(document) {
87781
+ const variants = document.variants ?? [];
87782
+ if (variants.length === 0) {
87783
+ return { document, roots: NO_PLACEMENT_ROOTS };
87784
+ }
87785
+ const scope = withVariantOwnershipRoots(document, variants);
87786
+ return {
87787
+ document: scope.document,
87788
+ roots: scope.roots.map((root) => ({
87789
+ member: root.member,
87790
+ valueId: root.valueId,
87791
+ position: VARIANT_ROOT_POSITION
87792
+ }))
87793
+ };
87794
+ }
87795
+ var NO_PLACEMENT_ROOTS, VARIANT_ROOT_POSITION;
87052
87796
  var init_variant_value_graph = __esm({
87053
87797
  "../src/database/variant-value-graph.ts"() {
87054
87798
  "use strict";
@@ -87056,56 +87800,958 @@ var init_variant_value_graph = __esm({
87056
87800
  init_classes();
87057
87801
  init_core();
87058
87802
  init_constructor_argument_ownership();
87803
+ NO_PLACEMENT_ROOTS = [];
87804
+ VARIANT_ROOT_POSITION = {
87805
+ insideAnimationOverrideGraph: false
87806
+ };
87059
87807
  }
87060
87808
  });
87061
87809
 
87062
- // ../src/database/canonical-json.ts
87063
- function canonicalJsonStringify(value) {
87064
- return JSON.stringify(toCanonicalJsonValue(value));
87810
+ // ../src/database/project-version-intents.ts
87811
+ function createProjectVersionIntent(type, details) {
87812
+ if (details === void 0) {
87813
+ return {
87814
+ type,
87815
+ schemaVersion: PROJECT_VERSION_INTENT_SCHEMA_VERSION
87816
+ };
87817
+ }
87818
+ return {
87819
+ type,
87820
+ schemaVersion: PROJECT_VERSION_INTENT_SCHEMA_VERSION,
87821
+ details
87822
+ };
87065
87823
  }
87066
- function canonicallyEqual2(left, right) {
87824
+ function isKnownProjectVersionIntentType(value) {
87825
+ return Object.values(ProjectVersionIntentType).includes(
87826
+ value
87827
+ );
87828
+ }
87829
+ var ProjectVersionIntentType, PROJECT_VERSION_INTENT_SCHEMA_VERSION;
87830
+ var init_project_version_intents = __esm({
87831
+ "../src/database/project-version-intents.ts"() {
87832
+ "use strict";
87833
+ ProjectVersionIntentType = {
87834
+ ProjectCreate: "project.create",
87835
+ ProjectUpdate: "project.update",
87836
+ MemberCreate: "member.create",
87837
+ MemberUpdate: "member.update",
87838
+ MemberRename: "member.rename",
87839
+ MemberSetValue: "member.set-value",
87840
+ MemberClearValue: "member.clear-value",
87841
+ MemberDelete: "member.delete",
87842
+ ClassCreate: "class.create",
87843
+ ClassUpdate: "class.update",
87844
+ ClassDelete: "class.delete",
87845
+ ClassAddSchemaEntry: "class.add-schema-entry",
87846
+ ConstructorCreate: "constructor.create",
87847
+ ConstructorUpdate: "constructor.update",
87848
+ ConstructorDelete: "constructor.delete",
87849
+ VariantCreate: "variant.create",
87850
+ VariantUpdate: "variant.update",
87851
+ VariantDelete: "variant.delete",
87852
+ VariantFolderCreate: "variant-folder.create",
87853
+ VariantFolderUpdate: "variant-folder.update",
87854
+ VariantFolderDelete: "variant-folder.delete",
87855
+ InternalRecordRelationCreate: "internal-record-relation.create",
87856
+ InternalRecordRelationUpdate: "internal-record-relation.update",
87857
+ InternalRecordRelationDelete: "internal-record-relation.delete",
87858
+ EnumCreate: "enum.create",
87859
+ EnumUpdate: "enum.update",
87860
+ EnumDelete: "enum.delete",
87861
+ InterfaceCreate: "interface.create",
87862
+ InterfaceUpdate: "interface.update",
87863
+ InterfaceDelete: "interface.delete",
87864
+ EnumOptionRename: "enum-option.rename",
87865
+ EnumOptionDelete: "enum-option.delete",
87866
+ ValueCreate: "value.create",
87867
+ ValueUpdate: "value.update",
87868
+ /** P76 §3: a row rewritten only because its member's distribution moved. */
87869
+ ValueRedistribute: "value.redistribute",
87870
+ ValueDelete: "value.delete",
87871
+ ValueEntryRenameKey: "value-entry.rename-key",
87872
+ DialogueCreate: "dialogue.create",
87873
+ DialogueUpdate: "dialogue.update",
87874
+ DialogueDelete: "dialogue.delete",
87875
+ DialogueNodeCreate: "dialogue-node.create",
87876
+ DialogueNodeUpdate: "dialogue-node.update",
87877
+ DialogueNodeDelete: "dialogue-node.delete",
87878
+ DialogueGroupCreate: "dialogue-group.create",
87879
+ DialogueGroupUpdate: "dialogue-group.update",
87880
+ DialogueGroupDelete: "dialogue-group.delete",
87881
+ PriorityGroupCreate: "priority-group.create",
87882
+ PriorityGroupUpdate: "priority-group.update",
87883
+ PriorityGroupDelete: "priority-group.delete",
87884
+ ProjectFileCreate: "project-file.create",
87885
+ ProjectFileUpdate: "project-file.update",
87886
+ ProjectFileDelete: "project-file.delete",
87887
+ UnityTextureTemplateCreate: "unity-texture-template.create",
87888
+ UnityTextureTemplateUpdate: "unity-texture-template.update",
87889
+ UnityTextureTemplateDelete: "unity-texture-template.delete",
87890
+ UnityAudioClipTemplateCreate: "unity-audio-clip-template.create",
87891
+ UnityAudioClipTemplateUpdate: "unity-audio-clip-template.update",
87892
+ UnityAudioClipTemplateDelete: "unity-audio-clip-template.delete",
87893
+ LocalizationConfigCreate: "localization-config.create",
87894
+ LocalizationConfigUpdate: "localization-config.update",
87895
+ LocalizationStatusCreate: "localization-status.create",
87896
+ LocalizationStatusUpdate: "localization-status.update",
87897
+ LocalizationStatusDelete: "localization-status.delete",
87898
+ LocalizedTextCreate: "localized-text.create",
87899
+ LocalizedTextUpdate: "localized-text.update",
87900
+ LocalizedTextDelete: "localized-text.delete",
87901
+ MigrationCreate: "migration.create",
87902
+ MigrationUpdate: "migration.update",
87903
+ MigrationDelete: "migration.delete"
87904
+ };
87905
+ PROJECT_VERSION_INTENT_SCHEMA_VERSION = 1;
87906
+ }
87907
+ });
87908
+
87909
+ // ../src/database/packed-value-write-fold.ts
87910
+ function schemaPacksAnyMember(members) {
87911
+ const cached = packedSchemaCache.get(members);
87912
+ if (cached !== void 0) return cached;
87913
+ let packs = false;
87914
+ for (const member of members) {
87915
+ if (effectiveMemberDistribution(member, members) !== 1 /* Packed */) {
87916
+ continue;
87917
+ }
87918
+ packs = true;
87919
+ break;
87920
+ }
87921
+ packedSchemaCache.set(members, packs);
87922
+ return packs;
87923
+ }
87924
+ function packableParentValueId(args) {
87925
+ if (args.placement.parentValueId === null) return null;
87926
+ if (args.row.containerId !== void 0) return null;
87927
+ if (args.parentRow === void 0) return null;
87928
+ if (args.parentRow.mapKey !== args.row.mapKey) return null;
87929
+ return args.placement.parentValueId;
87930
+ }
87931
+ function packedChildPlacement(args) {
87932
+ const placement = args.placement;
87933
+ if (placement === void 0) return null;
87934
+ const parentValueId = packableParentValueId({ ...args, placement });
87935
+ if (parentValueId === null) return null;
87936
+ if (effectiveMemberDistribution(placement.member, args.members) !== 1 /* Packed */) {
87937
+ return null;
87938
+ }
87939
+ return parentValueId;
87940
+ }
87941
+ function foldPackedValueRows(args) {
87942
+ const expanded = args.residency === void 0 ? expandWithResidency(args.rows) : { ...args.residency, logicalRows: args.rows };
87943
+ if (expanded.rootByPackedId.size === 0 && !schemaPacksAnyMember(args.document.members)) {
87944
+ return { rows: args.rows, rootByFoldedId: NO_FOLDED_IDS };
87945
+ }
87946
+ const rowsById = /* @__PURE__ */ new Map();
87947
+ for (const row of expanded.logicalRows) rowsById.set(row.id, row);
87948
+ const scope = withVariantPlacementRoots({
87949
+ ...args.document,
87950
+ values: [...expanded.logicalRows]
87951
+ });
87952
+ const placements = findSemanticOwnerPlacementsForValues(
87953
+ scope.document,
87954
+ new Set(rowsById.keys()),
87955
+ scope.roots
87956
+ );
87957
+ const parentByPackedId = /* @__PURE__ */ new Map();
87958
+ for (const row of expanded.logicalRows) {
87959
+ const placement = placements.get(row.id);
87960
+ const parentValueId = packedChildPlacement({
87961
+ row,
87962
+ placement,
87963
+ parentRow: placement?.parentValueId == null ? void 0 : rowsById.get(placement.parentValueId),
87964
+ members: args.document.members
87965
+ });
87966
+ if (parentValueId !== null) {
87967
+ parentByPackedId.set(row.id, parentValueId);
87968
+ continue;
87969
+ }
87970
+ const residentParent = expanded.parentByPackedId.get(row.id);
87971
+ if (residentParent === void 0) continue;
87972
+ const residentParentRow = rowsById.get(residentParent);
87973
+ if (residentParentRow === void 0) continue;
87974
+ if (!rowNamesChild(residentParentRow, row.id)) continue;
87975
+ parentByPackedId.set(row.id, residentParent);
87976
+ }
87977
+ if (parentByPackedId.size === 0) {
87978
+ return { rows: args.rows, rootByFoldedId: NO_FOLDED_IDS };
87979
+ }
87980
+ const rootByFoldedId = /* @__PURE__ */ new Map();
87981
+ const packedChildIdsByParentId = /* @__PURE__ */ new Map();
87982
+ for (const [childId, parentId] of parentByPackedId) {
87983
+ const siblings = packedChildIdsByParentId.get(parentId);
87984
+ if (siblings === void 0) {
87985
+ packedChildIdsByParentId.set(parentId, [childId]);
87986
+ } else {
87987
+ siblings.push(childId);
87988
+ }
87989
+ rootByFoldedId.set(childId, distributionRootOf(childId, parentByPackedId));
87990
+ }
87991
+ const encodeRootIds = args.encodeOnlyRootIds?.(rootByFoldedId);
87992
+ const rows = [];
87993
+ for (const row of expanded.logicalRows) {
87994
+ if (parentByPackedId.has(row.id)) continue;
87995
+ if (!packedChildIdsByParentId.has(row.id)) {
87996
+ rows.push(row);
87997
+ continue;
87998
+ }
87999
+ if (encodeRootIds !== void 0 && !encodeRootIds.has(row.id)) {
88000
+ rows.push(row);
88001
+ continue;
88002
+ }
88003
+ rows.push(
88004
+ encodePackedValueRow({ parent: row, rowsById, packedChildIdsByParentId })
88005
+ );
88006
+ }
88007
+ return { rows, rootByFoldedId };
88008
+ }
88009
+ function distributionRootOf(childId, parentByPackedId) {
88010
+ let current = childId;
88011
+ for (let step = 0; step < PACKED_ANCESTOR_LIMIT; step += 1) {
88012
+ const parent = parentByPackedId.get(current);
88013
+ if (parent === void 0) return current;
88014
+ current = parent;
88015
+ }
88016
+ throw new PackedValueEncodingError(
88017
+ `Packed value "${childId}" has more than ${PACKED_ANCESTOR_LIMIT} packed ancestors, so its distribution root cannot be resolved.`
88018
+ );
88019
+ }
88020
+ function expandWithResidency(rows) {
88021
+ let firstPacked = -1;
88022
+ for (let index = 0; index < rows.length; index += 1) {
88023
+ const row = rows[index];
88024
+ if (row === void 0 || !rowCarriesPackedValueContent(row)) continue;
88025
+ firstPacked = index;
88026
+ break;
88027
+ }
88028
+ if (firstPacked < 0) {
88029
+ return {
88030
+ logicalRows: rows,
88031
+ parentByPackedId: NO_RESIDENCY,
88032
+ rootByPackedId: NO_RESIDENCY
88033
+ };
88034
+ }
88035
+ const logicalRows = rows.slice(0, firstPacked);
88036
+ const parentByPackedId = /* @__PURE__ */ new Map();
88037
+ const rootByPackedId = /* @__PURE__ */ new Map();
88038
+ for (let index = firstPacked; index < rows.length; index += 1) {
88039
+ const row = rows[index];
88040
+ if (row === void 0) continue;
88041
+ const decoded = decodePackedValueRow(row);
88042
+ logicalRows.push(decoded.row, ...decoded.children);
88043
+ for (const [parentId, childIds] of decoded.packedChildIdsByParentId) {
88044
+ for (const childId of childIds) {
88045
+ parentByPackedId.set(childId, parentId);
88046
+ rootByPackedId.set(childId, row.id);
88047
+ }
88048
+ }
88049
+ }
88050
+ return { logicalRows, parentByPackedId, rootByPackedId };
88051
+ }
88052
+ function foldPackedValueWriteChanges(args) {
88053
+ const valueChangesById = collectValueChanges(args.changes);
88054
+ if (valueChangesById.size === 0) return args.changes;
88055
+ const base = expandWithResidency(args.document.values);
88056
+ if (base.rootByPackedId.size === 0 && !schemaPacksAnyMember(args.document.members)) {
88057
+ return args.changes;
88058
+ }
88059
+ const basePhysicalById = /* @__PURE__ */ new Map();
88060
+ for (const row of args.document.values) basePhysicalById.set(row.id, row);
88061
+ const postLogicalById = /* @__PURE__ */ new Map();
88062
+ for (const row of base.logicalRows) postLogicalById.set(row.id, row);
88063
+ applyValueChanges(postLogicalById, valueChangesById);
88064
+ const parentByPackedId = new Map(base.parentByPackedId);
88065
+ const rootByPackedId = new Map(base.rootByPackedId);
88066
+ decodePhysicalPostRows({
88067
+ post: postLogicalById,
88068
+ valueChangesById,
88069
+ parentByPackedId,
88070
+ rootByPackedId
88071
+ });
88072
+ releaseRedistributedResidency({
88073
+ valueChangesById,
88074
+ parentByPackedId,
88075
+ rootByPackedId
88076
+ });
88077
+ const baseRootOf = (id2) => base.rootByPackedId.get(id2);
88078
+ const fold = foldPackedValueRows({
88079
+ rows: [...postLogicalById.values()],
88080
+ document: args.document,
88081
+ residency: { parentByPackedId, rootByPackedId },
88082
+ encodeOnlyRootIds: touchedRootIds(valueChangesById, baseRootOf)
88083
+ });
88084
+ return emitFoldedValueChanges({
88085
+ changes: args.changes,
88086
+ valueChangesById,
88087
+ fold,
88088
+ basePhysicalOf: (id2) => basePhysicalById.get(id2),
88089
+ baseRootOf
88090
+ });
88091
+ }
88092
+ function namedIds(container) {
88093
+ if (typeof container !== "object" || container === null) return [];
88094
+ const entries = Array.isArray(container) ? container : Object.values(container);
88095
+ const ids = [];
88096
+ for (const entry of entries) {
88097
+ if (typeof entry === "string") ids.push(entry);
88098
+ }
88099
+ return ids;
88100
+ }
88101
+ function collectValueChanges(changes) {
88102
+ const valueChangesById = /* @__PURE__ */ new Map();
88103
+ for (const change of changes) {
88104
+ if (change.recordKind !== ProjectRecordKind.Value) continue;
88105
+ valueChangesById.set(change.recordId, change);
88106
+ }
88107
+ return valueChangesById;
88108
+ }
88109
+ function applyValueChanges(rowsById, valueChangesById) {
88110
+ for (const change of valueChangesById.values()) {
88111
+ if (change.deleted === true) {
88112
+ rowsById.delete(change.recordId);
88113
+ continue;
88114
+ }
88115
+ if (!isMemberValue(change.nextData)) {
88116
+ throw new Error(
88117
+ `Value "${change.recordId}" cannot be prepared for packed storage because its change carries no value row.`
88118
+ );
88119
+ }
88120
+ rowsById.set(change.recordId, change.nextData);
88121
+ }
88122
+ }
88123
+ function decodePhysicalPostRows(args) {
88124
+ for (const change of args.valueChangesById.values()) {
88125
+ if (change.deleted === true) continue;
88126
+ const row = args.post.get(change.recordId);
88127
+ if (row === void 0 || !rowCarriesPackedValueContent(row)) continue;
88128
+ const decoded = decodePackedValueRow(row);
88129
+ args.post.set(decoded.row.id, decoded.row);
88130
+ for (const child of decoded.children) {
88131
+ if (args.valueChangesById.has(child.id)) continue;
88132
+ args.post.set(child.id, child);
88133
+ }
88134
+ for (const [parentId, childIds] of decoded.packedChildIdsByParentId) {
88135
+ for (const childId of childIds) {
88136
+ args.parentByPackedId.set(childId, parentId);
88137
+ args.rootByPackedId.set(childId, row.id);
88138
+ }
88139
+ }
88140
+ }
88141
+ }
88142
+ function releaseRedistributedResidency(args) {
88143
+ for (const change of args.valueChangesById.values()) {
88144
+ if (change.intent.type !== ProjectVersionIntentType.ValueRedistribute) {
88145
+ continue;
88146
+ }
88147
+ args.parentByPackedId.delete(change.recordId);
88148
+ args.rootByPackedId.delete(change.recordId);
88149
+ }
88150
+ }
88151
+ function rowNamesChild(parent, childId) {
88152
+ if (namedIds(parent.value).includes(childId)) return true;
88153
+ if (!isLiteralValueContent(parent)) return false;
88154
+ return namedIds(parent.constructorArgs).includes(childId);
88155
+ }
88156
+ function touchedRootIds(valueChangesById, baseRootOf) {
88157
+ return (rootByFoldedId) => {
88158
+ const ids = /* @__PURE__ */ new Set();
88159
+ for (const valueId of valueChangesById.keys()) {
88160
+ ids.add(valueId);
88161
+ const foldedRoot = rootByFoldedId.get(valueId);
88162
+ if (foldedRoot !== void 0) ids.add(foldedRoot);
88163
+ const baseRoot = baseRootOf(valueId);
88164
+ if (baseRoot !== void 0) ids.add(baseRoot);
88165
+ }
88166
+ return ids;
88167
+ };
88168
+ }
88169
+ function emitFoldedValueChanges(args) {
88170
+ const { valueChangesById, fold } = args;
88171
+ const postPhysicalById = /* @__PURE__ */ new Map();
88172
+ for (const row of fold.rows) postPhysicalById.set(row.id, row);
88173
+ const originByPhysicalId = /* @__PURE__ */ new Map();
88174
+ const remember = (physicalId, origin) => {
88175
+ if (physicalId === void 0) return;
88176
+ if (originByPhysicalId.has(physicalId)) return;
88177
+ originByPhysicalId.set(physicalId, origin);
88178
+ };
88179
+ for (const [valueId, change] of valueChangesById) remember(valueId, change);
88180
+ for (const [valueId, change] of valueChangesById) {
88181
+ remember(fold.rootByFoldedId.get(valueId), change);
88182
+ remember(args.baseRootOf(valueId), change);
88183
+ }
88184
+ const folded = [];
88185
+ const emittedIds = /* @__PURE__ */ new Set();
88186
+ const emit = (change) => {
88187
+ if (emittedIds.has(change.recordId)) return;
88188
+ emittedIds.add(change.recordId);
88189
+ folded.push(change);
88190
+ };
88191
+ const removeRecord = (recordId, origin) => {
88192
+ emit({
88193
+ ...carriedChangeFields(origin, recordId),
88194
+ recordKind: ProjectRecordKind.Value,
88195
+ recordId,
88196
+ operation: ProjectVersionRecordOperation.Delete,
88197
+ deleted: true
88198
+ });
88199
+ };
88200
+ const emitPhysical = (physicalId, origin, requested) => {
88201
+ const next = postPhysicalById.get(physicalId);
88202
+ const storedBase = args.basePhysicalOf(physicalId);
88203
+ if (next === void 0) {
88204
+ if (storedBase === void 0) return;
88205
+ removeRecord(physicalId, origin);
88206
+ return;
88207
+ }
88208
+ if (!requested && storedBase !== void 0 && rowsAreIdentical(storedBase, next)) {
88209
+ return;
88210
+ }
88211
+ emit({
88212
+ ...carriedChangeFields(origin, physicalId),
88213
+ recordKind: ProjectRecordKind.Value,
88214
+ recordId: physicalId,
88215
+ operation: storedBase === void 0 ? ProjectVersionRecordOperation.Create : ProjectVersionRecordOperation.Update,
88216
+ deleted: false,
88217
+ nextData: next
88218
+ });
88219
+ };
88220
+ for (const change of args.changes) {
88221
+ if (change.recordKind !== ProjectRecordKind.Value) {
88222
+ folded.push(change);
88223
+ continue;
88224
+ }
88225
+ const physicalId = postPhysicalById.has(change.recordId) || args.basePhysicalOf(change.recordId) !== void 0 ? change.recordId : fold.rootByFoldedId.get(change.recordId);
88226
+ if (physicalId === void 0) continue;
88227
+ const origin = originByPhysicalId.get(physicalId) ?? change;
88228
+ emitPhysical(physicalId, origin, origin.recordId === physicalId);
88229
+ }
88230
+ for (const [physicalId, origin] of originByPhysicalId) {
88231
+ if (emittedIds.has(physicalId)) continue;
88232
+ emitPhysical(physicalId, origin, false);
88233
+ }
88234
+ for (const [foldedId, rootId] of fold.rootByFoldedId) {
88235
+ if (args.basePhysicalOf(foldedId) === void 0) continue;
88236
+ const origin = originByPhysicalId.get(rootId);
88237
+ if (origin === void 0) continue;
88238
+ removeRecord(foldedId, origin);
88239
+ }
88240
+ return folded;
88241
+ }
88242
+ function carriedChangeFields(origin, physicalId) {
88243
+ if (origin.recordId === physicalId) {
88244
+ const {
88245
+ nextData: _nextData,
88246
+ recordKind: _recordKind,
88247
+ recordId: _recordId,
88248
+ operation: _operation,
88249
+ deleted: _deleted,
88250
+ ...carried
88251
+ } = origin;
88252
+ return carried;
88253
+ }
88254
+ return { intent: origin.intent };
88255
+ }
88256
+ function rowsAreIdentical(left, right) {
88257
+ if (left === right) return true;
87067
88258
  return canonicalJsonStringify(left) === canonicalJsonStringify(right);
87068
88259
  }
87069
- function toCanonicalJsonValue(value) {
87070
- if (value === null) return null;
87071
- if (value === void 0) return void 0;
87072
- if (value instanceof Date) return value.toISOString();
87073
- if (typeof value === "string") return value;
87074
- if (typeof value === "boolean") return value;
87075
- if (typeof value === "number") {
87076
- if (!Number.isFinite(value)) {
87077
- throw new Error("Cannot canonicalize a non-finite number.");
88260
+ function expandPackedValueWriteChanges(args) {
88261
+ const decodedByValueId = /* @__PURE__ */ new Map();
88262
+ const directValueIds = /* @__PURE__ */ new Set();
88263
+ for (const change of args.changes) {
88264
+ if (change.recordKind !== ProjectRecordKind.Value) continue;
88265
+ if (isDeleteChange(change)) continue;
88266
+ directValueIds.add(change.recordId);
88267
+ if (!isMemberValue(change.nextData)) continue;
88268
+ if (!rowCarriesPackedValueContent(change.nextData)) continue;
88269
+ decodedByValueId.set(
88270
+ change.recordId,
88271
+ decodePackedValueRow(change.nextData)
88272
+ );
88273
+ }
88274
+ if (decodedByValueId.size === 0) return args.changes;
88275
+ const packedChildIds = /* @__PURE__ */ new Set();
88276
+ for (const decoded of decodedByValueId.values()) {
88277
+ for (const child of decoded.children) packedChildIds.add(child.id);
88278
+ }
88279
+ const baseValueIds = /* @__PURE__ */ new Set();
88280
+ for (const row of args.baseValues) baseValueIds.add(row.id);
88281
+ const expanded = [];
88282
+ for (const change of args.changes) {
88283
+ if (change.recordKind !== ProjectRecordKind.Value) {
88284
+ expanded.push(change);
88285
+ continue;
88286
+ }
88287
+ if (isDeleteChange(change) && packedChildIds.has(change.recordId)) continue;
88288
+ const decoded = decodedByValueId.get(change.recordId);
88289
+ if (decoded === void 0) {
88290
+ expanded.push(change);
88291
+ continue;
88292
+ }
88293
+ expanded.push({ ...change, nextData: decoded.row });
88294
+ for (const child of decoded.children) {
88295
+ if (directValueIds.has(child.id)) continue;
88296
+ expanded.push({
88297
+ intent: change.intent,
88298
+ recordKind: ProjectRecordKind.Value,
88299
+ recordId: child.id,
88300
+ operation: baseValueIds.has(child.id) ? ProjectVersionRecordOperation.Update : ProjectVersionRecordOperation.Create,
88301
+ deleted: false,
88302
+ nextData: child
88303
+ });
87078
88304
  }
87079
- return value;
87080
88305
  }
87081
- if (typeof value === "bigint") {
87082
- throw new Error("Cannot canonicalize bigint values.");
88306
+ return expanded;
88307
+ }
88308
+ function isDeleteChange(change) {
88309
+ if (change.operation === ProjectVersionRecordOperation.Delete) return true;
88310
+ return change.deleted === true;
88311
+ }
88312
+ var NO_FOLDED_IDS, PACKED_ANCESTOR_LIMIT, packedSchemaCache, NO_RESIDENCY;
88313
+ var init_packed_value_write_fold = __esm({
88314
+ "../src/database/packed-value-write-fold.ts"() {
88315
+ "use strict";
88316
+ init_project2();
88317
+ init_member_kinds();
88318
+ init_effective_distribution();
88319
+ init_member_subtree_distribution();
88320
+ init_packed_value_encoding();
88321
+ init_canonical_json();
88322
+ init_constructor_argument_ownership();
88323
+ init_variant_value_graph();
88324
+ init_project_version_intents();
88325
+ NO_FOLDED_IDS = /* @__PURE__ */ new Map();
88326
+ PACKED_ANCESTOR_LIMIT = 512;
88327
+ packedSchemaCache = /* @__PURE__ */ new WeakMap();
88328
+ NO_RESIDENCY = /* @__PURE__ */ new Map();
87083
88329
  }
87084
- if (typeof value === "symbol") {
87085
- throw new Error("Cannot canonicalize symbol values.");
88330
+ });
88331
+
88332
+ // src/project-source/packed-value-parity.ts
88333
+ function logicalValueBaseRecordsV4(records2) {
88334
+ let expanded = null;
88335
+ for (const [key, record3] of Object.entries(records2)) {
88336
+ if (record3.recordKind !== "value") continue;
88337
+ if (!isObjectRecord2(record3.data)) continue;
88338
+ if (!rowCarriesPackedValueContent(record3.data)) continue;
88339
+ if (!isMemberValue(record3.data)) {
88340
+ throw new PackedValueEncodingError(
88341
+ `Workspace base row "${key}" packs a child but is not a well-formed value row, so its packed payload cannot be expanded.`
88342
+ );
88343
+ }
88344
+ const decoded = decodePackedValueRow(record3.data);
88345
+ expanded ??= { ...records2 };
88346
+ expanded[key] = { ...record3, data: decoded.row };
88347
+ for (const child of decoded.children) {
88348
+ expanded[`value:${child.id}`] = {
88349
+ recordKind: "value",
88350
+ recordId: child.id,
88351
+ contentHash: record3.contentHash,
88352
+ ...record3.file === void 0 ? {} : { file: record3.file },
88353
+ data: child
88354
+ };
88355
+ }
87086
88356
  }
87087
- if (typeof value === "function") {
87088
- throw new Error("Cannot canonicalize function values.");
88357
+ return expanded ?? records2;
88358
+ }
88359
+ function foldCandidateValueRowsV4(args) {
88360
+ if (args.candidates.size === 0) return EMPTY_FOLD;
88361
+ const rows = [];
88362
+ const inputById = /* @__PURE__ */ new Map();
88363
+ for (const [valueId, body] of args.candidates) {
88364
+ const row = completeCandidateRow(valueId, body, args.base, args.projectId);
88365
+ if (row === null) return EMPTY_FOLD;
88366
+ rows.push(row);
88367
+ inputById.set(valueId, row);
88368
+ }
88369
+ const fold = foldPackedValueRows({ rows, document: args.schema });
88370
+ if (fold.rootByFoldedId.size === 0) return EMPTY_FOLD;
88371
+ const adoptedRootIds = /* @__PURE__ */ new Set();
88372
+ for (const [childId, rootId] of fold.rootByFoldedId) {
88373
+ if (adoptedRootIds.has(rootId)) continue;
88374
+ if (!args.touchedValueIds.has(childId) && !args.touchedValueIds.has(rootId))
88375
+ continue;
88376
+ adoptedRootIds.add(rootId);
87089
88377
  }
87090
- if (Array.isArray(value)) {
87091
- return value.map((item) => {
87092
- const canonicalItem = toCanonicalJsonValue(item);
87093
- if (canonicalItem === void 0) return null;
87094
- return canonicalItem;
88378
+ if (adoptedRootIds.size === 0) return EMPTY_FOLD;
88379
+ const foldedValueIds = /* @__PURE__ */ new Set();
88380
+ for (const [childId, rootId] of fold.rootByFoldedId) {
88381
+ if (adoptedRootIds.has(rootId)) foldedValueIds.add(childId);
88382
+ }
88383
+ const bodyByValueId = /* @__PURE__ */ new Map();
88384
+ for (const row of fold.rows) {
88385
+ if (!adoptedRootIds.has(row.id)) continue;
88386
+ if (row === inputById.get(row.id)) continue;
88387
+ const candidate = args.candidates.get(row.id);
88388
+ if (candidate === void 0) {
88389
+ throw new PackedValueEncodingError(
88390
+ `Packed fold produced a physical row for "${row.id}", which is not a candidate value row of this push.`
88391
+ );
88392
+ }
88393
+ bodyByValueId.set(row.id, storedContentApplied(candidate, row));
88394
+ }
88395
+ return { bodyByValueId, foldedValueIds };
88396
+ }
88397
+ function completeCandidateRow(valueId, body, base, projectId) {
88398
+ if (isMemberValue(body)) return body;
88399
+ const stored = base[`value:${valueId}`]?.data;
88400
+ const envelope = isObjectRecord2(stored) ? stored : void 0;
88401
+ const completed = { ...body, id: valueId };
88402
+ if (typeof completed.projectId !== "string") {
88403
+ completed.projectId = projectId;
88404
+ }
88405
+ if (!isEpochMillis(completed.createdAt)) {
88406
+ completed.createdAt = isEpochMillis(envelope?.createdAt) ? envelope.createdAt : 0;
88407
+ }
88408
+ if (!isEpochMillis(completed.updatedAt)) {
88409
+ completed.updatedAt = isEpochMillis(envelope?.updatedAt) ? envelope.updatedAt : 0;
88410
+ }
88411
+ return isMemberValue(completed) ? completed : null;
88412
+ }
88413
+ function storedContentApplied(candidate, row) {
88414
+ if (!isLiteralValueContent(row)) {
88415
+ throw new PackedValueEncodingError(
88416
+ `Packed fold rewrote value "${row.id}", which stores an initializer rather than a literal body.`
88417
+ );
88418
+ }
88419
+ const applied = { ...candidate, value: row.value };
88420
+ if (Object.hasOwn(row, "constructorArgs")) {
88421
+ applied.constructorArgs = row.constructorArgs;
88422
+ } else {
88423
+ delete applied.constructorArgs;
88424
+ }
88425
+ return applied;
88426
+ }
88427
+ var EMPTY_FOLD;
88428
+ var init_packed_value_parity = __esm({
88429
+ "src/project-source/packed-value-parity.ts"() {
88430
+ "use strict";
88431
+ init_core();
88432
+ init_members();
88433
+ init_packed_value_write_fold();
88434
+ init_projection();
88435
+ EMPTY_FOLD = {
88436
+ bodyByValueId: /* @__PURE__ */ new Map(),
88437
+ foldedValueIds: /* @__PURE__ */ new Set()
88438
+ };
88439
+ }
88440
+ });
88441
+
88442
+ // ../src/database/headless-virtual-instance-lookups.ts
88443
+ function headlessVirtualInstanceLookups(document, options = {}) {
88444
+ const members = document.members;
88445
+ const expandedDocument = expandPackedDocumentValues(document);
88446
+ const values = expandedDocument.values;
88447
+ const indexed = makeEvaluatorLookups(
88448
+ members,
88449
+ values,
88450
+ options.includeValueGraphIndexes === true ? {
88451
+ includeValueGraphIndexes: true,
88452
+ constructorInitializerDocument: {
88453
+ classes: document.classes,
88454
+ members,
88455
+ values
88456
+ }
88457
+ } : {}
88458
+ );
88459
+ const virtual = createHeadlessVirtualInstanceResolver({
88460
+ document: {
88461
+ ...expandedDocument,
88462
+ ...options.initializerCompiler === void 0 ? {} : { initializerCompiler: options.initializerCompiler }
88463
+ },
88464
+ // A thunk: the resolver resolves nested reads through the lookups being
88465
+ // built around it.
88466
+ resolverLookups: () => lookups
88467
+ });
88468
+ const lookups = {
88469
+ ...indexed,
88470
+ // Raw first, then virtual: a materialized row always wins over the
88471
+ // expansion that would otherwise answer for it.
88472
+ valueById: (id2) => indexed.valueById(id2) ?? virtual.valueById(id2),
88473
+ rowForValueReference: (value) => indexed.rowForValueReference(value) ?? virtual.rowForValueReference(value),
88474
+ virtualInstanceRowsForValue: (receiverValueId) => virtual.virtualInstanceRowsForValue(receiverValueId),
88475
+ // Stored-construction replay evaluates `ToVariant`, and production's
88476
+ // variant-constructed placements collapse through exactly this path.
88477
+ resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument({
88478
+ document,
88479
+ resolverLookups: lookups,
88480
+ ...args
88481
+ }),
88482
+ // A write to a virtual key must MATERIALIZE it (a pin row at the
88483
+ // deterministic virtual id plus the sparse spine); the planner needs the
88484
+ // owning graph, not just its rows.
88485
+ virtualInstanceGraphForValue: (valueId) => virtual.virtualInstanceGraphForValue(valueId)
88486
+ };
88487
+ return lookups;
88488
+ }
88489
+ var init_headless_virtual_instance_lookups = __esm({
88490
+ "../src/database/headless-virtual-instance-lookups.ts"() {
88491
+ "use strict";
88492
+ init_virtual_instance_values();
88493
+ init_packed_value_encoding();
88494
+ init_neoscript_evaluator();
88495
+ }
88496
+ });
88497
+
88498
+ // src/evaluator-lookups.ts
88499
+ function cliEvaluatorLookups(document, options = {}) {
88500
+ return cliEvaluatorRuntime(document, options).databaseVM;
88501
+ }
88502
+ function cliEvaluatorRuntime(document, options = {}) {
88503
+ const initializerCompiler = isPulledInitializerCompilationDocumentV4(document) ? pulledInitializerCompilerV4(document) : void 0;
88504
+ const databaseVM = headlessVirtualInstanceLookups(document, {
88505
+ ...options,
88506
+ ...initializerCompiler === void 0 ? {} : { initializerCompiler }
88507
+ });
88508
+ return {
88509
+ databaseVM,
88510
+ ...initializerCompiler === void 0 ? {} : { initializerCompiler }
88511
+ };
88512
+ }
88513
+ function cliEvaluatorReceiverValue(lookups, valueId) {
88514
+ if (typeof valueId !== "string") return null;
88515
+ return lookups.valueById(valueId)?.value ?? null;
88516
+ }
88517
+ var init_evaluator_lookups = __esm({
88518
+ "src/evaluator-lookups.ts"() {
88519
+ "use strict";
88520
+ init_headless_virtual_instance_lookups();
88521
+ init_initializer_replay();
88522
+ }
88523
+ });
88524
+
88525
+ // src/project-source/materialized-construction-cache.ts
88526
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
88527
+ import { createHash as createHash3 } from "node:crypto";
88528
+ import { dirname as dirname2, join as join3 } from "node:path";
88529
+ function createMaterializedConstructionExpressionsV1(args) {
88530
+ const warm = args.useBuildCaches ? readMaterializedConstructionBuildCacheV2(args.root, args.state) : null;
88531
+ const emitted = /* @__PURE__ */ new Map();
88532
+ const overrideKeys = /* @__PURE__ */ new Map();
88533
+ let emitters;
88534
+ return {
88535
+ get(valueId) {
88536
+ const cached = warm?.expressions.get(valueId);
88537
+ if (cached !== void 0) return cached;
88538
+ if (emitted.has(valueId)) return emitted.get(valueId);
88539
+ emitters ??= storedConstructionEmitters(args.state, args.manifest);
88540
+ const expression = emitters.construction(valueId);
88541
+ emitted.set(valueId, expression);
88542
+ return expression;
88543
+ },
88544
+ overrideSchemaKeys(valueId) {
88545
+ const cached = warm?.overrideKeys.get(valueId);
88546
+ if (cached !== void 0) return cached;
88547
+ if (overrideKeys.has(valueId)) return overrideKeys.get(valueId);
88548
+ emitters ??= storedConstructionEmitters(args.state, args.manifest);
88549
+ const keys = emitters.overrideSchemaKeys(valueId);
88550
+ overrideKeys.set(valueId, keys);
88551
+ return keys;
88552
+ }
88553
+ };
88554
+ }
88555
+ function storedConstructionEmitters(state, manifest) {
88556
+ const records2 = /* @__PURE__ */ new Map();
88557
+ const candidateRoots = /* @__PURE__ */ new Set();
88558
+ for (const record3 of Object.values(state.records)) {
88559
+ records2.set(`${record3.recordKind}:${record3.recordId}`, {
88560
+ recordKind: record3.recordKind,
88561
+ recordId: record3.recordId,
88562
+ contentHash: record3.contentHash,
88563
+ deleted: false,
88564
+ data: record3.data
87095
88565
  });
88566
+ if (record3.recordKind !== "value") continue;
88567
+ if (!isObjectRecord2(record3.data)) continue;
88568
+ if (!isObjectRecord2(record3.data.value)) continue;
88569
+ const constructorArgs = record3.data.constructorArgs;
88570
+ const hasInstanceProvenance = carriesStoredInstanceProvenance(record3.data);
88571
+ if (constructorArgs !== void 0 && constructorArgs !== null && !hasInstanceProvenance) {
88572
+ continue;
88573
+ }
88574
+ candidateRoots.add(record3.recordId);
87096
88575
  }
87097
- const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
87098
- const canonicalObject = {};
87099
- for (const [key, entryValue] of entries) {
87100
- const canonicalValue = toCanonicalJsonValue(entryValue);
87101
- if (canonicalValue === void 0) continue;
87102
- canonicalObject[key] = canonicalValue;
88576
+ const document = readPulledProjectDocumentV4(records2);
88577
+ const owners = resolveOwnerMembersForValues(document, candidateRoots);
88578
+ const storedPlacements = buildStoredValuePlacementIndexV4(records2.values());
88579
+ const membersById2 = new Map(
88580
+ document.members.map((member) => [member.id, member])
88581
+ );
88582
+ for (const valueId of candidateRoots) {
88583
+ if (owners.has(valueId)) continue;
88584
+ const memberId = storedPlacements.placementByChildValueId.get(valueId)?.memberId;
88585
+ const member = memberId === null || memberId === void 0 ? void 0 : membersById2.get(memberId);
88586
+ if (member !== void 0) owners.set(valueId, member);
87103
88587
  }
87104
- return canonicalObject;
88588
+ const probe = createStoredConstructionProbeV4(records2, manifest);
88589
+ let parents;
88590
+ const parentByChildId = () => parents ??= storedValueParentIndex(records2, storedPlacements);
88591
+ const root = (valueId) => {
88592
+ const member = owners.get(valueId);
88593
+ return member === void 0 ? void 0 : {
88594
+ member,
88595
+ valueId
88596
+ };
88597
+ };
88598
+ const probedRootIds = /* @__PURE__ */ new Set();
88599
+ const probeRootOnce = (rootValueId, ownedRoot) => {
88600
+ if (probedRootIds.has(rootValueId)) {
88601
+ return /* @__PURE__ */ new Set();
88602
+ }
88603
+ probedRootIds.add(rootValueId);
88604
+ return probe.overrideKeys(ownedRoot);
88605
+ };
88606
+ return {
88607
+ construction(valueId) {
88608
+ const ownedRoot = root(valueId);
88609
+ if (ownedRoot === void 0) return void 0;
88610
+ return probe.construction(ownedRoot);
88611
+ },
88612
+ overrideSchemaKeys(valueId) {
88613
+ const recorded = probe.overrideKeysOf(valueId);
88614
+ if (recorded !== void 0) return recorded;
88615
+ const ownedRoot = root(valueId);
88616
+ if (ownedRoot !== void 0) return probeRootOnce(valueId, ownedRoot);
88617
+ const ancestor = nearestOwnedAncestor(valueId, parentByChildId(), owners);
88618
+ if (ancestor === null) return void 0;
88619
+ const ancestorRoot = root(ancestor);
88620
+ if (ancestorRoot === void 0) return void 0;
88621
+ if (probedRootIds.has(ancestor)) return void 0;
88622
+ probeRootOnce(ancestor, ancestorRoot);
88623
+ return probe.overrideKeysOf(valueId);
88624
+ }
88625
+ };
87105
88626
  }
87106
- var init_canonical_json = __esm({
87107
- "../src/database/canonical-json.ts"() {
88627
+ function storedValueParentIndex(records2, placements) {
88628
+ const parents = /* @__PURE__ */ new Map();
88629
+ const values = storedValueRowsByIdV4(records2.values());
88630
+ for (const [valueId, data] of values) {
88631
+ const containerId = data.containerId;
88632
+ if (typeof containerId === "string" && values.has(containerId)) {
88633
+ parents.set(valueId, containerId);
88634
+ }
88635
+ const body = data.value;
88636
+ if (Array.isArray(body)) {
88637
+ for (const entry of body) {
88638
+ if (typeof entry === "string" && values.has(entry)) {
88639
+ parents.set(entry, valueId);
88640
+ }
88641
+ }
88642
+ continue;
88643
+ }
88644
+ if (!isObjectRecord2(body)) continue;
88645
+ for (const child of Object.values(body)) {
88646
+ if (typeof child === "string" && values.has(child)) {
88647
+ parents.set(child, valueId);
88648
+ }
88649
+ }
88650
+ }
88651
+ for (const edge of placements.placementByChildValueId.values()) {
88652
+ if (edge.source !== "constructor") continue;
88653
+ if (!parents.has(edge.childValueId)) {
88654
+ parents.set(edge.childValueId, edge.parentValueId);
88655
+ }
88656
+ }
88657
+ return parents;
88658
+ }
88659
+ function nearestOwnedAncestor(valueId, parents, owners) {
88660
+ const seen = /* @__PURE__ */ new Set([valueId]);
88661
+ let cursor = parents.get(valueId);
88662
+ while (cursor !== void 0 && !seen.has(cursor)) {
88663
+ if (owners.has(cursor)) return cursor;
88664
+ seen.add(cursor);
88665
+ cursor = parents.get(cursor);
88666
+ }
88667
+ return null;
88668
+ }
88669
+ function carriesStoredInstanceProvenance(value) {
88670
+ return isVirtualInstanceRootShape(value);
88671
+ }
88672
+ function readMaterializedConstructionBuildCacheV2(root, state) {
88673
+ try {
88674
+ const parsed = JSON.parse(
88675
+ readFileSync3(
88676
+ join3(root, MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH),
88677
+ "utf8"
88678
+ )
88679
+ );
88680
+ if (parsed === null || typeof parsed !== "object") return null;
88681
+ const cache = parsed;
88682
+ if (cache.revision !== MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION || cache.stateFingerprint !== materializedConstructionStateFingerprint(state) || cache.expressions === null || typeof cache.expressions !== "object" || Array.isArray(cache.expressions)) {
88683
+ return null;
88684
+ }
88685
+ const expressions = /* @__PURE__ */ new Map();
88686
+ for (const [valueId, expression] of Object.entries(cache.expressions)) {
88687
+ if (typeof expression !== "string") return null;
88688
+ expressions.set(valueId, expression);
88689
+ }
88690
+ const overrideKeys = /* @__PURE__ */ new Map();
88691
+ if (cache.overrideKeys !== void 0) {
88692
+ if (cache.overrideKeys === null || typeof cache.overrideKeys !== "object" || Array.isArray(cache.overrideKeys)) {
88693
+ return null;
88694
+ }
88695
+ for (const [valueId, keys] of Object.entries(cache.overrideKeys)) {
88696
+ if (!Array.isArray(keys) || keys.some((key) => typeof key !== "string")) {
88697
+ return null;
88698
+ }
88699
+ overrideKeys.set(valueId, new Set(keys));
88700
+ }
88701
+ }
88702
+ return { expressions, overrideKeys };
88703
+ } catch {
88704
+ return null;
88705
+ }
88706
+ }
88707
+ function writeMaterializedConstructionBuildCacheV2(root, state, cache) {
88708
+ const file = join3(root, MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH);
88709
+ mkdirSync3(dirname2(file), { recursive: true });
88710
+ const temporary = `${file}.${process.pid}.tmp`;
88711
+ writeFileSync3(
88712
+ temporary,
88713
+ `${JSON.stringify({
88714
+ revision: MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION,
88715
+ stateFingerprint: materializedConstructionStateFingerprint(state),
88716
+ expressions: Object.fromEntries(
88717
+ [...cache.expressions].sort(
88718
+ ([left], [right]) => left.localeCompare(right)
88719
+ )
88720
+ ),
88721
+ overrideKeys: Object.fromEntries(
88722
+ [...cache.overrideKeys ?? /* @__PURE__ */ new Map()].sort(([left], [right]) => left.localeCompare(right)).map(([valueId, keys]) => [valueId, [...keys].sort()])
88723
+ )
88724
+ })}
88725
+ `,
88726
+ "utf8"
88727
+ );
88728
+ renameSync(temporary, file);
88729
+ }
88730
+ function materializedConstructionStateFingerprint(state) {
88731
+ const hash = createHash3("sha256");
88732
+ hash.update(String(MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION));
88733
+ for (const [key, record3] of Object.entries(state.records).sort(
88734
+ ([left], [right]) => left.localeCompare(right)
88735
+ )) {
88736
+ hash.update("\0");
88737
+ hash.update(key);
88738
+ hash.update("\0");
88739
+ hash.update(record3.contentHash);
88740
+ }
88741
+ return hash.digest("hex");
88742
+ }
88743
+ var MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH, MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION;
88744
+ var init_materialized_construction_cache = __esm({
88745
+ "src/project-source/materialized-construction-cache.ts"() {
87108
88746
  "use strict";
88747
+ init_projection();
88748
+ init_initializer_replay();
88749
+ init_value_row_owner_members();
88750
+ init_instance_provenance();
88751
+ init_value_sources();
88752
+ init_stored_value_placements();
88753
+ MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH = ".neo/build/materialized-constructions-v1.json";
88754
+ MATERIALIZED_CONSTRUCTION_BUILD_CACHE_REVISION = 2;
87109
88755
  }
87110
88756
  });
87111
88757
 
@@ -87444,7 +89090,10 @@ function generatedConstructorMemberContractChanged(current, next) {
87444
89090
  "indexes",
87445
89091
  "setter",
87446
89092
  "setterCode",
87447
- "storage"
89093
+ "storage",
89094
+ // Where a value physically lives does not change the generated
89095
+ // constructor's parameter contract (P76 §1).
89096
+ "distribution"
87448
89097
  ]);
87449
89098
  const project = (value) => ({
87450
89099
  ...withoutFields(value, ignored),
@@ -88268,7 +89917,9 @@ function valueRowsFromWorkspace(workspace) {
88268
89917
  `Workspace contains invalid value row "${record3.recordId}".`
88269
89918
  );
88270
89919
  }
88271
- rows.set(record3.recordId, record3.data);
89920
+ const decoded = decodePackedValueRow(record3.data);
89921
+ rows.set(record3.recordId, decoded.row);
89922
+ for (const child of decoded.children) rows.set(child.id, child);
88272
89923
  }
88273
89924
  return rows;
88274
89925
  }
@@ -88361,7 +90012,7 @@ function materializeInitializersLocallyV4(args) {
88361
90012
  }
88362
90013
  return [row];
88363
90014
  });
88364
- const sparse = sparsifyConstructedInstance({
90015
+ const sparse2 = sparsifyConstructedInstance({
88365
90016
  document,
88366
90017
  rootMember: rootOwner,
88367
90018
  constructed: {
@@ -88379,12 +90030,12 @@ function materializeInitializersLocallyV4(args) {
88379
90030
  virtualValueIdForSource: (instanceRootId, sourceIdentity3) => isPendingId(instanceRootId) ? pendingVirtualValueId(instanceRootId, sourceIdentity3) : virtualValueId(instanceRootId, sourceIdentity3)
88380
90031
  });
88381
90032
  const evaluatedSparse = new Map(
88382
- [sparse.root, ...sparse.createdChildren].map((row) => [row.id, row])
90033
+ [sparse2.root, ...sparse2.createdChildren].map((row) => [row.id, row])
88383
90034
  );
88384
- const root = sparse.root;
88385
- const createdIds = sparse.createdChildren.map((row) => row.id);
90035
+ const root = sparse2.root;
90036
+ const createdIds = sparse2.createdChildren.map((row) => row.id);
88386
90037
  const replacements = /* @__PURE__ */ new Map();
88387
- const evaluatedRows = [root, ...sparse.createdChildren];
90038
+ const evaluatedRows = [root, ...sparse2.createdChildren];
88388
90039
  const valuesById = new Map(
88389
90040
  document.values.map((row) => [row.id, row])
88390
90041
  );
@@ -88590,103 +90241,6 @@ var init_local_initializer_materialization = __esm({
88590
90241
  }
88591
90242
  });
88592
90243
 
88593
- // ../src/database/project-version-intents.ts
88594
- function createProjectVersionIntent(type, details) {
88595
- if (details === void 0) {
88596
- return {
88597
- type,
88598
- schemaVersion: PROJECT_VERSION_INTENT_SCHEMA_VERSION
88599
- };
88600
- }
88601
- return {
88602
- type,
88603
- schemaVersion: PROJECT_VERSION_INTENT_SCHEMA_VERSION,
88604
- details
88605
- };
88606
- }
88607
- function isKnownProjectVersionIntentType(value) {
88608
- return Object.values(ProjectVersionIntentType).includes(
88609
- value
88610
- );
88611
- }
88612
- var ProjectVersionIntentType, PROJECT_VERSION_INTENT_SCHEMA_VERSION;
88613
- var init_project_version_intents = __esm({
88614
- "../src/database/project-version-intents.ts"() {
88615
- "use strict";
88616
- ProjectVersionIntentType = {
88617
- ProjectCreate: "project.create",
88618
- ProjectUpdate: "project.update",
88619
- MemberCreate: "member.create",
88620
- MemberUpdate: "member.update",
88621
- MemberRename: "member.rename",
88622
- MemberSetValue: "member.set-value",
88623
- MemberClearValue: "member.clear-value",
88624
- MemberDelete: "member.delete",
88625
- ClassCreate: "class.create",
88626
- ClassUpdate: "class.update",
88627
- ClassDelete: "class.delete",
88628
- ClassAddSchemaEntry: "class.add-schema-entry",
88629
- ConstructorCreate: "constructor.create",
88630
- ConstructorUpdate: "constructor.update",
88631
- ConstructorDelete: "constructor.delete",
88632
- VariantCreate: "variant.create",
88633
- VariantUpdate: "variant.update",
88634
- VariantDelete: "variant.delete",
88635
- VariantFolderCreate: "variant-folder.create",
88636
- VariantFolderUpdate: "variant-folder.update",
88637
- VariantFolderDelete: "variant-folder.delete",
88638
- InternalRecordRelationCreate: "internal-record-relation.create",
88639
- InternalRecordRelationUpdate: "internal-record-relation.update",
88640
- InternalRecordRelationDelete: "internal-record-relation.delete",
88641
- EnumCreate: "enum.create",
88642
- EnumUpdate: "enum.update",
88643
- EnumDelete: "enum.delete",
88644
- InterfaceCreate: "interface.create",
88645
- InterfaceUpdate: "interface.update",
88646
- InterfaceDelete: "interface.delete",
88647
- EnumOptionRename: "enum-option.rename",
88648
- EnumOptionDelete: "enum-option.delete",
88649
- ValueCreate: "value.create",
88650
- ValueUpdate: "value.update",
88651
- ValueDelete: "value.delete",
88652
- ValueEntryRenameKey: "value-entry.rename-key",
88653
- DialogueCreate: "dialogue.create",
88654
- DialogueUpdate: "dialogue.update",
88655
- DialogueDelete: "dialogue.delete",
88656
- DialogueNodeCreate: "dialogue-node.create",
88657
- DialogueNodeUpdate: "dialogue-node.update",
88658
- DialogueNodeDelete: "dialogue-node.delete",
88659
- DialogueGroupCreate: "dialogue-group.create",
88660
- DialogueGroupUpdate: "dialogue-group.update",
88661
- DialogueGroupDelete: "dialogue-group.delete",
88662
- PriorityGroupCreate: "priority-group.create",
88663
- PriorityGroupUpdate: "priority-group.update",
88664
- PriorityGroupDelete: "priority-group.delete",
88665
- ProjectFileCreate: "project-file.create",
88666
- ProjectFileUpdate: "project-file.update",
88667
- ProjectFileDelete: "project-file.delete",
88668
- UnityTextureTemplateCreate: "unity-texture-template.create",
88669
- UnityTextureTemplateUpdate: "unity-texture-template.update",
88670
- UnityTextureTemplateDelete: "unity-texture-template.delete",
88671
- UnityAudioClipTemplateCreate: "unity-audio-clip-template.create",
88672
- UnityAudioClipTemplateUpdate: "unity-audio-clip-template.update",
88673
- UnityAudioClipTemplateDelete: "unity-audio-clip-template.delete",
88674
- LocalizationConfigCreate: "localization-config.create",
88675
- LocalizationConfigUpdate: "localization-config.update",
88676
- LocalizationStatusCreate: "localization-status.create",
88677
- LocalizationStatusUpdate: "localization-status.update",
88678
- LocalizationStatusDelete: "localization-status.delete",
88679
- LocalizedTextCreate: "localized-text.create",
88680
- LocalizedTextUpdate: "localized-text.update",
88681
- LocalizedTextDelete: "localized-text.delete",
88682
- MigrationCreate: "migration.create",
88683
- MigrationUpdate: "migration.update",
88684
- MigrationDelete: "migration.delete"
88685
- };
88686
- PROJECT_VERSION_INTENT_SCHEMA_VERSION = 1;
88687
- }
88688
- });
88689
-
88690
90244
  // src/commands/push-change-intent.ts
88691
90245
  function createNeoCliPushIntent(change) {
88692
90246
  const intentType = `${change.recordKind}.${change.kind}`;
@@ -93514,6 +95068,7 @@ var init_project_migration_runner = __esm({
93514
95068
  init_compiler_adapter();
93515
95069
  init_neoscript_evaluator();
93516
95070
  init_members();
95071
+ init_packed_value_encoding();
93517
95072
  init_project_root_members();
93518
95073
  init_virtual_instance_values();
93519
95074
  init_project_version_intents();
@@ -95691,7 +97246,9 @@ function materializeLocalizableStringWriteChanges(args) {
95691
97246
  ...change,
95692
97247
  nextData: { ...change.nextData, value: textId }
95693
97248
  };
95694
- changes.push(
97249
+ changes.splice(
97250
+ index + 1,
97251
+ 0,
95695
97252
  localizedTextCreateChange({
95696
97253
  textId,
95697
97254
  literal: literal2,
@@ -96233,12 +97790,87 @@ function prepareServerOwnedSchemaCommit(args) {
96233
97790
  document: committedDocument,
96234
97791
  prepared
96235
97792
  });
96236
- attachPreparedValuePlacements(prepared, committedDocument);
96237
- attachPreparedConstructorAggregateEdges(prepared, committedDocument);
96238
- return orderVariantRootValuesWithVariants(
96239
- orderDeclaredMemberCreatesFirst(prepared, postDocument)
97793
+ const physical = foldPreparedPackedValueWrites({
97794
+ prepared,
97795
+ document: args.document,
97796
+ committedDocument
97797
+ });
97798
+ attachPreparedValuePlacements(physical, committedDocument);
97799
+ attachPreparedConstructorAggregateEdges(physical, committedDocument);
97800
+ return orderLocalizedTextWritesBesideLinks(
97801
+ orderVariantRootValuesWithVariants(
97802
+ orderDeclaredMemberCreatesFirst(physical, postDocument)
97803
+ )
96240
97804
  );
96241
97805
  }
97806
+ function orderLocalizedTextWritesBesideLinks(prepared) {
97807
+ const indexByLinkKey = /* @__PURE__ */ new Map();
97808
+ prepared.forEach((change, index) => {
97809
+ if (change.operation === "delete") return;
97810
+ if (change.recordKind !== "value" && change.recordKind !== "dialogue" && change.recordKind !== "dialogue-node") {
97811
+ return;
97812
+ }
97813
+ indexByLinkKey.set(`${change.recordKind}:${change.recordId}`, index);
97814
+ });
97815
+ if (indexByLinkKey.size === 0) return [...prepared];
97816
+ const followersByIndex = /* @__PURE__ */ new Map();
97817
+ const moved = /* @__PURE__ */ new Set();
97818
+ prepared.forEach((change, index) => {
97819
+ if (change.recordKind !== "localized-text") return;
97820
+ if (change.operation === "delete") return;
97821
+ let anchor = -1;
97822
+ for (const link of localizedTextLinkKeys(change.nextData)) {
97823
+ const linked = indexByLinkKey.get(link);
97824
+ if (linked !== void 0 && linked > anchor) anchor = linked;
97825
+ }
97826
+ if (anchor < 0) return;
97827
+ const followers = followersByIndex.get(anchor) ?? [];
97828
+ followers.push(change);
97829
+ followersByIndex.set(anchor, followers);
97830
+ moved.add(index);
97831
+ });
97832
+ if (moved.size === 0) return [...prepared];
97833
+ const ordered = [];
97834
+ prepared.forEach((change, index) => {
97835
+ if (moved.has(index)) return;
97836
+ ordered.push(change);
97837
+ const followers = followersByIndex.get(index);
97838
+ if (followers !== void 0) ordered.push(...followers);
97839
+ });
97840
+ return ordered;
97841
+ }
97842
+ function localizedTextLinkKeys(nextData) {
97843
+ const links = nextData?.links;
97844
+ if (!Array.isArray(links)) return [];
97845
+ const keys = [];
97846
+ for (const link of links) {
97847
+ if (typeof link !== "object" || link === null) continue;
97848
+ const { recordKind, recordId } = link;
97849
+ if (typeof recordKind !== "string" || typeof recordId !== "string") {
97850
+ continue;
97851
+ }
97852
+ keys.push(`${recordKind}:${recordId}`);
97853
+ }
97854
+ return keys;
97855
+ }
97856
+ function foldPreparedPackedValueWrites(args) {
97857
+ if (args.document.physicalValues === void 0) return args.prepared;
97858
+ const folded = foldPackedValueWriteChanges({
97859
+ changes: args.prepared,
97860
+ document: {
97861
+ classes: args.committedDocument.classes,
97862
+ members: args.committedDocument.members,
97863
+ constructors: args.committedDocument.constructors,
97864
+ // P67 §2.2. Post-transaction variants, so a variant this transaction
97865
+ // creates places the graph it creates with it.
97866
+ variants: args.committedDocument.variants,
97867
+ variantFolders: args.committedDocument.variantFolders,
97868
+ values: args.document.physicalValues
97869
+ }
97870
+ });
97871
+ if (folded === args.prepared) return args.prepared;
97872
+ return [...folded];
97873
+ }
96242
97874
  function attachPreparedValuePlacements(prepared, document) {
96243
97875
  const creates = prepared.filter(
96244
97876
  (change) => change.recordKind === "value" && change.operation === "create"
@@ -96449,7 +98081,7 @@ function materializePreparedInstanceInitializers(args) {
96449
98081
  constructionBaselineReplay: true,
96450
98082
  storedConstructionReplay: true
96451
98083
  });
96452
- const sparse = sparsifyConstructedInstance({
98084
+ const sparse2 = sparsifyConstructedInstance({
96453
98085
  document: materializationScope.document,
96454
98086
  rootMember: member,
96455
98087
  constructed: {
@@ -96469,9 +98101,9 @@ function materializePreparedInstanceInitializers(args) {
96469
98101
  if (original === void 0) continue;
96470
98102
  args.prepared[site.index] = {
96471
98103
  ...original,
96472
- nextData: sparse.root
98104
+ nextData: sparse2.root
96473
98105
  };
96474
- for (const created of sparse.createdChildren) {
98106
+ for (const created of sparse2.createdChildren) {
96475
98107
  const existing = existingValueById.get(created.id);
96476
98108
  if (existing !== void 0) {
96477
98109
  if (materializedValueRowsEqual(existing, created)) continue;
@@ -99848,6 +101480,7 @@ var init_project_version_schema_commit = __esm({
99848
101480
  init_localizable_member_value_writes();
99849
101481
  init_value_row_owner_members();
99850
101482
  init_init_backed_value_materialization();
101483
+ init_packed_value_write_fold();
99851
101484
  init_constructor_argument_ownership();
99852
101485
  init_constructors2();
99853
101486
  init_dialogue_node_index();
@@ -100514,38 +102147,28 @@ function assertProjectVersionWholeGraphWritesValid(args) {
100514
102147
  `Project version transaction operation "${args.operation}" is not a known operation.`
100515
102148
  );
100516
102149
  }
100517
- const projected = applyProjectVersionWriteChanges(
100518
- args.document,
100519
- args.changes
100520
- );
100521
- assertNoValueDematerialization({
100522
- document: args.document,
100523
- changes: args.changes
102150
+ const changes = expandPackedValueWriteChanges({
102151
+ changes: args.changes,
102152
+ baseValues: args.document.values
100524
102153
  });
100525
- assertStagedUnorderedContainmentValid(args.document, projected, args.changes);
100526
- assertStagedSchemaIdentifiersValid(projected, args.changes);
100527
- assertStagedActionListenersValid(projected, args.changes);
100528
- assertStagedVariantMemberValuesValid(projected, args.changes);
100529
- assertStagedUnitySingletonValid(projected, args.changes);
100530
- assertStagedProjectInterfaceValid(projected, args.changes);
100531
- assertStagedTileGridReferencesValid(args.document, projected, args.changes);
100532
- assertStagedInternalRecordRelationsValid(
100533
- args.document,
100534
- projected,
100535
- args.changes
100536
- );
100537
- assertStagedWorldContentLayerBindingsValid(
100538
- args.document,
100539
- projected,
100540
- args.changes
100541
- );
102154
+ const projected = applyProjectVersionWriteChanges(args.document, changes);
102155
+ assertNoValueDematerialization({ document: args.document, changes });
102156
+ assertStagedUnorderedContainmentValid(args.document, projected, changes);
102157
+ assertStagedSchemaIdentifiersValid(projected, changes);
102158
+ assertStagedActionListenersValid(projected, changes);
102159
+ assertStagedVariantMemberValuesValid(projected, changes);
102160
+ assertStagedUnitySingletonValid(projected, changes);
102161
+ assertStagedProjectInterfaceValid(projected, changes);
102162
+ assertStagedTileGridReferencesValid(args.document, projected, changes);
102163
+ assertStagedInternalRecordRelationsValid(args.document, projected, changes);
102164
+ assertStagedWorldContentLayerBindingsValid(args.document, projected, changes);
100542
102165
  assertAnimationClipDocumentValid(
100543
102166
  materializeDeclarationInitializersForAnimationValidation(projected)
100544
102167
  );
100545
102168
  if (args.operation === void 0 || !isSystemOwnedProjectVersionOperation(args.operation)) {
100546
102169
  assertProjectVersionSystemProtectedWritesValid({
100547
102170
  document: args.document,
100548
- changes: args.changes
102171
+ changes
100549
102172
  });
100550
102173
  }
100551
102174
  }
@@ -100569,12 +102192,17 @@ function assertStagedUnorderedContainmentValid(current, projected, changes) {
100569
102192
  const after = projectedValues.get(change.recordId);
100570
102193
  const beforeContainerId = typeof before?.containerId === "string" ? before.containerId : null;
100571
102194
  const afterContainerId = typeof after?.containerId === "string" ? after.containerId : null;
100572
- if (before !== void 0 && after !== void 0 && beforeContainerId !== afterContainerId) {
102195
+ if (before !== void 0 && after !== void 0 && beforeContainerId !== afterContainerId && !isStagedContainerRename(
102196
+ currentValues,
102197
+ projectedValues,
102198
+ beforeContainerId,
102199
+ afterContainerId
102200
+ )) {
100573
102201
  throw new Error(
100574
- `Value "${change.recordId}" cannot change containerId from ${beforeContainerId === null ? "unset" : `"${beforeContainerId}"`} to ${afterContainerId === null ? "unset" : `"${afterContainerId}"`}: unordered-list membership is stamped at creation and immutable (move = delete + recreate).`
102202
+ `Value "${change.recordId}" cannot change containerId from ${beforeContainerId === null ? "unset" : `"${beforeContainerId}"`} to ${afterContainerId === null ? "unset" : `"${afterContainerId}"`}: unordered-list membership is stamped at creation and immutable (a move is refused; a rename must delete the old container and create the new one in the same transaction).`
100575
102203
  );
100576
102204
  }
100577
- if (before === void 0 && afterContainerId !== null) {
102205
+ if (afterContainerId !== null && afterContainerId !== beforeContainerId) {
100578
102206
  if (afterContainerId === change.recordId) {
100579
102207
  throw new Error(
100580
102208
  `Value "${change.recordId}" cannot declare itself as its own containerId.`
@@ -100608,6 +102236,14 @@ function assertStagedUnorderedContainmentValid(current, projected, changes) {
100608
102236
  }
100609
102237
  }
100610
102238
  }
102239
+ function isStagedContainerRename(currentValues, projectedValues, fromContainerId, toContainerId) {
102240
+ if (fromContainerId === null) return false;
102241
+ if (toContainerId === null) return false;
102242
+ if (!currentValues.has(fromContainerId)) return false;
102243
+ if (projectedValues.has(fromContainerId)) return false;
102244
+ if (currentValues.has(toContainerId)) return false;
102245
+ return projectedValues.has(toContainerId);
102246
+ }
100611
102247
  function assertNoValueDematerialization(args) {
100612
102248
  const updates = args.changes.filter(
100613
102249
  (change) => change.recordKind === "value" && change.operation === "update" && change.deleted !== true
@@ -101609,6 +103245,7 @@ var init_project_version_whole_graph_validation = __esm({
101609
103245
  init_animation_clips();
101610
103246
  init_projectInterfaceValidation();
101611
103247
  init_project_schema_identifier_validation();
103248
+ init_packed_value_write_fold();
101612
103249
  init_project_version_schema_commit();
101613
103250
  init_project_version_system_protection_writes();
101614
103251
  init_reserved_record_id_validation();
@@ -101783,7 +103420,9 @@ function computeWorkspaceStatus(workspace, options) {
101783
103420
  binaryFiles: []
101784
103421
  };
101785
103422
  }
101786
- const loweringRecords = loweringBaseRecords(workspace.state.records);
103423
+ const loweringRecords = logicalValueBaseRecordsV4(
103424
+ loweringBaseRecords(workspace.state.records)
103425
+ );
101787
103426
  const baseDocuments = schemaBaseDocuments(workspace);
101788
103427
  const staticMemberOwnershipRecoveries = [];
101789
103428
  const baseManifest = baseDocuments.length === 0 ? void 0 : documentsToProjectSchemaManifest(baseDocuments, {
@@ -102180,12 +103819,15 @@ function computeWorkspaceStatus(workspace, options) {
102180
103819
  }
102181
103820
  continue;
102182
103821
  }
102183
- const baseState = workspace.state.records[key];
102184
103822
  const schemaDocument = documentsByKey.get(key);
102185
- const reconstructedData = schemaDocument === void 0 ? mergeMigrationServerFields(record3.fileFields, baseState?.data) : schemaDocument.data;
103823
+ const reconstructedData = schemaDocument === void 0 ? mergeMigrationServerFields(
103824
+ record3.fileFields,
103825
+ loweringRecords[key]?.data
103826
+ ) : schemaDocument.data;
102186
103827
  const staticValueId = record3.recordKind === "member" ? staticMemberValueIds.get(record3.recordId) : void 0;
102187
103828
  const fullData = staticValueId === void 0 ? reconstructedData : { ...reconstructedData, valueId: staticValueId };
102188
103829
  reconstructed3.set(key, { ...record3, fullData });
103830
+ const baseState = workspace.state.records[key];
102189
103831
  if (baseState === void 0 || isPendingId(record3.recordId)) {
102190
103832
  changes.push({
102191
103833
  kind: "create",
@@ -102326,6 +103968,18 @@ function computeWorkspaceStatus(workspace, options) {
102326
103968
  changes.splice(index, 1);
102327
103969
  }
102328
103970
  }
103971
+ applyPackedValueFoldV4({
103972
+ workspace,
103973
+ loweringRecords,
103974
+ schema: packedFoldSchemaV4(
103975
+ documents,
103976
+ loweringRecords,
103977
+ workspace.config.projectId
103978
+ ),
103979
+ reconstructed: reconstructed3,
103980
+ changes
103981
+ });
103982
+ reportPhase("packed-value-fold");
102329
103983
  for (const change of changes) {
102330
103984
  if (change.recordKind !== "value" || change.kind !== "update") continue;
102331
103985
  const refusal = valueDematerializationRefusal({
@@ -102741,7 +104395,7 @@ function prospectiveAnimationDocumentV4(records2) {
102741
104395
  }
102742
104396
  if (project === void 0) return null;
102743
104397
  const classIdByName = new Map(classes.map((value) => [value.name, value.id]));
102744
- const validationValues = values.map((value) => {
104398
+ const validationValues = expandPackedValueRows(values).map((value) => {
102745
104399
  if (typeof value.classId === "string") return value;
102746
104400
  const authoredInit = Reflect.get(value, "init");
102747
104401
  const init = isObjectRecord2(authoredInit) ? authoredInit : null;
@@ -102795,6 +104449,154 @@ function expandProspectiveAnimationInstances(document) {
102795
104449
  }
102796
104450
  return [...byId.values()];
102797
104451
  }
104452
+ function applyPackedValueFoldV4(args) {
104453
+ const candidates = /* @__PURE__ */ new Map();
104454
+ const touchedValueIds = /* @__PURE__ */ new Set();
104455
+ for (const [key, record3] of args.reconstructed) {
104456
+ if (record3.recordKind !== "value") continue;
104457
+ candidates.set(record3.recordId, record3.fullData);
104458
+ const logicalBase = args.loweringRecords[key];
104459
+ const physicalBase = args.workspace.state.records[key];
104460
+ if (logicalBase === void 0 || physicalBase === void 0 || physicalBase.conflictServerHash !== void 0 || isPendingId(record3.recordId) || !recordsSemanticallyEqual("value", record3.fullData, logicalBase.data)) {
104461
+ touchedValueIds.add(record3.recordId);
104462
+ }
104463
+ }
104464
+ const fold = foldCandidateValueRowsV4({
104465
+ candidates,
104466
+ base: args.loweringRecords,
104467
+ touchedValueIds,
104468
+ projectId: args.workspace.config.projectId,
104469
+ schema: args.schema
104470
+ });
104471
+ if (fold.foldedValueIds.size === 0) return;
104472
+ const changeForValue = (valueId, nextData) => {
104473
+ const key = recordStateKey("value", valueId);
104474
+ const file = args.reconstructed.get(key)?.file ?? null;
104475
+ const base = args.workspace.state.records[key];
104476
+ if (base === void 0 || isPendingId(valueId)) {
104477
+ return {
104478
+ kind: "create",
104479
+ recordKind: "value",
104480
+ recordId: valueId,
104481
+ file,
104482
+ nextData
104483
+ };
104484
+ }
104485
+ if (base.conflictServerHash === void 0 && recordsSemanticallyEqual("value", nextData, base.data)) {
104486
+ return null;
104487
+ }
104488
+ return recordUpsertChange({
104489
+ base,
104490
+ recordKind: "value",
104491
+ recordId: valueId,
104492
+ file,
104493
+ nextData
104494
+ });
104495
+ };
104496
+ const rewritten = [];
104497
+ const rebuiltRootIds = /* @__PURE__ */ new Set();
104498
+ const deletedValueIds = /* @__PURE__ */ new Set();
104499
+ for (const change of args.changes) {
104500
+ if (change.recordKind !== "value") {
104501
+ rewritten.push(change);
104502
+ continue;
104503
+ }
104504
+ if (change.kind === "delete") {
104505
+ deletedValueIds.add(change.recordId);
104506
+ rewritten.push(change);
104507
+ continue;
104508
+ }
104509
+ if (fold.foldedValueIds.has(change.recordId)) continue;
104510
+ const packedBody = fold.bodyByValueId.get(change.recordId);
104511
+ if (packedBody === void 0) {
104512
+ rewritten.push(change);
104513
+ continue;
104514
+ }
104515
+ rebuiltRootIds.add(change.recordId);
104516
+ const rebuilt = changeForValue(change.recordId, packedBody);
104517
+ if (rebuilt !== null) rewritten.push(rebuilt);
104518
+ }
104519
+ for (const [rootId, packedBody] of fold.bodyByValueId) {
104520
+ if (rebuiltRootIds.has(rootId)) continue;
104521
+ const rebuilt = changeForValue(rootId, packedBody);
104522
+ if (rebuilt !== null) rewritten.push(rebuilt);
104523
+ }
104524
+ for (const valueId of fold.foldedValueIds) {
104525
+ if (deletedValueIds.has(valueId)) continue;
104526
+ const key = recordStateKey("value", valueId);
104527
+ const base = args.workspace.state.records[key];
104528
+ if (base === void 0) continue;
104529
+ rewritten.push({
104530
+ kind: "delete",
104531
+ recordKind: "value",
104532
+ recordId: valueId,
104533
+ file: base.file ?? args.reconstructed.get(key)?.file ?? null,
104534
+ baseData: base.data,
104535
+ baseContentHash: base.contentHash,
104536
+ casBaseHash: base.conflictServerHash ?? base.contentHash
104537
+ });
104538
+ }
104539
+ args.changes.length = 0;
104540
+ args.changes.push(...rewritten);
104541
+ for (const valueId of fold.foldedValueIds) {
104542
+ args.reconstructed.delete(recordStateKey("value", valueId));
104543
+ }
104544
+ for (const [rootId, packedBody] of fold.bodyByValueId) {
104545
+ const key = recordStateKey("value", rootId);
104546
+ const record3 = args.reconstructed.get(key);
104547
+ if (record3 === void 0) continue;
104548
+ args.reconstructed.set(key, { ...record3, fullData: packedBody });
104549
+ }
104550
+ }
104551
+ function packedFoldSchemaV4(documents, base, projectId) {
104552
+ const seedEnvelope = { projectId, createdAt: 0, updatedAt: 0 };
104553
+ const completed = /* @__PURE__ */ new Map();
104554
+ for (const document of documents) {
104555
+ if (!isObjectRecord2(document.data)) continue;
104556
+ const key = recordStateKey(document.recordKind, document.recordId);
104557
+ const data = { ...document.data };
104558
+ const envelope = {
104559
+ ...seedEnvelope,
104560
+ ...serverEnvelope(base[key]?.data)
104561
+ };
104562
+ for (const [field, value] of Object.entries(envelope)) {
104563
+ if (data[field] === void 0) data[field] = value;
104564
+ }
104565
+ completed.set(key, data);
104566
+ }
104567
+ const memberRecords = /* @__PURE__ */ new Map();
104568
+ for (const document of documents) {
104569
+ if (document.recordKind !== "member") continue;
104570
+ const data = completed.get(recordStateKey("member", document.recordId));
104571
+ if (data !== void 0) memberRecords.set(document.recordId, data);
104572
+ }
104573
+ const classes = [];
104574
+ const members = [];
104575
+ const constructors = [];
104576
+ const variants = [];
104577
+ const variantFolders = [];
104578
+ for (const document of documents) {
104579
+ const data = completed.get(
104580
+ recordStateKey(document.recordKind, document.recordId)
104581
+ );
104582
+ if (data === void 0) continue;
104583
+ if (document.recordKind === "class") {
104584
+ if (isNeoSchemaClass(data)) classes.push(data);
104585
+ } else if (document.recordKind === "member") {
104586
+ const member = hydrateProspectiveMemberOverride(data, memberRecords);
104587
+ if (isMember(member)) members.push(member);
104588
+ } else if (document.recordKind === "constructor") {
104589
+ if (isNeoClassConstructor(data) || isUncompiledNeoClassConstructor(data)) {
104590
+ constructors.push(data);
104591
+ }
104592
+ } else if (document.recordKind === "variant") {
104593
+ if (isNeoClassVariant(data)) variants.push(data);
104594
+ } else if (document.recordKind === "variant-folder") {
104595
+ if (isNeoClassVariantFolder(data)) variantFolders.push(data);
104596
+ }
104597
+ }
104598
+ return { classes, members, constructors, variants, variantFolders };
104599
+ }
102798
104600
  function hydrateProspectiveMemberOverride(data, members) {
102799
104601
  if (typeof data.extendsMemberId !== "string") {
102800
104602
  return data;
@@ -102805,6 +104607,7 @@ function hydrateProspectiveMemberOverride(data, members) {
102805
104607
  "modifier",
102806
104608
  "storage",
102807
104609
  "storageKey",
104610
+ "distribution",
102808
104611
  "minValue",
102809
104612
  "maxValue",
102810
104613
  "decimalPoints",
@@ -103166,6 +104969,9 @@ var init_workspace_status_core = __esm({
103166
104969
  init_classes();
103167
104970
  init_members();
103168
104971
  init_value_row_owner_members();
104972
+ init_constructors2();
104973
+ init_packed_value_parity();
104974
+ init_variants2();
103169
104975
  init_project2();
103170
104976
  init_project_version_types();
103171
104977
  init_instance_provenance();
@@ -104573,7 +106379,7 @@ function buildValueEmitContext(records2, manifest) {
104573
106379
  })
104574
106380
  );
104575
106381
  const classes = dataById(records2, "class");
104576
- const values = dataById(records2, "value");
106382
+ const values = storedValueRowsByIdV4(records2.values());
104577
106383
  const enums = dataById(records2, "enum");
104578
106384
  const localizedTexts = dataById(records2, "localized-text");
104579
106385
  const dialogues = dataById(records2, "dialogue");
@@ -105678,6 +107484,7 @@ function variantRootMember(context, binding) {
105678
107484
  overrideOf: null,
105679
107485
  system: null,
105680
107486
  storage: "immutable",
107487
+ distribution: null,
105681
107488
  storageKey: null
105682
107489
  };
105683
107490
  }
@@ -112834,6 +114641,16 @@ function listNeoWorkspaceFilesV1(root) {
112834
114641
  function listProjectSourceFilesV4(root) {
112835
114642
  return listNeoWorkspaceFilesV1(root).production;
112836
114643
  }
114644
+ function requiredProjectSourceKindV4(path) {
114645
+ const kind = neoProjectSourceKind(path);
114646
+ if (kind === null) {
114647
+ throw new Error(`"${path}" is not a Neo project source path.`);
114648
+ }
114649
+ if (!isNeoProjectProductionSourceKind(kind)) {
114650
+ throw new Error(`"${path}" is test-only source, not production source.`);
114651
+ }
114652
+ return kind;
114653
+ }
112837
114654
  function listProjectTestFilesV1(root) {
112838
114655
  return listNeoWorkspaceFilesV1(root).specs;
112839
114656
  }
@@ -116169,12 +117986,9 @@ function childStorageKeyDeclaration(args) {
116169
117986
  }
116170
117987
  function collectValueRows(records2) {
116171
117988
  const values = /* @__PURE__ */ new Map();
116172
- for (const record3 of Object.values(records2)) {
116173
- if (record3.recordKind !== "value") continue;
116174
- const data = record3.data;
116175
- if (!isObjectRecord2(data)) continue;
116176
- values.set(record3.recordId, {
116177
- id: record3.recordId,
117989
+ for (const [valueId, data] of storedValueRowsByIdV4(Object.values(records2))) {
117990
+ values.set(valueId, {
117991
+ id: valueId,
116178
117992
  classId: typeof data.classId === "string" ? data.classId : null,
116179
117993
  mapKey: typeof data.mapKey === "string" ? data.mapKey : null,
116180
117994
  containerId: typeof data.containerId === "string" ? data.containerId : null,
@@ -119153,6 +120967,49 @@ var init_project_file_push = __esm({
119153
120967
  }
119154
120968
  });
119155
120969
 
120970
+ // ../src/database/packed-value-record-validation.ts
120971
+ function packedValueRecordViolation(row) {
120972
+ if (!rowCarriesPackedValueContent(row)) return null;
120973
+ let decoded;
120974
+ try {
120975
+ decoded = decodePackedValueRow(row);
120976
+ } catch (error) {
120977
+ if (error instanceof PackedValueEncodingError) return error.message;
120978
+ throw error;
120979
+ }
120980
+ const rootViolation = decodedRowViolation(
120981
+ decoded.row,
120982
+ `distribution root "${decoded.row.id}"`
120983
+ );
120984
+ if (rootViolation !== null) return rootViolation;
120985
+ for (const child of decoded.children) {
120986
+ const childViolation = decodedRowViolation(
120987
+ child,
120988
+ `packed child "${child.id}"`
120989
+ );
120990
+ if (childViolation !== null) return childViolation;
120991
+ }
120992
+ return null;
120993
+ }
120994
+ function decodedRowViolation(row, label) {
120995
+ if (!isMemberValue(row)) {
120996
+ return `Decoded ${label} is not a valid value row.`;
120997
+ }
120998
+ const provenance = canonicalInstanceProvenanceViolation(row);
120999
+ if (provenance !== null) {
121000
+ return `Decoded ${label} violates canonical instance provenance: ${provenance}.`;
121001
+ }
121002
+ return null;
121003
+ }
121004
+ var init_packed_value_record_validation = __esm({
121005
+ "../src/database/packed-value-record-validation.ts"() {
121006
+ "use strict";
121007
+ init_instance_provenance();
121008
+ init_member_kinds();
121009
+ init_packed_value_encoding();
121010
+ }
121011
+ });
121012
+
119156
121013
  // ../src/models/project-file-authoring-identifiers.ts
119157
121014
  function isValidProjectFileAuthoringIdentifier(value) {
119158
121015
  return isValidProjectSourceIdentifier(value);
@@ -119191,7 +121048,13 @@ function validateProjectRecordByKind(recordKind, data, options = {}) {
119191
121048
  if (memberGuard(data)) return;
119192
121049
  }
119193
121050
  if (recordKind === ProjectRecordKind.Value) {
119194
- if (isMemberValue(data)) return;
121051
+ if (isMemberValue(data)) {
121052
+ const packedViolation = packedValueRecordViolation(data);
121053
+ if (packedViolation === null) return;
121054
+ throw new Error(
121055
+ `Value "${data.id}" carries an invalid packed subtree: ${packedViolation}`
121056
+ );
121057
+ }
119195
121058
  }
119196
121059
  if (recordKind === ProjectRecordKind.Class) {
119197
121060
  if (isNeoSchemaClass(data)) return;
@@ -119271,6 +121134,7 @@ var init_project_version_validation = __esm({
119271
121134
  init_classes();
119272
121135
  init_constructors2();
119273
121136
  init_inheritance();
121137
+ init_packed_value_record_validation();
119274
121138
  init_generics();
119275
121139
  init_enum2();
119276
121140
  init_interfaces();
@@ -122295,8 +124159,8 @@ var init_registry2 = __esm({
122295
124159
  "use strict";
122296
124160
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
122297
124161
  formatVersion: 4,
122298
- contractVersion: "4.0",
122299
- cliVersion: "0.40.0",
124162
+ contractVersion: "4.1",
124163
+ cliVersion: "0.41.0",
122300
124164
  projectFileUploadBatchSize: 32,
122301
124165
  documentRecords: {
122302
124166
  member: {
@@ -122314,6 +124178,11 @@ var init_registry2 = __esm({
122314
124178
  "system",
122315
124179
  "storage",
122316
124180
  "storageKey",
124181
+ // Deliberately carries no normalization rule (P76 §1): absence is the
124182
+ // canonical automatic setting and explicit ordinal 0 is an explicit
124183
+ // `.Sparse`, so `absentMeansDefault` would collapse the two states
124184
+ // that the whole contract exists to keep apart.
124185
+ "distribution",
122317
124186
  "minValue",
122318
124187
  "maxValue",
122319
124188
  "decimalPoints",
@@ -122638,6 +124507,7 @@ var init_registry2 = __esm({
122638
124507
  NeoListKind: ["Ordered", "Unordered"],
122639
124508
  NeoDictionaryKeyKind: ["String", "Enum"],
122640
124509
  NeoClassVisibility: ["Visible", "Hidden"],
124510
+ NeoSubtreeDistribution: ["Sparse", "Packed"],
122641
124511
  NeoStringFormat: ["Localized", "Plain"],
122642
124512
  NeoMemberSearchBy: ["None", "MemberKey"],
122643
124513
  NeoListIndexKind: ["Bucket", "Unique"],
@@ -125521,7 +127391,7 @@ function inspectSourceContract(workspace) {
125521
127391
  try {
125522
127392
  const inputs = files.map((file, index) => ({
125523
127393
  uri: relativeFiles[index],
125524
- kind: requiredSourceKind(relativeFiles[index]),
127394
+ kind: requiredProjectSourceKindV4(relativeFiles[index]),
125525
127395
  text: readFileSync17(file, "utf8")
125526
127396
  }));
125527
127397
  const analysis = compileNeoProjectSources(inputs);
@@ -125642,13 +127512,6 @@ function inspectTrackedBinary(root, record3, errors) {
125642
127512
  errors.push(`Tracked project file ${path} is not readable.`);
125643
127513
  }
125644
127514
  }
125645
- function requiredSourceKind(path) {
125646
- const kind = neoProjectSourceKind(path);
125647
- if (kind !== null && isNeoProjectProductionSourceKind(kind)) return kind;
125648
- throw new Error(
125649
- `Unsupported Neo project source path ${JSON.stringify(path)}.`
125650
- );
125651
- }
125652
127515
  function errorDiagnostics(diagnostics) {
125653
127516
  return diagnostics.filter(
125654
127517
  (diagnostic) => diagnostic.severity === "error" && !isPullRecoveryDiagnosticCode(diagnostic.code)
@@ -125769,6 +127632,440 @@ var init_doctor = __esm({
125769
127632
  }
125770
127633
  });
125771
127634
 
127635
+ // ../src/database/p76-canonical-value-id-plan.ts
127636
+ function rewriteP76CanonicalValueIds(args) {
127637
+ if (args.newByOldValueId.size === 0) return args.data;
127638
+ return rewriteRecord(args.recordKind, args.data, args.newByOldValueId);
127639
+ }
127640
+ function rewriteRecord(recordKind, data, newByOldValueId) {
127641
+ if (!isPlainRecord5(data)) return data;
127642
+ return mapRecord(data, (field, child) => {
127643
+ if (field === "id") {
127644
+ return recordKind === ProjectRecordKind.Value ? remap(child, newByOldValueId) : child;
127645
+ }
127646
+ if (field === "sourceValueId") return child;
127647
+ if (ROW_CONTENT_FIELDS.has(field)) {
127648
+ return rewriteRowContent(child, newByOldValueId);
127649
+ }
127650
+ if (isRelationEndpoint(recordKind, data, field)) {
127651
+ return remap(child, newByOldValueId);
127652
+ }
127653
+ return rewriteByFieldName(child, field, newByOldValueId);
127654
+ });
127655
+ }
127656
+ function isRelationEndpoint(recordKind, data, field) {
127657
+ if (recordKind !== ProjectRecordKind.InternalRecordRelation) return false;
127658
+ if (field === "sourceRecordId") {
127659
+ return data.sourceRecordKind === ProjectRecordKind.Value;
127660
+ }
127661
+ if (field === "targetRecordId") {
127662
+ return data.targetRecordKind === ProjectRecordKind.Value;
127663
+ }
127664
+ return false;
127665
+ }
127666
+ function rewriteRowContent(node, newByOldValueId) {
127667
+ if (typeof node === "string") return remap(node, newByOldValueId);
127668
+ if (Array.isArray(node)) {
127669
+ return mapArray(node, (entry) => rewriteRowContent(entry, newByOldValueId));
127670
+ }
127671
+ if (!isPlainRecord5(node)) return node;
127672
+ if (Object.hasOwn(node, STRUCTURED_LEAF_PARTIAL_KEY)) return node;
127673
+ const packed = node[PACKED_VALUE_ENTRY_KEY];
127674
+ if (packed !== void 0) {
127675
+ const rewritten = rewritePackedEntry(packed, newByOldValueId);
127676
+ if (rewritten === packed) return node;
127677
+ return { ...node, [PACKED_VALUE_ENTRY_KEY]: rewritten };
127678
+ }
127679
+ return mapRecord(
127680
+ node,
127681
+ (_field, child) => rewriteRowContent(child, newByOldValueId)
127682
+ );
127683
+ }
127684
+ function rewritePackedEntry(entry, newByOldValueId) {
127685
+ if (!isPlainRecord5(entry)) return entry;
127686
+ return mapRecord(entry, (field, child) => {
127687
+ if (field === "id") return remap(child, newByOldValueId);
127688
+ if (field === "sourceValueId") return child;
127689
+ if (ROW_CONTENT_FIELDS.has(field)) {
127690
+ return rewriteRowContent(child, newByOldValueId);
127691
+ }
127692
+ return rewriteByFieldName(child, field, newByOldValueId);
127693
+ });
127694
+ }
127695
+ function rewriteByFieldName(node, field, newByOldValueId) {
127696
+ if (typeof node === "string") {
127697
+ if (isCompilerReferenceField(field)) return remap(node, newByOldValueId);
127698
+ if (AUTHORED_VALUE_ID_FIELDS.has(field)) {
127699
+ return remap(node, newByOldValueId);
127700
+ }
127701
+ return node;
127702
+ }
127703
+ if (Array.isArray(node)) {
127704
+ return mapArray(
127705
+ node,
127706
+ (entry) => rewriteByFieldName(entry, field, newByOldValueId)
127707
+ );
127708
+ }
127709
+ if (!isPlainRecord5(node)) return node;
127710
+ if (Object.hasOwn(node, STRUCTURED_LEAF_PARTIAL_KEY)) return node;
127711
+ return mapRecord(node, (childField, child) => {
127712
+ if (childField === "sourceValueId") return child;
127713
+ if (ROW_CONTENT_FIELDS.has(childField)) {
127714
+ return rewriteRowContent(child, newByOldValueId);
127715
+ }
127716
+ return rewriteByFieldName(child, childField, newByOldValueId);
127717
+ });
127718
+ }
127719
+ function remap(node, newByOldValueId) {
127720
+ if (typeof node !== "string") return node;
127721
+ return newByOldValueId.get(node) ?? node;
127722
+ }
127723
+ function mapRecord(record3, rewrite) {
127724
+ let changed = false;
127725
+ const next = {};
127726
+ for (const [field, child] of Object.entries(record3)) {
127727
+ const rewritten = rewrite(field, child);
127728
+ if (rewritten !== child) changed = true;
127729
+ next[field] = rewritten;
127730
+ }
127731
+ return changed ? next : record3;
127732
+ }
127733
+ function mapArray(entries, rewrite) {
127734
+ let changed = false;
127735
+ const next = new Array(entries.length);
127736
+ for (const [index, entry] of entries.entries()) {
127737
+ const rewritten = rewrite(entry);
127738
+ if (rewritten !== entry) changed = true;
127739
+ next[index] = rewritten;
127740
+ }
127741
+ return changed ? next : entries;
127742
+ }
127743
+ function isPlainRecord5(value) {
127744
+ if (typeof value !== "object" || value === null) return false;
127745
+ return !Array.isArray(value);
127746
+ }
127747
+ var P76_CANONICAL_VALUE_ID_USE_SITES, AUTHORED_VALUE_ID_FIELDS, ROW_CONTENT_FIELDS;
127748
+ var init_p76_canonical_value_id_plan = __esm({
127749
+ "../src/database/p76-canonical-value-id-plan.ts"() {
127750
+ "use strict";
127751
+ init_inheritance();
127752
+ init_instance_provenance();
127753
+ init_member_kinds();
127754
+ init_member_value_id();
127755
+ init_packed_value_encoding();
127756
+ init_stored_value_placement_index();
127757
+ init_structured_leaf_fields();
127758
+ init_project2();
127759
+ init_neo_script_recompile_scope();
127760
+ init_virtual_instance_values();
127761
+ P76_CANONICAL_VALUE_ID_USE_SITES = [
127762
+ "value.id",
127763
+ "value.containerId",
127764
+ "value.instanceVariantRowValueId",
127765
+ "value.sourceValueId",
127766
+ "value.constructorArgs.*",
127767
+ "value.value.*",
127768
+ `value.value.${PACKED_VALUE_ENTRY_KEY}.id`,
127769
+ `value.value.${PACKED_VALUE_ENTRY_KEY}.value.*`,
127770
+ `value.value.${PACKED_VALUE_ENTRY_KEY}.constructorArgs.*`,
127771
+ `value.value.${PACKED_VALUE_ENTRY_KEY}.instanceVariantRowValueId`,
127772
+ `value.value.${PACKED_VALUE_ENTRY_KEY}.sourceValueId`,
127773
+ "value.init.**",
127774
+ "member.valueId",
127775
+ "member.collectionValueId",
127776
+ "member.defaultValue.*",
127777
+ "member.getter.**",
127778
+ "member.setter.**",
127779
+ "member.action.**",
127780
+ "member.uiAction.**",
127781
+ "variant.valueId",
127782
+ "variant-folder.binding.collectionValueId",
127783
+ "constructor.action.**",
127784
+ "constructor.compiledBaseArguments.**",
127785
+ "constructor.compiledBaseInitializerFields.**",
127786
+ "dialogue.primaryLinkedValueId",
127787
+ "dialogue.linkedValues.*.valueId",
127788
+ "dialogue-node.primaryLinkedValueId",
127789
+ "dialogue-node.linkedValues.*.valueId",
127790
+ "dialogue-node.dialogueGroupSettings.lookupValueId",
127791
+ "dialogue-node.**",
127792
+ "dialogue-group.collectionValueId",
127793
+ "dialogue-group.conditions.**",
127794
+ "localized-text.links.*.valueId",
127795
+ "internal-record-relation.sourceRecordId",
127796
+ "internal-record-relation.targetRecordId"
127797
+ ];
127798
+ AUTHORED_VALUE_ID_FIELDS = /* @__PURE__ */ new Set([
127799
+ "assetValueId",
127800
+ "containerId",
127801
+ "instanceVariantRowValueId",
127802
+ "lookupValueId",
127803
+ "rowValueId"
127804
+ ]);
127805
+ ROW_CONTENT_FIELDS = /* @__PURE__ */ new Set([
127806
+ "value",
127807
+ "constructorArgs"
127808
+ ]);
127809
+ }
127810
+ });
127811
+
127812
+ // src/commands/migrate-rekey.ts
127813
+ import { readFileSync as readFileSync18, rmSync as rmSync8, writeFileSync as writeFileSync12 } from "node:fs";
127814
+ import { join as join17, relative as relative8, sep as sep8 } from "node:path";
127815
+ import { ConvexError as ConvexError2 } from "convex/values";
127816
+ function rekeyCanonicalValueIdsInSource(text, newByOldValueId) {
127817
+ let pins = 0;
127818
+ let references = 0;
127819
+ const pinned = text.replace(
127820
+ ID_PIN_PATTERN,
127821
+ (match, open, oldId, close) => {
127822
+ const newId = newByOldValueId.get(oldId);
127823
+ if (newId === void 0) return match;
127824
+ pins += 1;
127825
+ return `${open}${newId}${close}`;
127826
+ }
127827
+ );
127828
+ const rewritten = pinned.replace(
127829
+ REFERENCE_ID_PATTERN,
127830
+ (match, open, oldId, close) => {
127831
+ const newId = newByOldValueId.get(oldId);
127832
+ if (newId === void 0) return match;
127833
+ references += 1;
127834
+ return `${open}${newId}${close}`;
127835
+ }
127836
+ );
127837
+ return { text: rewritten, pins, references };
127838
+ }
127839
+ function assertNoOldValueIdsInSource(files, oldValueIds) {
127840
+ for (const file of files) {
127841
+ for (const match of file.text.matchAll(QUOTED_STRING_PATTERN)) {
127842
+ const quoted = match[1];
127843
+ if (quoted === void 0) continue;
127844
+ if (!oldValueIds.has(quoted)) continue;
127845
+ const line = file.text.slice(0, match.index).split("\n").length;
127846
+ throw new Error(
127847
+ `${file.path}:${String(line)} still quotes pre-migration value id "${quoted}" outside an @id pin or Reference(id:) literal. Rewrite that use by hand, then rerun "neo migrate rekey".`
127848
+ );
127849
+ }
127850
+ }
127851
+ }
127852
+ function rekeyWorkspaceState(state, newByOldValueId) {
127853
+ const nextRecords = {};
127854
+ let recordsRekeyed = 0;
127855
+ let recordsDataRewritten = 0;
127856
+ for (const [key, record3] of Object.entries(state.records)) {
127857
+ if (!isProjectRecordKind(record3.recordKind)) {
127858
+ throw new Error(
127859
+ `Workspace state entry "${key}" has unknown record kind "${record3.recordKind}".`
127860
+ );
127861
+ }
127862
+ const data = rewriteP76CanonicalValueIds({
127863
+ recordKind: record3.recordKind,
127864
+ data: record3.data,
127865
+ newByOldValueId
127866
+ });
127867
+ if (data !== record3.data) recordsDataRewritten += 1;
127868
+ const newValueId = record3.recordKind === ProjectRecordKind.Value ? newByOldValueId.get(record3.recordId) : void 0;
127869
+ if (newValueId === void 0) {
127870
+ nextRecords[key] = { ...record3, data };
127871
+ continue;
127872
+ }
127873
+ const nextKey = recordStateKey(record3.recordKind, newValueId);
127874
+ if (Object.hasOwn(state.records, nextKey)) {
127875
+ throw new Error(
127876
+ `Workspace state entry "${key}" rekeys to "${nextKey}", which the working copy already tracks.`
127877
+ );
127878
+ }
127879
+ if (Object.hasOwn(nextRecords, nextKey)) {
127880
+ throw new Error(
127881
+ `Workspace state entry "${key}" rekeys to "${nextKey}", which another entry already claimed.`
127882
+ );
127883
+ }
127884
+ nextRecords[nextKey] = { ...record3, data, recordId: newValueId };
127885
+ recordsRekeyed += 1;
127886
+ }
127887
+ state.records = nextRecords;
127888
+ delete state.documentRevisionCursor;
127889
+ delete state.headTransactionHash;
127890
+ return { recordsRekeyed, recordsDataRewritten };
127891
+ }
127892
+ async function runMigrateRekey(workspace, dependencies = {}) {
127893
+ const mappings = await (dependencies.fetchMappings ?? fetchCanonicalValueIdMappings)(workspace);
127894
+ if (mappings.length === 0) {
127895
+ console.log("Nothing to rekey.");
127896
+ return;
127897
+ }
127898
+ const newByOldValueId = new Map(
127899
+ mappings.map((mapping) => [mapping.oldValueId, mapping.newValueId])
127900
+ );
127901
+ const status = (dependencies.computeStatus ?? computeWorkspaceStatus2)(
127902
+ workspace
127903
+ );
127904
+ if (status.conflictedFiles.length > 0) {
127905
+ throw new Error(
127906
+ `Resolve conflict markers before rekeying canonical value ids: ${status.conflictedFiles.join(", ")}`
127907
+ );
127908
+ }
127909
+ for (const [key, record3] of Object.entries(workspace.state.records)) {
127910
+ if (record3.conflictServerHash === void 0) continue;
127911
+ throw new Error(
127912
+ `Workspace state entry "${key}" holds an unresolved pull conflict; run "neo resolve" before rekeying canonical value ids.`
127913
+ );
127914
+ }
127915
+ const rewrites = rewriteTrackedSources(workspace.root, newByOldValueId);
127916
+ assertNoOldValueIdsInSource(
127917
+ rewrites.map((rewrite) => ({
127918
+ path: rewrite.path,
127919
+ text: rewrite.text
127920
+ })),
127921
+ new Set(newByOldValueId.keys())
127922
+ );
127923
+ const changedFiles = rewrites.filter(
127924
+ (rewrite) => rewrite.text !== rewrite.original
127925
+ );
127926
+ if (changedFiles.length > 0) {
127927
+ assertRekeyedSourceCompiles(rewrites, newByOldValueId);
127928
+ }
127929
+ const stateResult = rekeyWorkspaceState(workspace.state, newByOldValueId);
127930
+ if (changedFiles.length === 0 && stateResult.recordsRekeyed === 0 && stateResult.recordsDataRewritten === 0) {
127931
+ console.log("Already rekeyed \u2014 no pre-migration value ids remain.");
127932
+ return;
127933
+ }
127934
+ for (const rewrite of changedFiles) {
127935
+ writeFileSync12(join17(workspace.root, rewrite.path), rewrite.text, "utf8");
127936
+ }
127937
+ writeWorkspaceState(workspace.root, workspace.state);
127938
+ for (const path of DERIVED_CACHE_PATHS) {
127939
+ rmSync8(join17(workspace.root, path), { force: true });
127940
+ }
127941
+ let pins = 0;
127942
+ let references = 0;
127943
+ for (const file of changedFiles) {
127944
+ pins += file.pins;
127945
+ references += file.references;
127946
+ }
127947
+ console.log(
127948
+ `Rekeyed ${String(changedFiles.length)} source file(s): ${String(pins)} @id pin(s), ${String(references)} Reference(id:) literal(s).`
127949
+ );
127950
+ console.log(
127951
+ `Rekeyed ${String(stateResult.recordsRekeyed)} state record(s) and rewrote ids in ${String(stateResult.recordsDataRewritten)}. Run "neo pull" next.`
127952
+ );
127953
+ }
127954
+ function rewriteTrackedSources(root, newByOldValueId) {
127955
+ const rewrites = [];
127956
+ const collect = (absolutePaths, production) => {
127957
+ for (const absolutePath of absolutePaths) {
127958
+ const original = readFileSync18(absolutePath, "utf8");
127959
+ rewrites.push({
127960
+ path: relative8(root, absolutePath).split(sep8).join("/"),
127961
+ original,
127962
+ production,
127963
+ ...rekeyCanonicalValueIdsInSource(original, newByOldValueId)
127964
+ });
127965
+ }
127966
+ };
127967
+ collect(listProjectSourceFilesV4(root), true);
127968
+ collect(listProjectTestFilesV1(root), false);
127969
+ return rewrites;
127970
+ }
127971
+ function assertRekeyedSourceCompiles(rewrites, newByOldValueId) {
127972
+ const production = rewrites.filter((rewrite) => rewrite.production);
127973
+ const inputs = production.map((rewrite) => ({
127974
+ uri: rewrite.path,
127975
+ kind: requiredProjectSourceKindV4(rewrite.path),
127976
+ text: rewrite.original
127977
+ }));
127978
+ const before = new Set(
127979
+ blockingDiagnostics(compileNeoProjectSources(inputs)).map(
127980
+ (diagnostic) => diagnosticSignature(diagnostic, newByOldValueId)
127981
+ )
127982
+ );
127983
+ const introduced = blockingDiagnostics(
127984
+ compileNeoProjectSources(
127985
+ inputs.map((input, index) => ({
127986
+ ...input,
127987
+ text: production[index].text
127988
+ }))
127989
+ )
127990
+ ).filter(
127991
+ (diagnostic) => !before.has(diagnosticSignature(diagnostic, newByOldValueId))
127992
+ );
127993
+ if (introduced.length === 0) return;
127994
+ throw new Error(
127995
+ `Canonical value-id rekey produced invalid source:
127996
+ ${introduced.map(
127997
+ (diagnostic) => ` ${diagnostic.uri}:${String(diagnostic.range.start.line + 1)}:${String(diagnostic.range.start.character + 1)} ${diagnostic.message}`
127998
+ ).join("\n")}`
127999
+ );
128000
+ }
128001
+ function blockingDiagnostics(analysis) {
128002
+ return analysis.diagnostics.filter(
128003
+ (diagnostic) => diagnostic.severity === "error" && !isPullRecoveryDiagnosticCode(diagnostic.code)
128004
+ );
128005
+ }
128006
+ function diagnosticSignature(diagnostic, newByOldValueId) {
128007
+ const message = diagnostic.message.replace(
128008
+ /[A-Za-z0-9_-]+/g,
128009
+ (token) => newByOldValueId.get(token) ?? token
128010
+ );
128011
+ return `${diagnostic.uri} ${diagnostic.code ?? ""} ${message}`;
128012
+ }
128013
+ async function fetchCanonicalValueIdMappings(workspace) {
128014
+ const convex = await createConvexClient(workspace);
128015
+ const mappings = [];
128016
+ let cursor = null;
128017
+ for (; ; ) {
128018
+ const page = await queryMappingsPage(convex, workspace, cursor);
128019
+ for (const mapping of page.page) mappings.push(mapping);
128020
+ if (page.isDone) break;
128021
+ cursor = page.continueCursor;
128022
+ }
128023
+ return mappings;
128024
+ }
128025
+ async function queryMappingsPage(convex, workspace, cursor) {
128026
+ try {
128027
+ return await convex.query(
128028
+ api2.projectDocuments.getCanonicalValueIdMappingsPage,
128029
+ {
128030
+ projectId: workspace.config.projectId,
128031
+ versionId: workspace.config.versionId,
128032
+ paginationOpts: { cursor, numItems: MAPPING_PAGE_SIZE }
128033
+ }
128034
+ );
128035
+ } catch (error) {
128036
+ if (error instanceof ConvexError2 && typeof error.data === "string") {
128037
+ throw new Error(error.data);
128038
+ }
128039
+ throw error;
128040
+ }
128041
+ }
128042
+ var MAPPING_PAGE_SIZE, ID_PIN_PATTERN, REFERENCE_ID_PATTERN, QUOTED_STRING_PATTERN, DERIVED_CACHE_PATHS;
128043
+ var init_migrate_rekey = __esm({
128044
+ "src/commands/migrate-rekey.ts"() {
128045
+ "use strict";
128046
+ init_src();
128047
+ init_p76_canonical_value_id_plan();
128048
+ init_project2();
128049
+ init_convex();
128050
+ init_materialized_construction_cache();
128051
+ init_project_document_cache();
128052
+ init_project_documents();
128053
+ init_source_diagnostics();
128054
+ init_workspace_status();
128055
+ init_workspace();
128056
+ MAPPING_PAGE_SIZE = 512;
128057
+ ID_PIN_PATTERN = /(@id\s*\(\s*")([^"]*)("\s*\))/g;
128058
+ REFERENCE_ID_PATTERN = /(Reference\s*\(\s*id\s*:\s*")([^"]*)(")/g;
128059
+ QUOTED_STRING_PATTERN = /"([^"\n]*)"/g;
128060
+ DERIVED_CACHE_PATHS = [
128061
+ PROJECT_SOURCE_ANALYSIS_V4_CACHE_PATH,
128062
+ PROJECT_SOURCE_BUILD_CACHE_PATH,
128063
+ PROJECT_SOURCE_DOCUMENT_BUILD_CACHE_PATH,
128064
+ MATERIALIZED_CONSTRUCTION_BUILD_CACHE_PATH
128065
+ ];
128066
+ }
128067
+ });
128068
+
125772
128069
  // src/commands/migrate.ts
125773
128070
  var migrate_exports = {};
125774
128071
  __export(migrate_exports, {
@@ -125779,8 +128076,8 @@ __export(migrate_exports, {
125779
128076
  runMigrate: () => runMigrate
125780
128077
  });
125781
128078
  import { randomUUID as randomUUID4 } from "node:crypto";
125782
- import { existsSync as existsSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync6, writeFileSync as writeFileSync12 } from "node:fs";
125783
- import { join as join17 } from "node:path";
128079
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, readdirSync as readdirSync6, writeFileSync as writeFileSync13 } from "node:fs";
128080
+ import { join as join18 } from "node:path";
125784
128081
  async function runMigrate(workspace, subcommand, positional, targetRef, json, dependencies = {}) {
125785
128082
  if (subcommand === "new") {
125786
128083
  const name = positional[0];
@@ -125789,7 +128086,7 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
125789
128086
  "Usage: neo migrate new <name> [--target <ClassName|project>]"
125790
128087
  );
125791
128088
  }
125792
- const migrationsDir = join17(workspace.root, "Migrations");
128089
+ const migrationsDir = join18(workspace.root, "Migrations");
125793
128090
  mkdirSync12(migrationsDir, { recursive: true });
125794
128091
  let nextOrder = 1;
125795
128092
  if (existsSync15(migrationsDir)) {
@@ -125801,7 +128098,7 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
125801
128098
  }
125802
128099
  }
125803
128100
  const relPath = migrationFileName(nextOrder, name);
125804
- const absolute = join17(workspace.root, relPath);
128101
+ const absolute = join18(workspace.root, relPath);
125805
128102
  if (existsSync15(absolute)) {
125806
128103
  throw new Error(`"${relPath}" already exists.`);
125807
128104
  }
@@ -125813,11 +128110,18 @@ async function runMigrate(workspace, subcommand, positional, targetRef, json, de
125813
128110
  target === "project" ? "// Runs once with root context. Write the NeoScript action below." : `// Runs once per ${target} value; \`this\` is the instance.`,
125814
128111
  ""
125815
128112
  ].join("\n");
125816
- writeFileSync12(absolute, template, "utf8");
128113
+ writeFileSync13(absolute, template, "utf8");
125817
128114
  console.log(`Created ${relPath} \u2014 edit the action body, then "neo push".`);
125818
128115
  console.log("(The id is assigned at push, same as schema creates.)");
125819
128116
  return;
125820
128117
  }
128118
+ if (subcommand === "rekey") {
128119
+ await runMigrateRekey(workspace, {
128120
+ ...dependencies.fetchCanonicalValueIdMappings === void 0 ? {} : { fetchMappings: dependencies.fetchCanonicalValueIdMappings },
128121
+ ...dependencies.computeStatus === void 0 ? {} : { computeStatus: dependencies.computeStatus }
128122
+ });
128123
+ return;
128124
+ }
125821
128125
  const { raw } = await (dependencies.fetchDocument ?? fetchProjectDocument)(
125822
128126
  workspace
125823
128127
  );
@@ -126940,6 +129244,7 @@ var init_migrate = __esm({
126940
129244
  init_virtual_instance_values();
126941
129245
  init_script();
126942
129246
  init_project_migration_created_values();
129247
+ init_migrate_rekey();
126943
129248
  }
126944
129249
  });
126945
129250
 
@@ -127552,7 +129857,7 @@ __export(content_exports, {
127552
129857
  makeContentContext: () => makeContentContext,
127553
129858
  runLoc: () => runLoc
127554
129859
  });
127555
- import { readFileSync as readFileSync18 } from "node:fs";
129860
+ import { readFileSync as readFileSync19 } from "node:fs";
127556
129861
  import { randomUUID as randomUUID5 } from "node:crypto";
127557
129862
  function versionPath2(workspace, suffix) {
127558
129863
  return `/api/projects/${workspace.config.projectId}/versions/${workspace.config.versionId}/${suffix}`;
@@ -127560,9 +129865,9 @@ function versionPath2(workspace, suffix) {
127560
129865
  function readBatch(file) {
127561
129866
  let raw = null;
127562
129867
  if (file !== null) {
127563
- raw = readFileSync18(file, "utf8");
129868
+ raw = readFileSync19(file, "utf8");
127564
129869
  } else if (!process.stdin.isTTY) {
127565
- raw = readFileSync18(0, "utf8");
129870
+ raw = readFileSync19(0, "utf8");
127566
129871
  if (raw.trim().length === 0) raw = null;
127567
129872
  }
127568
129873
  if (raw === null) return null;
@@ -128594,8 +130899,8 @@ var export_exports = {};
128594
130899
  __export(export_exports, {
128595
130900
  runExportUnity: () => runExportUnity
128596
130901
  });
128597
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "node:fs";
128598
- import { join as join18 } from "node:path";
130902
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync14 } from "node:fs";
130903
+ import { join as join19 } from "node:path";
128599
130904
  async function runExportUnity(workspace, outDir) {
128600
130905
  if (outDir === null) {
128601
130906
  throw new Error(
@@ -128607,23 +130912,23 @@ async function runExportUnity(workspace, outDir) {
128607
130912
  `/api/projects/${workspace.config.projectId}/export`,
128608
130913
  { versionId: workspace.config.versionId }
128609
130914
  );
128610
- const resourcesDir = join18(outDir, "Resources", "Neo");
128611
- const localizationDir = join18(resourcesDir, "Localization");
128612
- const scriptsDir = join18(outDir, "Scripts", "Neo");
130915
+ const resourcesDir = join19(outDir, "Resources", "Neo");
130916
+ const localizationDir = join19(resourcesDir, "Localization");
130917
+ const scriptsDir = join19(outDir, "Scripts", "Neo");
128613
130918
  mkdirSync13(localizationDir, { recursive: true });
128614
130919
  mkdirSync13(scriptsDir, { recursive: true });
128615
- writeFileSync13(join18(resourcesDir, "project.json"), response.projectJson);
128616
- writeFileSync13(
128617
- join18(scriptsDir, "NeoGeneratedTypes.cs"),
130920
+ writeFileSync14(join19(resourcesDir, "project.json"), response.projectJson);
130921
+ writeFileSync14(
130922
+ join19(scriptsDir, "NeoGeneratedTypes.cs"),
128618
130923
  response.generatedTypes
128619
130924
  );
128620
130925
  for (const file of response.localizationFiles ?? []) {
128621
- writeFileSync13(join18(localizationDir, file.fileName), file.content);
130926
+ writeFileSync14(join19(localizationDir, file.fileName), file.content);
128622
130927
  }
128623
- console.log(`wrote ${join18(resourcesDir, "project.json")}`);
128624
- console.log(`wrote ${join18(scriptsDir, "NeoGeneratedTypes.cs")}`);
130928
+ console.log(`wrote ${join19(resourcesDir, "project.json")}`);
130929
+ console.log(`wrote ${join19(scriptsDir, "NeoGeneratedTypes.cs")}`);
128625
130930
  for (const file of response.localizationFiles ?? []) {
128626
- console.log(`wrote ${join18(localizationDir, file.fileName)}`);
130931
+ console.log(`wrote ${join19(localizationDir, file.fileName)}`);
128627
130932
  }
128628
130933
  const diagnostics = response.diagnostics ?? [];
128629
130934
  for (const diagnostic of diagnostics) {
@@ -128646,7 +130951,7 @@ __export(dev_exports, {
128646
130951
  runDev: () => runDev
128647
130952
  });
128648
130953
  import { watch } from "node:fs";
128649
- import { join as join19 } from "node:path";
130954
+ import { join as join20 } from "node:path";
128650
130955
  import { emitKeypressEvents } from "node:readline";
128651
130956
  import { ConvexClient } from "convex/browser";
128652
130957
  function isSchemaSignal(value) {
@@ -128756,7 +131061,7 @@ async function runDev(workspace, options) {
128756
131061
  };
128757
131062
  for (const dir of ["Classes", "Enums"]) {
128758
131063
  try {
128759
- watch(join19(workspace.root, dir), { persistent: true }, onFileChange);
131064
+ watch(join20(workspace.root, dir), { persistent: true }, onFileChange);
128760
131065
  } catch {
128761
131066
  }
128762
131067
  }
@@ -128811,16 +131116,16 @@ __export(resolve_exports, {
128811
131116
  runResolve: () => runResolve,
128812
131117
  workspaceFilePath: () => workspaceFilePath
128813
131118
  });
128814
- import { readFileSync as readFileSync19, rmSync as rmSync8, writeFileSync as writeFileSync14 } from "node:fs";
128815
- import { join as join20 } from "node:path";
131119
+ import { readFileSync as readFileSync20, rmSync as rmSync9, writeFileSync as writeFileSync15 } from "node:fs";
131120
+ import { join as join21 } from "node:path";
128816
131121
  function runResolve(workspace, side) {
128817
131122
  const resolvedRecords = adoptServerConflictBases(workspace);
128818
131123
  let resolvedFiles = 0;
128819
131124
  for (const filePath of listProjectSourceFilesV4(workspace.root)) {
128820
- const source = readFileSync19(filePath, "utf8");
131125
+ const source = readFileSync20(filePath, "utf8");
128821
131126
  if (detectConflictMarkers(source) === null) continue;
128822
131127
  const resolved = resolveMarkers(source, side);
128823
- writeFileSync14(filePath, resolved, "utf8");
131128
+ writeFileSync15(filePath, resolved, "utf8");
128824
131129
  resolvedFiles += 1;
128825
131130
  }
128826
131131
  let resolvedBinaries = 0;
@@ -128828,22 +131133,22 @@ function runResolve(workspace, side) {
128828
131133
  const binary = state.projectBinary;
128829
131134
  const conflict2 = binary?.conflict;
128830
131135
  if (binary === void 0 || conflict2 === void 0) continue;
128831
- const destination = join20(workspace.root, binary.path);
131136
+ const destination = join21(workspace.root, binary.path);
128832
131137
  if (side === "theirs") {
128833
131138
  if (conflict2.remoteSha256 !== null && conflict2.artifactPath !== void 0) {
128834
131139
  writeVerifiedBinaryDownloadV4(
128835
131140
  destination,
128836
- readFileSync19(join20(workspace.root, conflict2.artifactPath)),
131141
+ readFileSync20(join21(workspace.root, conflict2.artifactPath)),
128837
131142
  conflict2.remoteSha256
128838
131143
  );
128839
131144
  binary.sha256 = conflict2.remoteSha256;
128840
131145
  } else {
128841
- rmSync8(destination, { force: true });
131146
+ rmSync9(destination, { force: true });
128842
131147
  binary.sha256 = null;
128843
131148
  }
128844
131149
  }
128845
131150
  if (conflict2.artifactPath !== void 0) {
128846
- rmSync8(join20(workspace.root, conflict2.artifactPath), { force: true });
131151
+ rmSync9(join21(workspace.root, conflict2.artifactPath), { force: true });
128847
131152
  }
128848
131153
  delete binary.conflict;
128849
131154
  resolvedBinaries += 1;
@@ -128912,7 +131217,7 @@ function resolveMarkers(source, side) {
128912
131217
  return output.join("\n");
128913
131218
  }
128914
131219
  function workspaceFilePath(workspace, file) {
128915
- return join20(workspace.root, file);
131220
+ return join21(workspace.root, file);
128916
131221
  }
128917
131222
  var init_resolve = __esm({
128918
131223
  "src/commands/resolve.ts"() {
@@ -128983,7 +131288,7 @@ ${h("Content & scripts")}
128983
131288
  loc ${d("locales | list | set | create | delete | archive | restore | ...")}
128984
131289
  dialogue ${d("dryrun <ref> [--json]")}
128985
131290
  script ${d("check | eval | compile [--mode getter|action|setter|nsfunction] [--member <id-or-name>]")}
128986
- migrate ${d("new | list | check | run | prune")}
131291
+ migrate ${d("new | list | check | run | prune | rekey")}
128987
131292
  export ${d("unity [--out <path>]")}
128988
131293
 
128989
131294
  Run any command with missing arguments in a terminal and ${h("neo")} will ask.
@@ -129117,7 +131422,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
129117
131422
  async function main() {
129118
131423
  const args = parseArgs(process.argv.slice(2));
129119
131424
  if (args.command === "--version") {
129120
- console.log("0.40.0");
131425
+ console.log("0.41.0");
129121
131426
  return;
129122
131427
  }
129123
131428
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
@@ -129234,7 +131539,7 @@ async function main() {
129234
131539
  const sub = args.positional[0];
129235
131540
  if (sub === void 0) {
129236
131541
  throw new Error(
129237
- "neo migrate requires a subcommand: new | list | check | run."
131542
+ "neo migrate requires a subcommand: new | list | check | run | prune | rekey."
129238
131543
  );
129239
131544
  }
129240
131545
  const { runMigrate: runMigrate2 } = await Promise.resolve().then(() => (init_migrate(), migrate_exports));