@platforma-open/milaboratories.sort-seq-analysis.block 1.0.6 → 1.1.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
@@ -19,16 +19,51 @@ const PColumnName$1 = {
19
19
  /** The per-variant mutation list, shown as "Mutations". */
20
20
  Mutations: "pl7.app/repertoire/mutations"
21
21
  };
22
+ /** "Which gate" — an axis in the distribution view, a domain key on the enrichment columns.
23
+ * One constant so a rename cannot break the join silently. */
24
+ const GATE = "pl7.app/facsBin/gate";
22
25
  /** Names this block mints, all under one namespace segment. */
23
26
  const FacsBin = {
24
27
  GateRankMean: "pl7.app/facsBin/gateRankMean",
25
28
  BinScore: "pl7.app/facsBin/binScore",
29
+ GateEnrichment: "pl7.app/facsBin/gateEnrichment",
26
30
  GateFrequency: "pl7.app/facsBin/gateFrequency",
27
31
  GateReads: "pl7.app/facsBin/gateReads",
28
- GateAxis: "pl7.app/facsBin/gate",
32
+ GateAxis: GATE,
29
33
  ConditionDomain: "pl7.app/facsBin/condition",
34
+ /**
35
+ * A domain key, NOT an axis. The Mutation Explorer's score picker only sees columns keyed on
36
+ * the variant axis alone, so a gate axis would hide these and add a one-choice selector.
37
+ */
38
+ GateDomain: GATE,
30
39
  ReferenceModeDomain: "pl7.app/facsBin/referenceMode",
31
- SortYieldCorrectedAnnotation: "pl7.app/facsBin/sortYieldCorrected"
40
+ /** Per parent, for the whole run. Emitted in every mode, so the parents are always visible. */
41
+ ParentVariants: "pl7.app/facsBin/parentVariants",
42
+ ParentReads: "pl7.app/facsBin/parentReads",
43
+ /** The enrichment divided by its own parent's baseline. 1.0 is a variant of no effect. */
44
+ GateEnrichmentVsBaseline: "pl7.app/facsBin/gateEnrichmentVsBaseline",
45
+ /** The noise band on `binScore`, per condition. Gate-ranking mode only. */
46
+ BinScoreBaselineLevel: "pl7.app/facsBin/binScoreBaselineLevel",
47
+ /**
48
+ * The per-gate baseline, keyed on `[parentId]` rather than the variant axis — one row per
49
+ * parent, so a dataset carrying several reports each.
50
+ */
51
+ GateBaselineLevel: "pl7.app/facsBin/gateBaselineLevel",
52
+ GateBaselineP5: "pl7.app/facsBin/gateBaselineP5",
53
+ GateBaselineP95: "pl7.app/facsBin/gateBaselineP95",
54
+ GateBaselineVariants: "pl7.app/facsBin/gateBaselineVariants",
55
+ SortYieldCorrectedAnnotation: "pl7.app/facsBin/sortYieldCorrected",
56
+ /** The baseline as measured at this column's gate. Absent where none was resolved. */
57
+ BaselineLevelAnnotation: "pl7.app/facsBin/baselineLevel",
58
+ /** The four percentiles, as a JSON object. Never a standard error — see `BaselineSummary`. */
59
+ BaselineSpreadAnnotation: "pl7.app/facsBin/baselineSpread",
60
+ BaselineVariantsAnnotation: "pl7.app/facsBin/baselineVariants"
61
+ };
62
+ /** Domain key on the variant axis that tells the nucleotide grain from the protein grain. */
63
+ const AlphabetDomain = "pl7.app/alphabet";
64
+ const Alphabet = {
65
+ Nucleotide: "nucleotide",
66
+ AminoAcid: "aminoacid"
32
67
  };
