@tangle-network/agent-eval 0.198.0 → 0.198.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +3 -1
- package/dist/adapters/http.d.ts +1 -1
- package/dist/analyst/index.d.ts +1 -1
- package/dist/analyst/index.js +1 -1
- package/dist/{benchmark-command-D8E5TaPC.js → benchmark-command-DKQuLrrD.js} +2 -2
- package/dist/{benchmark-command-D8E5TaPC.js.map → benchmark-command-DKQuLrrD.js.map} +1 -1
- package/dist/benchmarks/index.d.ts +2 -2
- package/dist/benchmarks/index.js +2 -2
- package/dist/campaign/index.d.ts +2 -2
- package/dist/campaign/index.js +5 -5
- package/dist/{campaign-Dlg2iOzH.js → campaign-DRdKwxm-.js} +6 -6
- package/dist/{campaign-Dlg2iOzH.js.map → campaign-DRdKwxm-.js.map} +1 -1
- package/dist/cli.js +16 -12
- package/dist/cli.js.map +1 -1
- package/dist/contract/index.d.ts +4 -4
- package/dist/contract/index.js +3 -3
- package/dist/{define-agent-eval-By9PImpa.d.ts → define-agent-eval-9JYoCkDI.d.ts} +3 -3
- package/dist/{define-agent-eval-By9PImpa.d.ts.map → define-agent-eval-9JYoCkDI.d.ts.map} +1 -1
- package/dist/{define-agent-eval-DvBgSzAI.js → define-agent-eval-DkfcqaCF.js} +2 -2
- package/dist/{define-agent-eval-DvBgSzAI.js.map → define-agent-eval-DkfcqaCF.js.map} +1 -1
- package/dist/{index-BhoOCduB.d.ts → index-BXJHJ_jE.d.ts} +2 -2
- package/dist/{index-BhoOCduB.d.ts.map → index-BXJHJ_jE.d.ts.map} +1 -1
- package/dist/{index-D-tI1vgf.d.ts → index-DzQ6T34s.d.ts} +3 -3
- package/dist/{index-D-tI1vgf.d.ts.map → index-DzQ6T34s.d.ts.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/{llm-judge-BYWXsxhZ.js → llm-judge-3ncNcWNT.js} +3 -3
- package/dist/{llm-judge-BYWXsxhZ.js.map → llm-judge-3ncNcWNT.js.map} +1 -1
- package/dist/openapi.json +1 -1
- package/dist/{produced-state-DOfmCEwP.js → produced-state-qIhqN3V5.js} +2 -2
- package/dist/{produced-state-DOfmCEwP.js.map → produced-state-qIhqN3V5.js.map} +1 -1
- package/dist/search/index.d.ts +39 -14
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +2 -2
- package/dist/{search-kernel-D8_kxChy.js → search-kernel-CumYAjA3.js} +55 -27
- package/dist/search-kernel-CumYAjA3.js.map +1 -0
- package/dist/{search-kernel-CuvbakC_.d.ts → search-kernel-TLoiMMcq.d.ts} +15 -6
- package/dist/search-kernel-TLoiMMcq.d.ts.map +1 -0
- package/dist/{search-summary-Dmppg8kV.js → search-summary-dJOaZ3Dw.js} +2 -2
- package/dist/{search-summary-Dmppg8kV.js.map → search-summary-dJOaZ3Dw.js.map} +1 -1
- package/dist/{skillopt-optimization-method-BMP2qV_1.js → skillopt-optimization-method-BL_j6mX8.js} +2 -2
- package/dist/{skillopt-optimization-method-BMP2qV_1.js.map → skillopt-optimization-method-BL_j6mX8.js.map} +1 -1
- package/dist/{tree-DHHWsH-X.js → tree-DxGfhISA.js} +115 -60
- package/dist/tree-DxGfhISA.js.map +1 -0
- package/docs/search-ledger.md +6 -4
- package/docs/trace-contracts.md +1 -3
- package/package.json +1 -1
- package/dist/search-kernel-CuvbakC_.d.ts.map +0 -1
- package/dist/search-kernel-D8_kxChy.js.map +0 -1
- package/dist/tree-DHHWsH-X.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { a as hashCanonical, i as compareCodeUnits, r as canonicalString } from "./canonical-BsZVgBhW.js";
|
|
2
|
-
import { s as zQuantile } from "./internal-BMFSR8Ns.js";
|
|
2
|
+
import { a as medianInPlace, s as zQuantile } from "./internal-BMFSR8Ns.js";
|
|
3
3
|
import { t as mulberry32 } from "./random-Dn5fPWkt.js";
|
|
4
4
|
import { r as holm } from "./multiplicity-D9cjmStq.js";
|
|
5
5
|
import { a as pairedSignTest, n as DECISION_PAIRED_DELTA_STATISTIC } from "./paired-tests-C8iCsioC.js";
|
|
6
6
|
import { i as pairedDeltaTest, r as minimumPairsForPairedDeltaTest } from "./paired-promotion-decision-D5B1Cxc2.js";
|
|
7
|
-
import { C as
|
|
7
|
+
import { C as searchEstimateMethod, D as paretoFrontier, T as seedFromDigest, _ as rankingSplit, a as searchPolicyView, b as estimateNode, g as INSUFFICIENT_FROM, u as verifySearchClaim, v as summarizeSamples, w as searchPosterior } from "./search-kernel-CumYAjA3.js";
|
|
8
8
|
import { f as searchUnitScores } from "./search-ledger-BnUytR8X.js";
|
|
9
9
|
import { defineInlineResource } from "@tangle-network/agent-interface";
|
|
10
10
|
//#region src/search/lenses/edit-credit.ts
|
|
@@ -594,7 +594,7 @@ function lineageRows(state, nodes, byId, contents, carried) {
|
|
|
594
594
|
*/
|
|
595
595
|
function pairedEstimate(input) {
|
|
596
596
|
const pairs = input.carrier.length;
|
|
597
|
-
const method =
|
|
597
|
+
const method = searchEstimateMethod(pairs);
|
|
598
598
|
const base = {
|
|
599
599
|
against: input.against,
|
|
600
600
|
split: input.split,
|
|
@@ -663,12 +663,6 @@ const chanceReusable = (() => {
|
|
|
663
663
|
return size;
|
|
664
664
|
};
|
|
665
665
|
})();
|
|
666
|
-
function methodFor(units) {
|
|
667
|
-
if (units < 2) return "none";
|
|
668
|
-
if (units < DESCRIPTIVE_FROM) return "insufficient";
|
|
669
|
-
if (units < 20) return "descriptive";
|
|
670
|
-
return "bootstrap";
|
|
671
|
-
}
|
|
672
666
|
/** The worse end of the interval, as an improvement; -Infinity without one. */
|
|
673
667
|
function improvementLow(credit, sign) {
|
|
674
668
|
if (credit.interval === null) return Number.NEGATIVE_INFINITY;
|
|
@@ -765,7 +759,7 @@ function interactionPairs(input) {
|
|
|
765
759
|
}
|
|
766
760
|
function interactionEstimate(genes, steps, values, sign) {
|
|
767
761
|
const units = values.length;
|
|
768
|
-
const method =
|
|
762
|
+
const method = searchEstimateMethod(units);
|
|
769
763
|
const base = {
|
|
770
764
|
genes,
|
|
771
765
|
steps,
|
|
@@ -933,6 +927,25 @@ function plain(value) {
|
|
|
933
927
|
}
|
|
934
928
|
//#endregion
|
|
935
929
|
//#region src/search/lenses/front.ts
|
|
930
|
+
/**
|
|
931
|
+
* `front(state, axes)`: the Pareto front over a node's score and its known
|
|
932
|
+
* cost per cell, with room for caller-declared axes (search-tree-design §12).
|
|
933
|
+
*
|
|
934
|
+
* Reuses the existing frontier primitive (`../../pareto`, already the parent
|
|
935
|
+
* selector behind `crowdedFrontierParent` in `search-policy.ts`) rather than
|
|
936
|
+
* a second dominance implementation.
|
|
937
|
+
*
|
|
938
|
+
* The cost axis is the node's cost per attempted cell on the ranking split,
|
|
939
|
+
* not its total spend: an allocator gives a node more cells as it advances,
|
|
940
|
+
* so a total would rank a node by how far it was measured, and a node pruned
|
|
941
|
+
* after its screen would look cheap only for having run fewer cells. A node
|
|
942
|
+
* enters the frontier only when its score rests on 2 or more units (one unit
|
|
943
|
+
* is no estimate, §6.4), every attempted cell on the split has a known cost
|
|
944
|
+
* (an unknown cost is never floored to its known partial or imputed), and it
|
|
945
|
+
* was not decided `invalid` (a judge integrity or admission failure, whose
|
|
946
|
+
* score a reward hack may have produced; such a node never becomes a parent,
|
|
947
|
+
* §6.6).
|
|
948
|
+
*/
|
|
936
949
|
function front(state, options = {}) {
|
|
937
950
|
const split = options.split ?? rankingSplit(state);
|
|
938
951
|
const direction = state.header?.objective.direction ?? "maximize";
|
|
@@ -940,15 +953,31 @@ function front(state, options = {}) {
|
|
|
940
953
|
const rows = state.nodes().map((node) => {
|
|
941
954
|
const units = state.unitScores(node.nodeId, split);
|
|
942
955
|
const score = units.length > 0 ? units.reduce((sum, u) => sum + u.mean, 0) / units.length : null;
|
|
956
|
+
let attempted = 0;
|
|
957
|
+
let spent = 0;
|
|
958
|
+
let known = true;
|
|
959
|
+
for (const cell of state.cells({ nodeId: node.nodeId })) {
|
|
960
|
+
if (cell.split !== split || cell.attempts === 0) continue;
|
|
961
|
+
attempted += 1;
|
|
962
|
+
spent += cell.spentUsd;
|
|
963
|
+
if (!cell.costKnown) known = false;
|
|
964
|
+
}
|
|
965
|
+
const extra = extraAxes.map((axis) => axis.value(state, node.nodeId));
|
|
966
|
+
const costPerCellUsd = known && attempted > 0 ? spent / attempted : null;
|
|
967
|
+
const excluded = node.status === "invalid" ? "invalid" : score === null ? "unscored" : units.length < 2 ? "one-unit" : costPerCellUsd === null ? "unknown-cost" : extra.every((value) => Number.isFinite(value)) ? null : "extra-axis";
|
|
943
968
|
return {
|
|
944
969
|
nodeId: node.nodeId,
|
|
945
970
|
score,
|
|
971
|
+
units: units.length,
|
|
972
|
+
method: searchEstimateMethod(units.length),
|
|
973
|
+
costPerCellUsd,
|
|
946
974
|
knownCostUsd: node.spend.knownUsd,
|
|
947
975
|
costKnown: node.spend.unknownCostCells === 0,
|
|
948
|
-
|
|
976
|
+
excluded,
|
|
977
|
+
extra
|
|
949
978
|
};
|
|
950
979
|
});
|
|
951
|
-
const eligible = rows.filter((row) => row.
|
|
980
|
+
const eligible = rows.filter((row) => row.excluded === null);
|
|
952
981
|
const objectives = [
|
|
953
982
|
{
|
|
954
983
|
name: "score",
|
|
@@ -956,9 +985,9 @@ function front(state, options = {}) {
|
|
|
956
985
|
value: (row) => row.score
|
|
957
986
|
},
|
|
958
987
|
{
|
|
959
|
-
name: "
|
|
988
|
+
name: "costPerCellUsd",
|
|
960
989
|
direction: "minimize",
|
|
961
|
-
value: (row) => row.
|
|
990
|
+
value: (row) => row.costPerCellUsd
|
|
962
991
|
},
|
|
963
992
|
...extraAxes.map((axis, index) => ({
|
|
964
993
|
name: axis.name,
|
|
@@ -967,13 +996,20 @@ function front(state, options = {}) {
|
|
|
967
996
|
}))
|
|
968
997
|
];
|
|
969
998
|
const frontierIds = eligible.length > 0 ? new Set(paretoFrontier(eligible, objectives).frontier.map((r) => r.nodeId)) : /* @__PURE__ */ new Set();
|
|
970
|
-
const
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
}
|
|
999
|
+
const exclusions = {
|
|
1000
|
+
invalid: 0,
|
|
1001
|
+
unscored: 0,
|
|
1002
|
+
"one-unit": 0,
|
|
1003
|
+
"unknown-cost": 0,
|
|
1004
|
+
"extra-axis": 0
|
|
1005
|
+
};
|
|
1006
|
+
const outRows = rows.map(({ extra: _extra, ...row }) => {
|
|
1007
|
+
if (row.excluded) exclusions[row.excluded] += 1;
|
|
1008
|
+
return {
|
|
1009
|
+
...row,
|
|
1010
|
+
onFront: frontierIds.has(row.nodeId)
|
|
1011
|
+
};
|
|
1012
|
+
});
|
|
977
1013
|
const signalValue = {};
|
|
978
1014
|
for (const row of outRows) signalValue[row.nodeId] = row.onFront ? 1 : 0;
|
|
979
1015
|
return {
|
|
@@ -982,7 +1018,8 @@ function front(state, options = {}) {
|
|
|
982
1018
|
axes: objectives.map((o) => o.name),
|
|
983
1019
|
rows: outRows,
|
|
984
1020
|
frontierSize: frontierIds.size,
|
|
985
|
-
excludedCount: rows.length - eligible.length
|
|
1021
|
+
excludedCount: rows.length - eligible.length,
|
|
1022
|
+
exclusions
|
|
986
1023
|
},
|
|
987
1024
|
signal: {
|
|
988
1025
|
name: "front.membership",
|
|
@@ -990,13 +1027,6 @@ function front(state, options = {}) {
|
|
|
990
1027
|
}
|
|
991
1028
|
};
|
|
992
1029
|
}
|
|
993
|
-
/** The method `estimateNode` reports for a paired sample of `pairs` units. */
|
|
994
|
-
function estimateMethodFor(pairs) {
|
|
995
|
-
if (pairs < 2) return "none";
|
|
996
|
-
if (pairs < INSUFFICIENT_FROM) return "insufficient";
|
|
997
|
-
if (pairs < 20) return "descriptive";
|
|
998
|
-
return "bootstrap";
|
|
999
|
-
}
|
|
1000
1030
|
/**
|
|
1001
1031
|
* Nodes whose screen finished, in registration order, root first: the
|
|
1002
1032
|
* ledger's reading of the kernel's `screened` list. A node counts once it is
|
|
@@ -1034,10 +1064,7 @@ function round9(value) {
|
|
|
1034
1064
|
return rounded === 0 ? 0 : rounded;
|
|
1035
1065
|
}
|
|
1036
1066
|
function median(values) {
|
|
1037
|
-
|
|
1038
|
-
const sorted = [...values].sort((left, right) => left - right);
|
|
1039
|
-
const middle = Math.floor(sorted.length / 2);
|
|
1040
|
-
return sorted.length % 2 === 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
1067
|
+
return values.length === 0 ? null : medianInPlace([...values]);
|
|
1041
1068
|
}
|
|
1042
1069
|
/** At most `cap` items, evenly spaced by position: a deterministic sample
|
|
1043
1070
|
* that keeps a quadratic step bounded on a large search. */
|
|
@@ -1446,11 +1473,11 @@ function lineEditDistance(a, b) {
|
|
|
1446
1473
|
}
|
|
1447
1474
|
return max;
|
|
1448
1475
|
}
|
|
1449
|
-
const GRID_METHOD = "Gaussian-process regression (ordinary kriging) of node scores: a constant mean (generalized least squares), a squared-exponential covariance whose prior variance is the between-node variance of the scores minus their mean noise and whose length scale maximizes the marginal likelihood over 0.5, 1, 2 and 4 times the median nearest-neighbour distance, and each node's own noise variance (the pooled between-unit variance over its units shared with the root; the root is the reference at exactly 0); nodes with fewer than 2 shared units are left out; a cell is null where the posterior variance exceeds half the prior variance, so the surface never extends past the nodes that support it; no surface is drawn unless the length scale raises the log-likelihood by 1 or more over independent node scores";
|
|
1476
|
+
const GRID_METHOD = "Gaussian-process regression (ordinary kriging) of node scores: a constant mean (generalized least squares), a squared-exponential covariance whose prior variance is the between-node variance of the scores minus their mean noise and whose length scale maximizes the marginal likelihood over 0.5, 1, 2 and 4 times the median nearest-neighbour distance, and each node's own noise variance (the pooled between-unit variance over its units shared with the root; the root is the reference at exactly 0); nodes with fewer than 2 shared units, and nodes decided invalid, are left out; a cell is null where the posterior variance exceeds half the prior variance, so the surface never extends past the nodes that support it; no surface is drawn unless the length scale raises the log-likelihood by 1 or more over independent node scores";
|
|
1450
1477
|
/** Scored nodes a surface or a basin count needs: the library's minimum
|
|
1451
1478
|
* sample for anything descriptive, as for units. */
|
|
1452
1479
|
const SURFACE_MIN_NODES = INSUFFICIENT_FROM;
|
|
1453
|
-
const BASIN_METHOD = "0-dimensional persistence of node scores on the symmetric k-nearest-neighbour graph of placed nodes, read on the leading MDS axes that hold 80% of the positive eigenvalue mass (2 to 8), joined into one component by the shortest edge between components (ToMATo, Chazal et al. 2013): nodes enter from the highest score down, and where two components meet, the lower peak merges into the higher unless it stands above that saddle node by z standard errors of their difference, sqrt(pooled variance / shared units) per node, where z is the standard-normal quantile at 1 − 0.05 / (local maxima − 1), a Bonferroni bound over every peak that could survive, so a flat landscape of noisy nodes counts one basin at least 95% of the time; at most 2000 nodes, evenly spaced by registration plus the 100 best";
|
|
1480
|
+
const BASIN_METHOD = "0-dimensional persistence of node scores on the symmetric k-nearest-neighbour graph of placed nodes (not decided invalid, 2 or more units shared with the root), read on the leading MDS axes that hold 80% of the positive eigenvalue mass (2 to 8), joined into one component by the shortest edge between components (ToMATo, Chazal et al. 2013): nodes enter from the highest score down, and where two components meet, the lower peak merges into the higher unless it stands above that saddle node by z standard errors of their difference, sqrt(pooled variance / shared units) per node, where z is the standard-normal quantile at 1 − 0.05 / (local maxima − 1), a Bonferroni bound over every peak that could survive, so a flat landscape of noisy nodes counts one basin at least 95% of the time; at most 2000 nodes, evenly spaced by registration plus the 100 best";
|
|
1454
1481
|
/** Nodes the basin graph holds: evenly spaced by registration, plus the best. */
|
|
1455
1482
|
const BASIN_NODES = 2e3;
|
|
1456
1483
|
const BASIN_TOP = 100;
|
|
@@ -1506,7 +1533,7 @@ function landscape(state, embed = lineageEdits(), options = {}) {
|
|
|
1506
1533
|
score: entry.mean === null || entry.pairs < 2 && node.nodeId !== rootNodeId ? null : round9(entry.mean),
|
|
1507
1534
|
standardError: entry.variance === null ? null : round9(Math.sqrt(entry.variance)),
|
|
1508
1535
|
pairs: entry.pairs,
|
|
1509
|
-
method:
|
|
1536
|
+
method: searchEstimateMethod(entry.pairs),
|
|
1510
1537
|
basin: null
|
|
1511
1538
|
};
|
|
1512
1539
|
});
|
|
@@ -1522,7 +1549,7 @@ function landscape(state, embed = lineageEdits(), options = {}) {
|
|
|
1522
1549
|
});
|
|
1523
1550
|
}
|
|
1524
1551
|
}
|
|
1525
|
-
const scored = records.filter((record) => record.x !== null && record.score !== null && record.pairs >= 2);
|
|
1552
|
+
const scored = records.filter((record) => record.x !== null && record.score !== null && record.pairs >= 2 && record.status !== "invalid");
|
|
1526
1553
|
const gridResult = krige(records, scored, new Map(posterior.nodes.map((entry) => [entry.nodeId, entry.variance])), columns, surfaceNodes);
|
|
1527
1554
|
const fullOf = /* @__PURE__ */ new Map();
|
|
1528
1555
|
nodes.forEach((node, position) => {
|
|
@@ -1785,7 +1812,7 @@ function distanceRows(nodes, embed, adjacency) {
|
|
|
1785
1812
|
function krige(records, scored, variances, columns, surfaceNodes) {
|
|
1786
1813
|
if (scored.length < SURFACE_MIN_NODES) return {
|
|
1787
1814
|
grid: null,
|
|
1788
|
-
insufficient: `${plural$1(scored.length, "placed node")} share 2 or more units with the root; a surface needs ${SURFACE_MIN_NODES}`
|
|
1815
|
+
insufficient: `${plural$1(scored.length, "placed node")} not decided invalid share 2 or more units with the root; a surface needs ${SURFACE_MIN_NODES}`
|
|
1789
1816
|
};
|
|
1790
1817
|
const noiseOf = (node) => variances.get(node.nodeId) ?? null;
|
|
1791
1818
|
if (scored.some((node) => noiseOf(node) === null)) return {
|
|
@@ -2013,7 +2040,7 @@ function graphBasins(records, scoredNodes, fullOf, space, pooledVariance, degree
|
|
|
2013
2040
|
peaks: []
|
|
2014
2041
|
});
|
|
2015
2042
|
let scored = scoredNodes;
|
|
2016
|
-
if (scored.length < SURFACE_MIN_NODES) return empty(`${plural$1(scored.length, "placed node")} share 2 or more units with the root; basins need ${SURFACE_MIN_NODES}`);
|
|
2043
|
+
if (scored.length < SURFACE_MIN_NODES) return empty(`${plural$1(scored.length, "placed node")} not decided invalid share 2 or more units with the root; basins need ${SURFACE_MIN_NODES}`);
|
|
2017
2044
|
if (pooledVariance === null || pooledVariance <= 0) return empty("no pooled between-unit variance, so the noise a peak must clear is unknown");
|
|
2018
2045
|
const sample = new Set(evenSample(scored, BASIN_NODES));
|
|
2019
2046
|
for (const node of [...scored].sort((left, right) => right.score - left.score || left.ordinal - right.ordinal).slice(0, BASIN_TOP)) sample.add(node);
|
|
@@ -3045,7 +3072,7 @@ function skillManifold(state, k = "auto", options = {}) {
|
|
|
3045
3072
|
} else leaderRows = matrix.rows.map((row, index) => ({
|
|
3046
3073
|
row,
|
|
3047
3074
|
index
|
|
3048
|
-
})).filter(({ row }) => row.observed.size >= leaderFloor).sort((left, right) => sign * (predicted(fit.coordinates[right.index]) - predicted(fit.coordinates[left.index])) || left.row.ordinal - right.row.ordinal).slice(0, leaderCount).map(({ index }) => index);
|
|
3075
|
+
})).filter(({ row }) => row.observed.size >= leaderFloor && row.status !== "invalid").sort((left, right) => sign * (predicted(fit.coordinates[right.index]) - predicted(fit.coordinates[left.index])) || left.row.ordinal - right.row.ordinal).slice(0, leaderCount).map(({ index }) => index);
|
|
3049
3076
|
const leaderSet = new Set(leaderRows);
|
|
3050
3077
|
const next = intrinsic.value === 0 ? {
|
|
3051
3078
|
ranked: [],
|
|
@@ -3858,9 +3885,13 @@ function fixedOrDash(value) {
|
|
|
3858
3885
|
}
|
|
3859
3886
|
//#endregion
|
|
3860
3887
|
//#region src/search/lenses/task-matrix.ts
|
|
3888
|
+
const SPECIALIST_GAIN_METHOD = `per unit cluster, the best node's mean over the cluster's units minus the mean of the node means, in the objective's direction and the metric's units, among nodes not decided invalid that scored every unit of the cluster; reported from 2 such nodes and ${INSUFFICIENT_FROM} units; a point value with no interval: the largest of several noisy means exceeds their mean even when no node specializes, so read it against the spread of the node means`;
|
|
3861
3889
|
function taskMatrix(state, options = {}) {
|
|
3862
3890
|
const split = options.split ?? rankingSplit(state);
|
|
3891
|
+
const direction = state.header?.objective.direction ?? "maximize";
|
|
3892
|
+
const sign = direction === "maximize" ? 1 : -1;
|
|
3863
3893
|
const nodeIds = state.nodeIds();
|
|
3894
|
+
const invalid = new Set(state.nodes().filter((node) => node.status === "invalid").map((node) => node.nodeId));
|
|
3864
3895
|
const byNodeUnit = /* @__PURE__ */ new Map();
|
|
3865
3896
|
const unitSet = /* @__PURE__ */ new Set();
|
|
3866
3897
|
for (const nodeId of nodeIds) {
|
|
@@ -3871,7 +3902,7 @@ function taskMatrix(state, options = {}) {
|
|
|
3871
3902
|
}
|
|
3872
3903
|
byNodeUnit.set(nodeId, units);
|
|
3873
3904
|
}
|
|
3874
|
-
const unitIds = [...unitSet].sort(
|
|
3905
|
+
const unitIds = [...unitSet].sort(compareCodeUnits);
|
|
3875
3906
|
const nodeClusters = clusterBy(nodeIds, (a, b) => nodeDistance(byNodeUnit, a, b));
|
|
3876
3907
|
const unitClusters = clusterBy(unitIds, (a, b) => unitDistance(byNodeUnit, nodeIds, a, b));
|
|
3877
3908
|
const orderedNodeIds = nodeClusters.flatMap((c) => c.members);
|
|
@@ -3886,25 +3917,43 @@ function taskMatrix(state, options = {}) {
|
|
|
3886
3917
|
});
|
|
3887
3918
|
}
|
|
3888
3919
|
const specialistGain = unitClusters.map((cluster) => {
|
|
3889
|
-
const
|
|
3920
|
+
const contributing = [];
|
|
3890
3921
|
for (const nodeId of nodeIds) {
|
|
3922
|
+
if (invalid.has(nodeId)) continue;
|
|
3891
3923
|
const units = byNodeUnit.get(nodeId);
|
|
3892
|
-
|
|
3893
|
-
|
|
3924
|
+
let total = 0;
|
|
3925
|
+
let complete = true;
|
|
3926
|
+
for (const unitId of cluster.members) {
|
|
3927
|
+
const value = units.get(unitId);
|
|
3928
|
+
if (value === void 0) {
|
|
3929
|
+
complete = false;
|
|
3930
|
+
break;
|
|
3931
|
+
}
|
|
3932
|
+
total += value;
|
|
3933
|
+
}
|
|
3934
|
+
if (complete) contributing.push({
|
|
3935
|
+
nodeId,
|
|
3936
|
+
oriented: sign * total / cluster.members.length
|
|
3937
|
+
});
|
|
3894
3938
|
}
|
|
3895
|
-
|
|
3939
|
+
let best = null;
|
|
3940
|
+
for (const entry of contributing) if (best === null || entry.oriented > best.oriented) best = entry;
|
|
3941
|
+
const row = {
|
|
3896
3942
|
clusterId: cluster.id,
|
|
3897
3943
|
unitIds: cluster.members,
|
|
3944
|
+
bestNodeId: best?.nodeId ?? null,
|
|
3945
|
+
nodesContributing: contributing.length
|
|
3946
|
+
};
|
|
3947
|
+
if (contributing.length < 2 || cluster.members.length < INSUFFICIENT_FROM) return {
|
|
3948
|
+
...row,
|
|
3898
3949
|
gain: null,
|
|
3899
|
-
|
|
3950
|
+
insufficient: contributing.length < 2 ? `${contributing.length} node${contributing.length === 1 ? "" : "s"} scored every unit of the cluster; a gain needs 2` : `${cluster.members.length} of ${INSUFFICIENT_FROM} units`
|
|
3900
3951
|
};
|
|
3901
|
-
const mean =
|
|
3902
|
-
const gain = Math.max(...nodeMeans) - mean;
|
|
3952
|
+
const mean = contributing.reduce((sum, entry) => sum + entry.oriented, 0) / contributing.length;
|
|
3903
3953
|
return {
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
nodesContributing: nodeMeans.length
|
|
3954
|
+
...row,
|
|
3955
|
+
gain: best.oriented - mean,
|
|
3956
|
+
insufficient: null
|
|
3908
3957
|
};
|
|
3909
3958
|
});
|
|
3910
3959
|
const signalValue = {};
|
|
@@ -3912,6 +3961,8 @@ function taskMatrix(state, options = {}) {
|
|
|
3912
3961
|
return {
|
|
3913
3962
|
data: {
|
|
3914
3963
|
split,
|
|
3964
|
+
direction,
|
|
3965
|
+
method: SPECIALIST_GAIN_METHOD,
|
|
3915
3966
|
nodeIds: orderedNodeIds,
|
|
3916
3967
|
unitIds: orderedUnitIds,
|
|
3917
3968
|
nodeClusters,
|
|
@@ -3936,7 +3987,7 @@ function nodeDistance(byNodeUnit, a, b) {
|
|
|
3936
3987
|
sumSquares += (valueA - valueB) ** 2;
|
|
3937
3988
|
shared += 1;
|
|
3938
3989
|
}
|
|
3939
|
-
return shared === 0 ? Number.POSITIVE_INFINITY : Math.sqrt(sumSquares);
|
|
3990
|
+
return shared === 0 ? Number.POSITIVE_INFINITY : Math.sqrt(sumSquares / shared);
|
|
3940
3991
|
}
|
|
3941
3992
|
function unitDistance(byNodeUnit, nodeIds, a, b) {
|
|
3942
3993
|
let sumSquares = 0;
|
|
@@ -3949,15 +4000,17 @@ function unitDistance(byNodeUnit, nodeIds, a, b) {
|
|
|
3949
4000
|
sumSquares += (valueA - valueB) ** 2;
|
|
3950
4001
|
shared += 1;
|
|
3951
4002
|
}
|
|
3952
|
-
return shared === 0 ? Number.POSITIVE_INFINITY : Math.sqrt(sumSquares);
|
|
4003
|
+
return shared === 0 ? Number.POSITIVE_INFINITY : Math.sqrt(sumSquares / shared);
|
|
3953
4004
|
}
|
|
3954
4005
|
/**
|
|
3955
4006
|
* Single-linkage agglomerative clustering. The cutoff is the median of the
|
|
3956
4007
|
* finite pairwise distances measured before any merge — a threshold the data
|
|
3957
4008
|
* itself sets, not a constant this lens chooses. Two items with no finite
|
|
3958
|
-
* distance (no shared observation) can never merge.
|
|
3959
|
-
*
|
|
3960
|
-
*
|
|
4009
|
+
* distance (no shared observation) can never merge. Stopped at a cutoff,
|
|
4010
|
+
* single linkage yields the connected components of the graph whose edges
|
|
4011
|
+
* are the pairs at most the cutoff apart, so the merge order cannot change
|
|
4012
|
+
* the result. The clusters and their members are sorted by UTF-16 code unit,
|
|
4013
|
+
* never by the host's locale, so a cluster id is the same on every machine.
|
|
3961
4014
|
*/
|
|
3962
4015
|
function clusterBy(ids, distance) {
|
|
3963
4016
|
let clusters = ids.map((id) => [id]);
|
|
@@ -3987,10 +4040,10 @@ function clusterBy(ids, distance) {
|
|
|
3987
4040
|
clusters = clusters.filter((_, index) => index !== best.i && index !== best.j);
|
|
3988
4041
|
clusters.push(merged);
|
|
3989
4042
|
}
|
|
3990
|
-
return clusters.map(toCluster).sort((a, b) => a.id
|
|
4043
|
+
return clusters.map(toCluster).sort((a, b) => compareCodeUnits(a.id, b.id));
|
|
3991
4044
|
}
|
|
3992
4045
|
function toCluster(members) {
|
|
3993
|
-
const sorted = [...members].sort(
|
|
4046
|
+
const sorted = [...members].sort(compareCodeUnits);
|
|
3994
4047
|
return {
|
|
3995
4048
|
id: sorted[0],
|
|
3996
4049
|
members: sorted
|
|
@@ -4023,6 +4076,8 @@ function tree(state) {
|
|
|
4023
4076
|
depth: node.depth,
|
|
4024
4077
|
cellCount: node.cellCount,
|
|
4025
4078
|
knownCostUsd: node.spend.knownUsd,
|
|
4079
|
+
floorUsd: node.spend.floorUsd,
|
|
4080
|
+
unknownCostCells: node.spend.unknownCostCells,
|
|
4026
4081
|
operator: primaryOperator.get(node.nodeId) ?? null,
|
|
4027
4082
|
children: (childrenOf.get(nodeId) ?? []).map((childId) => build(childId))
|
|
4028
4083
|
};
|
|
@@ -4042,4 +4097,4 @@ function tree(state) {
|
|
|
4042
4097
|
//#endregion
|
|
4043
4098
|
export { editCreditText as A, draftOnPlateau as C, EDIT_CREDIT_ESTIMATOR as D, front as E, EDIT_CREDIT_SIGNAL as O, vectorEmbedding as S, screenedNodes as T, lineageEdits as _, skillCalibration as a, surfaceDigestEdits as b, META_SEARCH_SIGNAL as c, objectiveKey as d, renderMetaSearchText as f, lineEditDistance as g, landscape as h, nextUnitExtension as i, editCredit as k, metaSearch as l, formatLandscape as m, taskMatrix as n, skillManifold as o, searchPolicyGenome as p, formatSkillManifold as r, META_SEARCH_SCORE_SOURCE as s, tree as t, metaSearchScore as u, nearestNeighbours as v, searchPlateau as w, surfaceTextEdits as x, profileTextLines as y };
|
|
4044
4099
|
|
|
4045
|
-
//# sourceMappingURL=tree-
|
|
4100
|
+
//# sourceMappingURL=tree-DxGfhISA.js.map
|