@platforma-open/milaboratories.repertoire-mutation-heatmap.block 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -188,14 +188,14 @@ function mapChartStates(data, rewrite) {
188
188
  };
189
189
  }
190
190
  //#endregion
191
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/plugin_handle.js
191
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/plugin_handle.js
192
192
  const PLUGIN_OUTPUT_PREFIX = "plugin-output#";
193
193
  /** Construct the output key for a plugin output in the block outputs map. */
194
194
  function pluginOutputKey(handle, outputKey) {
195
195
  return `${PLUGIN_OUTPUT_PREFIX}${handle}#${outputKey}`;
196
196
  }
197
197
  //#endregion
198
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/block_storage.js
198
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/block_storage.js
199
199
  /**
200
200
  * Discriminator key for BlockStorage format detection.
201
201
  * This unique hash-based key identifies data as BlockStorage vs legacy formats.
@@ -4012,7 +4012,7 @@ objectType({
4012
4012
  content: stringType()
4013
4013
  });
4014
4014
  //#endregion
4015
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
4015
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
4016
4016
  /**
4017
4017
  * Compose a {@link BlockKindReference} from a kind's `name`/`version`.
4018
4018
  *
@@ -4028,7 +4028,7 @@ objectType({
4028
4028
  to: numberType().min(1)
4029
4029
  });
4030
4030
  //#endregion
4031
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/util.js
4031
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/util.js
4032
4032
  function assertNever(x) {
4033
4033
  throw new Error("Unexpected object: " + x);
4034
4034
  }
@@ -4040,7 +4040,7 @@ function uniqueBy(array, makeId) {
4040
4040
  return [...new Map(array.map((e) => [makeId(e), e])).values()];
4041
4041
  }
4042
4042
  //#endregion
4043
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
4043
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
4044
4044
  /**
4045
4045
  * Type guard function that checks if the given value is a valid DataInfo.
4046
4046
  *
@@ -4229,7 +4229,7 @@ function entriesToDataInfo(dataInfoEntries) {
4229
4229
  }
4230
4230
  }
4231
4231
  //#endregion
4232
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4232
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4233
4233
  var ServiceError = class extends Error {
4234
4234
  name = "ServiceError";
4235
4235
  };
@@ -4253,7 +4253,7 @@ function ensureError(value) {
4253
4253
  return new Error(stringifyValue(value));
4254
4254
  }
4255
4255
  //#endregion
4256
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4256
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4257
4257
  var import_canonicalize = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
4258
4258
  module.exports = function serialize(object) {
4259
4259
  if (typeof object === "number" && isNaN(object)) throw new Error("NaN is not allowed");
@@ -4286,7 +4286,7 @@ function parseJsonSafely(value, fallback) {
4286
4286
  }
4287
4287
  }
4288
4288
  //#endregion
4289
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4289
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4290
4290
  function readMetadata(metadata, key) {
4291
4291
  return metadata?.[key];
4292
4292
  }
@@ -4614,7 +4614,7 @@ function matchAxisId(query, target) {
4614
4614
  return query.name === target.name && matchDomain$1(query.domain, target.domain) && matchDomain$1(query.contextDomain, target.contextDomain);
4615
4615
  }
4616
4616
  //#endregion
4617
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4617
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4618
4618
  const BOOLEAN_TYPES = /* @__PURE__ */ new Set([
4619
4619
  "numericComparison",
4620
4620
  "stringEquals",
@@ -4719,7 +4719,7 @@ function collectSpecQueryColumns(query) {
4719
4719
  return result;
4720
4720
  }
4721
4721
  //#endregion
4722
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4722
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4723
4723
  function mapPTableDef(def, cb) {
4724
4724
  return {
4725
4725
  ...def,
@@ -4762,7 +4762,7 @@ function mapJoinEntry(entry, cb) {
4762
4762
  }
4763
4763
  }
4764
4764
  //#endregion
4765
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4765
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4766
4766
  function getPTableColumnId(spec) {
4767
4767
  switch (spec.type) {
4768
4768
  case "axis": return {
@@ -4776,7 +4776,7 @@ function getPTableColumnId(spec) {
4776
4776
  }
4777
4777
  }
4778
4778
  //#endregion
4779
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4779
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4780
4780
  function stringifyColumnFilteredId(key) {
4781
4781
  return canonicalizeJson(createColumnFilteredKey(key));
4782
4782
  }
@@ -4809,7 +4809,7 @@ function applyAxisFilters(spec, axisFilters) {
4809
4809
  };
4810
4810
  }
4811
4811
  //#endregion
4812
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4812
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4813
4813
  function isPObjectId(value) {
4814
4814
  if (typeof value !== "string") return false;
4815
4815
  return isPObjectKey(parseJsonSafely(value));
@@ -4844,6 +4844,10 @@ function isGlobalPObjectKey(value) {
4844
4844
  if (typeof value !== "object" || value === null) return false;
4845
4845
  return "__isRef" in value && "blockId" in value && "name" in value;
4846
4846
  }
4847
+ function isGlobalPObjectId(value) {
4848
+ if (typeof value !== "string") return false;
4849
+ return isGlobalPObjectKey(parseJsonSafely(value));
4850
+ }
4847
4851
  function isPObject(obj) {
4848
4852
  return typeof obj === "object" && obj !== null && "id" in obj && "spec" in obj && "data" in obj;
4849
4853
  }
@@ -4931,7 +4935,7 @@ function throwError(v) {
4931
4935
  else throw v;
4932
4936
  }
4933
4937
  //#endregion
4934
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4938
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4935
4939
  function isColumnDiscoveredKey(obj) {
4936
4940
  return typeof obj === "object" && obj !== null && "__isDiscovered" in obj;
4937
4941
  }
@@ -5211,7 +5215,7 @@ function isString(value) {
5211
5215
  return typeof value === "string";
5212
5216
  }
5213
5217
  //#endregion
5214
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5218
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5215
5219
  /**
5216
5220
  * Canonically serializes a column key to a branded string id. Accepts both
5217
5221
  * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}
@@ -5385,7 +5389,7 @@ function extractPObjectId(id) {
5385
5389
  throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);
5386
5390
  }
5387
5391
  //#endregion
5388
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5392
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5389
5393
  function isColumnOverriddenKey(obj) {
5390
5394
  return typeof obj === "object" && obj !== null && "__isOverridden" in obj;
5391
5395
  }
@@ -5507,7 +5511,7 @@ function mergeRecord(a, b) {
5507
5511
  };
5508
5512
  }
5509
5513
  //#endregion
5510
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5514
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5511
5515
  function axisKey(axis) {
5512
5516
  return (0, import_canonicalize.default)(getAxisId(axis));
5513
5517
  }
@@ -5753,7 +5757,7 @@ function isAnchorAxisRef(value) {
5753
5757
  return typeof value === "object" && "anchor" in value;
5754
5758
  }
5755
5759
  //#endregion
5756
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5760
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5757
5761
  /**
5758
5762
  * Determines if an axis ID matches an axis selector.
5759
5763
  *
@@ -5833,8 +5837,53 @@ function legacyColumnSelectorsToPredicate(predicateOrSelectors) {
5833
5837
  if (Array.isArray(predicateOrSelectors)) return (spec) => predicateOrSelectors.some((selector) => isPColumnSpec(spec) && matchPColumn(spec, selector));
5834
5838
  else return (spec) => isPColumnSpec(spec) && matchPColumn(spec, predicateOrSelectors);
5835
5839
  }
5840
+ function matchString(matcher, value) {
5841
+ return matcher.type === "exact" ? value === matcher.value : new RegExp(matcher.value).test(value);
5842
+ }
5843
+ function matchMatcherMap(map, target) {
5844
+ const t = target ?? {};
5845
+ for (const [key, matchers] of Object.entries(map)) {
5846
+ const v = t[key];
5847
+ if (v === void 0) return false;
5848
+ if (!matchers.some((m) => matchString(m, v))) return false;
5849
+ }
5850
+ return true;
5851
+ }
5852
+ function matchMultiAxis(selector, axis) {
5853
+ if (selector.type !== void 0 && !selector.type.includes(axis.type)) return false;
5854
+ if (selector.name !== void 0 && !selector.name.some((m) => matchString(m, axis.name))) return false;
5855
+ if (selector.domain !== void 0 && !matchMatcherMap(selector.domain, axis.domain)) return false;
5856
+ if (selector.contextDomain !== void 0 && !matchMatcherMap(selector.contextDomain, axis.contextDomain)) return false;
5857
+ return true;
5858
+ }
5859
+ /** Match a {@link PColumnSpec} against a {@link MultiColumnSelector}. */
5860
+ function matchMultiColumnSelector(spec, selector) {
5861
+ if (selector.type !== void 0 && !selector.type.includes(spec.valueType)) return false;
5862
+ if (selector.name !== void 0 && !selector.name.some((m) => matchString(m, spec.name))) return false;
5863
+ if (selector.domain !== void 0 && !matchMatcherMap(selector.domain, spec.domain)) return false;
5864
+ if (selector.contextDomain !== void 0 && !matchMatcherMap(selector.contextDomain, spec.contextDomain)) return false;
5865
+ if (selector.annotations !== void 0 && !matchMatcherMap(selector.annotations, spec.annotations)) return false;
5866
+ if (selector.axes !== void 0) {
5867
+ const columnAxes = spec.axesSpec.map(getAxisId);
5868
+ if (selector.partialAxesMatch ?? true) {
5869
+ for (const axisSelector of selector.axes) if (!columnAxes.some((axis) => matchMultiAxis(axisSelector, axis))) return false;
5870
+ } else {
5871
+ if (columnAxes.length !== selector.axes.length) return false;
5872
+ for (let i = 0; i < selector.axes.length; i++) if (!matchMultiAxis(selector.axes[i], columnAxes[i])) return false;
5873
+ }
5874
+ }
5875
+ return true;
5876
+ }
5877
+ /**
5878
+ * Convert a {@link MultiColumnSelector} (or array; selectors OR-ed) to a predicate.
5879
+ * Non-PColumn specs always return false.
5880
+ */
5881
+ function multiColumnSelectorsToPredicate(selectors) {
5882
+ const arr = Array.isArray(selectors) ? selectors : [selectors];
5883
+ return (spec) => isPColumnSpec(spec) && arr.some((sel) => matchMultiColumnSelector(spec, sel));
5884
+ }
5836
5885
  //#endregion
5837
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5886
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5838
5887
  function deriveNativeId(spec) {
5839
5888
  const result = {
5840
5889
  kind: spec.kind,
@@ -5846,7 +5895,7 @@ function deriveNativeId(spec) {
5846
5895
  return (0, import_canonicalize.default)(result);
5847
5896
  }
5848
5897
  //#endregion
5849
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5898
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5850
5899
  var LinkerMap = class LinkerMap {
5851
5900
  /** Graph of linkers connected by axes (single or grouped by parents) */
5852
5901
  data;
@@ -6023,7 +6072,7 @@ var LinkerMap = class LinkerMap {
6023
6072
  }
6024
6073
  };
6025
6074
  //#endregion
6026
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
6075
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
6027
6076
  /**
6028
6077
  * Required PFrames version. Bump this in lockstep with the `@milaboratories/pframes-rs-*`
6029
6078
  * version in `pnpm-workspace.yaml` so blocks built against the new SDK refuse to load on
@@ -6065,8 +6114,17 @@ function withEnrichments(ref, requireEnrichments = true) {
6065
6114
  return rest;
6066
6115
  }
6067
6116
  }
6117
+ function createEnrichmentRef(hit, options = {}) {
6118
+ const { path, qualifications } = options;
6119
+ return {
6120
+ __isEnrichment: "v1",
6121
+ hit,
6122
+ ...path !== void 0 && path.length > 0 ? { path } : {},
6123
+ ...qualifications !== void 0 && qualifications.length > 0 ? { qualifications } : {}
6124
+ };
6125
+ }
6068
6126
  //#endregion
6069
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
6127
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
6070
6128
  function mapValueInVOE(voe, cb) {
6071
6129
  return voe.ok ? {
6072
6130
  ok: true,
@@ -6074,7 +6132,7 @@ function mapValueInVOE(voe, cb) {
6074
6132
  } : voe;
6075
6133
  }
6076
6134
  //#endregion
6077
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
6135
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
6078
6136
  /** Well-known resource type names used across the platform. */
6079
6137
  const ResourceTypeName = {
6080
6138
  StreamManager: "StreamManager",
@@ -6123,7 +6181,7 @@ const ResourceTypeName = {
6123
6181
  SharedEnvelope: "SharedEnvelope"
6124
6182
  };
6125
6183
  //#endregion
6126
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
6184
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
6127
6185
  const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
6128
6186
  const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
6129
6187
  const typeMap = /* @__PURE__ */ new Map();
@@ -6162,7 +6220,7 @@ const { service, isNodeService, isWasmService, isMainService, getServiceKind, ge
6162
6220
  };
6163
6221
  })();
6164
6222
  //#endregion
6165
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
6223
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
6166
6224
  const Services = {
6167
6225
  PFrameSpec: service()({
6168
6226
  type: "wasm",
@@ -6256,7 +6314,7 @@ function resolveRequiredServices(flags) {
6256
6314
  }
6257
6315
  Object.fromEntries(Object.keys(Services).map((key) => [`requires${key}`, true]));
6258
6316
  //#endregion
6259
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6317
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6260
6318
  function buildMethodMap(pick) {
6261
6319
  const result = {};
6262
6320
  for (const id of Object.values(Services)) result[id] = [...pick(id)];
@@ -6265,7 +6323,7 @@ function buildMethodMap(pick) {
6265
6323
  buildMethodMap(getServiceUiMethods);
6266
6324
  buildMethodMap(getServiceModelMethods);
6267
6325
  //#endregion
6268
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6326
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6269
6327
  /** Resource types that hold column collections — DFS stops here and collects. */
6270
6328
  const COLLECT_TYPES = [ResourceTypeName.PFrame];
6271
6329
  /** Resource types DFS descends through when looking for PFrames. */
@@ -6373,7 +6431,7 @@ function indexPoolBlock(block) {
6373
6431
  return result;
6374
6432
  }
6375
6433
  //#endregion
6376
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6434
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6377
6435
  /**
6378
6436
  * Id-index over a set of {@link ColumnEntriesProvider}s. Sole job:
6379
6437
  * {@link PObjectId} → {@link LeafEntry}. Generic over the accessor flavour, so
@@ -6410,7 +6468,7 @@ var ColumnRegistry = class {
6410
6468
  }
6411
6469
  };
6412
6470
  //#endregion
6413
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6471
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6414
6472
  /**
6415
6473
  * Two-track dedup over an item stream keyed by `ColumnUniversalId`:
6416
6474
  *
@@ -6451,7 +6509,7 @@ function dedupColumns(items, getId, getSpec) {
6451
6509
  return out;
6452
6510
  }
6453
6511
  //#endregion
6454
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6512
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6455
6513
  /**
6456
6514
  * Generic entries provider over a single accessor root. Walks `<root>` once
6457
6515
  * from the supplied `rootPath`, builds an id → {@link LeafEntry} map and
@@ -6508,7 +6566,7 @@ var ResultPoolEntriesProvider = class {
6508
6566
  }
6509
6567
  };
6510
6568
  //#endregion
6511
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6569
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6512
6570
  /**
6513
6571
  * Whether `value` is a reference in the readable spelling.
6514
6572
  *
@@ -6577,7 +6635,7 @@ function expandTemplatePlRef(ref) {
6577
6635
  };
6578
6636
  }
6579
6637
  //#endregion
6580
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.52.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6638
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.53.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6581
6639
  /**
6582
6640
  * Point every column identifier in a block's params at the blocks of the project being built.
6583
6641
  *
@@ -6637,7 +6695,7 @@ function relocateBlockIds(params, blockIds) {
6637
6695
  return walk(params);
6638
6696
  }
6639
6697
  //#endregion
6640
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/block_migrations.js
6698
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/block_migrations.js
6641
6699
  /** Create a DataVersioned wrapper with correct shape */
6642
6700
  function makeVersionedData(version, data) {
6643
6701
  return {
@@ -7215,7 +7273,7 @@ var DataModel = class DataModel {
7215
7273
  }
7216
7274
  };
7217
7275
  //#endregion
7218
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/internal.js
7276
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/internal.js
7219
7277
  /** Utility code helping to identify whether the code is running in actual UI environment */
7220
7278
  function isInUI() {
7221
7279
  return typeof globalThis.getPlatforma !== "undefined" || typeof globalThis.platforma !== "undefined";
@@ -7285,7 +7343,7 @@ function registerFutureAwait(handle, onResolve) {
7285
7343
  futureResolves.get(handle).push(onResolve);
7286
7344
  }
7287
7345
  //#endregion
7288
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7346
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7289
7347
  /**
7290
7348
  * All facade callback names as constants.
7291
7349
  * These are the source of truth - the interface is derived from these.
@@ -7323,7 +7381,7 @@ function registerFacadeCallbacks(callbacks) {
7323
7381
  for (const key of Object.values(BlockStorageFacadeCallbacks)) tryRegisterCallback(key, callbacks[key]);
7324
7382
  }
7325
7383
  //#endregion
7326
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/services/block_services.js
7384
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/services/block_services.js
7327
7385
  /**
7328
7386
  * Services required by all V3 blocks by default.
7329
7387
  * Edit this when a new service should be available to all blocks.
@@ -7339,7 +7397,7 @@ const BLOCK_SERVICE_FLAGS = {
7339
7397
  };
7340
7398
  resolveRequiredServices(BLOCK_SERVICE_FLAGS);
7341
7399
  //#endregion
7342
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/future.js
7400
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/future.js
7343
7401
  var FutureRef = class FutureRef {
7344
7402
  handle;
7345
7403
  postProcess;
@@ -7367,7 +7425,7 @@ var FutureRef = class FutureRef {
7367
7425
  }
7368
7426
  };
7369
7427
  //#endregion
7370
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/accessor.js
7428
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/accessor.js
7371
7429
  function ifDef(value, cb) {
7372
7430
  return value === void 0 ? void 0 : cb(value);
7373
7431
  }
@@ -7617,11 +7675,11 @@ var TreeNodeAccessor = class TreeNodeAccessor {
7617
7675
  }
7618
7676
  };
7619
7677
  //#endregion
7620
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/internal.js
7678
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/internal.js
7621
7679
  const MainAccessorName = "main";
7622
7680
  const StagingAccessorName = "staging";
7623
7681
  //#endregion
7624
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7682
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7625
7683
  function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7626
7684
  const sortedFilters = [...axisFilters].sort((a, b) => b[0] - a[0]);
7627
7685
  const { type } = dataInfoEntries;
@@ -7685,7 +7743,7 @@ function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7685
7743
  }
7686
7744
  }
7687
7745
  //#endregion
7688
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7746
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7689
7747
  /**
7690
7748
  * Structural postfix derivation for linked columns (phase 2 of `deriveDistinctLabels`).
7691
7749
  *
@@ -7868,7 +7926,7 @@ function derivePostfixes(entries, format = defaultLinkerFormatter) {
7868
7926
  });
7869
7927
  }
7870
7928
  //#endregion
7871
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7929
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7872
7930
  const DISTANCE_PENALTY = .001;
7873
7931
  const LABEL_TYPE = "__LABEL__";
7874
7932
  const LABEL_TYPE_FULL = "__LABEL__@1";
@@ -7910,6 +7968,7 @@ function deriveStems(values, options) {
7910
7968
  if (labelForced) forcedSet.add(LABEL_TYPE_FULL);
7911
7969
  const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);
7912
7970
  const build = (typeSet, force) => buildLabels(records, typeSet, forceTraceElements, separator, force);
7971
+ const finalize = (minimized, rendered) => repairBareLabels(rendered, minimized, records, stats, forceTraceElements, separator);
7913
7972
  if (mainTypes.length === 0) {
7914
7973
  if (secondaryTypes.length !== 0) throw new Error("Non-empty secondary types list while main types list is empty.");
7915
7974
  return build(/* @__PURE__ */ new Set([LABEL_TYPE_FULL]), true) ?? throwError("Failed to derive labels using native column labels");
@@ -7923,7 +7982,7 @@ function deriveStems(values, options) {
7923
7982
  const candidateResult = build(currentSet, false);
7924
7983
  if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) {
7925
7984
  const minimized = minimizeTypeSet(currentSet, records, stats, forceTraceElements, forcedSet, separator);
7926
- return repairBareByPresence(build(minimized, false) ?? throwError("Failed to derive unique labels"), minimized, records, stats, forcedSet, forceTraceElements, separator);
7985
+ return finalize(minimized, build(minimized, false) ?? throwError("Failed to derive unique labels"));
7927
7986
  }
7928
7987
  additionalType++;
7929
7988
  if (additionalType >= mainTypes.length) {
@@ -7936,7 +7995,7 @@ function deriveStems(values, options) {
7936
7995
  ...mainTypes,
7937
7996
  ...secondaryTypes
7938
7997
  ]), records, stats, forceTraceElements, forcedSet, separator);
7939
- return repairBareByPresence(build(minimized, true) ?? throwError("Failed to derive unique labels"), minimized, records, stats, forcedSet, forceTraceElements, separator);
7998
+ return finalize(minimized, build(minimized, true) ?? throwError("Failed to derive unique labels"));
7940
7999
  }
7941
8000
  function extractEntryParts(entry) {
7942
8001
  if (!("spec" in entry && typeof entry.spec === "object")) return {
@@ -8101,62 +8160,202 @@ function minimizeTypeSet(typeSet, records, stats, forceTraceElements, forcedSet,
8101
8160
  }
8102
8161
  return result;
8103
8162
  }
8104
- const ABSENT_VALUE = "\0absent";
8105
- /** Whether `fullType`'s rendered value differs across the group (absence counts as a value). */
8106
- function typeDistinguishes(records, group, fullType) {
8107
- const values = /* @__PURE__ */ new Set();
8108
- for (const i of group) {
8109
- const ft = records[i].fullTrace.find((e) => e.fullType === fullType);
8110
- values.add(ft?.label ?? ABSENT_VALUE);
8111
- if (values.size > 1) return true;
8112
- }
8113
- return false;
8114
- }
8115
- /** The highest-importance trace type this row HAS (outside `typeSet`) that sets it apart from its
8116
- * group peers. `undefined` when the row carries nothing distinguishing of its own. */
8117
- function bestDistinguishingType(records, group, row, typeSet, forcedSet, forceTraceElements, stats) {
8118
- return records[row].fullTrace.reduce((best, ft) => {
8119
- if (typeSet.has(ft.fullType) || forcedSet.has(ft.fullType) || forceTraceElements?.has(ft.type)) return best;
8120
- if (!typeDistinguishes(records, group, ft.fullType)) return best;
8121
- const imp = stats.importances.get(ft.fullType) ?? 0;
8122
- return best === void 0 || imp > best.imp ? {
8123
- type: ft.fullType,
8124
- imp
8125
- } : best;
8126
- }, void 0)?.type;
8127
- }
8128
- /**
8129
- * Un-bare columns distinguished only "by absence". After minimization a column can end up with a
8130
- * bare trace zone (only the forced native label) while a peer sharing that same base renders extra
8131
- * tokens — the column reads as unique purely because it LACKS what the peer has. For each such bare
8132
- * column this re-renders JUST that column's label with the highest-importance trace type it actually
8133
- * carries that tells it apart from its peers, so every colliding column is distinguished by a token
8134
- * it HAS rather than by omission.
8135
- *
8136
- * Patches individual labels rather than the shared type set on purpose: the set is global, so adding
8137
- * a type there would also decorate unrelated columns in other groups that happen to carry it. Only
8138
- * bare columns' labels grow (a superset of their previous value), so uniqueness is preserved. Groups
8139
- * are keyed by the base = the label rendered from the forced types alone.
8140
- */
8141
- function repairBareByPresence(labels, minimized, records, stats, forcedSet, forceTraceElements, separator) {
8142
- const base = records.map((r) => renderRecordLabel(r, forcedSet, forceTraceElements, separator));
8143
- const isBare = records.map((r, i) => renderRecordLabel(r, minimized, forceTraceElements, separator) === base[i]);
8144
- const groups = records.reduce((acc, _, i) => acc.set(base[i] ?? "", [...acc.get(base[i] ?? "") ?? [], i]), /* @__PURE__ */ new Map());
8163
+ /**
8164
+ * Repairs labels told apart only by what they lack: in a group with the same shown base, a
8165
+ * member is bare when its shown parts are a strict subset of a peer's. The group is re-labelled
8166
+ * from parts all members carry, or bare members add a hidden part (group-wide when labels stay
8167
+ * unique), whichever keeps the more important distinction; labels stay unique across the list.
8168
+ */
8169
+ function repairBareLabels(labels, minimized, records, stats, forceTraceElements, separator) {
8170
+ const traces = records.map((r) => new Map(r.fullTrace.map((ft) => [ft.fullType, ft.label])));
8171
+ const isQualification = (t) => isSyntheticType(t.split("@")[0]);
8172
+ const depths = records.map((r) => {
8173
+ const steps = r.fullTrace.filter((ft) => ft.fullType !== LABEL_TYPE_FULL && !isQualification(ft.fullType));
8174
+ return new Map(steps.map((ft, idx) => [ft.fullType, steps.length - idx]));
8175
+ });
8176
+ const isForced = (t) => forceTraceElements?.has(t.split("@")[0]) === true;
8177
+ const isDistinctionType = (t) => t !== LABEL_TYPE_FULL && !isQualification(t);
8178
+ const importance = (t) => stats.importances.get(t) ?? 0;
8179
+ const byImportance = (a, b) => importance(b) - importance(a);
8180
+ const render = (i, types) => renderRecordLabel(records[i], types, forceTraceElements, separator);
8181
+ const partKey = (t, l) => `${t}\u0000${l}`;
8182
+ const labelShown = minimized.has(LABEL_TYPE_FULL);
8183
+ const baseTypes = new Set(labelShown ? [LABEL_TYPE_FULL] : []);
8184
+ const qualTypes = [...minimized].filter(isQualification);
8185
+ const groups = /* @__PURE__ */ new Map();
8186
+ records.forEach((_, i) => {
8187
+ const key = render(i, baseTypes) ?? "";
8188
+ const group = groups.get(key);
8189
+ if (group) group.push(i);
8190
+ else groups.set(key, [i]);
8191
+ });
8145
8192
  const patched = [...labels];
8146
- for (const group of groups.values()) {
8147
- if (!group.some((i) => !isBare[i])) continue;
8148
- for (const i of group) {
8149
- if (!isBare[i]) continue;
8150
- const chosen = bestDistinguishingType(records, group, i, minimized, forcedSet, forceTraceElements, stats);
8151
- if (chosen === void 0) continue;
8152
- const withToken = /* @__PURE__ */ new Set([...minimized, chosen]);
8153
- patched[i] = renderRecordLabel(records[i], withToken, forceTraceElements, separator) ?? patched[i];
8154
- }
8193
+ const counts = /* @__PURE__ */ new Map();
8194
+ const addCount = (l, d) => counts.set(l, (counts.get(l) ?? 0) + d);
8195
+ for (const l of patched) addCount(l, 1);
8196
+ const tryApply = (members, next) => {
8197
+ if (new Set(next).size !== members.length) return false;
8198
+ for (const i of members) addCount(patched[i], -1);
8199
+ const clashes = next.some((l) => (counts.get(l) ?? 0) > 0);
8200
+ members.forEach((i, k) => {
8201
+ if (!clashes) patched[i] = next[k];
8202
+ addCount(patched[i], 1);
8203
+ });
8204
+ return !clashes;
8205
+ };
8206
+ for (const [key, group] of groups) {
8207
+ if (group.length < 2) continue;
8208
+ const shown = group.map((i) => [...traces[i]].filter(([t]) => t !== LABEL_TYPE_FULL && (minimized.has(t) || isForced(t))));
8209
+ const partKeys = shown.map((parts) => parts.map(([t, l]) => partKey(t, l)));
8210
+ const sigIndex = /* @__PURE__ */ new Map();
8211
+ const setKeys = [];
8212
+ const setMembers = [];
8213
+ const sigOf = partKeys.map((keys, k) => {
8214
+ const sig = [...keys].sort().join("");
8215
+ let s = sigIndex.get(sig);
8216
+ if (s === void 0) {
8217
+ s = setKeys.length;
8218
+ sigIndex.set(sig, s);
8219
+ setKeys.push(keys);
8220
+ setMembers.push([]);
8221
+ }
8222
+ setMembers[s].push(k);
8223
+ return s;
8224
+ });
8225
+ const setSets = setKeys.map((keys) => new Set(keys));
8226
+ const postings = /* @__PURE__ */ new Map();
8227
+ setKeys.forEach((keys, s) => keys.forEach((p) => {
8228
+ const list = postings.get(p);
8229
+ if (list) list.push(s);
8230
+ else postings.set(p, [s]);
8231
+ }));
8232
+ const withParts = setKeys.map((_, s) => s).filter((s) => setKeys[s].length > 0);
8233
+ const supersetSets = setKeys.map((keys, s) => {
8234
+ if (keys.length === 0) return withParts;
8235
+ const rarest = keys.reduce((a, b) => postings.get(a).length <= postings.get(b).length ? a : b);
8236
+ return postings.get(rarest).filter((t) => t !== s && setSets[t].size > keys.length && keys.every((x) => setSets[t].has(x)));
8237
+ });
8238
+ const bare = group.map((_, k) => supersetSets[sigOf[k]].length > 0);
8239
+ if (!bare.some(Boolean)) continue;
8240
+ const typeCount = /* @__PURE__ */ new Map();
8241
+ for (const i of group) for (const t of traces[i].keys()) typeCount.set(t, (typeCount.get(t) ?? 0) + 1);
8242
+ const isUneven = (t) => (typeCount.get(t) ?? 0) > 0 && typeCount.get(t) < group.length;
8243
+ const unevenMax = Math.max(...[...minimized].filter((t) => isDistinctionType(t) && !isForced(t) && isUneven(t)).map(importance));
8244
+ let sharedLabels;
8245
+ let sharedMax = Number.NEGATIVE_INFINITY;
8246
+ if (labelShown && key !== "") {
8247
+ const shared = [...typeCount].filter(([t, n]) => n === group.length && isDistinctionType(t)).map(([t]) => t).sort(byImportance);
8248
+ const chosen = new Set(baseTypes);
8249
+ const distinctCount = (types) => new Set(group.map((i) => render(i, types) ?? "")).size;
8250
+ let count = distinctCount(chosen);
8251
+ for (const t of shared) {
8252
+ if (count === group.length) break;
8253
+ const next = distinctCount(/* @__PURE__ */ new Set([...chosen, t]));
8254
+ if (next > count) {
8255
+ if (chosen.size === baseTypes.size) sharedMax = importance(t);
8256
+ chosen.add(t);
8257
+ count = next;
8258
+ }
8259
+ }
8260
+ const withTags = /* @__PURE__ */ new Set([...chosen, ...qualTypes]);
8261
+ const complete = group.map((i) => render(i, withTags)).filter((l) => l !== void 0);
8262
+ if (count === group.length && complete.length === group.length && new Set(complete).size === group.length) sharedLabels = complete;
8263
+ }
8264
+ const applyBareFix = () => {
8265
+ const bareMembers = group.filter((_, k) => bare[k]);
8266
+ const oldBare = /* @__PURE__ */ new Map();
8267
+ for (const i of bareMembers) oldBare.set(patched[i], (oldBare.get(patched[i]) ?? 0) + 1);
8268
+ const isFree = (l) => (counts.get(l) ?? 0) - (oldBare.get(l) ?? 0) === 0;
8269
+ const shownTypes = (k) => [
8270
+ ...baseTypes,
8271
+ ...shown[k].map(([t]) => t),
8272
+ ...qualTypes
8273
+ ];
8274
+ const setLabels = /* @__PURE__ */ new Map();
8275
+ const labelsIn = (s) => {
8276
+ let byType = setLabels.get(s);
8277
+ if (byType) return byType;
8278
+ byType = /* @__PURE__ */ new Map();
8279
+ for (const m of setMembers[s]) for (const [t, l] of traces[group[m]]) {
8280
+ const entry = byType.get(t) ?? {
8281
+ labels: /* @__PURE__ */ new Set(),
8282
+ n: 0
8283
+ };
8284
+ entry.labels.add(l);
8285
+ entry.n++;
8286
+ byType.set(t, entry);
8287
+ }
8288
+ setLabels.set(s, byType);
8289
+ return byType;
8290
+ };
8291
+ const someDiffers = (s, u, mine) => {
8292
+ const entry = labelsIn(s).get(u);
8293
+ if (entry === void 0) return mine !== void 0;
8294
+ if (entry.n < setMembers[s].length) return true;
8295
+ return entry.labels.size > 1 || !entry.labels.has(mine ?? "");
8296
+ };
8297
+ const extraDepthsOf = /* @__PURE__ */ new Map();
8298
+ const extraDepths = (s) => {
8299
+ let depthsSet = extraDepthsOf.get(s);
8300
+ if (depthsSet) return depthsSet;
8301
+ depthsSet = new Set(supersetSets[s].flatMap((t) => {
8302
+ const rep = setMembers[t][0];
8303
+ return shown[rep].filter(([u, l]) => !isQualification(u) && !setSets[s].has(partKey(u, l))).map(([u]) => depths[group[rep]].get(u));
8304
+ }));
8305
+ extraDepthsOf.set(s, depthsSet);
8306
+ return depthsSet;
8307
+ };
8308
+ const picks = /* @__PURE__ */ new Map();
8309
+ group.forEach((i, k) => {
8310
+ if (!bare[k]) return;
8311
+ const peers = supersetSets[sigOf[k]];
8312
+ const kindDepths = extraDepths(sigOf[k]);
8313
+ const sameKind = (u) => kindDepths.has(depths[i].get(u)) ? 1 : 0;
8314
+ 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));
8315
+ for (const u of candidates) {
8316
+ const label = render(i, /* @__PURE__ */ new Set([...shownTypes(k), u]));
8317
+ if (label !== void 0 && isFree(label)) {
8318
+ picks.set(i, {
8319
+ type: u,
8320
+ label
8321
+ });
8322
+ break;
8323
+ }
8324
+ }
8325
+ });
8326
+ if (picks.size === 0) return false;
8327
+ if (labelShown && key !== "") {
8328
+ const picked = [...new Set([...picks.values()].map((p) => p.type))];
8329
+ const full = group.map((i, k) => render(i, /* @__PURE__ */ new Set([...shownTypes(k), ...picked]))).filter((l) => l !== void 0);
8330
+ if (full.length === group.length && tryApply(group, full)) return true;
8331
+ }
8332
+ const proposed = new Map([...picks].map(([i, p]) => [i, p.label]));
8333
+ for (let changed = true; changed;) {
8334
+ changed = false;
8335
+ const firstOld = /* @__PURE__ */ new Map();
8336
+ for (const [i, l] of proposed) {
8337
+ const old = firstOld.get(l);
8338
+ if (old === void 0) firstOld.set(l, patched[i]);
8339
+ else if (old !== patched[i]) changed = proposed.delete(i);
8340
+ }
8341
+ const kept = new Set(bareMembers.filter((i) => !proposed.has(i)).map((i) => patched[i]));
8342
+ for (const [i, l] of proposed) if (kept.has(l)) changed = proposed.delete(i);
8343
+ }
8344
+ for (const i of bareMembers) addCount(patched[i], -1);
8345
+ for (const i of bareMembers) {
8346
+ patched[i] = proposed.get(i) ?? patched[i];
8347
+ addCount(patched[i], 1);
8348
+ }
8349
+ return proposed.size > 0;
8350
+ };
8351
+ if (sharedLabels && sharedMax >= unevenMax && tryApply(group, sharedLabels)) continue;
8352
+ if (applyBareFix()) continue;
8353
+ if (sharedLabels && sharedMax < unevenMax) tryApply(group, sharedLabels);
8155
8354
  }
8156
8355
  return patched;
8157
8356
  }
8158
8357
  //#endregion
8159
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/util/label.js
8358
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/util/label.js
8160
8359
  /** @deprecated Use deriveDistinctLabels */
8161
8360
  function deriveLabels(values, getSpec, options = {}) {
8162
8361
  return deriveDistinctLabels(values.map(getSpec), options).map((label, i) => ({
@@ -8165,7 +8364,7 @@ function deriveLabels(values, getSpec, options = {}) {
8165
8364
  }));
8166
8365
  }
8167
8366
  //#endregion
8168
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8367
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8169
8368
  const RT_RESOURCE_MAP = "PColumnData/ResourceMap";
8170
8369
  const RT_RESOURCE_MAP_PARTITIONED = "PColumnData/Partitioned/ResourceMap";
8171
8370
  const RT_JSON_PARTITIONED = "PColumnData/JsonPartitioned";
@@ -8459,7 +8658,7 @@ function allPColumnsReady(columns) {
8459
8658
  return columns.every(isPColumnReady);
8460
8659
  }
8461
8660
  //#endregion
8462
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8661
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8463
8662
  function isPColumnValues(value) {
8464
8663
  if (!Array.isArray(value)) return false;
8465
8664
  if (value.length === 0) return true;
@@ -8737,7 +8936,7 @@ var PColumnCollection = class {
8737
8936
  }
8738
8937
  };
8739
8938
  //#endregion
8740
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8939
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8741
8940
  /**
8742
8941
  * Builds a ServiceProxy from a ServiceDispatch.
8743
8942
  * Each service method call is forwarded to dispatch.callServiceMethod.
@@ -8746,7 +8945,7 @@ function createServiceProxy(dispatch) {
8746
8945
  return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
8747
8946
  }
8748
8947
  //#endregion
8749
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/services/get_services.js
8948
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/services/get_services.js
8750
8949
  const cachedServices = /* @__PURE__ */ new WeakMap();
8751
8950
  function getService(name, deps) {
8752
8951
  const ctx = deps?.ctx ?? getCfgRenderCtx();
@@ -8760,7 +8959,7 @@ function getService(name, deps) {
8760
8959
  })();
8761
8960
  }
8762
8961
  //#endregion
8763
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8962
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8764
8963
  function patchInSetFilters(filters) {
8765
8964
  const inSetToOrEqual = (predicate) => {
8766
8965
  if (predicate.operator !== "InSet") return predicate;
@@ -8798,7 +8997,7 @@ function patchInSetFilters(filters) {
8798
8997
  return filters.map((filter) => mapFilter(filter, inSetToOrEqual));
8799
8998
  }
8800
8999
  //#endregion
8801
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/render/api.js
9000
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/render/api.js
8802
9001
  /**
8803
9002
  * Helper function to match domain objects
8804
9003
  * @param query Optional domain to match against
@@ -9247,27 +9446,27 @@ var PluginRenderCtx = class extends RenderCtxBase {
9247
9446
  }
9248
9447
  };
9249
9448
  //#endregion
9250
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/plugin_model.js
9449
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/plugin_model.js
9251
9450
  /** Internal plugin↔block handshake. `Symbol.for` (not `Symbol`) so it stays
9252
9451
  * identical across multiple `@platforma-sdk/model` copies in one process. */
9253
9452
  const CREATE_PLUGIN_MODEL = Symbol.for("@platforma-sdk/model:createPluginModel");
9254
9453
  //#endregion
9255
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/version.js
9256
- const PlatformaSDKVersion = "1.84.10";
9454
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/version.js
9455
+ const PlatformaSDKVersion = "1.85.2";
9257
9456
  //#endregion
9258
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9457
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9259
9458
  function isConfigLambda(cfgOrFh) {
9260
9459
  return cfgOrFh.__renderLambda === true;
9261
9460
  }
9262
9461
  //#endregion
9263
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9462
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9264
9463
  function downgradeCfgOrLambda(data) {
9265
9464
  if (data === void 0) return void 0;
9266
9465
  if (isConfigLambda(data)) return data.handle;
9267
9466
  return data;
9268
9467
  }
9269
9468
  //#endregion
9270
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9469
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9271
9470
  /**
9272
9471
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
9273
9472
  *
@@ -9621,7 +9820,7 @@ function deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams) {
9621
9820
  }
9622
9821
  }
9623
9822
  //#endregion
9624
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/block_model.js
9823
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/block_model.js
9625
9824
  /**
9626
9825
  * Merges two feature flag objects with type-aware logic:
9627
9826
  * - `supports*` (boolean): OR — `true` if either side is `true`
@@ -9987,7 +10186,7 @@ var BlockModelV3 = class BlockModelV3 {
9987
10186
  }
9988
10187
  };
9989
10188
  //#endregion
9990
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
10189
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9991
10190
  /** Create id for column copy with added keys in axes domains */
9992
10191
  const colId = (id, domains, contextDomains) => {
9993
10192
  let wid = id.toString();
@@ -10093,7 +10292,7 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
10093
10292
  })];
10094
10293
  }
10095
10294
  //#endregion
10096
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
10295
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
10097
10296
  /**
10098
10297
  * Replace every column leaf whose id equals `fromId` with `toId`, leaving
10099
10298
  * other column refs (linkers, sub-anchors) intact. Wrapper recipes
@@ -10761,7 +10960,7 @@ var U = class d {
10761
10960
  }
10762
10961
  };
10763
10962
  //#endregion
10764
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10963
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10765
10964
  /**
10766
10965
  * Unified memoised factory dispatching to the right provider flavour by the
10767
10966
  * source shape:
@@ -10850,7 +11049,7 @@ function hashRawPool(rawPool) {
10850
11049
  return rawPool.map((b) => `${b.blockId}\x1f${b.prodCtx ?? ""}\x1f${b.stagingCtx ?? ""}\x1f${b.prodIncomplete ? 1 : 0}\x1f${b.stagingIncomplete ? 1 : 0}`).join("");
10851
11050
  }
10852
11051
  //#endregion
10853
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
11052
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10854
11053
  /**
10855
11054
  * Build the default set of ColumnsProviders for the ambient render ctx:
10856
11055
  * - `AccessorColumnsProvider` over `outputs` (if present)
@@ -10885,7 +11084,7 @@ function isColumnProvider(source) {
10885
11084
  return typeof p.getColumns === "function" && typeof p.isFinal === "function";
10886
11085
  }
10887
11086
  //#endregion
10888
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/data_column.js
11087
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10889
11088
  /**
10890
11089
  * Thrown by leaf-recipe factories when the requested column is provably
10891
11090
  * absent in the active render ctx — i.e. every relevant accessor reports
@@ -11125,7 +11324,7 @@ function memoizeByEntry(fn) {
11125
11324
  };
11126
11325
  }
11127
11326
  //#endregion
11128
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11327
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11129
11328
  /**
11130
11329
  * Recipe wrapper that overlays {@link SpecOverrides} on top of any other
11131
11330
  * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.
@@ -11263,7 +11462,7 @@ var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
11263
11462
  }
11264
11463
  };
11265
11464
  //#endregion
11266
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11465
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11267
11466
  /**
11268
11467
  * Recipe wrapper that fixes the values of selected axes of an inner recipe
11269
11468
  * (axis slicing). The id is `FilteredPColumnId { source: inner.id,
@@ -11389,7 +11588,7 @@ function toAxisSelector(axis) {
11389
11588
  return selector;
11390
11589
  }
11391
11590
  //#endregion
11392
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11591
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11393
11592
  /**
11394
11593
  * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching
11395
11594
  * concrete recipe variant based on the id's encoding and recurses on
@@ -11440,7 +11639,7 @@ function ColumnRecipeGetStatus(id, opts = {}) {
11440
11639
  }
11441
11640
  const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
11442
11641
  //#endregion
11443
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11642
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11444
11643
  /**
11445
11644
  * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base
11446
11645
  * column + a `path` of linkers + qualifications.
@@ -11611,7 +11810,7 @@ function referencedUniIdsOf(key) {
11611
11810
  return /* @__PURE__ */ new Set([key.column, ...(key.path ?? []).map((item) => item.column)]);
11612
11811
  }
11613
11812
  //#endregion
11614
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/column.js
11813
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/column.js
11615
11814
  /**
11616
11815
  * Unified entry point — routes between the two top-level dispatchers:
11617
11816
  * - string id (`PObjectId` / `ColumnUniversalId`) → {@link ColumnRecipe}
@@ -11625,7 +11824,7 @@ function Column(source, opts) {
11625
11824
  return DataColumn(source, opts);
11626
11825
  }
11627
11826
  //#endregion
11628
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11827
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11629
11828
  /**
11630
11829
  * Build a {@link ColumnsCollection} from sandbox-side source descriptors.
11631
11830
  * Resolves the `columnsCollection` driver (either from `deps.driver` or via
@@ -11734,7 +11933,7 @@ function defaultCtxSources(ctx) {
11734
11933
  return [...currentBlockSources(ctx), { kind: "result_pool" }];
11735
11934
  }
11736
11935
  //#endregion
11737
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/columns/utils.js
11936
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/columns/utils.js
11738
11937
  /**
11739
11938
  * PObjectIds of every non-hit column referenced by `recipe.getQuery()`,
11740
11939
  * deduped in traversal order. The hit column is
@@ -11865,7 +12064,7 @@ function hasSingleDataColumn(recipe) {
11865
12064
  return recipe.getReferencedIds().length === 1;
11866
12065
  }
11867
12066
  //#endregion
11868
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
12067
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11869
12068
  function getAllRelatedColumns(ctx, predicate) {
11870
12069
  const columns = new PColumnCollection();
11871
12070
  columns.addColumnProvider(ctx.resultPool);
@@ -11941,7 +12140,7 @@ function discoverIntegrableColumnIds(ctx, rootColumns) {
11941
12140
  }
11942
12141
  }
11943
12142
  //#endregion
11944
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
12143
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11945
12144
  function isHiddenFromGraphColumn(column) {
11946
12145
  return !!readAnnotationJson(column, Annotation.HideDataFromGraphs);
11947
12146
  }
@@ -11970,7 +12169,169 @@ function createPFrameForGraphs(ctx, blockColumns) {
11970
12169
  }));
11971
12170
  }
11972
12171
  //#endregion
11973
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/filters/traverse.js
12172
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/filter_discovery.js
12173
+ /**
12174
+ * Matches columns annotated `pl7.app/isSubset: "true"` whose axes ⊆ anchor axes.
12175
+ *
12176
+ * Filter-intent: only the dataset's own direct subset columns, no linker
12177
+ * traversal — so this uses `.filter()` (pins `maxHops: 0`), not `.discover()`
12178
+ * (which would default to 4 hops and surface subset columns from other,
12179
+ * linker-reachable datasets). `.filter()` still applies the default
12180
+ * `enrichment` matching mode (`allowFloatingHitAxes: false`), which enforces
12181
+ * the axes-subset constraint. See `matchingModeToConstraints()`.
12182
+ */
12183
+ function findFilterColumns(options) {
12184
+ return ColumnsCollection([...options.sources], { driver: options.driver }).filter({
12185
+ anchors: { main: options.anchorSpec },
12186
+ include: { annotations: { [Annotation.IsSubset]: "true" } }
12187
+ }).getColumns();
12188
+ }
12189
+ /**
12190
+ * Derive labeled options from filter column variants, for use in DatasetOption.filters.
12191
+ *
12192
+ * Entries whose column id has no PlRef in `refsByObjectId` are silently
12193
+ * skipped — they cannot be exposed as user-selectable options.
12194
+ */
12195
+ function filterMatchesToOptions(variants, options) {
12196
+ if (variants.length === 0) return [];
12197
+ const { refsByObjectId, datasetSpec, labelOptions } = options;
12198
+ const entries = variants.flatMap((variant) => {
12199
+ const ref = refsByObjectId.get(extractPObjectId(variant.id));
12200
+ if (ref === void 0) return [];
12201
+ return [{
12202
+ ref,
12203
+ spec: variant.getSpec(),
12204
+ linkerPath: collectLinkerColumns(variant).map((linker) => ({ spec: linker.getSpec() }))
12205
+ }];
12206
+ });
12207
+ const labels = deriveDistinctLabels([...entries, { spec: datasetSpec }], {
12208
+ ...labelOptions,
12209
+ formatters: {
12210
+ ...labelOptions?.formatters,
12211
+ native: () => void 0
12212
+ }
12213
+ });
12214
+ return entries.map(({ ref }, i) => ({
12215
+ ref,
12216
+ label: labels[i]
12217
+ }));
12218
+ }
12219
+ /** Build the `refsByObjectId` map from `ctx.resultPool.getSpecs().entries`. */
12220
+ function buildRefMap(entries) {
12221
+ return new Map(entries.map((e) => [(0, import_canonicalize.default)(e.ref), e.ref]));
12222
+ }
12223
+ //#endregion
12224
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/enrichment_discovery.js
12225
+ /**
12226
+ * Linker-reached hits attached to the anchor primary. Drops zero-hop variants
12227
+ * (filters / the primary itself) and structural hits (subset, linker, label
12228
+ * columns). Narrow further with `include` selectors or a `predicate`.
12229
+ */
12230
+ function findEnrichmentColumns(options) {
12231
+ const include = options.include === void 0 ? void 0 : Array.isArray(options.include) ? options.include : [options.include];
12232
+ const columns = ColumnsCollection([...options.sources], { driver: options.driver }).discover({
12233
+ anchors: { main: options.anchorSpec },
12234
+ mode: "enrichment",
12235
+ maxHops: options.maxHops ?? 4,
12236
+ include,
12237
+ exclude: [
12238
+ { annotations: { [Annotation.IsSubset]: "true" } },
12239
+ { annotations: { [Annotation.IsLinkerColumn]: "true" } },
12240
+ { name: Annotation.Label }
12241
+ ]
12242
+ }).getColumns();
12243
+ const predicate = options.predicate;
12244
+ return columns.filter((v) => {
12245
+ if (hasSingleDataColumn(v)) return false;
12246
+ if (predicate !== void 0 && !predicate(v.getSpec())) return false;
12247
+ if (!isGlobalPObjectId(extractPObjectId(v.id))) return false;
12248
+ if (collectLinkerIds(v).some((id) => !isGlobalPObjectId(id))) return false;
12249
+ return true;
12250
+ });
12251
+ }
12252
+ /**
12253
+ * Pair each variant with a path-disambiguated label (so export headers stay
12254
+ * unique) and carry hit/linker `PObjectId`s through verbatim. Propagates
12255
+ * `qualifications.forHit`; `forQueries` is re-derived by the table builder.
12256
+ */
12257
+ function enrichmentVariantsToRefs(variants, labelOptions) {
12258
+ if (variants.length === 0) return [];
12259
+ const linkerIdsByVariant = variants.map((v) => collectLinkerIds(v));
12260
+ const hitQualsByVariant = variants.map((v) => [...hitQualifications(v)]);
12261
+ const labels = deriveDistinctLabels(variants.map((variant, i) => ({
12262
+ spec: variant.getSpec(),
12263
+ linkerPath: collectLinkerColumns(variant).map((linker) => ({ spec: linker.getSpec() })),
12264
+ qualifications: {
12265
+ forHit: hitQualsByVariant[i],
12266
+ forQueries: queriesQualifications(variant)
12267
+ }
12268
+ })), labelOptions);
12269
+ return variants.map((variant, i) => {
12270
+ const path = linkerIdsByVariant[i].length === 0 ? void 0 : linkerIdsByVariant[i].map((id) => ({
12271
+ type: "linker",
12272
+ linker: id
12273
+ }));
12274
+ return {
12275
+ ref: createEnrichmentRef(extractPObjectId(variant.id), {
12276
+ path,
12277
+ qualifications: hitQualsByVariant[i]
12278
+ }),
12279
+ label: labels[i]
12280
+ };
12281
+ });
12282
+ }
12283
+ //#endregion
12284
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/build_dataset_options.js
12285
+ function toPredicate(opt) {
12286
+ if (opt === void 0) return () => true;
12287
+ return typeof opt === "function" ? opt : multiColumnSelectorsToPredicate(opt);
12288
+ }
12289
+ /**
12290
+ * Usage:
12291
+ * ```ts
12292
+ * .output("datasetOptions", (ctx) => buildDatasetOptions(ctx))
12293
+ * ```
12294
+ */
12295
+ function buildDatasetOptions(ctx, opts) {
12296
+ const primaryPredicate = toPredicate(opts?.primary);
12297
+ const filterPredicate = toPredicate(opts?.filter);
12298
+ const options = ctx.resultPool.getOptions(primaryPredicate, { refsWithEnrichments: opts?.requireEnrichments ?? true });
12299
+ if (options.length === 0) return [];
12300
+ const refMap = buildRefMap(ctx.resultPool.getSpecs().entries);
12301
+ const withEnrichments = opts?.withEnrichments ?? false;
12302
+ const filterSource = ColumnsProvider(ctx.ctx.getUpstreamBlockCtx());
12303
+ const enrichmentSources = withEnrichments ? getCtxProviders(ctx) : void 0;
12304
+ return options.map((primary) => {
12305
+ const datasetSpec = ctx.resultPool.getPColumnSpecByRef(primary.ref);
12306
+ if (!datasetSpec) return { primary };
12307
+ const filterMatches = findFilterColumns({
12308
+ sources: [filterSource],
12309
+ anchorSpec: datasetSpec
12310
+ }).filter((m) => filterPredicate(m.getSpec()));
12311
+ const filters = filterMatches.length === 0 ? void 0 : filterMatchesToOptions(filterMatches, {
12312
+ refsByObjectId: refMap,
12313
+ datasetSpec,
12314
+ labelOptions: opts?.labelOptions
12315
+ });
12316
+ let enrichments;
12317
+ if (enrichmentSources && withEnrichments) {
12318
+ const enrichmentVariants = findEnrichmentColumns({
12319
+ sources: enrichmentSources,
12320
+ anchorSpec: datasetSpec,
12321
+ maxHops: opts?.enrichmentMaxHops,
12322
+ ...typeof withEnrichments === "function" ? { predicate: withEnrichments } : { include: withEnrichments }
12323
+ });
12324
+ if (enrichmentVariants.length > 0) enrichments = enrichmentVariantsToRefs(enrichmentVariants, opts?.labelOptions);
12325
+ }
12326
+ return {
12327
+ primary,
12328
+ ...filters !== void 0 && filters.length > 0 ? { filters } : {},
12329
+ ...enrichments !== void 0 && enrichments.length > 0 ? { enrichments } : {}
12330
+ };
12331
+ });
12332
+ }
12333
+ //#endregion
12334
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/filters/traverse.js
11974
12335
  /**
11975
12336
  * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.
11976
12337
  *
@@ -12009,7 +12370,7 @@ function collectFilterSpecColumns(filter) {
12009
12370
  });
12010
12371
  }
12011
12372
  //#endregion
12012
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
12373
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
12013
12374
  /** Converts a QueryColumnId object into a SpecQueryExpression reference. */
12014
12375
  function resolveColumnRef(col) {
12015
12376
  return col.type === "axis" ? {
@@ -12396,7 +12757,7 @@ function isEmpty(value) {
12396
12757
  return true;
12397
12758
  }
12398
12759
  //#endregion
12399
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/filters/distill.js
12760
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/filters/distill.js
12400
12761
  /**
12401
12762
  * Strips non-FilterSpec metadata (whitelist approach) and removes
12402
12763
  * unfilled leaves (type is undefined or any required field is undefined).
@@ -12501,7 +12862,7 @@ const REQUIRED_KEYS_BY_TYPE = {
12501
12862
  greaterThanColumnOrEqual: ["column", "rhs"]
12502
12863
  };
12503
12864
  //#endregion
12504
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12865
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12505
12866
  /** Upgrade PlDataTableStateV2 to the latest version */
12506
12867
  function upgradePlDataTableStateV2(state) {
12507
12868
  if (!state) return createPlDataTableStateV2();
@@ -12859,7 +13220,7 @@ function parseLegacyLeafColumn(s) {
12859
13220
  return parsed;
12860
13221
  }
12861
13222
  //#endregion
12862
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
13223
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
12863
13224
  /** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */
12864
13225
  function toRuleColumn(col) {
12865
13226
  return {
@@ -12957,7 +13318,7 @@ function deriveAllLabels(options) {
12957
13318
  })), deriveLabelsOptions).reduce((acc, label, index) => (acc[columns[index].id] = label, acc), {});
12958
13319
  }
12959
13320
  //#endregion
12960
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
13321
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
12961
13322
  /**
12962
13323
  * Assemble a ptable def directly from recipes. Each secondary recipe is its own
12963
13324
  * outer-joined subtree: `getQuery()` encodes its linker chain, and its
@@ -13021,7 +13382,7 @@ function columnToJoinEntry(col, qualifications) {
13021
13382
  };
13022
13383
  }
13023
13384
  //#endregion
13024
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13385
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13025
13386
  function createColumnResolver(columns) {
13026
13387
  const axisIds = [];
13027
13388
  for (const c of columns) for (const ax of c.getSpec().axesSpec) axisIds.push(getAxisId(ax));
@@ -13043,7 +13404,7 @@ function createColumnResolver(columns) {
13043
13404
  };
13044
13405
  }
13045
13406
  //#endregion
13046
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13407
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13047
13408
  /**
13048
13409
  * Discover columns from sources/anchors and split them into primary
13049
13410
  * (direct anchor hits — zero-hop, query is a bare column) and secondary
@@ -13089,7 +13450,7 @@ function discoverLabelColumns(ctx, primary) {
13089
13450
  }).getColumns();
13090
13451
  }
13091
13452
  //#endregion
13092
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.10/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13453
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.85.2/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13093
13454
  function createPlDataTableV3(ctx, options) {
13094
13455
  const state = upgradePlDataTableStateV2(options.tableState);
13095
13456
  const primaryJoinType = options.primaryJoinType ?? "full";
@@ -13514,15 +13875,6 @@ function poolSpecByRef(ctx, ref) {
13514
13875
  }
13515
13876
  //#endregion
13516
13877
  //#region ../model/dist/specs.js
13517
- /**
13518
- * Column and axis names this block shares with its workflow and with the profiler upstream.
13519
- *
13520
- * Every string here is a contract: change one and the matching literal in
13521
- * `workflow/src/main.tpl.tengo` — or in the profiler that emits it — has to change with it, or
13522
- * the column simply stops being found and an output goes quietly empty. They live in one file so
13523
- * that obligation is visible rather than buried among the render helpers.
13524
- */
13525
- const STATE_MATRIX = "pl7.app/repertoire/stateMatrix";
13526
13878
  const LANDSCAPE_SCORE_REF = "pl7.app/repertoire/landscapeScoreRef";
13527
13879
  const MUTATION_ID_AXIS = "pl7.app/repertoire/mutationId";
13528
13880
  const MUTATION_VARIANT_LINK = "pl7.app/repertoire/mutationVariantLink";
@@ -13798,6 +14150,30 @@ function isLandscapeScoreColumn(spec, variantAxisName) {
13798
14150
  if (variantAxisName === void 0) return false;
13799
14151
  return spec.axesSpec.length === 1 && spec.axesSpec[0].name === variantAxisName;
13800
14152
  }
14153
+ /** The subset a column was computed on (Clonotype Enrichment's stamp), if any. */
14154
+ function subsetStampOf(spec) {
14155
+ return spec.domain?.["pl7.app/inputSubset"];
14156
+ }
14157
+ /**
14158
+ * Picker entries for score and round columns. Only columns that fit the run: full-data ones, or
14159
+ * ones computed on the run's own subset. Labels come from the trace, so a subset's copy is named.
14160
+ */
14161
+ function runColumnOptions(entries, inputFilter) {
14162
+ const fitting = entries.filter((e) => {
14163
+ const stamp = subsetStampOf(e.spec);
14164
+ return stamp === void 0 || stamp === inputFilter;
14165
+ });
14166
+ const labels = deriveDistinctLabels(fitting.map((e) => e.spec));
14167
+ return fitting.map((e, i) => ({
14168
+ label: labels[i] ?? e.id,
14169
+ value: e.id,
14170
+ ...subsetStampOf(e.spec) !== void 0 && { subset: subsetStampOf(e.spec) }
14171
+ }));
14172
+ }
14173
+ /** The run's subset as the workflow and the stamp write it. */
14174
+ function inputFilterOf(data) {
14175
+ return data.filterRef && createGlobalPObjectId(data.filterRef.blockId, data.filterRef.name);
14176
+ }
13801
14177
  /** The section href of one landscape page. */
13802
14178
  function landscapeHref(scoreKey) {
13803
14179
  return `/?score=${encodeURIComponent(scoreKey)}`;
@@ -13880,22 +14256,30 @@ const platforma$1 = BlockModelV3.create({
13880
14256
  if (data.selectedParentId === void 0) throw new Error("Select a parent");
13881
14257
  return {
13882
14258
  stateMatrixRef: data.stateMatrixRef,
14259
+ ...data.filterRef !== void 0 && { inputFilter: createGlobalPObjectId(data.filterRef.blockId, data.filterRef.name) },
13883
14260
  selectedParentId: data.selectedParentId,
13884
14261
  roundFrequencyRefs: data.roundFrequencyRefs ?? [],
13885
14262
  compositionEpsilon: data.compositionEpsilon ?? 1e-6,
13886
14263
  scoreRefs: data.scoreRefs ?? []
13887
14264
  };
13888
14265
  }).templateParams(() => ({})).output("stateMatrixOptions", (ctx) => {
13889
- const options = ctx.resultPool.getOptions([{ name: STATE_MATRIX }], { label: { includeNativeLabel: false } });
14266
+ const options = buildDatasetOptions(ctx, {
14267
+ primary: (spec) => isPColumnSpec(spec) && spec.name === "pl7.app/repertoire/stateMatrix",
14268
+ filter: (spec) => isPColumnSpec(spec) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/variantKey",
14269
+ requireEnrichments: false
14270
+ }) ?? [];
13890
14271
  const labelCounts = /* @__PURE__ */ new Map();
13891
- for (const o of options) labelCounts.set(o.label, (labelCounts.get(o.label) ?? 0) + 1);
14272
+ for (const { primary } of options) labelCounts.set(primary.label, (labelCounts.get(primary.label) ?? 0) + 1);
13892
14273
  return options.map((o) => {
13893
- if ((labelCounts.get(o.label) ?? 0) <= 1) return o;
13894
- const alphabet = ctx.resultPool.getPColumnSpecByRef(o.ref)?.axesSpec.find((a) => a.domain?.["pl7.app/alphabet"])?.domain?.["pl7.app/alphabet"];
14274
+ if ((labelCounts.get(o.primary.label) ?? 0) <= 1) return o;
14275
+ const alphabet = ctx.resultPool.getPColumnSpecByRef(o.primary.ref)?.axesSpec.find((a) => a.domain?.["pl7.app/alphabet"])?.domain?.["pl7.app/alphabet"];
13895
14276
  const suffix = alphabet === "aminoacid" ? " (aa)" : alphabet === "nucleotide" ? " (nt)" : "";
13896
14277
  return {
13897
14278
  ...o,
13898
- label: o.label + suffix
14279
+ primary: {
14280
+ ...o.primary,
14281
+ label: o.primary.label + suffix
14282
+ }
13899
14283
  };
13900
14284
  });
13901
14285
  }).output("scoreOptions", (ctx) => {
@@ -13912,35 +14296,49 @@ const platforma$1 = BlockModelV3.create({
13912
14296
  }).getColumns();
13913
14297
  const variantAxisName = stateSpec.axesSpec[0]?.name;
13914
14298
  const seen = /* @__PURE__ */ new Set();
13915
- const options = [];
14299
+ const entries = [];
13916
14300
  for (const recipe of columns) {
13917
14301
  const spec = recipe.getSpec();
13918
14302
  if (!isLandscapeScoreColumn(spec, variantAxisName)) continue;
13919
14303
  const dedupKey = spec.name + "|" + JSON.stringify(spec.domain ?? {});
13920
14304
  if (seen.has(dedupKey)) continue;
13921
14305
  seen.add(dedupKey);
13922
- options.push({
13923
- label: spec.annotations?.["pl7.app/label"] ?? recipe.id,
13924
- value: recipe.id
14306
+ entries.push({
14307
+ id: recipe.id,
14308
+ spec
13925
14309
  });
13926
14310
  }
13927
- return options;
14311
+ return runColumnOptions(entries, inputFilterOf(ctx.data));
13928
14312
  }).output("roundFrequencyOptions", (ctx) => {
13929
14313
  const stateMatrixRef = ctx.data.stateMatrixRef;
13930
14314
  if (stateMatrixRef === void 0) return void 0;
13931
14315
  const stateSpec = poolSpecByRef(ctx, stateMatrixRef);
13932
14316
  if (!stateSpec) return void 0;
13933
- return dedupByLeafId(ColumnsCollection(["result_pool"]).discover({
14317
+ return runColumnOptions(dedupByLeafId(ColumnsCollection(["result_pool"]).discover({
13934
14318
  include: { name: exactMatch("pl7.app/frequency") },
13935
14319
  anchors: { main: stateSpec },
13936
14320
  mode: "enrichment",
13937
14321
  maxHops: 0
13938
- }).getColumns()).map((recipe) => {
13939
- return {
13940
- label: recipe.getSpec().annotations?.["pl7.app/label"] ?? recipe.id,
13941
- value: recipe.id
13942
- };
13943
- });
14322
+ }).getColumns()).map((recipe) => ({
14323
+ id: recipe.id,
14324
+ spec: recipe.getSpec()
14325
+ })), inputFilterOf(ctx.data));
14326
+ }).output("subsetParentsFrame", (ctx) => {
14327
+ const { stateMatrixRef, filterRef } = ctx.data;
14328
+ if (stateMatrixRef === void 0 || filterRef === void 0) return void 0;
14329
+ const variantAxis = poolSpecByRef(ctx, stateMatrixRef)?.axesSpec[0];
14330
+ const filter = ctx.resultPool.getPColumnByRef(filterRef);
14331
+ if (variantAxis === void 0 || filter === void 0) return void 0;
14332
+ const linker = ctx.resultPool.selectColumns((spec) => spec.name === "pl7.app/repertoire/parentLink" && spec.axesSpec.some((a) => a.name === variantAxis.name && Object.entries(variantAxis.domain ?? {}).every(([k, v]) => a.domain?.[k] === v))).find((c) => c.data !== void 0);
14333
+ if (linker?.data === void 0) return void 0;
14334
+ return {
14335
+ frame: ctx.createPFrame([{
14336
+ ...linker,
14337
+ data: linker.data
14338
+ }, filter]),
14339
+ linkerId: linker.id,
14340
+ filterId: filter.id
14341
+ };
13944
14342
  }).output("stateMatrixPf", (ctx) => {
13945
14343
  const { stateMatrixRef } = ctx.data;
13946
14344
  if (stateMatrixRef === void 0) return void 0;