@platforma-open/milaboratories.antibody-variant-designer.block 1.2.1 → 1.2.3

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/index.js CHANGED
@@ -30,14 +30,14 @@ function deriveTemplateParams(data) {
30
30
  };
31
31
  }
32
32
  //#endregion
33
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/plugin_handle.js
33
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/plugin_handle.js
34
34
  const PLUGIN_OUTPUT_PREFIX = "plugin-output#";
35
35
  /** Construct the output key for a plugin output in the block outputs map. */
36
36
  function pluginOutputKey(handle, outputKey) {
37
37
  return `${PLUGIN_OUTPUT_PREFIX}${handle}#${outputKey}`;
38
38
  }
39
39
  //#endregion
40
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_storage.js
40
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/block_storage.js
41
41
  /**
42
42
  * Discriminator key for BlockStorage format detection.
43
43
  * This unique hash-based key identifies data as BlockStorage vs legacy formats.
@@ -3844,20 +3844,6 @@ const coerce = {
3844
3844
  coerce: true
3845
3845
  }))
3846
3846
  };
3847
- objectType({
3848
- type: literalType("plain"),
3849
- content: stringType()
3850
- });
3851
- //#endregion
3852
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3853
- /**
3854
- * Compose a {@link BlockKindReference} from a kind's `name`/`version`.
3855
- *
3856
- * The single place that decides how the reference is assembled. If global
3857
- * uniqueness later requires the name segment to be org-qualified, this is the
3858
- * one line that changes.
3859
- */
3860
- const formatKindRef = (k) => `${k.name}@${k.version}`;
3861
3847
  objectType({
3862
3848
  /** Included left border. */
3863
3849
  from: numberType().min(0),
@@ -3865,7 +3851,7 @@ objectType({
3865
3851
  to: numberType().min(1)
3866
3852
  });
3867
3853
  //#endregion
3868
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/util.js
3854
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/util.js
3869
3855
  function assertNever(x) {
3870
3856
  throw new Error("Unexpected object: " + x);
3871
3857
  }
@@ -3877,7 +3863,7 @@ function uniqueBy(array, makeId) {
3877
3863
  return [...new Map(array.map((e) => [makeId(e), e])).values()];
3878
3864
  }
3879
3865
  //#endregion
3880
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
3866
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
3881
3867
  /**
3882
3868
  * Type guard function that checks if the given value is a valid DataInfo.
3883
3869
  *
@@ -4066,7 +4052,7 @@ function entriesToDataInfo(dataInfoEntries) {
4066
4052
  }
4067
4053
  }
4068
4054
  //#endregion
4069
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4055
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/errors.js
4070
4056
  var ServiceError = class extends Error {
4071
4057
  name = "ServiceError";
4072
4058
  };
@@ -4090,7 +4076,7 @@ function ensureError(value) {
4090
4076
  return new Error(stringifyValue(value));
4091
4077
  }
4092
4078
  //#endregion
4093
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4079
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/json.js
4094
4080
  var import_canonicalize = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
4095
4081
  module.exports = function serialize(object) {
4096
4082
  if (typeof object === "number" && isNaN(object)) throw new Error("NaN is not allowed");
@@ -4123,7 +4109,7 @@ function parseJsonSafely(value, fallback) {
4123
4109
  }
4124
4110
  }
4125
4111
  //#endregion
4126
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4112
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4127
4113
  function readMetadata(metadata, key) {
4128
4114
  return metadata?.[key];
4129
4115
  }
@@ -4451,7 +4437,7 @@ function matchAxisId(query, target) {
4451
4437
  return query.name === target.name && matchDomain$1(query.domain, target.domain) && matchDomain$1(query.contextDomain, target.contextDomain);
4452
4438
  }
4453
4439
  //#endregion
4454
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4440
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4455
4441
  const BOOLEAN_TYPES = /* @__PURE__ */ new Set([
4456
4442
  "numericComparison",
4457
4443
  "stringEquals",
@@ -4556,7 +4542,7 @@ function collectSpecQueryColumns(query) {
4556
4542
  return result;
4557
4543
  }
4558
4544
  //#endregion
4559
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4545
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4560
4546
  function mapPTableDef(def, cb) {
4561
4547
  return {
4562
4548
  ...def,
@@ -4599,7 +4585,7 @@ function mapJoinEntry(entry, cb) {
4599
4585
  }
4600
4586
  }
4601
4587
  //#endregion
4602
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4588
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4603
4589
  function getPTableColumnId(spec) {
4604
4590
  switch (spec.type) {
4605
4591
  case "axis": return {
@@ -4613,7 +4599,7 @@ function getPTableColumnId(spec) {
4613
4599
  }
4614
4600
  }
4615
4601
  //#endregion
4616
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4602
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4617
4603
  function stringifyColumnFilteredId(key) {
4618
4604
  return canonicalizeJson(createColumnFilteredKey(key));
4619
4605
  }
@@ -4646,7 +4632,7 @@ function applyAxisFilters(spec, axisFilters) {
4646
4632
  };
4647
4633
  }
4648
4634
  //#endregion
4649
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4635
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4650
4636
  function isPObjectId(value) {
4651
4637
  if (typeof value !== "string") return false;
4652
4638
  return isPObjectKey(parseJsonSafely(value));
@@ -4733,7 +4719,7 @@ function extractAllColumns(entry) {
4733
4719
  return [...columns.values()];
4734
4720
  }
4735
4721
  //#endregion
4736
- //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.5/node_modules/@milaboratories/helpers/dist/utils.js
4722
+ //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.7/node_modules/@milaboratories/helpers/dist/utils.js
4737
4723
  function isNil$1(v) {
4738
4724
  return v === null || v === void 0;
4739
4725
  }
@@ -4766,13 +4752,13 @@ function isPlainObject$1(value) {
4766
4752
  return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
4767
4753
  }
4768
4754
  //#endregion
4769
- //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.5/node_modules/@milaboratories/helpers/dist/error.js
4755
+ //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.7/node_modules/@milaboratories/helpers/dist/error.js
4770
4756
  function throwError(v) {
4771
4757
  if (typeof v === "string") throw new Error(v);
4772
4758
  else throw v;
4773
4759
  }
4774
4760
  //#endregion
4775
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4761
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4776
4762
  function isColumnDiscoveredKey(obj) {
4777
4763
  return typeof obj === "object" && obj !== null && "__isDiscovered" in obj;
4778
4764
  }
@@ -5052,7 +5038,12 @@ function isString$1(value) {
5052
5038
  return typeof value === "string";
5053
5039
  }
5054
5040
  //#endregion
5055
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5041
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/column_value.js
5042
+ function isColumnValueKey(obj) {
5043
+ return typeof obj === "object" && obj !== null && "__isColumnValue" in obj && obj.__isColumnValue === true && "column" in obj && isColumnUniversalId(obj.column) && "value" in obj && isString$1(obj.value);
5044
+ }
5045
+ //#endregion
5046
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5056
5047
  /**
5057
5048
  * Canonically serializes a column key to a branded string id. Accepts both
5058
5049
  * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}
@@ -5072,6 +5063,10 @@ function parseColumnIdSafely(str, fallback = void 0) {
5072
5063
  function isColumnUniversalKey(value) {
5073
5064
  return isPObjectKey(value) || isColumnFilteredKey(value) || isColumnDiscoveredKey(value) || isColumnOverriddenKey(value);
5074
5065
  }
5066
+ function isColumnUniversalId(value) {
5067
+ const key = isString$1(value) ? parseJsonSafely(value, false) : false;
5068
+ return key === false ? false : isColumnUniversalKey(key);
5069
+ }
5075
5070
  /**
5076
5071
  * Take a value out of however many `JSON.stringify` passes wrapped it, or `undefined`
5077
5072
  * when `s` is not JSON at all.
@@ -5111,7 +5106,8 @@ function peelJsonLayers(s) {
5111
5106
  }
5112
5107
  }
5113
5108
  /**
5114
- * Rewrite every block id buried inside a column id.
5109
+ * Rewrite every block id buried inside a column id, or inside the column of a column value
5110
+ * id — a picked value names its producer through that column's leaf.
5115
5111
  *
5116
5112
  * A {@link GlobalPObjectKey} leaf names its upstream by block id, and the wrapper key forms
5117
5113
  * nest by *string* id rather than by object — so a block id can sit under several layers of
@@ -5141,17 +5137,43 @@ function remapColumnIdBlockIds(id, remapBlockId) {
5141
5137
  *
5142
5138
  * Escape padding is peeled and put back, so an id that reached params through an extra
5143
5139
  * `JSON.stringify` is rewritten in place and comes back wrapped as it was found. A string
5144
- * that does not peel to a column key is left alone: params hold ordinary strings too.
5140
+ * that peels to neither a column key nor a column value key is left alone: params hold
5141
+ * ordinary strings too.
5145
5142
  */
5146
5143
  function remapIdString(id, remapBlockId) {
5147
5144
  const peeled = peelJsonLayers(id);
5148
- if (peeled === void 0 || !isColumnUniversalKey(peeled.value)) return void 0;
5149
- const remappedKey = remapKey(peeled.value, remapBlockId);
5150
- if (remappedKey === void 0) return void 0;
5151
- let rebuilt = stringifyColumnId(remappedKey);
5145
+ if (peeled === void 0) return void 0;
5146
+ let rebuilt;
5147
+ if (isColumnValueKey(peeled.value)) {
5148
+ const remappedKey = remapValueKey(peeled.value, remapBlockId);
5149
+ if (remappedKey === void 0) return void 0;
5150
+ rebuilt = canonicalizeJson(remappedKey);
5151
+ } else if (isColumnUniversalKey(peeled.value)) {
5152
+ const remappedKey = remapKey(peeled.value, remapBlockId);
5153
+ if (remappedKey === void 0) return void 0;
5154
+ rebuilt = stringifyColumnId(remappedKey);
5155
+ } else return;
5152
5156
  for (let layer = 0; layer < peeled.layers; layer++) rebuilt = JSON.stringify(rebuilt);
5153
5157
  return rebuilt;
5154
5158
  }
5159
+ /**
5160
+ * {@link remapIdString} over a column id. Remapping keeps an id's shape, so a column id comes
5161
+ * back a column id.
5162
+ */
5163
+ function remapColumnIdString(id, remapBlockId) {
5164
+ return remapIdString(id, remapBlockId);
5165
+ }
5166
+ /**
5167
+ * The value-id half of {@link remapIdString}. `undefined` means "nothing to change". Only the
5168
+ * column carries block ids; the value is cell data and stays as it is.
5169
+ */
5170
+ function remapValueKey(key, remapBlockId) {
5171
+ const column = remapColumnIdString(key.column, remapBlockId);
5172
+ return column === void 0 ? void 0 : {
5173
+ ...key,
5174
+ column
5175
+ };
5176
+ }
5155
5177
  /** The key half of {@link remapColumnIdBlockIds}. `undefined` means "nothing to change". */
5156
5178
  function remapKey(key, remapBlockId) {
5157
5179
  if (isGlobalPObjectKey(key)) {
@@ -5163,7 +5185,7 @@ function remapKey(key, remapBlockId) {
5163
5185
  }
5164
5186
  if (isLocalPObjectKey(key)) return void 0;
5165
5187
  if (isColumnFilteredKey(key)) {
5166
- const source = remapIdString(key.source, remapBlockId);
5188
+ const source = remapColumnIdString(key.source, remapBlockId);
5167
5189
  return source === void 0 ? void 0 : {
5168
5190
  ...key,
5169
5191
  source
@@ -5185,10 +5207,10 @@ function remapKey(key, remapBlockId) {
5185
5207
  * id is the map key, not the value.
5186
5208
  */
5187
5209
  function remapDiscoveredKey(key, remapBlockId) {
5188
- const column = remapIdString(key.column, remapBlockId);
5210
+ const column = remapColumnIdString(key.column, remapBlockId);
5189
5211
  let pathChanged = false;
5190
5212
  const path = key.path?.map((item) => {
5191
- const itemColumn = remapIdString(item.column, remapBlockId);
5213
+ const itemColumn = remapColumnIdString(item.column, remapBlockId);
5192
5214
  if (itemColumn === void 0) return item;
5193
5215
  pathChanged = true;
5194
5216
  return {
@@ -5226,7 +5248,7 @@ function extractPObjectId(id) {
5226
5248
  throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);
5227
5249
  }
5228
5250
  //#endregion
5229
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5251
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5230
5252
  function isColumnOverriddenKey(obj) {
5231
5253
  return typeof obj === "object" && obj !== null && "__isOverridden" in obj;
5232
5254
  }
@@ -5348,7 +5370,7 @@ function mergeRecord(a, b) {
5348
5370
  };
5349
5371
  }
5350
5372
  //#endregion
5351
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5373
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5352
5374
  function axisKey(axis) {
5353
5375
  return (0, import_canonicalize.default)(getAxisId(axis));
5354
5376
  }
@@ -5594,7 +5616,7 @@ function isAnchorAxisRef(value) {
5594
5616
  return typeof value === "object" && "anchor" in value;
5595
5617
  }
5596
5618
  //#endregion
5597
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5619
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5598
5620
  /**
5599
5621
  * Determines if an axis ID matches an axis selector.
5600
5622
  *
@@ -5720,7 +5742,7 @@ function multiColumnSelectorsToPredicate(selectors) {
5720
5742
  return (spec) => isPColumnSpec(spec) && arr.some((sel) => matchMultiColumnSelector(spec, sel));
5721
5743
  }
5722
5744
  //#endregion
5723
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5745
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5724
5746
  function deriveNativeId(spec) {
5725
5747
  const result = {
5726
5748
  kind: spec.kind,
@@ -5732,7 +5754,7 @@ function deriveNativeId(spec) {
5732
5754
  return (0, import_canonicalize.default)(result);
5733
5755
  }
5734
5756
  //#endregion
5735
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5757
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5736
5758
  var LinkerMap = class LinkerMap {
5737
5759
  /** Graph of linkers connected by axes (single or grouped by parents) */
5738
5760
  data;
@@ -5909,7 +5931,71 @@ var LinkerMap = class LinkerMap {
5909
5931
  }
5910
5932
  };
5911
5933
  //#endregion
5912
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5934
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5935
+ /** Well-known resource type names used across the platform. */
5936
+ const ResourceTypeName = {
5937
+ StreamManager: "StreamManager",
5938
+ StdMap: "StdMap",
5939
+ StdMapSlash: "std/map",
5940
+ EphStdMap: "EphStdMap",
5941
+ PFrame: "PFrame",
5942
+ ParquetChunk: "ParquetChunk",
5943
+ BContext: "BContext",
5944
+ BlockPackCustom: "BlockPackCustom",
5945
+ BinaryMap: "BinaryMap",
5946
+ BinaryValue: "BinaryValue",
5947
+ BlobMap: "BlobMap",
5948
+ BResolveSingle: "BResolveSingle",
5949
+ BResolveSingleNoResult: "BResolveSingleNoResult",
5950
+ BResolveChoice: "BResolveChoice",
5951
+ BQueryResult: "BQueryResult",
5952
+ TengoTemplate: "TengoTemplate",
5953
+ TengoLib: "TengoLib",
5954
+ SoftwareInfo: "SoftwareInfo",
5955
+ Dummy: "Dummy",
5956
+ JsonResourceError: "json/resourceError",
5957
+ JsonObject: "json/object",
5958
+ JsonGzObject: "json-gz/object",
5959
+ JsonString: "json/string",
5960
+ JsonArray: "json/array",
5961
+ JsonNumber: "json/number",
5962
+ JsonBool: "json/bool",
5963
+ JsonNull: "json/null",
5964
+ JsonErrorTrace: "json/errorTrace",
5965
+ BContextEnd: "BContextEnd",
5966
+ FrontendFromUrl: "Frontend/FromUrl",
5967
+ FrontendFromFolder: "Frontend/FromFolder",
5968
+ FrontendFromLocalTgz: "Frontend/FromLocalTgz",
5969
+ BObjectSpec: "BObjectSpec",
5970
+ Blob: "Blob",
5971
+ Null: "Null",
5972
+ Binary: "binary",
5973
+ LSProvider: "LSProvider",
5974
+ WorkingDirectory: "WorkingDirectory",
5975
+ UserProject: "UserProject",
5976
+ Projects: "Projects",
5977
+ ClientRoot: "ClientRoot",
5978
+ SharingOutbox: "SharingOutbox",
5979
+ SharingState: "SharingState",
5980
+ SharedEnvelope: "SharedEnvelope",
5981
+ ActionContext: "ActionContext"
5982
+ };
5983
+ objectType({
5984
+ type: literalType("plain"),
5985
+ content: stringType()
5986
+ });
5987
+ //#endregion
5988
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
5989
+ /**
5990
+ * Compose a {@link BlockKindReference} from a kind's `name`/`version`.
5991
+ *
5992
+ * The single place that decides how the reference is assembled. If global
5993
+ * uniqueness later requires the name segment to be org-qualified, this is the
5994
+ * one line that changes.
5995
+ */
5996
+ const formatKindRef = (k) => `${k.name}@${k.version}`;
5997
+ //#endregion
5998
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5913
5999
  /**
5914
6000
  * Required PFrames version. Bump this in lockstep with the `@milaboratories/pframes-rs-*`
5915
6001
  * version in `pnpm-workspace.yaml` so blocks built against the new SDK refuse to load on
@@ -5917,10 +6003,16 @@ var LinkerMap = class LinkerMap {
5917
6003
  */
5918
6004
  const REQUIRES_PFRAMES_VERSION = 1001031;
5919
6005
  stringType().length(24).regex(/[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]/);
6006
+ //#endregion
6007
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/ref.js
6008
+ /** One output of one block: the block and the name of the output in its output context. */
6009
+ const BlockOutput = objectType({
6010
+ blockId: stringType().describe("Upstream block id"),
6011
+ name: stringType().describe("Name of the output provided to the upstream block's output context")
6012
+ });
5920
6013
  objectType({
5921
6014
  __isRef: literalType(true).describe("Crucial marker for the block dependency tree reconstruction"),
5922
- blockId: stringType().describe("Upstream block id"),
5923
- name: stringType().describe("Name of the output provided to the upstream block's output context"),
6015
+ ...BlockOutput.shape,
5924
6016
  requireEnrichments: literalType(true).optional().describe("True if current block that stores this reference in its args, may need enrichments for the references value originating from the blocks in between current and referenced block")
5925
6017
  }).describe("Universal reference type, allowing to set block connections. It is crucial that {@link __isRef} is present and equal to true, internal logic relies on this marker to build block dependency trees.").readonly();
5926
6018
  /**
@@ -5961,7 +6053,41 @@ function createEnrichmentRef(hit, options = {}) {
5961
6053
  };
5962
6054
  }
5963
6055
  //#endregion
5964
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
6056
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/args_issue.js
6057
+ /**
6058
+ * Reads one {@link ArgsIssue} from a value of unknown origin.
6059
+ *
6060
+ * Any severity other than `"warning"` is read as `"error"`: an issue whose weight cannot be
6061
+ * told keeps the block from running rather than letting it run on a misread finding.
6062
+ *
6063
+ * @throws when `value` is not an object carrying a string `message`
6064
+ */
6065
+ function parseArgsIssue(value) {
6066
+ if (typeof value !== "object" || value === null) throw new Error(`An args issue must be an object, got ${describe$1(value)}`);
6067
+ const message = "message" in value ? value.message : void 0;
6068
+ if (!isString$1(message)) throw new Error(`An args issue must carry a string message, got ${describe$1(message)}`);
6069
+ return {
6070
+ severity: "severity" in value && value.severity === "warning" ? "warning" : "error",
6071
+ message
6072
+ };
6073
+ }
6074
+ /**
6075
+ * Reads a list of {@link ArgsIssue}s from a value of unknown origin, each entry as
6076
+ * {@link parseArgsIssue} reads it.
6077
+ *
6078
+ * @throws when `value` is not an array, or one of its entries is not an issue
6079
+ */
6080
+ function parseArgsIssues(value) {
6081
+ if (!Array.isArray(value)) throw new Error(`Args issues must be an array, got ${describe$1(value)}`);
6082
+ return value.map(parseArgsIssue);
6083
+ }
6084
+ function describe$1(value) {
6085
+ if (value === null) return "null";
6086
+ if (Array.isArray(value)) return "an array";
6087
+ return typeof value;
6088
+ }
6089
+ //#endregion
6090
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
5965
6091
  function mapValueInVOE(voe, cb) {
5966
6092
  return voe.ok ? {
5967
6093
  ok: true,
@@ -5969,51 +6095,7 @@ function mapValueInVOE(voe, cb) {
5969
6095
  } : voe;
5970
6096
  }
5971
6097
  //#endregion
5972
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5973
- /** Well-known resource type names used across the platform. */
5974
- const ResourceTypeName = {
5975
- StreamManager: "StreamManager",
5976
- StdMap: "StdMap",
5977
- StdMapSlash: "std/map",
5978
- EphStdMap: "EphStdMap",
5979
- PFrame: "PFrame",
5980
- ParquetChunk: "ParquetChunk",
5981
- BContext: "BContext",
5982
- BlockPackCustom: "BlockPackCustom",
5983
- BinaryMap: "BinaryMap",
5984
- BinaryValue: "BinaryValue",
5985
- BlobMap: "BlobMap",
5986
- BResolveSingle: "BResolveSingle",
5987
- BResolveSingleNoResult: "BResolveSingleNoResult",
5988
- BQueryResult: "BQueryResult",
5989
- TengoTemplate: "TengoTemplate",
5990
- TengoLib: "TengoLib",
5991
- SoftwareInfo: "SoftwareInfo",
5992
- Dummy: "Dummy",
5993
- JsonResourceError: "json/resourceError",
5994
- JsonObject: "json/object",
5995
- JsonGzObject: "json-gz/object",
5996
- JsonString: "json/string",
5997
- JsonArray: "json/array",
5998
- JsonNumber: "json/number",
5999
- BContextEnd: "BContextEnd",
6000
- FrontendFromUrl: "Frontend/FromUrl",
6001
- FrontendFromFolder: "Frontend/FromFolder",
6002
- BObjectSpec: "BObjectSpec",
6003
- Blob: "Blob",
6004
- Null: "Null",
6005
- Binary: "binary",
6006
- LSProvider: "LSProvider",
6007
- WorkingDirectory: "WorkingDirectory",
6008
- UserProject: "UserProject",
6009
- Projects: "Projects",
6010
- ClientRoot: "ClientRoot",
6011
- SharingOutbox: "SharingOutbox",
6012
- SharingState: "SharingState",
6013
- SharedEnvelope: "SharedEnvelope"
6014
- };
6015
- //#endregion
6016
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
6098
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
6017
6099
  const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
6018
6100
  const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
6019
6101
  const typeMap = /* @__PURE__ */ new Map();
@@ -6052,7 +6134,7 @@ const { service, isNodeService, isWasmService, isMainService, getServiceKind, ge
6052
6134
  };
6053
6135
  })();
6054
6136
  //#endregion
6055
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
6137
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
6056
6138
  const Services = {
6057
6139
  PFrameSpec: service()({
6058
6140
  type: "wasm",
@@ -6146,7 +6228,7 @@ function resolveRequiredServices(flags) {
6146
6228
  }
6147
6229
  Object.fromEntries(Object.keys(Services).map((key) => [`requires${key}`, true]));
6148
6230
  //#endregion
6149
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6231
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6150
6232
  function buildMethodMap(pick) {
6151
6233
  const result = {};
6152
6234
  for (const id of Object.values(Services)) result[id] = [...pick(id)];
@@ -6155,7 +6237,7 @@ function buildMethodMap(pick) {
6155
6237
  buildMethodMap(getServiceUiMethods);
6156
6238
  buildMethodMap(getServiceModelMethods);
6157
6239
  //#endregion
6158
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6240
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6159
6241
  /** Resource types that hold column collections — DFS stops here and collects. */
6160
6242
  const COLLECT_TYPES = [ResourceTypeName.PFrame];
6161
6243
  /** Resource types DFS descends through when looking for PFrames. */
@@ -6263,7 +6345,7 @@ function indexPoolBlock(block) {
6263
6345
  return result;
6264
6346
  }
6265
6347
  //#endregion
6266
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6348
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6267
6349
  /**
6268
6350
  * Id-index over a set of {@link ColumnEntriesProvider}s. Sole job:
6269
6351
  * {@link PObjectId} → {@link LeafEntry}. Generic over the accessor flavour, so
@@ -6300,7 +6382,7 @@ var ColumnRegistry = class {
6300
6382
  }
6301
6383
  };
6302
6384
  //#endregion
6303
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6385
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6304
6386
  /**
6305
6387
  * Two-track dedup over an item stream keyed by `ColumnUniversalId`:
6306
6388
  *
@@ -6341,7 +6423,7 @@ function dedupColumns(items, getId, getSpec) {
6341
6423
  return out;
6342
6424
  }
6343
6425
  //#endregion
6344
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6426
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6345
6427
  /**
6346
6428
  * Generic entries provider over a single accessor root. Walks `<root>` once
6347
6429
  * from the supplied `rootPath`, builds an id → {@link LeafEntry} map and
@@ -6398,7 +6480,7 @@ var ResultPoolEntriesProvider = class {
6398
6480
  }
6399
6481
  };
6400
6482
  //#endregion
6401
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6483
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6402
6484
  /**
6403
6485
  * Whether `value` is a reference in the readable spelling.
6404
6486
  *
@@ -6467,7 +6549,7 @@ function expandTemplatePlRef(ref) {
6467
6549
  };
6468
6550
  }
6469
6551
  //#endregion
6470
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6552
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.55.2/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6471
6553
  /**
6472
6554
  * Point every column identifier in a block's params at the blocks of the project being built.
6473
6555
  *
@@ -6527,7 +6609,7 @@ function relocateBlockIds(params, blockIds) {
6527
6609
  return walk(params);
6528
6610
  }
6529
6611
  //#endregion
6530
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_migrations.js
6612
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/block_migrations.js
6531
6613
  /** Create a DataVersioned wrapper with correct shape */
6532
6614
  function makeVersionedData(version, data) {
6533
6615
  return {
@@ -6839,9 +6921,10 @@ var DataModelInitialChain = class extends DataModelMigrationChain {
6839
6921
  if (data !== null && typeof data === "object" && "args" in data) return fn(data);
6840
6922
  return data;
6841
6923
  };
6924
+ const initialVersion = this.versionChain[0];
6842
6925
  const step = {
6843
6926
  fromVersion: DATA_MODEL_LEGACY_VERSION,
6844
- toVersion: this.versionChain[0],
6927
+ toVersion: initialVersion,
6845
6928
  migrate: wrappedFn
6846
6929
  };
6847
6930
  return new DataModelMigrationChainWithRecover({
@@ -7105,7 +7188,7 @@ var DataModel = class DataModel {
7105
7188
  }
7106
7189
  };
7107
7190
  //#endregion
7108
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/internal.js
7191
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/internal.js
7109
7192
  /** Utility code helping to identify whether the code is running in actual UI environment */
7110
7193
  function isInUI() {
7111
7194
  return typeof globalThis.getPlatforma !== "undefined" || typeof globalThis.platforma !== "undefined";
@@ -7175,7 +7258,7 @@ function registerFutureAwait(handle, onResolve) {
7175
7258
  futureResolves.get(handle).push(onResolve);
7176
7259
  }
7177
7260
  //#endregion
7178
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7261
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7179
7262
  /**
7180
7263
  * All facade callback names as constants.
7181
7264
  * These are the source of truth - the interface is derived from these.
@@ -7213,7 +7296,7 @@ function registerFacadeCallbacks(callbacks) {
7213
7296
  for (const key of Object.values(BlockStorageFacadeCallbacks)) tryRegisterCallback(key, callbacks[key]);
7214
7297
  }
7215
7298
  //#endregion
7216
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/services/block_services.js
7299
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/services/block_services.js
7217
7300
  /**
7218
7301
  * Services required by all V3 blocks by default.
7219
7302
  * Edit this when a new service should be available to all blocks.
@@ -7229,7 +7312,7 @@ const BLOCK_SERVICE_FLAGS = {
7229
7312
  };
7230
7313
  resolveRequiredServices(BLOCK_SERVICE_FLAGS);
7231
7314
  //#endregion
7232
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/future.js
7315
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/future.js
7233
7316
  var FutureRef = class FutureRef {
7234
7317
  handle;
7235
7318
  postProcess;
@@ -7257,7 +7340,7 @@ var FutureRef = class FutureRef {
7257
7340
  }
7258
7341
  };
7259
7342
  //#endregion
7260
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/accessor.js
7343
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/accessor.js
7261
7344
  function ifDef(value, cb) {
7262
7345
  return value === void 0 ? void 0 : cb(value);
7263
7346
  }
@@ -7507,11 +7590,11 @@ var TreeNodeAccessor = class TreeNodeAccessor {
7507
7590
  }
7508
7591
  };
7509
7592
  //#endregion
7510
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/internal.js
7593
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/internal.js
7511
7594
  const MainAccessorName = "main";
7512
7595
  const StagingAccessorName = "staging";
7513
7596
  //#endregion
7514
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7597
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7515
7598
  function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7516
7599
  const sortedFilters = [...axisFilters].sort((a, b) => b[0] - a[0]);
7517
7600
  const { type } = dataInfoEntries;
@@ -7575,7 +7658,7 @@ function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7575
7658
  }
7576
7659
  }
7577
7660
  //#endregion
7578
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7661
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7579
7662
  /**
7580
7663
  * Structural postfix derivation for linked columns (phase 2 of `deriveDistinctLabels`).
7581
7664
  *
@@ -7747,7 +7830,10 @@ function resolveGroup(entries, indices, format) {
7747
7830
  * linked columns by the difference between their sources.
7748
7831
  */
7749
7832
  function derivePostfixes(entries, format = defaultLinkerFormatter) {
7750
- const postfix = [...entries.reduce((acc, e, idx) => acc.set(e.stem, [...acc.get(e.stem) ?? [], idx]), /* @__PURE__ */ new Map()).values()].reduce((acc, idxs) => {
7833
+ const postfix = [...entries.reduce((acc, e, idx) => {
7834
+ const key = `${e.stem}\u0000${e.marker ?? ""}`;
7835
+ return acc.set(key, [...acc.get(key) ?? [], idx]);
7836
+ }, /* @__PURE__ */ new Map()).values()].reduce((acc, idxs) => {
7751
7837
  if (idxs.length < 2) return acc;
7752
7838
  const resolved = resolveGroup(idxs.map((i) => entries[i]), idxs, format);
7753
7839
  return idxs.reduce((m, i, k) => m.set(i, resolved[k]), acc);
@@ -7758,7 +7844,7 @@ function derivePostfixes(entries, format = defaultLinkerFormatter) {
7758
7844
  });
7759
7845
  }
7760
7846
  //#endregion
7761
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7847
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7762
7848
  const DISTANCE_PENALTY = .001;
7763
7849
  const LABEL_TYPE = "__LABEL__";
7764
7850
  const LABEL_TYPE_FULL = "__LABEL__@1";
@@ -7780,9 +7866,10 @@ function isSyntheticType(t) {
7780
7866
  function deriveDistinctLabels(values, options = {}) {
7781
7867
  const stems = deriveStems(values, options);
7782
7868
  return derivePostfixes(values.map((v, i) => {
7783
- const { spec, linkerPath } = extractEntryParts(v);
7869
+ const { spec, linkerPath, marker } = extractEntryParts(v);
7784
7870
  return {
7785
7871
  stem: stems[i],
7872
+ marker,
7786
7873
  hit: spec,
7787
7874
  linkers: (linkerPath ?? []).map((s) => s.spec)
7788
7875
  };
@@ -7800,6 +7887,7 @@ function deriveStems(values, options) {
7800
7887
  if (labelForced) forcedSet.add(LABEL_TYPE_FULL);
7801
7888
  const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);
7802
7889
  const build = (typeSet, force) => buildLabels(records, typeSet, forceTraceElements, separator, force);
7890
+ const finalize = (minimized, rendered) => repairBareLabels(rendered, minimized, records, stats, forceTraceElements, separator);
7803
7891
  if (mainTypes.length === 0) {
7804
7892
  if (secondaryTypes.length !== 0) throw new Error("Non-empty secondary types list while main types list is empty.");
7805
7893
  return build(/* @__PURE__ */ new Set([LABEL_TYPE_FULL]), true) ?? throwError("Failed to derive labels using native column labels");
@@ -7813,7 +7901,7 @@ function deriveStems(values, options) {
7813
7901
  const candidateResult = build(currentSet, false);
7814
7902
  if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) {
7815
7903
  const minimized = minimizeTypeSet(currentSet, records, stats, forceTraceElements, forcedSet, separator);
7816
- return repairBareByPresence(build(minimized, false) ?? throwError("Failed to derive unique labels"), minimized, records, stats, forcedSet, forceTraceElements, separator);
7904
+ return finalize(minimized, build(minimized, false) ?? throwError("Failed to derive unique labels"));
7817
7905
  }
7818
7906
  additionalType++;
7819
7907
  if (additionalType >= mainTypes.length) {
@@ -7826,20 +7914,22 @@ function deriveStems(values, options) {
7826
7914
  ...mainTypes,
7827
7915
  ...secondaryTypes
7828
7916
  ]), records, stats, forceTraceElements, forcedSet, separator);
7829
- return repairBareByPresence(build(minimized, true) ?? throwError("Failed to derive unique labels"), minimized, records, stats, forcedSet, forceTraceElements, separator);
7917
+ return finalize(minimized, build(minimized, true) ?? throwError("Failed to derive unique labels"));
7830
7918
  }
7831
7919
  function extractEntryParts(entry) {
7832
7920
  if (!("spec" in entry && typeof entry.spec === "object")) return {
7833
7921
  spec: entry,
7834
7922
  extraTrace: void 0,
7835
7923
  linkerPath: void 0,
7836
- qualifications: void 0
7924
+ qualifications: void 0,
7925
+ marker: void 0
7837
7926
  };
7838
7927
  return {
7839
7928
  spec: entry.spec,
7840
7929
  extraTrace: entry.extraTrace,
7841
7930
  linkerPath: entry.linkerPath,
7842
- qualifications: entry.qualifications
7931
+ qualifications: entry.qualifications,
7932
+ marker: entry.marker
7843
7933
  };
7844
7934
  }
7845
7935
  function formatQualification(q) {
@@ -7991,62 +8081,202 @@ function minimizeTypeSet(typeSet, records, stats, forceTraceElements, forcedSet,
7991
8081
  }
7992
8082
  return result;
7993
8083
  }
7994
- const ABSENT_VALUE = "\0absent";
7995
- /** Whether `fullType`'s rendered value differs across the group (absence counts as a value). */
7996
- function typeDistinguishes(records, group, fullType) {
7997
- const values = /* @__PURE__ */ new Set();
7998
- for (const i of group) {
7999
- const ft = records[i].fullTrace.find((e) => e.fullType === fullType);
8000
- values.add(ft?.label ?? ABSENT_VALUE);
8001
- if (values.size > 1) return true;
8002
- }
8003
- return false;
8004
- }
8005
- /** The highest-importance trace type this row HAS (outside `typeSet`) that sets it apart from its
8006
- * group peers. `undefined` when the row carries nothing distinguishing of its own. */
8007
- function bestDistinguishingType(records, group, row, typeSet, forcedSet, forceTraceElements, stats) {
8008
- return records[row].fullTrace.reduce((best, ft) => {
8009
- if (typeSet.has(ft.fullType) || forcedSet.has(ft.fullType) || forceTraceElements?.has(ft.type)) return best;
8010
- if (!typeDistinguishes(records, group, ft.fullType)) return best;
8011
- const imp = stats.importances.get(ft.fullType) ?? 0;
8012
- return best === void 0 || imp > best.imp ? {
8013
- type: ft.fullType,
8014
- imp
8015
- } : best;
8016
- }, void 0)?.type;
8017
- }
8018
- /**
8019
- * Un-bare columns distinguished only "by absence". After minimization a column can end up with a
8020
- * bare trace zone (only the forced native label) while a peer sharing that same base renders extra
8021
- * tokens — the column reads as unique purely because it LACKS what the peer has. For each such bare
8022
- * column this re-renders JUST that column's label with the highest-importance trace type it actually
8023
- * carries that tells it apart from its peers, so every colliding column is distinguished by a token
8024
- * it HAS rather than by omission.
8025
- *
8026
- * Patches individual labels rather than the shared type set on purpose: the set is global, so adding
8027
- * a type there would also decorate unrelated columns in other groups that happen to carry it. Only
8028
- * bare columns' labels grow (a superset of their previous value), so uniqueness is preserved. Groups
8029
- * are keyed by the base = the label rendered from the forced types alone.
8030
- */
8031
- function repairBareByPresence(labels, minimized, records, stats, forcedSet, forceTraceElements, separator) {
8032
- const base = records.map((r) => renderRecordLabel(r, forcedSet, forceTraceElements, separator));
8033
- const isBare = records.map((r, i) => renderRecordLabel(r, minimized, forceTraceElements, separator) === base[i]);
8034
- const groups = records.reduce((acc, _, i) => acc.set(base[i] ?? "", [...acc.get(base[i] ?? "") ?? [], i]), /* @__PURE__ */ new Map());
8084
+ /**
8085
+ * Repairs labels told apart only by what they lack: in a group with the same shown base, a
8086
+ * member is bare when its shown parts are a strict subset of a peer's. The group is re-labelled
8087
+ * from parts all members carry, or bare members add a hidden part (group-wide when labels stay
8088
+ * unique), whichever keeps the more important distinction; labels stay unique across the list.
8089
+ */
8090
+ function repairBareLabels(labels, minimized, records, stats, forceTraceElements, separator) {
8091
+ const traces = records.map((r) => new Map(r.fullTrace.map((ft) => [ft.fullType, ft.label])));
8092
+ const isQualification = (t) => isSyntheticType(t.split("@")[0]);
8093
+ const depths = records.map((r) => {
8094
+ const steps = r.fullTrace.filter((ft) => ft.fullType !== LABEL_TYPE_FULL && !isQualification(ft.fullType));
8095
+ return new Map(steps.map((ft, idx) => [ft.fullType, steps.length - idx]));
8096
+ });
8097
+ const isForced = (t) => forceTraceElements?.has(t.split("@")[0]) === true;
8098
+ const isDistinctionType = (t) => t !== LABEL_TYPE_FULL && !isQualification(t);
8099
+ const importance = (t) => stats.importances.get(t) ?? 0;
8100
+ const byImportance = (a, b) => importance(b) - importance(a);
8101
+ const render = (i, types) => renderRecordLabel(records[i], types, forceTraceElements, separator);
8102
+ const partKey = (t, l) => `${t}\u0000${l}`;
8103
+ const labelShown = minimized.has(LABEL_TYPE_FULL);
8104
+ const baseTypes = new Set(labelShown ? [LABEL_TYPE_FULL] : []);
8105
+ const qualTypes = [...minimized].filter(isQualification);
8106
+ const groups = /* @__PURE__ */ new Map();
8107
+ records.forEach((_, i) => {
8108
+ const key = render(i, baseTypes) ?? "";
8109
+ const group = groups.get(key);
8110
+ if (group) group.push(i);
8111
+ else groups.set(key, [i]);
8112
+ });
8035
8113
  const patched = [...labels];
8036
- for (const group of groups.values()) {
8037
- if (!group.some((i) => !isBare[i])) continue;
8038
- for (const i of group) {
8039
- if (!isBare[i]) continue;
8040
- const chosen = bestDistinguishingType(records, group, i, minimized, forcedSet, forceTraceElements, stats);
8041
- if (chosen === void 0) continue;
8042
- const withToken = /* @__PURE__ */ new Set([...minimized, chosen]);
8043
- patched[i] = renderRecordLabel(records[i], withToken, forceTraceElements, separator) ?? patched[i];
8044
- }
8114
+ const counts = /* @__PURE__ */ new Map();
8115
+ const addCount = (l, d) => counts.set(l, (counts.get(l) ?? 0) + d);
8116
+ for (const l of patched) addCount(l, 1);
8117
+ const tryApply = (members, next) => {
8118
+ if (new Set(next).size !== members.length) return false;
8119
+ for (const i of members) addCount(patched[i], -1);
8120
+ const clashes = next.some((l) => (counts.get(l) ?? 0) > 0);
8121
+ members.forEach((i, k) => {
8122
+ if (!clashes) patched[i] = next[k];
8123
+ addCount(patched[i], 1);
8124
+ });
8125
+ return !clashes;
8126
+ };
8127
+ for (const [key, group] of groups) {
8128
+ if (group.length < 2) continue;
8129
+ const shown = group.map((i) => [...traces[i]].filter(([t]) => t !== LABEL_TYPE_FULL && (minimized.has(t) || isForced(t))));
8130
+ const partKeys = shown.map((parts) => parts.map(([t, l]) => partKey(t, l)));
8131
+ const sigIndex = /* @__PURE__ */ new Map();
8132
+ const setKeys = [];
8133
+ const setMembers = [];
8134
+ const sigOf = partKeys.map((keys, k) => {
8135
+ const sig = [...keys].sort().join("");
8136
+ let s = sigIndex.get(sig);
8137
+ if (s === void 0) {
8138
+ s = setKeys.length;
8139
+ sigIndex.set(sig, s);
8140
+ setKeys.push(keys);
8141
+ setMembers.push([]);
8142
+ }
8143
+ setMembers[s].push(k);
8144
+ return s;
8145
+ });
8146
+ const setSets = setKeys.map((keys) => new Set(keys));
8147
+ const postings = /* @__PURE__ */ new Map();
8148
+ setKeys.forEach((keys, s) => keys.forEach((p) => {
8149
+ const list = postings.get(p);
8150
+ if (list) list.push(s);
8151
+ else postings.set(p, [s]);
8152
+ }));
8153
+ const withParts = setKeys.map((_, s) => s).filter((s) => setKeys[s].length > 0);
8154
+ const supersetSets = setKeys.map((keys, s) => {
8155
+ if (keys.length === 0) return withParts;
8156
+ const rarest = keys.reduce((a, b) => postings.get(a).length <= postings.get(b).length ? a : b);
8157
+ return postings.get(rarest).filter((t) => t !== s && setSets[t].size > keys.length && keys.every((x) => setSets[t].has(x)));
8158
+ });
8159
+ const bare = group.map((_, k) => supersetSets[sigOf[k]].length > 0);
8160
+ if (!bare.some(Boolean)) continue;
8161
+ const typeCount = /* @__PURE__ */ new Map();
8162
+ for (const i of group) for (const t of traces[i].keys()) typeCount.set(t, (typeCount.get(t) ?? 0) + 1);
8163
+ const isUneven = (t) => (typeCount.get(t) ?? 0) > 0 && typeCount.get(t) < group.length;
8164
+ const unevenMax = Math.max(...[...minimized].filter((t) => isDistinctionType(t) && !isForced(t) && isUneven(t)).map(importance));
8165
+ let sharedLabels;
8166
+ let sharedMax = Number.NEGATIVE_INFINITY;
8167
+ if (labelShown && key !== "") {
8168
+ const shared = [...typeCount].filter(([t, n]) => n === group.length && isDistinctionType(t)).map(([t]) => t).sort(byImportance);
8169
+ const chosen = new Set(baseTypes);
8170
+ const distinctCount = (types) => new Set(group.map((i) => render(i, types) ?? "")).size;
8171
+ let count = distinctCount(chosen);
8172
+ for (const t of shared) {
8173
+ if (count === group.length) break;
8174
+ const next = distinctCount(/* @__PURE__ */ new Set([...chosen, t]));
8175
+ if (next > count) {
8176
+ if (chosen.size === baseTypes.size) sharedMax = importance(t);
8177
+ chosen.add(t);
8178
+ count = next;
8179
+ }
8180
+ }
8181
+ const withTags = /* @__PURE__ */ new Set([...chosen, ...qualTypes]);
8182
+ const complete = group.map((i) => render(i, withTags)).filter((l) => l !== void 0);
8183
+ if (count === group.length && complete.length === group.length && new Set(complete).size === group.length) sharedLabels = complete;
8184
+ }
8185
+ const applyBareFix = () => {
8186
+ const bareMembers = group.filter((_, k) => bare[k]);
8187
+ const oldBare = /* @__PURE__ */ new Map();
8188
+ for (const i of bareMembers) oldBare.set(patched[i], (oldBare.get(patched[i]) ?? 0) + 1);
8189
+ const isFree = (l) => (counts.get(l) ?? 0) - (oldBare.get(l) ?? 0) === 0;
8190
+ const shownTypes = (k) => [
8191
+ ...baseTypes,
8192
+ ...shown[k].map(([t]) => t),
8193
+ ...qualTypes
8194
+ ];
8195
+ const setLabels = /* @__PURE__ */ new Map();
8196
+ const labelsIn = (s) => {
8197
+ let byType = setLabels.get(s);
8198
+ if (byType) return byType;
8199
+ byType = /* @__PURE__ */ new Map();
8200
+ for (const m of setMembers[s]) for (const [t, l] of traces[group[m]]) {
8201
+ const entry = byType.get(t) ?? {
8202
+ labels: /* @__PURE__ */ new Set(),
8203
+ n: 0
8204
+ };
8205
+ entry.labels.add(l);
8206
+ entry.n++;
8207
+ byType.set(t, entry);
8208
+ }
8209
+ setLabels.set(s, byType);
8210
+ return byType;
8211
+ };
8212
+ const someDiffers = (s, u, mine) => {
8213
+ const entry = labelsIn(s).get(u);
8214
+ if (entry === void 0) return mine !== void 0;
8215
+ if (entry.n < setMembers[s].length) return true;
8216
+ return entry.labels.size > 1 || !entry.labels.has(mine ?? "");
8217
+ };
8218
+ const extraDepthsOf = /* @__PURE__ */ new Map();
8219
+ const extraDepths = (s) => {
8220
+ let depthsSet = extraDepthsOf.get(s);
8221
+ if (depthsSet) return depthsSet;
8222
+ depthsSet = new Set(supersetSets[s].flatMap((t) => {
8223
+ const rep = setMembers[t][0];
8224
+ return shown[rep].filter(([u, l]) => !isQualification(u) && !setSets[s].has(partKey(u, l))).map(([u]) => depths[group[rep]].get(u));
8225
+ }));
8226
+ extraDepthsOf.set(s, depthsSet);
8227
+ return depthsSet;
8228
+ };
8229
+ const picks = /* @__PURE__ */ new Map();
8230
+ group.forEach((i, k) => {
8231
+ if (!bare[k]) return;
8232
+ const peers = supersetSets[sigOf[k]];
8233
+ const kindDepths = extraDepths(sigOf[k]);
8234
+ const sameKind = (u) => kindDepths.has(depths[i].get(u)) ? 1 : 0;
8235
+ const candidates = [...traces[i].keys()].filter((u) => !minimized.has(u) && !isForced(u)).filter((u) => peers.some((t) => someDiffers(t, u, traces[i].get(u)))).sort((a, b) => sameKind(b) - sameKind(a) || byImportance(a, b));
8236
+ for (const u of candidates) {
8237
+ const label = render(i, /* @__PURE__ */ new Set([...shownTypes(k), u]));
8238
+ if (label !== void 0 && isFree(label)) {
8239
+ picks.set(i, {
8240
+ type: u,
8241
+ label
8242
+ });
8243
+ break;
8244
+ }
8245
+ }
8246
+ });
8247
+ if (picks.size === 0) return false;
8248
+ if (labelShown && key !== "") {
8249
+ const picked = [...new Set([...picks.values()].map((p) => p.type))];
8250
+ const full = group.map((i, k) => render(i, /* @__PURE__ */ new Set([...shownTypes(k), ...picked]))).filter((l) => l !== void 0);
8251
+ if (full.length === group.length && tryApply(group, full)) return true;
8252
+ }
8253
+ const proposed = new Map([...picks].map(([i, p]) => [i, p.label]));
8254
+ for (let changed = true; changed;) {
8255
+ changed = false;
8256
+ const firstOld = /* @__PURE__ */ new Map();
8257
+ for (const [i, l] of proposed) {
8258
+ const old = firstOld.get(l);
8259
+ if (old === void 0) firstOld.set(l, patched[i]);
8260
+ else if (old !== patched[i]) changed = proposed.delete(i);
8261
+ }
8262
+ const kept = new Set(bareMembers.filter((i) => !proposed.has(i)).map((i) => patched[i]));
8263
+ for (const [i, l] of proposed) if (kept.has(l)) changed = proposed.delete(i);
8264
+ }
8265
+ for (const i of bareMembers) addCount(patched[i], -1);
8266
+ for (const i of bareMembers) {
8267
+ patched[i] = proposed.get(i) ?? patched[i];
8268
+ addCount(patched[i], 1);
8269
+ }
8270
+ return proposed.size > 0;
8271
+ };
8272
+ if (sharedLabels && sharedMax >= unevenMax && tryApply(group, sharedLabels)) continue;
8273
+ if (applyBareFix()) continue;
8274
+ if (sharedLabels && sharedMax < unevenMax) tryApply(group, sharedLabels);
8045
8275
  }
8046
8276
  return patched;
8047
8277
  }
8048
8278
  //#endregion
8049
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/label.js
8279
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/util/label.js
8050
8280
  /** @deprecated Use deriveDistinctLabels */
8051
8281
  function deriveLabels(values, getSpec, options = {}) {
8052
8282
  return deriveDistinctLabels(values.map(getSpec), options).map((label, i) => ({
@@ -8055,7 +8285,7 @@ function deriveLabels(values, getSpec, options = {}) {
8055
8285
  }));
8056
8286
  }
8057
8287
  //#endregion
8058
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8288
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8059
8289
  const RT_RESOURCE_MAP = "PColumnData/ResourceMap";
8060
8290
  const RT_RESOURCE_MAP_PARTITIONED = "PColumnData/Partitioned/ResourceMap";
8061
8291
  const RT_JSON_PARTITIONED = "PColumnData/JsonPartitioned";
@@ -8349,7 +8579,7 @@ function allPColumnsReady(columns) {
8349
8579
  return columns.every(isPColumnReady);
8350
8580
  }
8351
8581
  //#endregion
8352
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8582
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8353
8583
  function isPColumnValues(value) {
8354
8584
  if (!Array.isArray(value)) return false;
8355
8585
  if (value.length === 0) return true;
@@ -8383,9 +8613,10 @@ function splitFiltersToAxisFilter(splitFilters) {
8383
8613
  }
8384
8614
  function fallbackIdDeriver(originalId, axisFilters) {
8385
8615
  if (!axisFilters || axisFilters.length === 0) return originalId;
8616
+ const filtersToCanonicalize = [...axisFilters].sort((a, b) => a[0] - b[0]);
8386
8617
  return (0, import_canonicalize.default)({
8387
8618
  id: originalId,
8388
- axisFilters: [...axisFilters].sort((a, b) => a[0] - b[0])
8619
+ axisFilters: filtersToCanonicalize
8389
8620
  });
8390
8621
  }
8391
8622
  /** Checks if a selector object uses any anchor properties */
@@ -8627,7 +8858,7 @@ var PColumnCollection = class {
8627
8858
  }
8628
8859
  };
8629
8860
  //#endregion
8630
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8861
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8631
8862
  /**
8632
8863
  * Builds a ServiceProxy from a ServiceDispatch.
8633
8864
  * Each service method call is forwarded to dispatch.callServiceMethod.
@@ -8636,7 +8867,7 @@ function createServiceProxy(dispatch) {
8636
8867
  return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
8637
8868
  }
8638
8869
  //#endregion
8639
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/services/get_services.js
8870
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/services/get_services.js
8640
8871
  const cachedServices = /* @__PURE__ */ new WeakMap();
8641
8872
  function getService(name, deps) {
8642
8873
  const ctx = deps?.ctx ?? getCfgRenderCtx();
@@ -8650,7 +8881,7 @@ function getService(name, deps) {
8650
8881
  })();
8651
8882
  }
8652
8883
  //#endregion
8653
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8884
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8654
8885
  function patchInSetFilters(filters) {
8655
8886
  const inSetToOrEqual = (predicate) => {
8656
8887
  if (predicate.operator !== "InSet") return predicate;
@@ -8688,7 +8919,7 @@ function patchInSetFilters(filters) {
8688
8919
  return filters.map((filter) => mapFilter(filter, inSetToOrEqual));
8689
8920
  }
8690
8921
  //#endregion
8691
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/api.js
8922
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/render/api.js
8692
8923
  /**
8693
8924
  * Helper function to match domain objects
8694
8925
  * @param query Optional domain to match against
@@ -9137,27 +9368,27 @@ var PluginRenderCtx = class extends RenderCtxBase {
9137
9368
  }
9138
9369
  };
9139
9370
  //#endregion
9140
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/plugin_model.js
9371
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/plugin_model.js
9141
9372
  /** Internal plugin↔block handshake. `Symbol.for` (not `Symbol`) so it stays
9142
9373
  * identical across multiple `@platforma-sdk/model` copies in one process. */
9143
9374
  const CREATE_PLUGIN_MODEL = Symbol.for("@platforma-sdk/model:createPluginModel");
9144
9375
  //#endregion
9145
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/version.js
9146
- const PlatformaSDKVersion = "1.84.1";
9376
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/version.js
9377
+ const PlatformaSDKVersion = "1.88.16";
9147
9378
  //#endregion
9148
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9379
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9149
9380
  function isConfigLambda(cfgOrFh) {
9150
9381
  return cfgOrFh.__renderLambda === true;
9151
9382
  }
9152
9383
  //#endregion
9153
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9384
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9154
9385
  function downgradeCfgOrLambda(data) {
9155
9386
  if (data === void 0) return void 0;
9156
9387
  if (isConfigLambda(data)) return data.handle;
9157
9388
  return data;
9158
9389
  }
9159
9390
  //#endregion
9160
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9391
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9161
9392
  /**
9162
9393
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
9163
9394
  *
@@ -9446,42 +9677,77 @@ function createInitialStorageFromParams(paramsJson, blockIdsJson, hooks) {
9446
9677
  }
9447
9678
  }
9448
9679
  /**
9449
- * Derives args from storage using the provided args function.
9450
- * This extracts data from storage and passes it to the block's args() function.
9680
+ * Derives args from storage using the block's args function, then finds the issues in them
9681
+ * with the block's `argsIssues()`.
9682
+ *
9683
+ * A throw from `argsIssues()`, or a result that is not a list of issues, is one error carrying
9684
+ * the thrown or parser message, so a broken check keeps the block from running instead of
9685
+ * letting it run unchecked.
9451
9686
  *
9452
9687
  * @param storageJson - Storage as JSON string
9453
- * @param deriveArgs - The block's args derivation function
9454
- * @returns ArgsDeriveResult with derived args or error
9688
+ * @param derivation - The block's args and args issues lambdas
9689
+ * @returns ArgsDeriveResult with derived args and args issues, or error
9455
9690
  */
9456
- function deriveArgsFromStorage(storageJson, deriveArgs) {
9691
+ function deriveArgsFromStorage(storageJson, derivation) {
9457
9692
  const { data } = normalizeStorage(storageJson);
9458
- try {
9459
- return { value: deriveArgs(data) };
9460
- } catch (e) {
9461
- return { error: `args() threw: ${e instanceof Error ? e.message : String(e)}` };
9462
- }
9693
+ const run = deriveArgsWithIssues(data, derivation);
9694
+ if (run.type === "threw") return { error: `args() threw: ${run.message}` };
9695
+ const { args, issues } = run;
9696
+ const errors = errorMessages(issues);
9697
+ if (errors.length > 0) return {
9698
+ error: errors.join("; "),
9699
+ args,
9700
+ issues
9701
+ };
9702
+ return {
9703
+ value: args,
9704
+ issues
9705
+ };
9463
9706
  }
9464
9707
  /**
9465
9708
  * Derives prerunArgs from storage.
9466
- * Uses derivePrerunArgs if provided, otherwise falls back to deriveArgs.
9709
+ *
9710
+ * A block with its own `prerunArgs()` is staged with what it returns, unless its
9711
+ * `prerunArgsIssues()` finds errors in it; `argsIssues()` is not consulted then. A `prerunArgs()`
9712
+ * that returns `undefined` skips staging, and `prerunArgsIssues()` is not called for it.
9713
+ *
9714
+ * A block without its own `prerunArgs()` is staged with its args, unless `argsIssues()` finds
9715
+ * errors in them: args that may not run are not staged either.
9716
+ *
9717
+ * A throw from either issues lambda, or a result that is not a list of issues, is one error
9718
+ * carrying the thrown or parser message.
9467
9719
  *
9468
9720
  * @param storageJson - Storage as JSON string
9469
- * @param deriveArgs - The block's args derivation function (fallback)
9470
- * @param derivePrerunArgs - Optional prerun args derivation function
9471
- * @returns ArgsDeriveResult with derived prerunArgs or error
9721
+ * @param derivation - The block's args, args issues and own staging lambdas
9722
+ * @returns PrerunArgsDeriveResult with derived prerunArgs and their issues, or error
9472
9723
  */
9473
- function derivePrerunArgsFromStorage(storageJson, deriveArgs, derivePrerunArgs) {
9724
+ function derivePrerunArgsFromStorage(storageJson, derivation) {
9474
9725
  const { data } = normalizeStorage(storageJson);
9475
- if (derivePrerunArgs) try {
9476
- return { value: derivePrerunArgs(data) };
9477
- } catch (e) {
9478
- return { error: `prerunArgs() threw: ${e instanceof Error ? e.message : String(e)}` };
9479
- }
9480
- try {
9481
- return { value: deriveArgs(data) };
9482
- } catch (e) {
9483
- return { error: `args() threw (fallback): ${e instanceof Error ? e.message : String(e)}` };
9726
+ const { ownPrerunArgs } = derivation;
9727
+ if (ownPrerunArgs !== void 0) {
9728
+ const run = derivePrerunArgsWithIssues(data, ownPrerunArgs);
9729
+ if (run.type === "threw") return { error: `prerunArgs() threw: ${run.message}` };
9730
+ const errors = errorMessages(run.issues);
9731
+ if (errors.length > 0) return {
9732
+ error: errors.join("; "),
9733
+ issues: run.issues
9734
+ };
9735
+ return {
9736
+ value: run.args,
9737
+ issues: run.issues
9738
+ };
9484
9739
  }
9740
+ const run = deriveArgsWithIssues(data, derivation);
9741
+ if (run.type === "threw") return { error: `args() threw (fallback): ${run.message}` };
9742
+ const errors = errorMessages(run.issues);
9743
+ if (errors.length > 0) return {
9744
+ error: `argsIssues() found errors (fallback): ${errors.join("; ")}`,
9745
+ issues: run.issues
9746
+ };
9747
+ return {
9748
+ value: run.args,
9749
+ issues: run.issues
9750
+ };
9485
9751
  }
9486
9752
  /**
9487
9753
  * Derives this block's template-entry params from storage.
@@ -9500,7 +9766,7 @@ function derivePrerunArgsFromStorage(storageJson, deriveArgs, derivePrerunArgs)
9500
9766
  *
9501
9767
  * @param storageJson - Storage as JSON string
9502
9768
  * @param deriveTemplateParams - The block's templateParams lambda
9503
- * @returns ArgsDeriveResult holding the params exactly as the block projected them
9769
+ * @returns DeriveResult holding the params exactly as the block projected them
9504
9770
  */
9505
9771
  function deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams) {
9506
9772
  const { data } = normalizeStorage(storageJson);
@@ -9510,8 +9776,76 @@ function deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams) {
9510
9776
  return { error: `templateParams() threw: ${e instanceof Error ? e.message : String(e)}` };
9511
9777
  }
9512
9778
  }
9779
+ function deriveArgsWithIssues(data, derivation) {
9780
+ const { deriveArgs, argsIssues } = derivation;
9781
+ let args;
9782
+ try {
9783
+ args = deriveArgs(data);
9784
+ } catch (e) {
9785
+ return {
9786
+ type: "threw",
9787
+ message: messageOf(e)
9788
+ };
9789
+ }
9790
+ if (argsIssues === void 0) return {
9791
+ type: "derived",
9792
+ args,
9793
+ issues: []
9794
+ };
9795
+ return {
9796
+ type: "derived",
9797
+ args,
9798
+ issues: collectIssues(() => argsIssues({
9799
+ args,
9800
+ data
9801
+ }))
9802
+ };
9803
+ }
9804
+ function derivePrerunArgsWithIssues(data, derivation) {
9805
+ const { derivePrerunArgs, prerunArgsIssues } = derivation;
9806
+ let prerunArgs;
9807
+ try {
9808
+ prerunArgs = derivePrerunArgs(data);
9809
+ } catch (e) {
9810
+ return {
9811
+ type: "threw",
9812
+ message: messageOf(e)
9813
+ };
9814
+ }
9815
+ if (prerunArgsIssues === void 0 || prerunArgs === void 0) return {
9816
+ type: "derived",
9817
+ args: prerunArgs,
9818
+ issues: []
9819
+ };
9820
+ return {
9821
+ type: "derived",
9822
+ args: prerunArgs,
9823
+ issues: collectIssues(() => prerunArgsIssues({
9824
+ prerunArgs,
9825
+ data
9826
+ }))
9827
+ };
9828
+ }
9829
+ /**
9830
+ * Calls an issues lambda of the block. Its result is parsed rather than trusted: a block's types
9831
+ * do not hold at run time, and an entry that cannot be read must count as an error, not slip
9832
+ * past. A throw, or a result that cannot be read, is one error carrying its message.
9833
+ */
9834
+ function collectIssues(issuesOf) {
9835
+ try {
9836
+ return parseArgsIssues(issuesOf());
9837
+ } catch (e) {
9838
+ return [{
9839
+ severity: "error",
9840
+ message: messageOf(e)
9841
+ }];
9842
+ }
9843
+ }
9844
+ function errorMessages(issues) {
9845
+ return issues.filter((issue) => issue.severity !== "warning").map((issue) => issue.message);
9846
+ }
9513
9847
  //#endregion
9514
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_model.js
9848
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/block_model.js
9515
9849
  /**
9516
9850
  * Merges two feature flag objects with type-aware logic:
9517
9851
  * - `supports*` (boolean): OR — `true` if either side is `true`
@@ -9539,10 +9873,12 @@ var BlockModelV3 = class BlockModelV3 {
9539
9873
  static FEATURE_FLAGS = {
9540
9874
  supportsLazyState: true,
9541
9875
  supportsPframeQueryRanking: true,
9876
+ supportsColumnLinks: true,
9542
9877
  requiresUIAPIVersion: 3,
9543
9878
  requiresModelAPIVersion: 2,
9544
9879
  requiresCreatePTable: 2,
9545
9880
  requiresPFramesVersion: REQUIRES_PFRAMES_VERSION,
9881
+ requiresArgsIssues: true,
9546
9882
  ...BLOCK_SERVICE_FLAGS
9547
9883
  };
9548
9884
  /** @deprecated Use FEATURE_FLAGS */
@@ -9586,7 +9922,9 @@ var BlockModelV3 = class BlockModelV3 {
9586
9922
  enrichmentTargets: void 0,
9587
9923
  featureFlags: { ...BlockModelV3.FEATURE_FLAGS },
9588
9924
  deriveArgs: void 0,
9925
+ argsIssues: void 0,
9589
9926
  derivePrerunArgs: void 0,
9927
+ prerunArgsIssues: void 0,
9590
9928
  deriveTemplateParams: void 0,
9591
9929
  plugins: {}
9592
9930
  });
@@ -9616,19 +9954,56 @@ var BlockModelV3 = class BlockModelV3 {
9616
9954
  * Sets a function to derive block args from data.
9617
9955
  * This is called during setData to compute the args that will be used for block execution.
9618
9956
  *
9957
+ * Build args even from incomplete data, and say what keeps the block from running in
9958
+ * {@link argsIssues}: args that exist let the platform see what the block references
9959
+ * before it is ready to run. Throwing here still works, and means there are no args at all.
9960
+ *
9961
+ * Setting args again drops a {@link argsIssues} set before, since it checked other args.
9962
+ *
9619
9963
  * @example
9620
9964
  * .args<BlockArgs>((data) => ({ numbers: data.numbers }))
9621
9965
  *
9622
9966
  * @example
9623
- * .args<BlockArgs>((data) => {
9624
- * if (data.numbers.length === 0) throw new Error('Numbers required'); // block not ready
9625
- * return { numbers: data.numbers };
9626
- * })
9967
+ * .args<BlockArgs>((data) => ({ numbers: data.numbers }))
9968
+ * .argsIssues(({ args }) =>
9969
+ * args.numbers.length === 0 ? [{ severity: 'error', message: 'Numbers required' }] : [],
9970
+ * )
9627
9971
  */
9628
9972
  args(lambda) {
9629
9973
  return new BlockModelV3({
9630
9974
  ...this.config,
9631
- deriveArgs: lambda
9975
+ deriveArgs: lambda,
9976
+ argsIssues: void 0
9977
+ });
9978
+ }
9979
+ /**
9980
+ * Sets a function that finds what keeps the block from running with the args {@link args}
9981
+ * derived (optional). It is called after `args()`, with its result and the data it was built
9982
+ * from.
9983
+ *
9984
+ * An issue of severity `"error"` keeps the block from running; a `"warning"` does not. A throw,
9985
+ * or a result that is not a list of issues, counts as one error carrying the thrown or parser
9986
+ * message. Without this function, args that `args()` returns are always runnable.
9987
+ *
9988
+ * A block without its own {@link prerunArgs} is staged with its args, and only while this
9989
+ * function finds no errors in them.
9990
+ *
9991
+ * Must be set after `.args()`, and is dropped when `.args()` is set again.
9992
+ *
9993
+ * @example
9994
+ * .args((data) => ({ dataset: data.dataset, threshold: data.threshold }))
9995
+ * .argsIssues(({ args }) => {
9996
+ * const issues: ArgsIssue[] = [];
9997
+ * if (args.dataset === undefined) issues.push({ severity: 'error', message: 'Select a dataset' });
9998
+ * if (args.threshold > 0.5) issues.push({ severity: 'warning', message: 'Threshold is high' });
9999
+ * return issues;
10000
+ * })
10001
+ */
10002
+ argsIssues(fn) {
10003
+ if (this.config.deriveArgs === void 0) throw new Error("argsIssues() must be set after args(): it checks the args they derive.");
10004
+ return new BlockModelV3({
10005
+ ...this.config,
10006
+ argsIssues: fn
9632
10007
  });
9633
10008
  }
9634
10009
  /**
@@ -9641,6 +10016,9 @@ var BlockModelV3 = class BlockModelV3 {
9641
10016
  * The staging / prerun phase runs only if currentPrerunArgs differs from the executed
9642
10017
  * version of prerunArgs (same comparison logic as currentArgs vs prodArgs).
9643
10018
  *
10019
+ * Setting prerun args again drops a {@link prerunArgsIssues} set before, since it checked other
10020
+ * args.
10021
+ *
9644
10022
  * @example
9645
10023
  * .prerunArgs((data) => ({ numbers: data.numbers }))
9646
10024
  *
@@ -9654,7 +10032,33 @@ var BlockModelV3 = class BlockModelV3 {
9654
10032
  prerunArgs(fn) {
9655
10033
  return new BlockModelV3({
9656
10034
  ...this.config,
9657
- derivePrerunArgs: fn
10035
+ derivePrerunArgs: fn,
10036
+ prerunArgsIssues: void 0
10037
+ });
10038
+ }
10039
+ /**
10040
+ * Sets a function that finds what keeps the block from being staged with the args
10041
+ * {@link prerunArgs} derived (optional). It is called after `prerunArgs()`, with its result
10042
+ * and the data it was built from; not when `prerunArgs()` returned `undefined`, which skips
10043
+ * staging anyway.
10044
+ *
10045
+ * An issue of severity `"error"` keeps the block from being staged; a `"warning"` does not. A
10046
+ * throw, or a result that is not a list of issues, counts as one error carrying the thrown or
10047
+ * parser message. {@link argsIssues} is not consulted for a block with its own prerun args.
10048
+ *
10049
+ * Must be set after `.prerunArgs()`, and is dropped when `.prerunArgs()` is set again.
10050
+ *
10051
+ * @example
10052
+ * .prerunArgs((data) => ({ dataset: data.dataset }))
10053
+ * .prerunArgsIssues(({ prerunArgs }) =>
10054
+ * prerunArgs.dataset === undefined ? [{ severity: 'error', message: 'Select a dataset' }] : [],
10055
+ * )
10056
+ */
10057
+ prerunArgsIssues(fn) {
10058
+ if (this.config.derivePrerunArgs === void 0) throw new Error("prerunArgsIssues() must be set after prerunArgs(): it checks the prerun args they derive.");
10059
+ return new BlockModelV3({
10060
+ ...this.config,
10061
+ prerunArgsIssues: fn
9658
10062
  });
9659
10063
  }
9660
10064
  /**
@@ -9711,6 +10115,11 @@ var BlockModelV3 = class BlockModelV3 {
9711
10115
  })
9712
10116
  });
9713
10117
  }
10118
+ /**
10119
+ * Sets a rendering function to derive block subtitle, shown below the title in the left
10120
+ * blocks-overview panel. Unlike the title, it can read the result pool, so it can name the
10121
+ * inputs the block reads (e.g. through `ctx.resultPool.getPColumnSpecByRef`).
10122
+ */
9714
10123
  subtitle(rf) {
9715
10124
  return new BlockModelV3({
9716
10125
  ...this.config,
@@ -9787,7 +10196,7 @@ var BlockModelV3 = class BlockModelV3 {
9787
10196
  const pluginRegistry = {};
9788
10197
  const pluginHandles = Object.keys(plugins);
9789
10198
  for (const handle of pluginHandles) pluginRegistry[handle] = plugins[handle].model.name;
9790
- const { dataModel, deriveArgs, derivePrerunArgs, deriveTemplateParams, parseInitializationParams } = this.config;
10199
+ const { dataModel, deriveArgs, argsIssues, derivePrerunArgs, prerunArgsIssues, deriveTemplateParams, parseInitializationParams } = this.config;
9791
10200
  function getPlugin(handle) {
9792
10201
  const plugin = plugins[handle];
9793
10202
  if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);
@@ -9810,8 +10219,18 @@ var BlockModelV3 = class BlockModelV3 {
9810
10219
  getPluginRegistry: () => pluginRegistry,
9811
10220
  createPluginData: (handle) => getPlugin(handle).model.getDefaultData()
9812
10221
  }),
9813
- [BlockStorageFacadeCallbacks.ArgsDerive]: (storageJson) => deriveArgsFromStorage(storageJson, deriveArgs),
9814
- [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (storageJson) => derivePrerunArgsFromStorage(storageJson, deriveArgs, derivePrerunArgs),
10222
+ [BlockStorageFacadeCallbacks.ArgsDerive]: (storageJson) => deriveArgsFromStorage(storageJson, {
10223
+ deriveArgs,
10224
+ argsIssues
10225
+ }),
10226
+ [BlockStorageFacadeCallbacks.PrerunArgsDerive]: (storageJson) => derivePrerunArgsFromStorage(storageJson, {
10227
+ deriveArgs,
10228
+ argsIssues,
10229
+ ownPrerunArgs: derivePrerunArgs === void 0 ? void 0 : {
10230
+ derivePrerunArgs,
10231
+ prerunArgsIssues
10232
+ }
10233
+ }),
9815
10234
  [BlockStorageFacadeCallbacks.InitializationParamsDerive]: (storageJson) => deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams),
9816
10235
  [BlockStorageFacadeCallbacks.StorageInitialFromParams]: (paramsJson, blockIdsJson) => createInitialStorageFromParams(paramsJson, blockIdsJson, {
9817
10236
  getBlockDataFromParams: (params) => dataModel.getDataFromParams(params),
@@ -9877,7 +10296,7 @@ var BlockModelV3 = class BlockModelV3 {
9877
10296
  }
9878
10297
  };
9879
10298
  //#endregion
9880
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
10299
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9881
10300
  /** Create id for column copy with added keys in axes domains */
9882
10301
  const colId = (id, domains, contextDomains) => {
9883
10302
  let wid = id.toString();
@@ -9983,7 +10402,7 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
9983
10402
  })];
9984
10403
  }
9985
10404
  //#endregion
9986
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
10405
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
9987
10406
  /**
9988
10407
  * Replace every column leaf whose id equals `fromId` with `toId`, leaving
9989
10408
  * other column refs (linkers, sub-anchors) intact. Wrapper recipes
@@ -10001,7 +10420,7 @@ function rebrandLeafId(node, fromId, toId) {
10001
10420
  return mapSpecQueryColumns(node, { column: (id) => id === fromId ? toId : id });
10002
10421
  }
10003
10422
  //#endregion
10004
- //#region ../node_modules/.pnpm/lru-cache@11.5.2/node_modules/lru-cache/dist/esm/browser/index.min.js
10423
+ //#region ../node_modules/.pnpm/lru-cache@11.5.3/node_modules/lru-cache/dist/esm/browser/index.min.js
10005
10424
  var L = { hasSubscribers: !1 };
10006
10425
  var S = L;
10007
10426
  var W = L;
@@ -10651,7 +11070,7 @@ var U = class d {
10651
11070
  }
10652
11071
  };
10653
11072
  //#endregion
10654
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
11073
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10655
11074
  /**
10656
11075
  * Unified memoised factory dispatching to the right provider flavour by the
10657
11076
  * source shape:
@@ -10711,7 +11130,7 @@ var AccessorColumnsProviderImpl = class extends AccessorEntriesProvider {
10711
11130
  }
10712
11131
  getColumns() {
10713
11132
  if (this.cachedColumns !== void 0) return this.cachedColumns;
10714
- return this.cachedColumns = Array.from(this.entries.values()).map((e) => DataColumn.fromAccessor(e)).filter((v) => !isNil(v));
11133
+ return this.cachedColumns = Array.from(this.entries.values(), DataColumn.fromAccessor).filter((column) => column !== void 0);
10715
11134
  }
10716
11135
  };
10717
11136
  /**
@@ -10733,14 +11152,14 @@ var ResultPoolColumnsProviderImpl = class extends ResultPoolEntriesProvider {
10733
11152
  }
10734
11153
  getColumns() {
10735
11154
  if (this.cachedColumns !== void 0) return this.cachedColumns;
10736
- return this.cachedColumns = Array.from(this.getPObjectEntries().values()).map((e) => DataColumn.fromAccessor(e)).filter((v) => !isNil(v));
11155
+ return this.cachedColumns = Array.from(this.getPObjectEntries().values(), DataColumn.fromAccessor).filter((column) => column !== void 0);
10737
11156
  }
10738
11157
  };
10739
11158
  function hashRawPool(rawPool) {
10740
11159
  return rawPool.map((b) => `${b.blockId}\x1f${b.prodCtx ?? ""}\x1f${b.stagingCtx ?? ""}\x1f${b.prodIncomplete ? 1 : 0}\x1f${b.stagingIncomplete ? 1 : 0}`).join("");
10741
11160
  }
10742
11161
  //#endregion
10743
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
11162
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10744
11163
  /**
10745
11164
  * Build the default set of ColumnsProviders for the ambient render ctx:
10746
11165
  * - `AccessorColumnsProvider` over `outputs` (if present)
@@ -10775,26 +11194,7 @@ function isColumnProvider(source) {
10775
11194
  return typeof p.getColumns === "function" && typeof p.isFinal === "function";
10776
11195
  }
10777
11196
  //#endregion
10778
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10779
- /**
10780
- * Thrown by leaf-recipe factories when the requested column is provably
10781
- * absent in the active render ctx — i.e. every relevant accessor reports
10782
- * `inputsLocked` and the column did not appear. Distinct from the
10783
- * `undefined` return that the factories still use for the "resolving" case
10784
- * (the column may still appear later).
10785
- *
10786
- * Catch at the boundary (resolver / filter+sort wiring / data-table assembly)
10787
- * when partial absence should be surfaced to the user rather than silently
10788
- * producing an empty result.
10789
- */
10790
- var ColumnAbsentError = class extends Error {
10791
- id;
10792
- constructor(id) {
10793
- super(`Column is absent in the active render ctx and will not appear: ${id}`);
10794
- this.id = id;
10795
- this.name = "ColumnAbsentError";
10796
- }
10797
- };
11197
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10798
11198
  /**
10799
11199
  * The leaf-recipe building block: a {@link DataColumnRecipe} whose `id` is a bare
10800
11200
  * {@link PObjectId} and whose readers are bound to a single tree-accessor
@@ -10847,29 +11247,15 @@ var DataColumnImpl = class DataColumnImpl {
10847
11247
  }
10848
11248
  /**
10849
11249
  * Resolve via the ambient {@link ColumnRegistry}. Spec is resolved eagerly:
10850
- * returns `undefined` if the leaf isn't reachable yet (resolving). Throws
10851
- * {@link ColumnAbsentError} when every relevant accessor is `inputsLocked`
10852
- * and the column did not appear — the column will not exist in this ctx.
11250
+ * returns `undefined` unless the id names a column whose spec is readable in
11251
+ * this ctx — while it is resolving, when it is absent, and when the id names
11252
+ * an export that is not a column (a `kind: "File"` object, for example).
10853
11253
  * Data and dataStatus stay lazy.
10854
11254
  */
10855
11255
  static fromId(id, { ctx } = {}) {
10856
- const registry = new ColumnRegistry(getCtxProviders({ ctx }));
10857
- const leaf = registry.resolve(id);
10858
- if (isNil(leaf)) {
10859
- if (registry.isFinal()) throw new ColumnAbsentError(id);
10860
- return;
10861
- }
10862
- const spec = readSpecAccessor(leaf);
10863
- if (isNil(spec)) {
10864
- if (leaf.accessor.getInputsLocked()) throw new ColumnAbsentError(id);
10865
- return;
10866
- }
10867
- if (!spec.hasData()) return void 0;
10868
- return new DataColumnImpl(id, {
10869
- getSpec: () => spec.getDataAsJson(),
10870
- getData: () => readDataAccessor(leaf),
10871
- getDataStatus: () => readDataStatus(leaf)
10872
- });
11256
+ const leaf = new ColumnRegistry(getCtxProviders({ ctx })).resolve(id);
11257
+ if (isNil(leaf)) return void 0;
11258
+ return DataColumnImpl.fromAccessor(leaf);
10873
11259
  }
10874
11260
  /** {@link PlRef} wrapper over {@link fromId}. */
10875
11261
  static fromPlRef(ref) {
@@ -10877,18 +11263,15 @@ var DataColumnImpl = class DataColumnImpl {
10877
11263
  }
10878
11264
  /**
10879
11265
  * Bind directly to an accessor-backed {@link LeafEntry} — no registry.
10880
- * Throws {@link ColumnAbsentError} if the leaf has no spec field and its
10881
- * accessor is `inputsLocked`. Returns `undefined` while still resolving.
11266
+ * Returns `undefined` unless the leaf's spec is readable and is a column
11267
+ * spec: while the spec is resolving, when it is absent, and for an export
11268
+ * that is not a column.
10882
11269
  */
10883
11270
  static fromAccessor(entry) {
10884
- const spec = readSpecAccessor(entry);
10885
- if (isNil(spec)) {
10886
- if (entry.accessor.getInputsLocked()) throw new ColumnAbsentError(entry.id);
10887
- return;
10888
- }
10889
- if (!spec.hasData()) return void 0;
11271
+ const spec = readSpec(entry);
11272
+ if (spec === void 0 || !isPColumnSpec(spec)) return void 0;
10890
11273
  return new DataColumnImpl(entry.id, {
10891
- getSpec: () => spec.getDataAsJson(),
11274
+ getSpec: () => spec,
10892
11275
  getData: () => readDataAccessor(entry),
10893
11276
  getDataStatus: () => readDataStatus(entry)
10894
11277
  });
@@ -10910,7 +11293,9 @@ var DataColumnImpl = class DataColumnImpl {
10910
11293
  * Distinguishes `present` / `resolving` / `absent` for a {@link PObjectId}
10911
11294
  * in the active render ctx. Falls back to the registry's `isFinal()`
10912
11295
  * when the id has no entry — only then we can say `absent` instead of
10913
- * `resolving`.
11296
+ * `resolving`. The status tells only whether the spec is readable: for an
11297
+ * export that is not a column it is `present`, and the factories return
11298
+ * `undefined`.
10914
11299
  */
10915
11300
  static getStatusById(id, { ctx } = {}) {
10916
11301
  const registry = new ColumnRegistry(getCtxProviders({ ctx }));
@@ -10979,6 +11364,12 @@ const readSpecAccessor = memoizeByEntry(({ accessor, name }) => accessor.travers
10979
11364
  assertFieldType: "Input",
10980
11365
  ignoreError: true
10981
11366
  }));
11367
+ /** The leaf's spec, or `undefined` until the spec resource has data. */
11368
+ const readSpec = memoizeByEntry((entry) => {
11369
+ const spec = readSpecAccessor(entry);
11370
+ if (isNil(spec) || !spec.hasData()) return void 0;
11371
+ return spec.getDataAsJson();
11372
+ });
10982
11373
  /**
10983
11374
  * Per-entry counterpart to {@link readDataStatus}: tells whether the leaf's
10984
11375
  * **spec** can be read in this ctx, and — for the negative cases —
@@ -11015,7 +11406,7 @@ function memoizeByEntry(fn) {
11015
11406
  };
11016
11407
  }
11017
11408
  //#endregion
11018
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11409
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11019
11410
  /**
11020
11411
  * Recipe wrapper that overlays {@link SpecOverrides} on top of any other
11021
11412
  * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.
@@ -11153,7 +11544,7 @@ var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
11153
11544
  }
11154
11545
  };
11155
11546
  //#endregion
11156
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11547
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11157
11548
  /**
11158
11549
  * Recipe wrapper that fixes the values of selected axes of an inner recipe
11159
11550
  * (axis slicing). The id is `FilteredPColumnId { source: inner.id,
@@ -11279,7 +11670,7 @@ function toAxisSelector(axis) {
11279
11670
  return selector;
11280
11671
  }
11281
11672
  //#endregion
11282
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11673
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11283
11674
  /**
11284
11675
  * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching
11285
11676
  * concrete recipe variant based on the id's encoding and recurses on
@@ -11317,8 +11708,8 @@ function ColumnRecipeBuild(id, opts = {}) {
11317
11708
  * Resolution status counterpart to {@link ColumnRecipeBuild}. Dispatches on
11318
11709
  * the parsed id shape to the matching `getStatusBy*` static — never
11319
11710
  * constructs the recipe. Use this at boundaries (resolver, filter/sort
11320
- * targets) to throw early on `absent` instead of silently producing an empty
11321
- * recipe via {@link ColumnRecipeBuild}.
11711
+ * targets) to tell an `absent` column from a `resolving` one: the recipe
11712
+ * factory returns `undefined` for both.
11322
11713
  */
11323
11714
  function ColumnRecipeGetStatus(id, opts = {}) {
11324
11715
  const parsed = parseColumnIdSafely(id);
@@ -11330,7 +11721,7 @@ function ColumnRecipeGetStatus(id, opts = {}) {
11330
11721
  }
11331
11722
  const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
11332
11723
  //#endregion
11333
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11724
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11334
11725
  /**
11335
11726
  * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base
11336
11727
  * column + a `path` of linkers + qualifications.
@@ -11501,7 +11892,7 @@ function referencedUniIdsOf(key) {
11501
11892
  return /* @__PURE__ */ new Set([key.column, ...(key.path ?? []).map((item) => item.column)]);
11502
11893
  }
11503
11894
  //#endregion
11504
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column.js
11895
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/column.js
11505
11896
  /**
11506
11897
  * Unified entry point — routes between the two top-level dispatchers:
11507
11898
  * - string id (`PObjectId` / `ColumnUniversalId`) → {@link ColumnRecipe}
@@ -11515,7 +11906,7 @@ function Column(source, opts) {
11515
11906
  return DataColumn(source, opts);
11516
11907
  }
11517
11908
  //#endregion
11518
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11909
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11519
11910
  /**
11520
11911
  * Build a {@link ColumnsCollection} from sandbox-side source descriptors.
11521
11912
  * Resolves the `columnsCollection` driver (either from `deps.driver` or via
@@ -11624,7 +12015,35 @@ function defaultCtxSources(ctx) {
11624
12015
  return [...currentBlockSources(ctx), { kind: "result_pool" }];
11625
12016
  }
11626
12017
  //#endregion
11627
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/utils.js
12018
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/peer_links.js
12019
+ /** Main axes of the datasets: the second axis of every column marked `pl7.app/isAnchor`. */
12020
+ function collectDatasetAxes(specs) {
12021
+ return new Set(specs.flatMap((spec) => {
12022
+ const main = spec.axesSpec[1];
12023
+ return readAnnotation(spec, Annotation.IsAnchor) === "true" && main !== void 0 ? [canonicalizeAxisId(main)] : [];
12024
+ }));
12025
+ }
12026
+ /** {@link collectDatasetAxes} over the result pool. */
12027
+ function getResultPoolDatasetAxes() {
12028
+ return collectDatasetAxes(ResultPoolColumnsProvider().getColumns().map((c) => c.getSpec()));
12029
+ }
12030
+ /**
12031
+ * Labels of the peer links on a linker path. A peer link joins two datasets' main axes, e.g. one
12032
+ * clonotype to another, so the columns behind it describe a different clonotype than the row.
12033
+ */
12034
+ function findPeerLinks(linkers, datasetAxes) {
12035
+ return uniq(linkers.flatMap((l) => {
12036
+ const peer = l.axesSpec.every((a) => datasetAxes.has(canonicalizeAxisId(a)));
12037
+ const label = readAnnotation(l, Annotation.LinkLabel) ?? readAnnotation(l, Annotation.Label);
12038
+ return peer && label ? [label] : [];
12039
+ }));
12040
+ }
12041
+ /** Hover text for the link icon. */
12042
+ function describePeerLinks(links) {
12043
+ return `Reached via ${links.join(", then ")}`;
12044
+ }
12045
+ //#endregion
12046
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/columns/utils.js
11628
12047
  /**
11629
12048
  * PObjectIds of every non-hit column referenced by `recipe.getQuery()`,
11630
12049
  * deduped in traversal order. The hit column is
@@ -11755,7 +12174,7 @@ function hasSingleDataColumn(recipe) {
11755
12174
  return recipe.getReferencedIds().length === 1;
11756
12175
  }
11757
12176
  //#endregion
11758
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
12177
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11759
12178
  function getAllRelatedColumns(ctx, predicate) {
11760
12179
  const columns = new PColumnCollection();
11761
12180
  columns.addColumnProvider(ctx.resultPool);
@@ -11831,7 +12250,7 @@ function discoverIntegrableColumnIds(ctx, rootColumns) {
11831
12250
  }
11832
12251
  }
11833
12252
  //#endregion
11834
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
12253
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11835
12254
  function isHiddenFromGraphColumn(column) {
11836
12255
  return !!readAnnotationJson(column, Annotation.HideDataFromGraphs);
11837
12256
  }
@@ -11860,12 +12279,12 @@ function createPFrameForGraphs(ctx, blockColumns) {
11860
12279
  }));
11861
12280
  }
11862
12281
  //#endregion
11863
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/dataset_selection.js
12282
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/dataset_selection.js
11864
12283
  function isDatasetSelection(value) {
11865
12284
  return typeof value === "object" && value !== null && value.__isDatasetSelection === "v1" && "primary" in value;
11866
12285
  }
11867
12286
  //#endregion
11868
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/filter_discovery.js
12287
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/filter_discovery.js
11869
12288
  /**
11870
12289
  * Matches columns annotated `pl7.app/isSubset: "true"` whose axes ⊆ anchor axes.
11871
12290
  *
@@ -11917,7 +12336,7 @@ function buildRefMap(entries) {
11917
12336
  return new Map(entries.map((e) => [(0, import_canonicalize.default)(e.ref), e.ref]));
11918
12337
  }
11919
12338
  //#endregion
11920
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/enrichment_discovery.js
12339
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/enrichment_discovery.js
11921
12340
  /**
11922
12341
  * Linker-reached hits attached to the anchor primary. Drops zero-hop variants
11923
12342
  * (filters / the primary itself) and structural hits (subset, linker, label
@@ -11977,7 +12396,7 @@ function enrichmentVariantsToRefs(variants, labelOptions) {
11977
12396
  });
11978
12397
  }
11979
12398
  //#endregion
11980
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/build_dataset_options.js
12399
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/build_dataset_options.js
11981
12400
  function toPredicate(opt) {
11982
12401
  if (opt === void 0) return () => true;
11983
12402
  return typeof opt === "function" ? opt : multiColumnSelectorsToPredicate(opt);
@@ -11991,7 +12410,7 @@ function toPredicate(opt) {
11991
12410
  function buildDatasetOptions(ctx, opts) {
11992
12411
  const primaryPredicate = toPredicate(opts?.primary);
11993
12412
  const filterPredicate = toPredicate(opts?.filter);
11994
- const options = ctx.resultPool.getOptions(primaryPredicate, { refsWithEnrichments: true });
12413
+ const options = ctx.resultPool.getOptions((spec) => isPColumnSpec(spec) && primaryPredicate(spec), { refsWithEnrichments: opts?.requireEnrichments ?? true });
11995
12414
  if (options.length === 0) return [];
11996
12415
  const refMap = buildRefMap(ctx.resultPool.getSpecs().entries);
11997
12416
  const withEnrichments = opts?.withEnrichments ?? false;
@@ -12027,7 +12446,7 @@ function buildDatasetOptions(ctx, opts) {
12027
12446
  });
12028
12447
  }
12029
12448
  //#endregion
12030
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/filters/traverse.js
12449
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/filters/traverse.js
12031
12450
  /**
12032
12451
  * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.
12033
12452
  *
@@ -12066,7 +12485,7 @@ function collectFilterSpecColumns(filter) {
12066
12485
  });
12067
12486
  }
12068
12487
  //#endregion
12069
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
12488
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
12070
12489
  /** Converts a QueryColumnId object into a SpecQueryExpression reference. */
12071
12490
  function resolveColumnRef(col) {
12072
12491
  return col.type === "axis" ? {
@@ -12453,7 +12872,7 @@ function isEmpty(value) {
12453
12872
  return true;
12454
12873
  }
12455
12874
  //#endregion
12456
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/filters/distill.js
12875
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/filters/distill.js
12457
12876
  /**
12458
12877
  * Strips non-FilterSpec metadata (whitelist approach) and removes
12459
12878
  * unfilled leaves (type is undefined or any required field is undefined).
@@ -12558,7 +12977,7 @@ const REQUIRED_KEYS_BY_TYPE = {
12558
12977
  greaterThanColumnOrEqual: ["column", "rhs"]
12559
12978
  };
12560
12979
  //#endregion
12561
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12980
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12562
12981
  /** Upgrade PlDataTableStateV2 to the latest version */
12563
12982
  function upgradePlDataTableStateV2(state) {
12564
12983
  if (!state) return createPlDataTableStateV2();
@@ -12576,6 +12995,7 @@ function upgradePlDataTableStateV2(state) {
12576
12995
  if (state.version === 5) state = migrateV5toV6(state);
12577
12996
  if (state.version === 6) state = migrateV6toV7(state);
12578
12997
  if (state.version === 7) state = migrateV7toV8(state);
12998
+ if (state.version === 8) state = migrateV8toV9(state);
12579
12999
  return state;
12580
13000
  }
12581
13001
  /** Migrate v5 to v6: unwrap `{source, labeled}` colIds in gridState. */
@@ -12823,7 +13243,7 @@ function createDefaultPTableParams() {
12823
13243
  }
12824
13244
  function createPlDataTableStateV2() {
12825
13245
  return {
12826
- version: 8,
13246
+ version: 9,
12827
13247
  stateCache: [],
12828
13248
  pTableParams: createDefaultPTableParams()
12829
13249
  };
@@ -12915,8 +13335,152 @@ function parseLegacyLeafColumn(s) {
12915
13335
  if (t !== "axis" && t !== "column") return void 0;
12916
13336
  return parsed;
12917
13337
  }
13338
+ function migrateV8toV9(state) {
13339
+ return {
13340
+ version: 9,
13341
+ stateCache: state.stateCache.map((entry) => ({
13342
+ ...entry,
13343
+ gridState: upgradeGridStateColumnIds(entry.gridState),
13344
+ filtersState: upgradeFilterColumnIds(entry.filtersState),
13345
+ defaultFiltersState: upgradeFilterColumnIds(entry.defaultFiltersState)
13346
+ })),
13347
+ pTableParams: upgradeParamsColumnIds(state.pTableParams)
13348
+ };
13349
+ }
13350
+ /** Keys a pre-rework discovered column id could carry; it had no marker. */
13351
+ const LEGACY_DISCOVERED_KEYS = /* @__PURE__ */ new Set([
13352
+ "column",
13353
+ "path",
13354
+ "columnQualifications",
13355
+ "queriesQualifications"
13356
+ ]);
13357
+ function isLegacyDiscoveredKey(value) {
13358
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
13359
+ if (!Object.keys(value).every((key) => LEGACY_DISCOVERED_KEYS.has(key))) return false;
13360
+ const { column, path } = value;
13361
+ if (typeof column !== "string") return false;
13362
+ if (path === void 0) return true;
13363
+ return Array.isArray(path) && path.every((item) => typeof item === "object" && item !== null && item.type === "linker" && typeof item.column === "string");
13364
+ }
13365
+ /**
13366
+ * A stored column id in its current form: unchanged when already current,
13367
+ * rewritten when it is a pre-rework discovered id, `undefined` when it cannot be
13368
+ * carried over (a pre-rework anchored or filtered id, or not an id at all).
13369
+ */
13370
+ function upgradeLegacyColumnId(id) {
13371
+ const key = parseJsonSafely(id);
13372
+ if (isColumnUniversalKey(key)) return id;
13373
+ if (!isLegacyDiscoveredKey(key)) return void 0;
13374
+ const column = upgradeLegacyColumnId(key.column);
13375
+ if (column === void 0) return void 0;
13376
+ const path = [];
13377
+ for (const item of key.path ?? []) {
13378
+ const linker = upgradeLegacyColumnId(item.column);
13379
+ if (linker === void 0) return void 0;
13380
+ path.push({
13381
+ type: "linker",
13382
+ column: linker
13383
+ });
13384
+ }
13385
+ const hasQualifications = (key.columnQualifications?.length ?? 0) > 0 || Object.keys(key.queriesQualifications ?? {}).length > 0;
13386
+ if (path.length === 0 && !hasQualifications) return column;
13387
+ return stringifyColumnDiscoveredId({
13388
+ column,
13389
+ path,
13390
+ columnQualifications: key.columnQualifications,
13391
+ queriesQualifications: key.queriesQualifications
13392
+ });
13393
+ }
13394
+ function upgradeColumnRef(ref) {
13395
+ if (ref.type !== "column") return ref;
13396
+ const id = upgradeLegacyColumnId(ref.id);
13397
+ return id === void 0 ? void 0 : {
13398
+ type: "column",
13399
+ id
13400
+ };
13401
+ }
13402
+ function upgradeParamsColumnIds(params) {
13403
+ if (params.sourceId === null) return params;
13404
+ const hiddenColIds = params.hiddenColIds === null ? null : params.hiddenColIds.flatMap((ref) => upgradeColumnRef(ref) ?? []);
13405
+ return {
13406
+ ...params,
13407
+ hiddenColIds,
13408
+ sorting: params.sorting === null ? null : upgradeSorting(params.sorting),
13409
+ filters: upgradeFilterColumnIds(params.filters),
13410
+ defaultFilters: upgradeFilterColumnIds(params.defaultFilters)
13411
+ };
13412
+ }
13413
+ /** `[]` is the user's cleared sorting and stays. A sorting emptied by dropped
13414
+ * entries falls back to the default (`null`) instead of reading as cleared. */
13415
+ function upgradeSorting(sorting) {
13416
+ if (sorting.length === 0) return sorting;
13417
+ const kept = sorting.flatMap((entry) => {
13418
+ const column = upgradeColumnRef(entry.column);
13419
+ return column === void 0 ? [] : [{
13420
+ ...entry,
13421
+ column
13422
+ }];
13423
+ });
13424
+ return kept.length === 0 ? null : kept;
13425
+ }
13426
+ function upgradeGridColId(colId) {
13427
+ const parsed = parseJsonSafely(colId);
13428
+ if (typeof parsed !== "object" || parsed === null || !("type" in parsed) || !("id" in parsed)) return colId;
13429
+ const ref = upgradeColumnRef(parsed);
13430
+ if (ref === void 0) return void 0;
13431
+ return ref === parsed ? colId : canonicalizeJson(ref);
13432
+ }
13433
+ function upgradeGridStateColumnIds(gridState) {
13434
+ const upgradeAll = (colIds) => colIds.flatMap((colId) => upgradeGridColId(colId) ?? []);
13435
+ return {
13436
+ ...gridState,
13437
+ ...gridState.columnOrder && { columnOrder: { orderedColIds: upgradeAll(gridState.columnOrder.orderedColIds) } },
13438
+ ...gridState.sort && { sort: { sortModel: gridState.sort.sortModel.flatMap((s) => {
13439
+ const colId = upgradeGridColId(s.colId);
13440
+ return colId === void 0 ? [] : [{
13441
+ ...s,
13442
+ colId
13443
+ }];
13444
+ }) } },
13445
+ ...gridState.columnVisibility && { columnVisibility: { hiddenColIds: upgradeAll(gridState.columnVisibility.hiddenColIds) } }
13446
+ };
13447
+ }
13448
+ function upgradeFilterColumnIds(node) {
13449
+ if (node === null) return null;
13450
+ const result = upgradeFilterNode(node);
13451
+ return result === void 0 ? null : result;
13452
+ }
13453
+ /** Rewrites the column ids in a filter tree. A leaf whose id cannot be carried
13454
+ * over is dropped, and a group left empty with it. */
13455
+ function upgradeFilterNode(node) {
13456
+ if (!node || typeof node !== "object") return void 0;
13457
+ const n = node;
13458
+ if (n.type === "and" || n.type === "or") {
13459
+ const kept = (n.filters ?? []).map(upgradeFilterNode).filter((f) => f !== void 0);
13460
+ if (kept.length === 0) return void 0;
13461
+ return {
13462
+ ...n,
13463
+ filters: kept
13464
+ };
13465
+ }
13466
+ if (n.type === "not") {
13467
+ const inner = upgradeFilterNode(n.filter);
13468
+ return inner === void 0 ? void 0 : {
13469
+ ...n,
13470
+ filter: inner
13471
+ };
13472
+ }
13473
+ const leaf = { ...n };
13474
+ for (const field of ["column", "rhs"]) {
13475
+ if (!(field in leaf)) continue;
13476
+ const ref = upgradeColumnRef(leaf[field]);
13477
+ if (ref === void 0) return void 0;
13478
+ leaf[field] = ref;
13479
+ }
13480
+ return leaf;
13481
+ }
12918
13482
  //#endregion
12919
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
13483
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
12920
13484
  /** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */
12921
13485
  function toRuleColumn(col) {
12922
13486
  return {
@@ -13010,11 +13574,12 @@ function deriveAllLabels(options) {
13010
13574
  return deriveDistinctLabels(columns.map((c) => ({
13011
13575
  spec: c.spec,
13012
13576
  linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),
13013
- qualifications: c.qualifications
13577
+ qualifications: c.qualifications,
13578
+ marker: c.marker
13014
13579
  })), deriveLabelsOptions).reduce((acc, label, index) => (acc[columns[index].id] = label, acc), {});
13015
13580
  }
13016
13581
  //#endregion
13017
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
13582
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
13018
13583
  /**
13019
13584
  * Assemble a ptable def directly from recipes. Each secondary recipe is its own
13020
13585
  * outer-joined subtree: `getQuery()` encodes its linker chain, and its
@@ -13078,7 +13643,7 @@ function columnToJoinEntry(col, qualifications) {
13078
13643
  };
13079
13644
  }
13080
13645
  //#endregion
13081
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13646
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13082
13647
  function createColumnResolver(columns) {
13083
13648
  const axisIds = [];
13084
13649
  for (const c of columns) for (const ax of c.getSpec().axesSpec) axisIds.push(getAxisId(ax));
@@ -13091,7 +13656,8 @@ function createColumnResolver(columns) {
13091
13656
  }
13092
13657
  return (ref) => {
13093
13658
  if (ref.type === "axis") return axisIds.some((a) => matchAxisId(ref.id, a)) ? ref : void 0;
13094
- const hit = byFullId.get(ref.id) ?? byPObjectId.get(extractPObjectId(ref.id));
13659
+ const pid = tryExtractPObjectId(ref.id);
13660
+ const hit = byFullId.get(ref.id) ?? (pid === void 0 ? void 0 : byPObjectId.get(pid));
13095
13661
  if (hit === void 0) return void 0;
13096
13662
  return {
13097
13663
  type: "column",
@@ -13099,8 +13665,17 @@ function createColumnResolver(columns) {
13099
13665
  };
13100
13666
  };
13101
13667
  }
13668
+ /** {@link extractPObjectId} for a stored reference: an id it cannot parse resolves to
13669
+ * nothing, so the one entry is dropped instead of failing the whole table. */
13670
+ function tryExtractPObjectId(id) {
13671
+ try {
13672
+ return extractPObjectId(id);
13673
+ } catch {
13674
+ return;
13675
+ }
13676
+ }
13102
13677
  //#endregion
13103
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13678
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13104
13679
  /**
13105
13680
  * Discover columns from sources/anchors and split them into primary
13106
13681
  * (direct anchor hits — zero-hop, query is a bare column) and secondary
@@ -13146,7 +13721,7 @@ function discoverLabelColumns(ctx, primary) {
13146
13721
  }).getColumns();
13147
13722
  }
13148
13723
  //#endregion
13149
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13724
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.88.16/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13150
13725
  function createPlDataTableV3(ctx, options) {
13151
13726
  const state = upgradePlDataTableStateV2(options.tableState);
13152
13727
  const primaryJoinType = options.primaryJoinType ?? "full";
@@ -13155,8 +13730,13 @@ function createPlDataTableV3(ctx, options) {
13155
13730
  const { primary, secondary } = resolved;
13156
13731
  if (primary.length === 0) return void 0;
13157
13732
  const { direct, linked } = splitByTopology(secondary);
13733
+ const labelable = [...primary, ...secondary].map(toLabelableColumn);
13734
+ const linkHints = collectLinkHints(labelable);
13158
13735
  const derivedLabels = deriveAllLabels({
13159
- columns: [...primary, ...secondary].filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),
13736
+ columns: labelable.filter((c) => !isColumnHidden(c.spec)).map((c) => ({
13737
+ ...c,
13738
+ marker: linkHints.get(c.id)
13739
+ })),
13160
13740
  deriveLabelsOptions: {
13161
13741
  includeNativeLabel: true,
13162
13742
  ...options.labelsOptions
@@ -13229,6 +13809,7 @@ function createPlDataTableV3(ctx, options) {
13229
13809
  ],
13230
13810
  primaryColumns: primary,
13231
13811
  derivedLabels,
13812
+ linkHints,
13232
13813
  visibilityByColId,
13233
13814
  orderByColId
13234
13815
  });
@@ -13270,6 +13851,15 @@ function splitByTopology(columns) {
13270
13851
  function collectLinkerSnapshots(linked) {
13271
13852
  return uniqueBy(linked.flatMap((c) => collectLinkerColumns(c)), (c) => c.id);
13272
13853
  }
13854
+ /** Link icon hover text per column, for columns reached through at least one peer link. */
13855
+ function collectLinkHints(columns) {
13856
+ if (!columns.some((c) => c.linkerPath?.length)) return /* @__PURE__ */ new Map();
13857
+ const datasetAxes = getResultPoolDatasetAxes();
13858
+ return new Map(columns.flatMap((c) => {
13859
+ const links = findPeerLinks(c.linkerPath?.map((step) => step.linker.spec) ?? [], datasetAxes);
13860
+ return links.length > 0 ? [[c.id, describePeerLinks(links)]] : [];
13861
+ }));
13862
+ }
13273
13863
  function toLabelableColumn(col) {
13274
13864
  return {
13275
13865
  id: col.id,
@@ -13290,7 +13880,7 @@ function toLabelableColumn(col) {
13290
13880
  * The UI overlays this onto the engine-emitted specs at render time.
13291
13881
  */
13292
13882
  function buildColumnsMeta(params) {
13293
- const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;
13883
+ const { fullColumns, visibleColumns, primaryColumns, derivedLabels, linkHints } = params;
13294
13884
  const { visibilityByColId, orderByColId } = params;
13295
13885
  const visibleStatus = buildDataStatusMap(visibleColumns);
13296
13886
  const columns = fullColumns.reduce((acc, c) => {
@@ -13299,7 +13889,8 @@ function buildColumnsMeta(params) {
13299
13889
  label: derivedLabels[c.id],
13300
13890
  visibility: getEffectiveVisibility(rc, visibilityByColId),
13301
13891
  order: getOrderPriority(rc, orderByColId),
13302
- status: visibleStatus[c.id]
13892
+ status: visibleStatus[c.id],
13893
+ linkHint: linkHints.get(c.id)
13303
13894
  };
13304
13895
  return acc;
13305
13896
  }, {});
@@ -13484,6 +14075,7 @@ const PlErrorLike = objectType({
13484
14075
  type: literalType("PlError"),
13485
14076
  name: stringType(),
13486
14077
  message: stringType(),
14078
+ /** The message with all details needed for SDK developers. */
13487
14079
  fullMessage: stringType().optional(),
13488
14080
  stack: stringType().optional()
13489
14081
  }).extend({
@@ -13511,9 +14103,9 @@ const ErrorShape = objectType({
13511
14103
  //#endregion
13512
14104
  //#region ../kind/dist/package.js
13513
14105
  var name = "@platforma-open/milaboratories.antibody-variant-designer.kind";
13514
- var version = "1.0.0";
14106
+ var version = "1.0.1";
13515
14107
  //#endregion
13516
- //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/params.js
14108
+ //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.1/node_modules/@platforma-sdk/block-kind/dist/params.js
13517
14109
  /**
13518
14110
  * Establish that a value is an object whose fields a kind can read — the half of a params
13519
14111
  * check every kind needs and no two kinds differ on.
@@ -13569,7 +14161,7 @@ function describe(value) {
13569
14161
  return `a ${typeof value} (${JSON.stringify(value) ?? String(value)})`;
13570
14162
  }
13571
14163
  //#endregion
13572
- //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/index.js
14164
+ //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.1/node_modules/@platforma-sdk/block-kind/dist/index.js
13573
14165
  /**
13574
14166
  * Define a block kind.
13575
14167
  *