33
68
  function isPColumnSpec$1(spec) {
34
69
  return spec.kind === "PColumn";
@@ -39,16 +74,11 @@ function annotation(spec, key) {
39
74
  /**
40
75
  * The anchor: per-sample abundance on the variant grain.
41
76
  *
42
- * Both annotation conditions are required and neither is redundant. The profiler emits a
43
- * second primary abundance column that is normalized (`pl7.app/readFraction`), so the
44
- * primary marker alone selects two candidates. And three further columns in the same block
45
- * carry the abundance marker without the primary one — one on the mutation-count axis, two
46
- * per-variant totals — so a predicate loose enough to admit them would compute a bin score
47
- * over aggregated totals and emit output of ordinary shape.
77
+ * Neither annotation is redundant. The profiler emits a second primary abundance column that is
78
+ * normalized, and three more carry the abundance marker without the primary one — admitting
79
+ * those computes a bin score over aggregated totals with output of ordinary shape.
48
80
  *
49
- * Two axes are required by count rather than by name: the sample axis and the variant axis
50
- * are what a per-sample-per-variant abundance has, and naming the variant axis is the live
51
- * defect described at the top of this file.
81
+ * Two axes by COUNT, not name — see the file header.
52
82
  */
53
83
  function isAbundanceAnchor(spec) {
54
84
  if (!isPColumnSpec$1(spec)) return false;
@@ -56,25 +86,11 @@ function isAbundanceAnchor(spec) {
56
86
  return annotation(spec, Annotation$1.AbundanceIsPrimary) === "true" && annotation(spec, Annotation$1.AbundanceNormalized) === "false";
57
87
  }
58
88
  /**
59
- * Per-sample metadata, in the anchor's context — the one option list the three roles are
60
- * picked from.
61
- *
62
- * **This predicate is expected to resolve to many.** It produces the option list, not an
63
- * answer. A spec predicate can establish that a column *is* per-sample metadata; it cannot
64
- * establish which role a given one plays, because the only per-column discriminator is a
65
- * value drawn from the user's own data. The roles are assigned by the user, one pick each.
89
+ * Per-sample metadata — the option list the three roles are picked from, so it is expected to
90
+ * resolve to many. Which role a column plays is the user's pick; no spec predicate can tell.
66
91
  *
67
- * `pl7.app/metadata` is the column's **name**, not an annotation — every per-sample metadata
68
- * column upstream is literally named that, with the sample axis as its only axis and its
69
- * user-facing header in `pl7.app/label`. Matching it as an annotation matches nothing, and does
70
- * so silently: the option list comes back empty and the pickers look broken while the metadata
71
- * is plainly loaded.
72
- *
73
- * This is still a match on a shared-vocabulary *term*, not on a particular column's instance
74
- * name.
75
- *
76
- * The single axis is bound to the anchor's sample axis by the anchor context rather than by
77
- * name.
92
+ * `pl7.app/metadata` is the column's NAME, not an annotation. Matching it as an annotation
93
+ * matches nothing silently: the list comes back empty and the pickers look broken.
78
94
  */
79
95
  const metadataSelector = {
80
96
  axes: [{
@@ -97,14 +113,14 @@ const sampleLabelSelector = {
97
113
  };
98
114
  PColumnName$1.MutationCount;
99
115
  //#endregion
100
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/plugin_handle.js
116
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/plugin_handle.js
101
117
  const PLUGIN_OUTPUT_PREFIX = "plugin-output#";
102
118
  /** Construct the output key for a plugin output in the block outputs map. */
103
119
  function pluginOutputKey(handle, outputKey) {
104
120
  return `${PLUGIN_OUTPUT_PREFIX}${handle}#${outputKey}`;
105
121
  }
106
122
  //#endregion
107
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_storage.js
123
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/block_storage.js
108
124
  /**
109
125
  * Discriminator key for BlockStorage format detection.
110
126
  * This unique hash-based key identifies data as BlockStorage vs legacy formats.
@@ -3899,7 +3915,7 @@ objectType({
3899
3915
  content: stringType()
3900
3916
  });
3901
3917
  //#endregion
3902
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3918
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3903
3919
  /**
3904
3920
  * Compose a {@link BlockKindReference} from a kind's `name`/`version`.
3905
3921
  *
@@ -3915,7 +3931,7 @@ objectType({
3915
3931
  to: numberType().min(1)
3916
3932
  });
3917
3933
  //#endregion
3918
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/util.js
3934
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/util.js
3919
3935
  function assertNever(x) {
3920
3936
  throw new Error("Unexpected object: " + x);
3921
3937
  }
@@ -3927,7 +3943,7 @@ function uniqueBy(array, makeId) {
3927
3943
  return [...new Map(array.map((e) => [makeId(e), e])).values()];
3928
3944
  }
3929
3945
  //#endregion
3930
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
3946
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
3931
3947
  /**
3932
3948
  * Type guard function that checks if the given value is a valid DataInfo.
3933
3949
  *
@@ -4116,7 +4132,7 @@ function entriesToDataInfo(dataInfoEntries) {
4116
4132
  }
4117
4133
  }
4118
4134
  //#endregion
4119
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4135
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4120
4136
  var ServiceError = class extends Error {
4121
4137
  name = "ServiceError";
4122
4138
  };
@@ -4140,7 +4156,7 @@ function ensureError(value) {
4140
4156
  return new Error(stringifyValue(value));
4141
4157
  }
4142
4158
  //#endregion
4143
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4159
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4144
4160
  var import_canonicalize = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
4145
4161
  module.exports = function serialize(object) {
4146
4162
  if (typeof object === "number" && isNaN(object)) throw new Error("NaN is not allowed");
@@ -4173,7 +4189,7 @@ function parseJsonSafely(value, fallback) {
4173
4189
  }
4174
4190
  }
4175
4191
  //#endregion
4176
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4192
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4177
4193
  function readMetadata(metadata, key) {
4178
4194
  return metadata?.[key];
4179
4195
  }
@@ -4195,6 +4211,36 @@ function readMetadataJson(metadata, metadataJson, key) {
4195
4211
  return;
4196
4212
  }
4197
4213
  }
4214
+ /**
4215
+ * Domain keys whose value is the id of a block, rather than a qualifier of the data.
4216
+ *
4217
+ * Applying a template repoints these at the blocks of the project being built: an axis a block
4218
+ * produced names that block in its domain, so an axis left naming the exported-from project
4219
+ * resolves to nothing. Listing the keys is what makes that safe — a template's entry ids are
4220
+ * arbitrary non-empty strings, so a hand-written template may name an entry `closest`, and a
4221
+ * qualifier that happens to read `closest` must not be mistaken for a reference to it.
4222
+ *
4223
+ * A key absent from here is simply left alone, which is the behaviour from before relocation
4224
+ * reached domains at all. Adding one is therefore safe; omitting one costs only that a template
4225
+ * carrying it applies still pointing at the project it came from.
4226
+ */
4227
+ const BlockScopedDomain = /* @__PURE__ */ new Set([
4228
+ "pl7.app/blockId",
4229
+ "pl7.app/block",
4230
+ "pl7.app/redefined-by",
4231
+ "pl7.app/annotationRunId",
4232
+ "pl7.app/clonotypeAnnotationRunId",
4233
+ "pl7.app/clustering/blockId",
4234
+ "pl7.app/umap/blockId",
4235
+ "pl7.app/peptide/extractionRunId",
4236
+ "pl7.app/repertoire/extractionRunId",
4237
+ "pl7.app/antibodyVariantDesigner/designRunId",
4238
+ "pl7.app/vdj/clonotypingRunId",
4239
+ "pl7.app/vdj/clustering/blockId",
4240
+ "pl7.app/vdj/integration/blockId",
4241
+ "pl7.app/vdj/spatiotemporalAnalysis/blockId",
4242
+ "pl7.app/vdj/libraryId"
4243
+ ]);
4198
4244
  const Annotation = {
4199
4245
  AxisNature: "pl7.app/axisNature",
4200
4246
  Alphabet: "pl7.app/alphabet",
@@ -4465,7 +4511,7 @@ function matchAxisId(query, target) {
4465
4511
  return query.name === target.name && matchDomain$1(query.domain, target.domain) && matchDomain$1(query.contextDomain, target.contextDomain);
4466
4512
  }
4467
4513
  //#endregion
4468
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4514
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4469
4515
  const BOOLEAN_TYPES = /* @__PURE__ */ new Set([
4470
4516
  "numericComparison",
4471
4517
  "stringEquals",
@@ -4570,7 +4616,7 @@ function collectSpecQueryColumns(query) {
4570
4616
  return result;
4571
4617
  }
4572
4618
  //#endregion
4573
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4619
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4574
4620
  function mapPTableDef(def, cb) {
4575
4621
  return {
4576
4622
  ...def,
@@ -4613,7 +4659,7 @@ function mapJoinEntry(entry, cb) {
4613
4659
  }
4614
4660
  }
4615
4661
  //#endregion
4616
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4662
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4617
4663
  function getPTableColumnId(spec) {
4618
4664
  switch (spec.type) {
4619
4665
  case "axis": return {
@@ -4627,7 +4673,7 @@ function getPTableColumnId(spec) {
4627
4673
  }
4628
4674
  }
4629
4675
  //#endregion
4630
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4676
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4631
4677
  function stringifyColumnFilteredId(key) {
4632
4678
  return canonicalizeJson(createColumnFilteredKey(key));
4633
4679
  }
@@ -4660,7 +4706,7 @@ function applyAxisFilters(spec, axisFilters) {
4660
4706
  };
4661
4707
  }
4662
4708
  //#endregion
4663
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4709
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4664
4710
  function isPObjectId(value) {
4665
4711
  if (typeof value !== "string") return false;
4666
4712
  return isPObjectKey(parseJsonSafely(value));
@@ -4770,7 +4816,7 @@ function isObject(value) {
4770
4816
  * isPlainObject([]); // false
4771
4817
  * ```
4772
4818
  */
4773
- function isPlainObject(value) {
4819
+ function isPlainObject$1(value) {
4774
4820
  if (!isObject(value)) return false;
4775
4821
  const prototype = Object.getPrototypeOf(value);
4776
4822
  return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
@@ -4782,7 +4828,7 @@ function throwError(v) {
4782
4828
  else throw v;
4783
4829
  }
4784
4830
  //#endregion
4785
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4831
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4786
4832
  function isColumnDiscoveredKey(obj) {
4787
4833
  return typeof obj === "object" && obj !== null && "__isDiscovered" in obj;
4788
4834
  }
@@ -4922,6 +4968,56 @@ function getTag(value) {
4922
4968
  return Object.prototype.toString.call(value);
4923
4969
  }
4924
4970
  //#endregion
4971
+ //#region ../node_modules/.pnpm/es-toolkit@1.50.0/node_modules/es-toolkit/dist/predicate/isPlainObject.mjs
4972
+ /**
4973
+ * Checks if a given value is a plain object.
4974
+ *
4975
+ * @param value - The value to check.
4976
+ * @returns True if the value is a plain object, otherwise false.
4977
+ *
4978
+ * @example
4979
+ * ```typescript
4980
+ * // ✅👇 True
4981
+ *
4982
+ * isPlainObject({ }); // ✅
4983
+ * isPlainObject({ key: 'value' }); // ✅
4984
+ * isPlainObject({ key: new Date() }); // ✅
4985
+ * isPlainObject(new Object()); // ✅
4986
+ * isPlainObject(Object.create(null)); // ✅
4987
+ * isPlainObject({ nested: { key: true} }); // ✅
4988
+ * isPlainObject(new Proxy({}, {})); // ✅
4989
+ * isPlainObject({ [Symbol('tag')]: 'A' }); // ✅
4990
+ *
4991
+ * // ✅👇 (cross-realms, node context, workers, ...)
4992
+ * const runInNewContext = await import('node:vm').then(
4993
+ * (mod) => mod.runInNewContext
4994
+ * );
4995
+ * isPlainObject(runInNewContext('({})')); // ✅
4996
+ *
4997
+ * // ❌👇 False
4998
+ *
4999
+ * class Test { };
5000
+ * isPlainObject(new Test()) // ❌
5001
+ * isPlainObject(10); // ❌
5002
+ * isPlainObject(null); // ❌
5003
+ * isPlainObject('hello'); // ❌
5004
+ * isPlainObject([]); // ❌
5005
+ * isPlainObject(new Date()); // ❌
5006
+ * isPlainObject(new Uint8Array([1])); // ❌
5007
+ * isPlainObject(Buffer.from('ABC')); // ❌
5008
+ * isPlainObject(Promise.resolve({})); // ❌
5009
+ * isPlainObject(Object.create({})); // ❌
5010
+ * isPlainObject(new (class Cls {})); // ❌
5011
+ * isPlainObject(globalThis); // ❌,
5012
+ * ```
5013
+ */
5014
+ function isPlainObject(value) {
5015
+ if (!value || typeof value !== "object") return false;
5016
+ const proto = Object.getPrototypeOf(value);
5017
+ if (!(proto === null || proto === Object.prototype || Object.getPrototypeOf(proto) === null)) return false;
5018
+ return Object.prototype.toString.call(value) === "[object Object]";
5019
+ }
5020
+ //#endregion
4925
5021
  //#region ../node_modules/.pnpm/es-toolkit@1.50.0/node_modules/es-toolkit/dist/predicate/isFunction.mjs
4926
5022
  /**
4927
5023
  * Checks if `value` is a function.
@@ -5012,7 +5108,7 @@ function isString(value) {
5012
5108
  return typeof value === "string";
5013
5109
  }
5014
5110
  //#endregion
5015
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5111
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5016
5112
  /**
5017
5113
  * Canonically serializes a column key to a branded string id. Accepts both
5018
5114
  * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}
@@ -5186,7 +5282,7 @@ function extractPObjectId(id) {
5186
5282
  throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);
5187
5283
  }
5188
5284
  //#endregion
5189
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5285
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5190
5286
  function isColumnOverriddenKey(obj) {
5191
5287
  return typeof obj === "object" && obj !== null && "__isOverridden" in obj;
5192
5288
  }
@@ -5308,7 +5404,7 @@ function mergeRecord(a, b) {
5308
5404
  };
5309
5405
  }
5310
5406
  //#endregion
5311
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5407
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5312
5408
  function axisKey(axis) {
5313
5409
  return (0, import_canonicalize.default)(getAxisId(axis));
5314
5410
  }
@@ -5554,7 +5650,7 @@ function isAnchorAxisRef(value) {
5554
5650
  return typeof value === "object" && "anchor" in value;
5555
5651
  }
5556
5652
  //#endregion
5557
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5653
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5558
5654
  /**
5559
5655
  * Checks if a given value is an anchored column identifier
5560
5656
  * @param id - The value to check
@@ -5643,7 +5739,7 @@ function legacyColumnSelectorsToPredicate(predicateOrSelectors) {
5643
5739
  else return (spec) => isPColumnSpec(spec) && matchPColumn(spec, predicateOrSelectors);
5644
5740
  }
5645
5741
  //#endregion
5646
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5742
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5647
5743
  function deriveNativeId(spec) {
5648
5744
  const result = {
5649
5745
  kind: spec.kind,
@@ -5655,7 +5751,7 @@ function deriveNativeId(spec) {
5655
5751
  return (0, import_canonicalize.default)(result);
5656
5752
  }
5657
5753
  //#endregion
5658
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5754
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5659
5755
  var LinkerMap = class LinkerMap {
5660
5756
  /** Graph of linkers connected by axes (single or grouped by parents) */
5661
5757
  data;
@@ -5832,7 +5928,7 @@ var LinkerMap = class LinkerMap {
5832
5928
  }
5833
5929
  };
5834
5930
  //#endregion
5835
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5931
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5836
5932
  /**
5837
5933
  * Required PFrames version. Bump this in lockstep with the `@milaboratories/pframes-rs-*`
5838
5934
  * version in `pnpm-workspace.yaml` so blocks built against the new SDK refuse to load on
@@ -5875,7 +5971,7 @@ function withEnrichments(ref, requireEnrichments = true) {
5875
5971
  }
5876
5972
  }
5877
5973
  //#endregion
5878
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
5974
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
5879
5975
  function mapValueInVOE(voe, cb) {
5880
5976
  return voe.ok ? {
5881
5977
  ok: true,
@@ -5883,7 +5979,7 @@ function mapValueInVOE(voe, cb) {
5883
5979
  } : voe;
5884
5980
  }
5885
5981
  //#endregion
5886
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5982
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5887
5983
  /** Well-known resource type names used across the platform. */
5888
5984
  const ResourceTypeName = {
5889
5985
  StreamManager: "StreamManager",
@@ -5927,7 +6023,7 @@ const ResourceTypeName = {
5927
6023
  SharedEnvelope: "SharedEnvelope"
5928
6024
  };
5929
6025
  //#endregion
5930
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
6026
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
5931
6027
  const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
5932
6028
  const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
5933
6029
  const typeMap = /* @__PURE__ */ new Map();
@@ -5966,7 +6062,7 @@ const { service, isNodeService, isWasmService, isMainService, getServiceKind, ge
5966
6062
  };
5967
6063
  })();
5968
6064
  //#endregion
5969
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
6065
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
5970
6066
  const Services = {
5971
6067
  PFrameSpec: service()({
5972
6068
  type: "wasm",
@@ -6060,7 +6156,7 @@ function resolveRequiredServices(flags) {
6060
6156
  }
6061
6157
  Object.fromEntries(Object.keys(Services).map((key) => [`requires${key}`, true]));
6062
6158
  //#endregion
6063
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6159
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6064
6160
  function buildMethodMap(pick) {
6065
6161
  const result = {};
6066
6162
  for (const id of Object.values(Services)) result[id] = [...pick(id)];
@@ -6069,7 +6165,7 @@ function buildMethodMap(pick) {
6069
6165
  buildMethodMap(getServiceUiMethods);
6070
6166
  buildMethodMap(getServiceModelMethods);
6071
6167
  //#endregion
6072
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6168
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6073
6169
  /** Resource types that hold column collections — DFS stops here and collects. */
6074
6170
  const COLLECT_TYPES = [ResourceTypeName.PFrame];
6075
6171
  /** Resource types DFS descends through when looking for PFrames. */
@@ -6177,7 +6273,7 @@ function indexPoolBlock(block) {
6177
6273
  return result;
6178
6274
  }
6179
6275
  //#endregion
6180
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6276
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6181
6277
  /**
6182
6278
  * Id-index over a set of {@link ColumnEntriesProvider}s. Sole job:
6183
6279
  * {@link PObjectId} → {@link LeafEntry}. Generic over the accessor flavour, so
@@ -6214,7 +6310,7 @@ var ColumnRegistry = class {
6214
6310
  }
6215
6311
  };
6216
6312
  //#endregion
6217
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6313
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6218
6314
  /**
6219
6315
  * Two-track dedup over an item stream keyed by `ColumnUniversalId`:
6220
6316
  *
@@ -6255,7 +6351,7 @@ function dedupColumns(items, getId, getSpec) {
6255
6351
  return out;
6256
6352
  }
6257
6353
  //#endregion
6258
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6354
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6259
6355
  /**
6260
6356
  * Generic entries provider over a single accessor root. Walks `<root>` once
6261
6357
  * from the supplied `rootPath`, builds an id → {@link LeafEntry} map and
@@ -6312,7 +6408,7 @@ var ResultPoolEntriesProvider = class {
6312
6408
  }
6313
6409
  };
6314
6410
  //#endregion
6315
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6411
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6316
6412
  /**
6317
6413
  * Whether `value` is a reference in the readable spelling.
6318
6414
  *
@@ -6381,7 +6477,7 @@ function expandTemplatePlRef(ref) {
6381
6477
  };
6382
6478
  }
6383
6479
  //#endregion
6384
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6480
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.49.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6385
6481
  /**
6386
6482
  * Point every column identifier in a block's params at the blocks of the project being built.
6387
6483
  *
@@ -6397,8 +6493,13 @@ function expandTemplatePlRef(ref) {
6397
6493
  *
6398
6494
  * Rewriting is structural, never textual: an identifier is taken apart, its `blockId` fields
6399
6495
  * are replaced, and it is rebuilt canonically. That is what keeps a value that merely *looks*
6400
- * like an id — a `domain` entry, an axis filter — from being rewritten along with it, and
6401
- * what re-sorts a qualifications map whose keys are identifiers.
6496
+ * like an id — an axis filter, a domain this package can see belongs to an identifier it
6497
+ * knows — from being rewritten along with it, and what re-sorts a qualifications map whose
6498
+ * keys are identifiers.
6499
+ *
6500
+ * A domain reached on its own is the exception, and `relocateDomain` below says why: an axis is
6501
+ * qualified by the block that produced it. Only the domain keys known to name a block are
6502
+ * repointed — matching an entry id is not on its own evidence of a reference.
6402
6503
  *
6403
6504
  * An id the map does not mention is left as it is. That is the ordering rule doing its work:
6404
6505
  * a caller building the map as it creates blocks passes only the entries already created, so
@@ -6416,13 +6517,27 @@ function relocateBlockIds(params, blockIds) {
6416
6517
  if (typeof node === "string") return remapColumnIdBlockIds(node, remapBlockId);
6417
6518
  if (isColumnUniversalKey(node)) return remapColumnIdBlockIds(node, remapBlockId);
6418
6519
  if (Array.isArray(node)) return node.map(walk);
6419
- if (typeof node === "object" && node !== null) return Object.fromEntries(Object.entries(node).map(([key, value]) => [remapColumnIdBlockIds(key, remapBlockId), walk(value)]));
6520
+ if (typeof node === "object" && node !== null) return Object.fromEntries(Object.entries(node).map(([key, value]) => [remapColumnIdBlockIds(key, remapBlockId), key === "domain" && isPlainObject(value) ? relocateDomain(value) : walk(value)]));
6420
6521
  return node;
6421
6522
  };
6523
+ /**
6524
+ * The block-naming entries of a domain, repointed at the project being built: an axis a block
6525
+ * produced names that block in its domain, so those are references like any other.
6526
+ *
6527
+ * Only the keys {@link BlockScopedDomain} lists, because a template's entry ids are arbitrary
6528
+ * non-empty strings — a hand-written template may name an entry `closest`, and a qualifier
6529
+ * reading `closest` is not a reference to it. Matching the map is not on its own enough to
6530
+ * tell one from the other; the key is.
6531
+ *
6532
+ * Reached only from the generic object case — inside an identifier this package recognizes a
6533
+ * domain is spec data and stays as it is, which is what keeps an overridden column's
6534
+ * `specOverrides.domain` untouched.
6535
+ */
6536
+ const relocateDomain = (domain) => Object.fromEntries(Object.entries(domain).map(([key, value]) => [key, typeof value === "string" && BlockScopedDomain.has(key) ? remapBlockId(value) : walk(value)]));
6422
6537
  return walk(params);
6423
6538
  }
6424
6539
  //#endregion
6425
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_migrations.js
6540
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/block_migrations.js
6426
6541
  /** Create a DataVersioned wrapper with correct shape */
6427
6542
  function makeVersionedData(version, data) {
6428
6543
  return {
@@ -7000,7 +7115,7 @@ var DataModel = class DataModel {
7000
7115
  }
7001
7116
  };
7002
7117
  //#endregion
7003
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/internal.js
7118
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/internal.js
7004
7119
  /** Utility code helping to identify whether the code is running in actual UI environment */
7005
7120
  function isInUI() {
7006
7121
  return typeof globalThis.getPlatforma !== "undefined" || typeof globalThis.platforma !== "undefined";
@@ -7070,7 +7185,7 @@ function registerFutureAwait(handle, onResolve) {
7070
7185
  futureResolves.get(handle).push(onResolve);
7071
7186
  }
7072
7187
  //#endregion
7073
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7188
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7074
7189
  /**
7075
7190
  * All facade callback names as constants.
7076
7191
  * These are the source of truth - the interface is derived from these.
@@ -7108,7 +7223,7 @@ function registerFacadeCallbacks(callbacks) {
7108
7223
  for (const key of Object.values(BlockStorageFacadeCallbacks)) tryRegisterCallback(key, callbacks[key]);
7109
7224
  }
7110
7225
  //#endregion
7111
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/services/block_services.js
7226
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/services/block_services.js
7112
7227
  /**
7113
7228
  * Services required by all V3 blocks by default.
7114
7229
  * Edit this when a new service should be available to all blocks.
@@ -7124,7 +7239,7 @@ const BLOCK_SERVICE_FLAGS = {
7124
7239
  };
7125
7240
  resolveRequiredServices(BLOCK_SERVICE_FLAGS);
7126
7241
  //#endregion
7127
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/future.js
7242
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/future.js
7128
7243
  var FutureRef = class FutureRef {
7129
7244
  handle;
7130
7245
  postProcess;
@@ -7152,7 +7267,7 @@ var FutureRef = class FutureRef {
7152
7267
  }
7153
7268
  };
7154
7269
  //#endregion
7155
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/accessor.js
7270
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/accessor.js
7156
7271
  function ifDef(value, cb) {
7157
7272
  return value === void 0 ? void 0 : cb(value);
7158
7273
  }
@@ -7402,11 +7517,11 @@ var TreeNodeAccessor = class TreeNodeAccessor {
7402
7517
  }
7403
7518
  };
7404
7519
  //#endregion
7405
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/internal.js
7520
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/internal.js
7406
7521
  const MainAccessorName = "main";
7407
7522
  const StagingAccessorName = "staging";
7408
7523
  //#endregion
7409
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7524
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7410
7525
  function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7411
7526
  const sortedFilters = [...axisFilters].sort((a, b) => b[0] - a[0]);
7412
7527
  const { type } = dataInfoEntries;
@@ -7470,7 +7585,7 @@ function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7470
7585
  }
7471
7586
  }
7472
7587
  //#endregion
7473
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7588
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7474
7589
  /**
7475
7590
  * Structural postfix derivation for linked columns (phase 2 of `deriveDistinctLabels`).
7476
7591
  *
@@ -7653,7 +7768,7 @@ function derivePostfixes(entries, format = defaultLinkerFormatter) {
7653
7768
  });
7654
7769
  }
7655
7770
  //#endregion
7656
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7771
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7657
7772
  const DISTANCE_PENALTY = .001;
7658
7773
  const LABEL_TYPE = "__LABEL__";
7659
7774
  const LABEL_TYPE_FULL = "__LABEL__@1";
@@ -7941,7 +8056,7 @@ function repairBareByPresence(labels, minimized, records, stats, forcedSet, forc
7941
8056
  return patched;
7942
8057
  }
7943
8058
  //#endregion
7944
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/label.js
8059
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/util/label.js
7945
8060
  /** @deprecated Use deriveDistinctLabels */
7946
8061
  function deriveLabels(values, getSpec, options = {}) {
7947
8062
  return deriveDistinctLabels(values.map(getSpec), options).map((label, i) => ({
@@ -7950,7 +8065,7 @@ function deriveLabels(values, getSpec, options = {}) {
7950
8065
  }));
7951
8066
  }
7952
8067
  //#endregion
7953
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8068
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
7954
8069
  const RT_RESOURCE_MAP = "PColumnData/ResourceMap";
7955
8070
  const RT_RESOURCE_MAP_PARTITIONED = "PColumnData/Partitioned/ResourceMap";
7956
8071
  const RT_JSON_PARTITIONED = "PColumnData/JsonPartitioned";
@@ -8244,7 +8359,7 @@ function allPColumnsReady(columns) {
8244
8359
  return columns.every(isPColumnReady);
8245
8360
  }
8246
8361
  //#endregion
8247
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8362
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8248
8363
  function isPColumnValues(value) {
8249
8364
  if (!Array.isArray(value)) return false;
8250
8365
  if (value.length === 0) return true;
@@ -8522,7 +8637,7 @@ var PColumnCollection = class {
8522
8637
  }
8523
8638
  };
8524
8639
  //#endregion
8525
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8640
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8526
8641
  /**
8527
8642
  * Builds a ServiceProxy from a ServiceDispatch.
8528
8643
  * Each service method call is forwarded to dispatch.callServiceMethod.
@@ -8531,7 +8646,7 @@ function createServiceProxy(dispatch) {
8531
8646
  return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
8532
8647
  }
8533
8648
  //#endregion
8534
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/services/get_services.js
8649
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/services/get_services.js
8535
8650
  const cachedServices = /* @__PURE__ */ new WeakMap();
8536
8651
  function getService(name, deps) {
8537
8652
  const ctx = deps?.ctx ?? getCfgRenderCtx();
@@ -8545,7 +8660,7 @@ function getService(name, deps) {
8545
8660
  })();
8546
8661
  }
8547
8662
  //#endregion
8548
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8663
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8549
8664
  function patchInSetFilters(filters) {
8550
8665
  const inSetToOrEqual = (predicate) => {
8551
8666
  if (predicate.operator !== "InSet") return predicate;
@@ -8583,7 +8698,7 @@ function patchInSetFilters(filters) {
8583
8698
  return filters.map((filter) => mapFilter(filter, inSetToOrEqual));
8584
8699
  }
8585
8700
  //#endregion
8586
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/api.js
8701
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/render/api.js
8587
8702
  /**
8588
8703
  * Helper function to match domain objects
8589
8704
  * @param query Optional domain to match against
@@ -9032,27 +9147,27 @@ var PluginRenderCtx = class extends RenderCtxBase {
9032
9147
  }
9033
9148
  };
9034
9149
  //#endregion
9035
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/plugin_model.js
9150
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/plugin_model.js
9036
9151
  /** Internal plugin↔block handshake. `Symbol.for` (not `Symbol`) so it stays
9037
9152
  * identical across multiple `@platforma-sdk/model` copies in one process. */
9038
9153
  const CREATE_PLUGIN_MODEL = Symbol.for("@platforma-sdk/model:createPluginModel");
9039
9154
  //#endregion
9040
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/version.js
9041
- const PlatformaSDKVersion = "1.83.9";
9155
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/version.js
9156
+ const PlatformaSDKVersion = "1.83.17";
9042
9157
  //#endregion
9043
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9158
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9044
9159
  function isConfigLambda(cfgOrFh) {
9045
9160
  return cfgOrFh.__renderLambda === true;
9046
9161
  }
9047
9162
  //#endregion
9048
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9163
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9049
9164
  function downgradeCfgOrLambda(data) {
9050
9165
  if (data === void 0) return void 0;
9051
9166
  if (isConfigLambda(data)) return data.handle;
9052
9167
  return data;
9053
9168
  }
9054
9169
  //#endregion
9055
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9170
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9056
9171
  /**
9057
9172
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
9058
9173
  *
@@ -9406,7 +9521,7 @@ function deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams) {
9406
9521
  }
9407
9522
  }
9408
9523
  //#endregion
9409
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_model.js
9524
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/block_model.js
9410
9525
  /**
9411
9526
  * Merges two feature flag objects with type-aware logic:
9412
9527
  * - `supports*` (boolean): OR — `true` if either side is `true`
@@ -9772,7 +9887,7 @@ var BlockModelV3 = class BlockModelV3 {
9772
9887
  }
9773
9888
  };
9774
9889
  //#endregion
9775
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9890
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9776
9891
  /** Create id for column copy with added keys in axes domains */
9777
9892
  const colId = (id, domains, contextDomains) => {
9778
9893
  let wid = id.toString();
@@ -9878,7 +9993,7 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
9878
9993
  })];
9879
9994
  }
9880
9995
  //#endregion
9881
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
9996
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
9882
9997
  /**
9883
9998
  * Replace every column leaf whose id equals `fromId` with `toId`, leaving
9884
9999
  * other column refs (linkers, sub-anchors) intact. Wrapper recipes
@@ -10546,7 +10661,7 @@ var U = class d {
10546
10661
  }
10547
10662
  };
10548
10663
  //#endregion
10549
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10664
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10550
10665
  /**
10551
10666
  * Unified memoised factory dispatching to the right provider flavour by the
10552
10667
  * source shape:
@@ -10635,7 +10750,7 @@ function hashRawPool(rawPool) {
10635
10750
  return rawPool.map((b) => `${b.blockId}\x1f${b.prodCtx ?? ""}\x1f${b.stagingCtx ?? ""}\x1f${b.prodIncomplete ? 1 : 0}\x1f${b.stagingIncomplete ? 1 : 0}`).join("");
10636
10751
  }
10637
10752
  //#endregion
10638
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10753
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10639
10754
  /**
10640
10755
  * Build the default set of ColumnsProviders for the ambient render ctx:
10641
10756
  * - `AccessorColumnsProvider` over `outputs` (if present)
@@ -10670,7 +10785,7 @@ function isColumnProvider(source) {
10670
10785
  return typeof p.getColumns === "function" && typeof p.isFinal === "function";
10671
10786
  }
10672
10787
  //#endregion
10673
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10788
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10674
10789
  /**
10675
10790
  * Thrown by leaf-recipe factories when the requested column is provably
10676
10791
  * absent in the active render ctx — i.e. every relevant accessor reports
@@ -10910,7 +11025,7 @@ function memoizeByEntry(fn) {
10910
11025
  };
10911
11026
  }
10912
11027
  //#endregion
10913
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11028
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
10914
11029
  /**
10915
11030
  * Recipe wrapper that overlays {@link SpecOverrides} on top of any other
10916
11031
  * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.
@@ -11048,7 +11163,7 @@ var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
11048
11163
  }
11049
11164
  };
11050
11165
  //#endregion
11051
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11166
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11052
11167
  /**
11053
11168
  * Recipe wrapper that fixes the values of selected axes of an inner recipe
11054
11169
  * (axis slicing). The id is `FilteredPColumnId { source: inner.id,
@@ -11174,7 +11289,7 @@ function toAxisSelector(axis) {
11174
11289
  return selector;
11175
11290
  }
11176
11291
  //#endregion
11177
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11292
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11178
11293
  /**
11179
11294
  * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching
11180
11295
  * concrete recipe variant based on the id's encoding and recurses on
@@ -11225,7 +11340,7 @@ function ColumnRecipeGetStatus(id, opts = {}) {
11225
11340
  }
11226
11341
  const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
11227
11342
  //#endregion
11228
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11343
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11229
11344
  /**
11230
11345
  * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base
11231
11346
  * column + a `path` of linkers + qualifications.
@@ -11396,7 +11511,7 @@ function referencedUniIdsOf(key) {
11396
11511
  return /* @__PURE__ */ new Set([key.column, ...(key.path ?? []).map((item) => item.column)]);
11397
11512
  }
11398
11513
  //#endregion
11399
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column.js
11514
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/column.js
11400
11515
  /**
11401
11516
  * Unified entry point — routes between the two top-level dispatchers:
11402
11517
  * - string id (`PObjectId` / `ColumnUniversalId`) → {@link ColumnRecipe}
@@ -11410,7 +11525,7 @@ function Column(source, opts) {
11410
11525
  return DataColumn(source, opts);
11411
11526
  }
11412
11527
  //#endregion
11413
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11528
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11414
11529
  /**
11415
11530
  * Build a {@link ColumnsCollection} from sandbox-side source descriptors.
11416
11531
  * Resolves the `columnsCollection` driver (either from `deps.driver` or via
@@ -11519,7 +11634,7 @@ function defaultCtxSources(ctx) {
11519
11634
  return [...currentBlockSources(ctx), { kind: "result_pool" }];
11520
11635
  }
11521
11636
  //#endregion
11522
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/utils.js
11637
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/columns/utils.js
11523
11638
  /**
11524
11639
  * PObjectIds of every non-hit column referenced by `recipe.getQuery()`,
11525
11640
  * deduped in traversal order. The hit column is
@@ -11650,7 +11765,7 @@ function hasSingleDataColumn(recipe) {
11650
11765
  return recipe.getReferencedIds().length === 1;
11651
11766
  }
11652
11767
  //#endregion
11653
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11768
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11654
11769
  function getAllRelatedColumns(ctx, predicate) {
11655
11770
  const columns = new PColumnCollection();
11656
11771
  columns.addColumnProvider(ctx.resultPool);
@@ -11726,7 +11841,7 @@ function discoverIntegrableColumnIds(ctx, rootColumns) {
11726
11841
  }
11727
11842
  }
11728
11843
  //#endregion
11729
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11844
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11730
11845
  function isHiddenFromGraphColumn(column) {
11731
11846
  return !!readAnnotationJson(column, Annotation.HideDataFromGraphs);
11732
11847
  }
@@ -11755,7 +11870,7 @@ function createPFrameForGraphs(ctx, blockColumns) {
11755
11870
  }));
11756
11871
  }
11757
11872
  //#endregion
11758
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/filters/traverse.js
11873
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/filters/traverse.js
11759
11874
  /**
11760
11875
  * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.
11761
11876
  *
@@ -11794,7 +11909,7 @@ function collectFilterSpecColumns(filter) {
11794
11909
  });
11795
11910
  }
11796
11911
  //#endregion
11797
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
11912
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
11798
11913
  /** Converts a QueryColumnId object into a SpecQueryExpression reference. */
11799
11914
  function resolveColumnRef(col) {
11800
11915
  return col.type === "axis" ? {
@@ -12181,7 +12296,7 @@ function isEmpty(value) {
12181
12296
  return true;
12182
12297
  }
12183
12298
  //#endregion
12184
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/filters/distill.js
12299
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/filters/distill.js
12185
12300
  /**
12186
12301
  * Strips non-FilterSpec metadata (whitelist approach) and removes
12187
12302
  * unfilled leaves (type is undefined or any required field is undefined).
@@ -12286,7 +12401,7 @@ const REQUIRED_KEYS_BY_TYPE = {
12286
12401
  greaterThanColumnOrEqual: ["column", "rhs"]
12287
12402
  };
12288
12403
  //#endregion
12289
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12404
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12290
12405
  /** Upgrade PlDataTableStateV2 to the latest version */
12291
12406
  function upgradePlDataTableStateV2(state) {
12292
12407
  if (!state) return createPlDataTableStateV2();
@@ -12644,7 +12759,7 @@ function parseLegacyLeafColumn(s) {
12644
12759
  return parsed;
12645
12760
  }
12646
12761
  //#endregion
12647
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
12762
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
12648
12763
  /** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */
12649
12764
  function toRuleColumn(col) {
12650
12765
  return {
@@ -12742,7 +12857,7 @@ function deriveAllLabels(options) {
12742
12857
  })), deriveLabelsOptions).reduce((acc, label, index) => (acc[columns[index].id] = label, acc), {});
12743
12858
  }
12744
12859
  //#endregion
12745
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
12860
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
12746
12861
  /**
12747
12862
  * Assemble a ptable def directly from recipes. Each secondary recipe is its own
12748
12863
  * outer-joined subtree: `getQuery()` encodes its linker chain, and its
@@ -12806,7 +12921,7 @@ function columnToJoinEntry(col, qualifications) {
12806
12921
  };
12807
12922
  }
12808
12923
  //#endregion
12809
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
12924
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
12810
12925
  function createColumnResolver(columns) {
12811
12926
  const axisIds = [];
12812
12927
  for (const c of columns) for (const ax of c.getSpec().axesSpec) axisIds.push(getAxisId(ax));
@@ -12828,7 +12943,7 @@ function createColumnResolver(columns) {
12828
12943
  };
12829
12944
  }
12830
12945
  //#endregion
12831
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
12946
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
12832
12947
  /**
12833
12948
  * Discover columns from sources/anchors and split them into primary
12834
12949
  * (direct anchor hits — zero-hop, query is a bare column) and secondary
@@ -12874,7 +12989,7 @@ function discoverLabelColumns(ctx, primary) {
12874
12989
  }).getColumns();
12875
12990
  }
12876
12991
  //#endregion
12877
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
12992
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.17/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
12878
12993
  function createPlDataTableV3(ctx, options) {
12879
12994
  const state = upgradePlDataTableStateV2(options.tableState);
12880
12995
  const primaryJoinType = options.primaryJoinType ?? "full";
@@ -12981,7 +13096,7 @@ function resolveInputColumns(ctx, options) {
12981
13096
  secondary: dedupColumns([...secondary, ...labels].filter((c) => !primaryIds.has(c.id)), (c) => c.id, (c) => c.getSpec())
12982
13097
  };
12983
13098
  }
12984
- if (isPlainObject(options.columns)) return discoverTableColumns(ctx, options.columns);
13099
+ if (isPlainObject$1(options.columns)) return discoverTableColumns(ctx, options.columns);
12985
13100
  }
12986
13101
  /** Split secondary recipes by query topology: leaves (no linker chain) vs joined. */
12987
13102
  function splitByTopology(columns) {
@@ -13413,12 +13528,13 @@ const kind = defineBlockKind({
13413
13528
  //#endregion
13414
13529
  //#region ../model/dist/dataModel.js
13415
13530
  /**
13416
- * `readFloor` is deliberately absent rather than 0: those are different runs. Absent applies no
13417
- * floor at all, where 0 would be a floor the block invented.
13418
- *
13419
- * Later shape changes add `.migrate<Next>("Ver_…", prev => …)` links rather than editing this.
13531
+ * `readFloor` is absent rather than 0: absent applies no floor, where 0 would be one the block
13532
+ * invented. Later shape changes add `.migrate<Next>(...)` links rather than editing this.
13420
13533
  */
13421
- const blockDataModel = new DataModelBuilder({ kind }).from("Ver_2026_08_07").init(({ params }) => ({
13534
+ const blockDataModel = new DataModelBuilder({ kind }).from("Ver_2026_08_07").migrate("Ver_2026_09_21", (previous) => ({
13535
+ ...previous,
13536
+ ntResultsTableState: createPlDataTableStateV2()
13537
+ })).init(({ params }) => ({
13422
13538
  conditionColumnRef: params?.conditionColumnRef,
13423
13539
  gateColumnRef: params?.gateColumnRef,
13424
13540
  sortFractionColumnRef: params?.sortFractionColumnRef,
@@ -13429,17 +13545,14 @@ const blockDataModel = new DataModelBuilder({ kind }).from("Ver_2026_08_07").ini
13429
13545
  excludedConditions: [],
13430
13546
  customBlockLabel: "",
13431
13547
  resultsTableState: createPlDataTableStateV2(),
13548
+ ntResultsTableState: createPlDataTableStateV2(),
13432
13549
  distributionGraphStates: {}
13433
13550
  }));
13434
13551
  //#endregion
13435
13552
  //#region ../model/dist/index.js
13436
13553
  /**
13437
- * Every configuration rule, checked here and **nowhere else**. These six are decidable from the
13438
- * arguments and snapshotted column values alone, so they are refused before the run starts.
13439
- *
13440
- * The one data-value rule — sort fractions — belongs to the computation and is deliberately not
13441
- * approximated here: a duplicated rule is one that will disagree, and it fails by drifting
13442
- * looser, so the settings pass and the run fails anyway with a different message.
13554
+ * Every configuration rule, checked here and nowhere else. The one data-value rule (sort
13555
+ * fractions) belongs to the computation and is deliberately not duplicated here.
13443
13556
  */
13444
13557
  function settingsIssues(data) {
13445
13558
  const issues = [];
@@ -13460,23 +13573,21 @@ function settingsIssues(data) {
13460
13573
  }
13461
13574
  if (data.conditionValues.length > 0 && data.conditionValues.every((value) => data.excludedConditions.includes(value))) issues.push("At least one condition must remain — every value is currently excluded");
13462
13575
  if (data.readFloor !== void 0 && data.readFloor < 0) issues.push("The read-count floor cannot be negative");
13576
+ if (data.gatesOrdered === false && data.inputGate === void 0) issues.push("Order the gates, or name an unsorted input — with neither there is nothing to compute");
13577
+ if (data.inputGate !== void 0) {
13578
+ if (data.gateOrder.includes(data.inputGate)) issues.push(`The input '${data.inputGate}' is also a ranked gate — remove it from the gate order`);
13579
+ else if (data.gateValues.length > 0 && !data.gateValues.includes(data.inputGate)) issues.push(`The gate column does not carry the input value '${data.inputGate}'`);
13580
+ }
13463
13581
  return issues;
13464
13582
  }
13465
- /**
13466
- * A bare string in a column selector is treated as a **regex**, so an exact name has to say so
13467
- * — otherwise `pl7.app/label` would also match any longer name containing it.
13468
- */
13583
+ /** A bare string in a selector is a REGEX, so an exact name must say so. */
13469
13584
  function exact(name) {
13470
13585
  return {
13471
13586
  type: "exact",
13472
13587
  value: name
13473
13588
  };
13474
13589
  }
13475
- /**
13476
- * A multi-condition run's column pairs are told apart by the condition domain key alone, so
13477
- * that key is the only place the condition can be read from. Sorted, because conditions carry
13478
- * no order of their own and callers must agree on one.
13479
- */
13590
+ /** Conditions read off the domain key, sorted — they carry no order of their own. */
13480
13591
  function distributionConditionsOf(columns) {
13481
13592
  const conditions = /* @__PURE__ */ new Set();
13482
13593
  for (const column of columns) {
@@ -13486,23 +13597,87 @@ function distributionConditionsOf(columns) {
13486
13597
  return [...conditions].sort();
13487
13598
  }
13488
13599
  /**
13489
- * Called two ways: with an entry for the plot's own title, carrying the drawn-variant count,
13490
- * and without one for the nav, which should name where a link goes rather than how much of it
13491
- * is drawn.
13492
- *
13493
- * The count comes from what the run actually drew, not from the cut the computation applies —
13494
- * that cut is a maximum, so repeating it here would read "Top 20" over a library of twelve. And
13495
- * where nothing was left out the suffix is absent entirely, rather than claiming a caveat.
13600
+ * With an entry for the plot's title, without one for the nav. The count is what the run drew,
13601
+ * not the computation's cut — that is a maximum, and would read "Top 20" over twelve variants.
13496
13602
  */
13497
13603
  function distributionPlotTitle(condition, entry) {
13498
13604
  return entry !== void 0 && entry.variantsPlotted < entry.variantsScored ? `Variant Frequency Top ${entry.variantsPlotted} — ${condition}` : `Variant Frequency — ${condition}`;
13499
13605
  }
13606
+ /**
13607
+ * One scores table for one grain. A nucleotide run emits two column families on two axes, told
13608
+ * apart by the `pl7.app/alphabet` domain. `undefined` where the run produced none.
13609
+ */
13610
+ function buildScoresTable(ctx, alphabet) {
13611
+ const all = ctx.outputs?.resolve("scoresPf")?.getPColumns();
13612
+ if (!all) return void 0;
13613
+ const own = all.filter((column) => column.spec.domain?.[AlphabetDomain] === alphabet);
13614
+ if (own.length === 0) return void 0;
13615
+ const pickAnchor = (name) => own.filter((column) => column.spec.name === name).sort((a, b) => ((a.spec.domain?.[FacsBin.ConditionDomain] ?? "") + "\0" + (a.spec.domain?.[FacsBin.GateDomain] ?? "")).localeCompare((b.spec.domain?.[FacsBin.ConditionDomain] ?? "") + "\0" + (b.spec.domain?.[FacsBin.GateDomain] ?? "")))[0];
13616
+ const anchor = pickAnchor(FacsBin.GateRankMean) ?? pickAnchor(FacsBin.GateEnrichment);
13617
+ if (!anchor) return void 0;
13618
+ const anchorKey = anchor.spec.axesSpec.map((axis) => axis.name).join("\0");
13619
+ const primaryColumns = own.filter((column) => column.spec.axesSpec.map((axis) => axis.name).join("\0") === anchorKey).map((column) => DataColumn.fromColumn(column));
13620
+ const { primary, secondary } = discoverTableColumns(ctx, {
13621
+ anchors: { main: anchor.spec },
13622
+ selector: {
13623
+ mode: "exact",
13624
+ exclude: [{ name: [{
13625
+ type: "regex",
13626
+ value: "^pl7\\.app/facsBin/.*$"
13627
+ }] }]
13628
+ }
13629
+ });
13630
+ return createPlDataTableV3(ctx, {
13631
+ primaryColumns,
13632
+ columns: [...primary, ...secondary],
13633
+ tableState: alphabet === Alphabet.Nucleotide ? ctx.data.ntResultsTableState : ctx.data.resultsTableState,
13634
+ displayOptions: {
13635
+ /**
13636
+ * First match wins, and an unmatched column keeps its own annotation — upstream sets
13637
+ * `default` on nearly everything, so the catch-all last is required.
13638
+ *
13639
+ * `optional` rather than `hidden`: they stay one click away in the column picker.
13640
+ */
13641
+ visibility: [
13642
+ {
13643
+ match: { name: exact(FacsBin.GateRankMean) },
13644
+ visibility: "default"
13645
+ },
13646
+ {
13647
+ match: { name: exact(FacsBin.BinScore) },
13648
+ visibility: "default"
13649
+ },
13650
+ {
13651
+ match: { name: exact(FacsBin.GateEnrichment) },
13652
+ visibility: "default"
13653
+ },
13654
+ {
13655
+ match: { name: exact(FacsBin.GateEnrichmentVsBaseline) },
13656
+ visibility: "default"
13657
+ },
13658
+ {
13659
+ match: { name: exact(PColumnName$1.VariantLabel) },
13660
+ visibility: "default"
13661
+ },
13662
+ {
13663
+ match: { name: exact(PColumnName$1.Mutations) },
13664
+ visibility: "default"
13665
+ },
13666
+ {
13667
+ match: { name: ".*" },
13668
+ visibility: "optional"
13669
+ }
13670
+ ] }
13671
+ });
13672
+ }
13500
13673
  const platforma$1 = BlockModelV3.create({
13501
13674
  dataModel: blockDataModel,
13502
13675
  kind
13503
13676
  }).args((data) => {
13504
13677
  const issues = settingsIssues(data);
13505
13678
  if (issues.length > 0) throw new Error(issues.join("; "));
13679
+ data.inputGate;
13680
+ const ordered = data.gatesOrdered !== false;
13506
13681
  return {
13507
13682
  abundanceRef: data.abundanceRef,
13508
13683
  conditionColumnRef: data.conditionColumnRef,
@@ -13510,7 +13685,11 @@ const platforma$1 = BlockModelV3.create({
13510
13685
  gateRanks: Object.fromEntries(data.gateOrder.map((gate, index) => [gate, index + 1])),
13511
13686
  excludedConditions: [...data.excludedConditions].sort(),
13512
13687
  readFloor: data.readFloor,
13513
- sortFractionColumnRef: data.sortFractionColumnRef
13688
+ sortFractionColumnRef: data.sortFractionColumnRef,
13689
+ inputGate: data.inputGate,
13690
+ gatesOrdered: ordered ? void 0 : false,
13691
+ baseline: void 0,
13692
+ baselineSequence: void 0
13514
13693
  };
13515
13694
  }).output("abundanceOptions", (ctx) => ctx.resultPool.getOptions(isAbundanceAnchor)).output("metadataColumns", (ctx) => {
13516
13695
  const anchor = ctx.data.abundanceRef;
@@ -13524,6 +13703,11 @@ const platforma$1 = BlockModelV3.create({
13524
13703
  objectId: column.id,
13525
13704
  label: column.spec.annotations?.[Annotation$1.Label] ?? column.spec.name
13526
13705
  }));
13706
+ }).output("datasetIsNucleotide", (ctx) => {
13707
+ const anchor = ctx.data.abundanceRef;
13708
+ if (!anchor) return void 0;
13709
+ const alphabet = ctx.resultPool.getPColumnSpecByRef(anchor)?.axesSpec?.[1]?.domain?.[AlphabetDomain];
13710
+ return alphabet === void 0 ? void 0 : alphabet === Alphabet.Nucleotide;
13527
13711
  }).output("conditionOptions", (ctx) => narrowTo(ctx, "conditionColumnRef")).output("gateOptions", (ctx) => narrowTo(ctx, "gateColumnRef")).output("sortFractionOptions", (ctx) => narrowTo(ctx, "sortFractionColumnRef")).output("metadataColumnsPframe", (ctx) => {
13528
13712
  const anchor = ctx.data.abundanceRef;
13529
13713
  if (!anchor) return void 0;
@@ -13540,62 +13724,15 @@ const platforma$1 = BlockModelV3.create({
13540
13724
  const anchor = ctx.data.abundanceRef;
13541
13725
  if (!anchor) return void 0;
13542
13726
  return ctx.resultPool.getAnchoredPColumns({ main: anchor }, [sampleLabelSelector])?.[0]?.id;
13543
- }).outputWithStatus("resultsTable", (ctx) => {
13727
+ }).outputWithStatus("resultsTable", (ctx) => buildScoresTable(ctx, Alphabet.AminoAcid)).outputWithStatus("ntResultsTable", (ctx) => buildScoresTable(ctx, Alphabet.Nucleotide)).output("scoreLevels", (ctx) => {
13544
13728
  const own = ctx.outputs?.resolve("scoresPf")?.getPColumns();
13545
13729
  if (!own) return void 0;
13546
- const anchor = own.filter((column) => column.spec.name === FacsBin.GateRankMean).sort((a, b) => (a.spec.domain?.[FacsBin.ConditionDomain] ?? "").localeCompare(b.spec.domain?.[FacsBin.ConditionDomain] ?? ""))[0];
13547
- if (!anchor) return void 0;
13548
- const primaryColumns = own.map((column) => DataColumn.fromColumn(column));
13549
- const { primary, secondary } = discoverTableColumns(ctx, {
13550
- anchors: { main: anchor.spec },
13551
- selector: {
13552
- mode: "exact",
13553
- exclude: [{ name: [{
13554
- type: "regex",
13555
- value: "^pl7\\.app/facsBin/.*$"
13556
- }] }]
13557
- }
13558
- });
13559
- return createPlDataTableV3(ctx, {
13560
- primaryColumns,
13561
- columns: [...primary, ...secondary],
13562
- tableState: ctx.data.resultsTableState,
13563
- displayOptions: {
13564
- /**
13565
- * First match wins, and an **unmatched column keeps its own annotation** — which
13566
- * upstream sets to `default` on nearly everything, so without the catch-all last the
13567
- * table opens with every reachable column on screen.
13568
- *
13569
- * `optional` rather than `hidden` for the remainder: they stay one click away in the
13570
- * column picker. Hiding a column a user wants, with no way to bring it back, is the
13571
- * worse failure.
13572
- *
13573
- * The two score rules are the block's own columns, which are primary and therefore
13574
- * always on screen; the rules state their visibility for the column picker's sake.
13575
- */
13576
- visibility: [
13577
- {
13578
- match: { name: exact(FacsBin.GateRankMean) },
13579
- visibility: "default"
13580
- },
13581
- {
13582
- match: { name: exact(FacsBin.BinScore) },
13583
- visibility: "default"
13584
- },
13585
- {
13586
- match: { name: exact(PColumnName$1.VariantLabel) },
13587
- visibility: "default"
13588
- },
13589
- {
13590
- match: { name: exact(PColumnName$1.Mutations) },
13591
- visibility: "default"
13592
- },
13593
- {
13594
- match: { name: ".*" },
13595
- visibility: "optional"
13596
- }
13597
- ] }
13598
- });
13730
+ const levels = /* @__PURE__ */ new Set();
13731
+ for (const column of own) {
13732
+ const alphabet = column.spec.domain?.[AlphabetDomain];
13733
+ if (alphabet !== void 0) levels.add(alphabet);
13734
+ }
13735
+ return [...levels].sort();
13599
13736
  }).output("distributionConditions", (ctx) => {
13600
13737
  const columns = ctx.outputs?.resolve("distributionPf")?.getPColumns();
13601
13738
  if (!columns) return void 0;
@@ -13611,7 +13748,19 @@ visibility: [
13611
13748
  id: column.id,
13612
13749
  spec: column.spec
13613
13750
  }));
13614
- }).output("manifest", (ctx) => ctx.outputs?.resolve("manifest")?.getDataAsJsonOrUndefined()).output("logHandle", (ctx) => ctx.outputs?.resolve("logHandle")?.getLogHandle()).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).output("settingsIssues", (ctx) => settingsIssues(ctx.data)).output("defaultBlockLabel", (ctx) => deriveBlockLabel(ctx.data)).templateParams((data) => ({
13751
+ }).output("manifest", (ctx) => ctx.outputs?.resolve("manifest")?.getDataAsJsonOrUndefined()).output("logHandle", (ctx) => ctx.outputs?.resolve("logHandle")?.getLogHandle()).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).output("settingsIssues", (ctx) => settingsIssues(ctx.data)).output("runShape", (ctx) => {
13752
+ const ordered = ctx.data.gatesOrdered !== false;
13753
+ const enrichment = ctx.data.inputGate !== void 0;
13754
+ if (!ordered && !enrichment) return {
13755
+ level: "warn",
13756
+ message: "Order the gates, or name an unsorted input to run the block."
13757
+ };
13758
+ const metrics = [...ordered ? ["Mean bin", "Mean bin vs parent"] : [], ...enrichment ? ["Enrichment per gate"] : []];
13759
+ return {
13760
+ level: "info",
13761
+ message: `With ${ordered ? "ordered gates" : "unordered gates"}${enrichment ? " and an unsorted input" : ""}, the following ${metrics.length === 1 ? "metric" : "metrics"} will be produced: ${metrics.join(", ")}.`
13762
+ };
13763
+ }).output("defaultBlockLabel", (ctx) => deriveBlockLabel(ctx.data)).templateParams((data) => ({
13615
13764
  conditionColumnRef: data.conditionColumnRef,
13616
13765
  gateColumnRef: data.gateColumnRef,
13617
13766
  sortFractionColumnRef: data.sortFractionColumnRef,
@@ -13621,24 +13770,27 @@ visibility: [
13621
13770
  conditionValues: data.conditionValues
13622
13771
  })).title(() => "Sort-Seq Analysis").subtitle((ctx) => ctx.data.customBlockLabel || deriveBlockLabel(ctx.data)).sections((ctx) => {
13623
13772
  const columns = ctx.outputs?.resolve("distributionPf")?.getPColumns();
13624
- return [{
13625
- type: "link",
13626
- href: "/",
13627
- label: "Variant Scores"
13628
- }, ...(columns ? distributionConditionsOf(columns) : []).map((condition) => ({
13629
- type: "link",
13630
- href: `/distribution?condition=${encodeURIComponent(condition)}`,
13631
- label: distributionPlotTitle(condition)
13632
- }))];
13773
+ return [
13774
+ {
13775
+ type: "link",
13776
+ href: "/",
13777
+ label: "AA Scores"
13778
+ },
13779
+ ...(ctx.outputs?.resolve("scoresPf")?.getPColumns() ?? []).some((column) => column.spec.domain?.["pl7.app/alphabet"] === Alphabet.Nucleotide) ? [{
13780
+ type: "link",
13781
+ href: "/nt",
13782
+ label: "NT Scores"
13783
+ }] : [],
13784
+ ...(columns ? distributionConditionsOf(columns) : []).map((condition) => ({
13785
+ type: "link",
13786
+ href: `/distribution?condition=${encodeURIComponent(condition)}`,
13787
+ label: distributionPlotTitle(condition)
13788
+ }))
13789
+ ];
13633
13790
  }).done();
13634
13791
  /**
13635
- * The block subtitle when the user has not overridden it.
13636
- *
13637
- * The gate selection is what distinguishes two instances of this block on one project —
13638
- * same dataset, different gate column or different gate order — so that is what the label
13639
- * names. It reads along the binding axis: weakest gate first, strongest last.
13640
- *
13641
- * A pure function of `data`, which is what keeps the subtitle out of hairpin territory.
13792
+ * The block subtitle when the user has not overridden it. The gate selection is what
13793
+ * distinguishes two instances on one project. A pure function of `data`.
13642
13794
  */
13643
13795
  function deriveBlockLabel(data) {
13644
13796
  const ordered = data.gateOrder;
@@ -13646,12 +13798,9 @@ function deriveBlockLabel(data) {
13646
13798
  return `${data.gateColumnLabel}: ${ordered.join("-")}`;
13647
13799
  }
13648
13800
  /**
13649
- * The metadata options minus whatever the other two roles already hold.
13650
- *
13651
- * The pickers narrow; they do not re-check distinctness. That refusal stays the single check
13652
- * in `args` — hiding a column another role holds keeps the user away from a refusal whose
13653
- * cause is not visible on the control. A role never hides its own current pick, or the
13654
- * control would render with no matching option and look empty.
13801
+ * The metadata options minus what the other two roles hold. The distinctness refusal stays in
13802
+ * `args`; this only keeps the user away from it. A role never hides its own current pick, or
13803
+ * the control renders empty.
13655
13804
  */
13656
13805
  function narrowTo(ctx, role) {
13657
13806
  const all = metadataColumnsOf(ctx);