@agent-e/core 1.5.0 → 1.5.2
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/README.md +70 -70
- package/dist/index.d.mts +78 -18
- package/dist/index.d.ts +78 -18
- package/dist/index.js +265 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +257 -123
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -4
package/dist/index.mjs
CHANGED
|
@@ -32,7 +32,7 @@ var DEFAULT_THRESHOLDS = {
|
|
|
32
32
|
cooldownTicks: 15,
|
|
33
33
|
// Currency (P13)
|
|
34
34
|
poolWinRate: 0.65,
|
|
35
|
-
|
|
35
|
+
poolOperatorShare: 0.1,
|
|
36
36
|
// Population balance (P9)
|
|
37
37
|
roleSwitchFrictionMax: 0.05,
|
|
38
38
|
// >5% of population switching in one period = herd
|
|
@@ -93,6 +93,12 @@ var Observer = class {
|
|
|
93
93
|
this.customMetricFns[name] = fn;
|
|
94
94
|
}
|
|
95
95
|
compute(state, recentEvents) {
|
|
96
|
+
if (!state.currencies || state.currencies.length === 0) {
|
|
97
|
+
console.warn("[AgentE] Warning: state.currencies is empty. Metrics will be zeroed.");
|
|
98
|
+
}
|
|
99
|
+
if (!state.agentBalances || Object.keys(state.agentBalances).length === 0) {
|
|
100
|
+
console.warn("[AgentE] Warning: state.agentBalances is empty.");
|
|
101
|
+
}
|
|
96
102
|
const tick = state.tick;
|
|
97
103
|
const roles = Object.values(state.agentRoles);
|
|
98
104
|
const totalAgents = Object.keys(state.agentBalances).length;
|
|
@@ -140,7 +146,7 @@ var Observer = class {
|
|
|
140
146
|
if (!actorsBySystem[e.system]) actorsBySystem[e.system] = /* @__PURE__ */ new Set();
|
|
141
147
|
actorsBySystem[e.system].add(e.actor);
|
|
142
148
|
const amt = e.amount ?? 0;
|
|
143
|
-
if (e.type === "mint"
|
|
149
|
+
if (e.type === "mint") {
|
|
144
150
|
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) + amt;
|
|
145
151
|
} else if (e.type === "burn" || e.type === "consume") {
|
|
146
152
|
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) - amt;
|
|
@@ -148,7 +154,7 @@ var Observer = class {
|
|
|
148
154
|
}
|
|
149
155
|
if (e.sourceOrSink) {
|
|
150
156
|
const amt = e.amount ?? 0;
|
|
151
|
-
if (e.type === "mint"
|
|
157
|
+
if (e.type === "mint") {
|
|
152
158
|
flowBySource[e.sourceOrSink] = (flowBySource[e.sourceOrSink] ?? 0) + amt;
|
|
153
159
|
} else if (e.type === "burn" || e.type === "consume") {
|
|
154
160
|
flowBySink[e.sourceOrSink] = (flowBySink[e.sourceOrSink] ?? 0) + amt;
|
|
@@ -187,7 +193,7 @@ var Observer = class {
|
|
|
187
193
|
const faucet = faucetVolumeByCurrency[curr] ?? 0;
|
|
188
194
|
const sink = sinkVolumeByCurrency[curr] ?? 0;
|
|
189
195
|
netFlowByCurrency[curr] = faucet - sink;
|
|
190
|
-
tapSinkRatioByCurrency[curr] = sink > 0 ? faucet / sink : faucet > 0 ?
|
|
196
|
+
tapSinkRatioByCurrency[curr] = sink > 0 ? Math.min(faucet / sink, 100) : faucet > 0 ? 100 : 1;
|
|
191
197
|
const prevSupply = this.previousMetrics?.totalSupplyByCurrency?.[curr] ?? totalSupplyByCurrency[curr] ?? 0;
|
|
192
198
|
const currSupply = totalSupplyByCurrency[curr] ?? 0;
|
|
193
199
|
inflationRateByCurrency[curr] = prevSupply > 0 ? (currSupply - prevSupply) / prevSupply : 0;
|
|
@@ -222,7 +228,7 @@ var Observer = class {
|
|
|
222
228
|
const faucetVolume = Object.values(faucetVolumeByCurrency).reduce((s, v) => s + v, 0);
|
|
223
229
|
const sinkVolume = Object.values(sinkVolumeByCurrency).reduce((s, v) => s + v, 0);
|
|
224
230
|
const netFlow = faucetVolume - sinkVolume;
|
|
225
|
-
const tapSinkRatio = sinkVolume > 0 ? faucetVolume / sinkVolume : faucetVolume > 0 ?
|
|
231
|
+
const tapSinkRatio = sinkVolume > 0 ? Math.min(faucetVolume / sinkVolume, 100) : faucetVolume > 0 ? 100 : 1;
|
|
226
232
|
const velocity = totalSupply > 0 ? tradeEvents.length / totalSupply : 0;
|
|
227
233
|
const prevTotalSupply = this.previousMetrics?.totalSupply ?? totalSupply;
|
|
228
234
|
const inflationRate = prevTotalSupply > 0 ? (totalSupply - prevTotalSupply) / prevTotalSupply : 0;
|
|
@@ -260,7 +266,9 @@ var Observer = class {
|
|
|
260
266
|
const pVals = Object.values(resourcePrices);
|
|
261
267
|
priceIndexByCurrency[curr] = pVals.length > 0 ? pVals.reduce((s, p) => s + p, 0) / pVals.length : 0;
|
|
262
268
|
}
|
|
263
|
-
this.previousPricesByCurrency =
|
|
269
|
+
this.previousPricesByCurrency = Object.fromEntries(
|
|
270
|
+
Object.entries(pricesByCurrency).map(([c, p]) => [c, { ...p }])
|
|
271
|
+
);
|
|
264
272
|
const prices = pricesByCurrency[defaultCurrency] ?? {};
|
|
265
273
|
const priceVolatility = priceVolatilityByCurrency[defaultCurrency] ?? {};
|
|
266
274
|
const priceIndex = priceIndexByCurrency[defaultCurrency] ?? 0;
|
|
@@ -280,9 +288,9 @@ var Observer = class {
|
|
|
280
288
|
for (const resource of /* @__PURE__ */ new Set([...Object.keys(supplyByResource), ...Object.keys(demandSignals)])) {
|
|
281
289
|
const s = supplyByResource[resource] ?? 0;
|
|
282
290
|
const d = demandSignals[resource] ?? 0;
|
|
283
|
-
if (d > 2 && s / d < 0.5) {
|
|
291
|
+
if (d > 0 && d > 2 && s / d < 0.5) {
|
|
284
292
|
pinchPoints[resource] = "scarce";
|
|
285
|
-
} else if (
|
|
293
|
+
} else if (d > 0 && s > 3 && s / d > 3) {
|
|
286
294
|
pinchPoints[resource] = "oversupplied";
|
|
287
295
|
} else {
|
|
288
296
|
pinchPoints[resource] = "optimal";
|
|
@@ -328,21 +336,11 @@ var Observer = class {
|
|
|
328
336
|
const arbitrageIndexByCurrency = {};
|
|
329
337
|
for (const curr of currencies) {
|
|
330
338
|
const cPrices = pricesByCurrency[curr] ?? {};
|
|
331
|
-
const
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
for (let j = i + 1; j < priceKeys.length; j++) {
|
|
337
|
-
const pA = cPrices[priceKeys[i]];
|
|
338
|
-
const pB = cPrices[priceKeys[j]];
|
|
339
|
-
let ratio = pA / pB;
|
|
340
|
-
ratio = Math.max(1e-3, Math.min(1e3, ratio));
|
|
341
|
-
totalDivergence += Math.abs(Math.log(ratio));
|
|
342
|
-
pairCount++;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
arbitrageIndexByCurrency[curr] = pairCount > 0 ? Math.min(1, totalDivergence / pairCount) : 0;
|
|
339
|
+
const logPrices = Object.values(cPrices).filter((p) => p > 0).map((p) => Math.log(p));
|
|
340
|
+
if (logPrices.length >= 2) {
|
|
341
|
+
const mean = logPrices.reduce((s, v) => s + v, 0) / logPrices.length;
|
|
342
|
+
const variance = logPrices.reduce((s, v) => s + (v - mean) ** 2, 0) / logPrices.length;
|
|
343
|
+
arbitrageIndexByCurrency[curr] = Math.min(1, Math.sqrt(variance));
|
|
346
344
|
} else {
|
|
347
345
|
arbitrageIndexByCurrency[curr] = 0;
|
|
348
346
|
}
|
|
@@ -429,10 +427,10 @@ var Observer = class {
|
|
|
429
427
|
prices,
|
|
430
428
|
priceVolatility,
|
|
431
429
|
poolSizes: poolSizesAggregate,
|
|
432
|
-
extractionRatio:
|
|
433
|
-
newUserDependency:
|
|
434
|
-
smokeTestRatio:
|
|
435
|
-
currencyInsulation:
|
|
430
|
+
extractionRatio: 0,
|
|
431
|
+
newUserDependency: 0,
|
|
432
|
+
smokeTestRatio: 0,
|
|
433
|
+
currencyInsulation: 0,
|
|
436
434
|
arbitrageIndex,
|
|
437
435
|
giftTradeRatio,
|
|
438
436
|
disposalTradeRatio,
|
|
@@ -454,8 +452,11 @@ var Observer = class {
|
|
|
454
452
|
timeToValue,
|
|
455
453
|
sharkToothPeaks: this.previousMetrics?.sharkToothPeaks ?? [],
|
|
456
454
|
sharkToothValleys: this.previousMetrics?.sharkToothValleys ?? [],
|
|
457
|
-
eventCompletionRate:
|
|
455
|
+
eventCompletionRate: 0,
|
|
458
456
|
contentDropAge,
|
|
457
|
+
systems: state.systems ?? [],
|
|
458
|
+
sources: state.sources ?? [],
|
|
459
|
+
sinks: state.sinks ?? [],
|
|
459
460
|
flowBySystem,
|
|
460
461
|
activityBySystem,
|
|
461
462
|
participantsBySystem,
|
|
@@ -483,7 +484,7 @@ function computeGini(sorted) {
|
|
|
483
484
|
for (let i = 0; i < n; i++) {
|
|
484
485
|
numerator += (2 * (i + 1) - n - 1) * (sorted[i] ?? 0);
|
|
485
486
|
}
|
|
486
|
-
return Math.abs(numerator) / (n * sum);
|
|
487
|
+
return Math.min(1, Math.abs(numerator) / (n * sum));
|
|
487
488
|
}
|
|
488
489
|
|
|
489
490
|
// src/Diagnoser.ts
|
|
@@ -579,10 +580,10 @@ function emptyMetrics(tick = 0) {
|
|
|
579
580
|
prices: {},
|
|
580
581
|
priceVolatility: {},
|
|
581
582
|
poolSizes: {},
|
|
582
|
-
extractionRatio:
|
|
583
|
-
newUserDependency:
|
|
584
|
-
smokeTestRatio:
|
|
585
|
-
currencyInsulation:
|
|
583
|
+
extractionRatio: 0,
|
|
584
|
+
newUserDependency: 0,
|
|
585
|
+
smokeTestRatio: 0,
|
|
586
|
+
currencyInsulation: 0,
|
|
586
587
|
arbitrageIndex: 0,
|
|
587
588
|
giftTradeRatio: 0,
|
|
588
589
|
disposalTradeRatio: 0,
|
|
@@ -603,8 +604,11 @@ function emptyMetrics(tick = 0) {
|
|
|
603
604
|
timeToValue: 0,
|
|
604
605
|
sharkToothPeaks: [],
|
|
605
606
|
sharkToothValleys: [],
|
|
606
|
-
eventCompletionRate:
|
|
607
|
+
eventCompletionRate: 0,
|
|
607
608
|
contentDropAge: 0,
|
|
609
|
+
systems: [],
|
|
610
|
+
sources: [],
|
|
611
|
+
sinks: [],
|
|
608
612
|
flowBySystem: {},
|
|
609
613
|
activityBySystem: {},
|
|
610
614
|
participantsBySystem: {},
|
|
@@ -805,9 +809,9 @@ var SUPPLY_CHAIN_PRINCIPLES = [
|
|
|
805
809
|
];
|
|
806
810
|
|
|
807
811
|
// src/principles/incentives.ts
|
|
808
|
-
var
|
|
812
|
+
var P5_ProfitabilityIsRelative = {
|
|
809
813
|
id: "P5",
|
|
810
|
-
name: "Profitability Is
|
|
814
|
+
name: "Profitability Is Relative, Not Absolute",
|
|
811
815
|
category: "incentive",
|
|
812
816
|
description: "Any profitability formula that returns the same number regardless of how many agents are already in that role will cause stampedes. 97 intermediaries happened because profit = transactions \xD7 10 with no competition denominator.",
|
|
813
817
|
check(metrics, thresholds) {
|
|
@@ -871,7 +875,7 @@ var P7_NonSpecialistsSubsidiseSpecialists = {
|
|
|
871
875
|
id: "P7",
|
|
872
876
|
name: "Non-Specialists Subsidise Specialists in Zero-Sum Games",
|
|
873
877
|
category: "incentive",
|
|
874
|
-
description: "In zero-sum pools (
|
|
878
|
+
description: "In zero-sum pools (staking, prize pools, etc.), the math only works if non-specialists overpay relative to specialists. If the pool is >70% specialists, there is no one left to subsidise and the pot drains.",
|
|
875
879
|
check(metrics, _thresholds) {
|
|
876
880
|
const { poolSizes } = metrics;
|
|
877
881
|
for (const [poolName, poolSize] of Object.entries(poolSizes)) {
|
|
@@ -907,7 +911,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
907
911
|
id: "P8",
|
|
908
912
|
name: "Regulator Cannot Fight the Design",
|
|
909
913
|
category: "incentive",
|
|
910
|
-
description: "If the economy is designed to have a majority role (e.g. dominant role exceeds 55%), the regulator must know this and exempt that role from population suppression. AgentE at tick 1 seeing dominant role exceeds 55% and slashing
|
|
914
|
+
description: "If the economy is designed to have a majority role (e.g. dominant role exceeds 55%), the regulator must know this and exempt that role from population suppression. AgentE at tick 1 seeing dominant role exceeds 55% and slashing pool rewards is overreach.",
|
|
911
915
|
check(metrics, _thresholds) {
|
|
912
916
|
const { roleShares, avgSatisfaction } = metrics;
|
|
913
917
|
if (avgSatisfaction < 45) {
|
|
@@ -932,7 +936,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
932
936
|
}
|
|
933
937
|
};
|
|
934
938
|
var INCENTIVE_PRINCIPLES = [
|
|
935
|
-
|
|
939
|
+
P5_ProfitabilityIsRelative,
|
|
936
940
|
P6_CrowdingMultiplierOnAllRoles,
|
|
937
941
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
938
942
|
P8_RegulatorCannotFightDesign
|
|
@@ -943,7 +947,7 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
943
947
|
id: "P9",
|
|
944
948
|
name: "Role Switching Needs Friction",
|
|
945
949
|
category: "population",
|
|
946
|
-
description: "If >5% of the population switches roles in a single evaluation period, it is a herd movement, not rational rebalancing. Without friction (satisfaction cost,
|
|
950
|
+
description: "If >5% of the population switches roles in a single evaluation period, it is a herd movement, not rational rebalancing. Without friction (satisfaction cost, minimum interval), one good tick causes mass migration.",
|
|
947
951
|
check(metrics, thresholds) {
|
|
948
952
|
const { churnByRole, roleShares } = metrics;
|
|
949
953
|
const totalChurn = Object.values(churnByRole).reduce((s, v) => s + v, 0);
|
|
@@ -966,7 +970,7 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
966
970
|
return { violated: false };
|
|
967
971
|
}
|
|
968
972
|
};
|
|
969
|
-
var
|
|
973
|
+
var P10_EntryWeightingUsesInversePopulation = {
|
|
970
974
|
id: "P10",
|
|
971
975
|
name: "Entry Weighting Uses Inverse Population",
|
|
972
976
|
category: "population",
|
|
@@ -1072,7 +1076,7 @@ var P46_PersonaDiversity = {
|
|
|
1072
1076
|
};
|
|
1073
1077
|
var POPULATION_PRINCIPLES = [
|
|
1074
1078
|
P9_RoleSwitchingNeedsFriction,
|
|
1075
|
-
|
|
1079
|
+
P10_EntryWeightingUsesInversePopulation,
|
|
1076
1080
|
P11_TwoTierPressure,
|
|
1077
1081
|
P46_PersonaDiversity
|
|
1078
1082
|
];
|
|
@@ -1128,7 +1132,7 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1128
1132
|
id: "P13",
|
|
1129
1133
|
name: "Pots Self-Regulate with Correct Multiplier",
|
|
1130
1134
|
category: "currency",
|
|
1131
|
-
description: "
|
|
1135
|
+
description: "Pool math: winRate \xD7 multiplier > (1 - operatorShare) drains the pot. At 65% win rate, multiplier must be \u2264 1.38. We use 1.5 for slight surplus buffer.",
|
|
1132
1136
|
check(metrics, thresholds) {
|
|
1133
1137
|
const { populationByRole } = metrics;
|
|
1134
1138
|
const roleEntries = Object.entries(populationByRole).sort((a, b) => b[1] - a[1]);
|
|
@@ -1137,8 +1141,8 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1137
1141
|
for (const curr of metrics.currencies) {
|
|
1138
1142
|
const poolSize = currencyAmounts[curr] ?? 0;
|
|
1139
1143
|
if (dominantCount > 5 && poolSize < 50) {
|
|
1140
|
-
const { poolWinRate,
|
|
1141
|
-
const maxSustainableMultiplier = (1 -
|
|
1144
|
+
const { poolWinRate, poolOperatorShare } = thresholds;
|
|
1145
|
+
const maxSustainableMultiplier = (1 - poolOperatorShare) / poolWinRate;
|
|
1142
1146
|
return {
|
|
1143
1147
|
violated: true,
|
|
1144
1148
|
severity: 7,
|
|
@@ -1163,7 +1167,7 @@ var P14_TrackActualInjection = {
|
|
|
1163
1167
|
id: "P14",
|
|
1164
1168
|
name: "Track Actual Currency Injection, Not Value Creation",
|
|
1165
1169
|
category: "currency",
|
|
1166
|
-
description: 'Counting resource
|
|
1170
|
+
description: 'Counting resource extraction as "currency injected" is misleading. Currency enters through faucet mechanisms (entering, rewards). Fake metrics break every downstream decision.',
|
|
1167
1171
|
check(metrics, _thresholds) {
|
|
1168
1172
|
for (const curr of metrics.currencies) {
|
|
1169
1173
|
const faucetVolume = metrics.faucetVolumeByCurrency[curr] ?? 0;
|
|
@@ -1421,7 +1425,7 @@ var P19_StartingSupplyExceedsDemand = {
|
|
|
1421
1425
|
parameterType: "reward",
|
|
1422
1426
|
direction: "increase",
|
|
1423
1427
|
magnitude: 0.2,
|
|
1424
|
-
reasoning: `${mostPopulatedRole} (${population} agents) has insufficient resources (${resourcesPerAgent.toFixed(2)} per agent). Cold-start scarcity. Boost
|
|
1428
|
+
reasoning: `${mostPopulatedRole} (${population} agents) has insufficient resources (${resourcesPerAgent.toFixed(2)} per agent). Cold-start scarcity. Boost pool reward to attract participation despite scarcity.`
|
|
1425
1429
|
},
|
|
1426
1430
|
confidence: 0.75,
|
|
1427
1431
|
estimatedLag: 5
|
|
@@ -1751,7 +1755,7 @@ var REGULATOR_PRINCIPLES = [
|
|
|
1751
1755
|
];
|
|
1752
1756
|
|
|
1753
1757
|
// src/principles/market-dynamics.ts
|
|
1754
|
-
var
|
|
1758
|
+
var P29_BottleneckDetection = {
|
|
1755
1759
|
id: "P29",
|
|
1756
1760
|
name: "Bottleneck Detection",
|
|
1757
1761
|
category: "market_dynamics",
|
|
@@ -1796,7 +1800,7 @@ var P29_PinchPoint = {
|
|
|
1796
1800
|
return { violated: false };
|
|
1797
1801
|
}
|
|
1798
1802
|
};
|
|
1799
|
-
var
|
|
1803
|
+
var P30_DynamicBottleneckRotation = {
|
|
1800
1804
|
id: "P30",
|
|
1801
1805
|
name: "Dynamic Bottleneck Rotation",
|
|
1802
1806
|
category: "market_dynamics",
|
|
@@ -1871,8 +1875,8 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1871
1875
|
}
|
|
1872
1876
|
};
|
|
1873
1877
|
var MARKET_DYNAMICS_PRINCIPLES = [
|
|
1874
|
-
|
|
1875
|
-
|
|
1878
|
+
P29_BottleneckDetection,
|
|
1879
|
+
P30_DynamicBottleneckRotation,
|
|
1876
1880
|
P57_CombinatorialPriceSpace
|
|
1877
1881
|
];
|
|
1878
1882
|
|
|
@@ -2166,7 +2170,7 @@ var P35_DestructionCreatesValue = {
|
|
|
2166
2170
|
scope: { tags: ["entry"] },
|
|
2167
2171
|
direction: "decrease",
|
|
2168
2172
|
magnitude: 0.1,
|
|
2169
|
-
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower
|
|
2173
|
+
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower pool entry to increase resource usage.`
|
|
2170
2174
|
},
|
|
2171
2175
|
confidence: 0.7,
|
|
2172
2176
|
estimatedLag: 5
|
|
@@ -2180,7 +2184,7 @@ var P40_ReplacementRate = {
|
|
|
2180
2184
|
id: "P40",
|
|
2181
2185
|
name: "Replacement Rate \u2265 2\xD7 Consumption",
|
|
2182
2186
|
category: "resource",
|
|
2183
|
-
description: "
|
|
2187
|
+
description: "Replacement/production rate must be at least 2\xD7 consumption rate for equilibrium. At 1\xD7 you drift toward depletion. At 2\xD7 you have a buffer for demand spikes.",
|
|
2184
2188
|
check(metrics, thresholds) {
|
|
2185
2189
|
const { productionIndex, sinkVolume } = metrics;
|
|
2186
2190
|
if (sinkVolume > 0 && productionIndex > 0) {
|
|
@@ -2547,7 +2551,7 @@ var OPEN_ECONOMY_PRINCIPLES = [
|
|
|
2547
2551
|
];
|
|
2548
2552
|
|
|
2549
2553
|
// src/principles/operations.ts
|
|
2550
|
-
var
|
|
2554
|
+
var P51_CyclicalEngagement = {
|
|
2551
2555
|
id: "P51",
|
|
2552
2556
|
name: "Cyclical Engagement Pattern",
|
|
2553
2557
|
category: "operations",
|
|
@@ -2603,7 +2607,7 @@ var P52_EndowmentEffect = {
|
|
|
2603
2607
|
id: "P52",
|
|
2604
2608
|
name: "Endowment Effect",
|
|
2605
2609
|
category: "operations",
|
|
2606
|
-
description: "Participants who never owned premium
|
|
2610
|
+
description: "Participants who never owned premium assets do not value them. Free trial activities that let participants experience premium assets drive conversions because ownership creates perceived value (endowment effect).",
|
|
2607
2611
|
check(metrics, _thresholds) {
|
|
2608
2612
|
const { avgSatisfaction, churnRate } = metrics;
|
|
2609
2613
|
const { eventCompletionRate } = metrics;
|
|
@@ -2672,11 +2676,11 @@ var P53_EventCompletionRate = {
|
|
|
2672
2676
|
return { violated: false };
|
|
2673
2677
|
}
|
|
2674
2678
|
};
|
|
2675
|
-
var
|
|
2679
|
+
var P54_OperationalCadence = {
|
|
2676
2680
|
id: "P54",
|
|
2677
2681
|
name: "Operational Cadence",
|
|
2678
2682
|
category: "operations",
|
|
2679
|
-
description: ">50% of activities that are re-wrapped existing
|
|
2683
|
+
description: ">50% of activities that are re-wrapped existing supply \u2192 stagnation. The cadence must include genuinely new supply at regular intervals. This is an advisory principle \u2014 AgentE can flag but cannot fix supply.",
|
|
2680
2684
|
check(metrics, _thresholds) {
|
|
2681
2685
|
const { velocity, avgSatisfaction } = metrics;
|
|
2682
2686
|
if (velocity < 2 && avgSatisfaction < 55 && metrics.tick > 100) {
|
|
@@ -2688,7 +2692,7 @@ var P54_LiveOpsCadence = {
|
|
|
2688
2692
|
parameterType: "reward",
|
|
2689
2693
|
direction: "increase",
|
|
2690
2694
|
magnitude: 0.1,
|
|
2691
|
-
reasoning: "Low velocity and satisfaction after long runtime. Possible
|
|
2695
|
+
reasoning: "Low velocity and satisfaction after long runtime. Possible supply stagnation. Increase rewards as bridge while new supply is developed (developer action required)."
|
|
2692
2696
|
},
|
|
2693
2697
|
confidence: 0.4,
|
|
2694
2698
|
estimatedLag: 30
|
|
@@ -2697,11 +2701,11 @@ var P54_LiveOpsCadence = {
|
|
|
2697
2701
|
return { violated: false };
|
|
2698
2702
|
}
|
|
2699
2703
|
};
|
|
2700
|
-
var
|
|
2704
|
+
var P56_SupplyShockAbsorption = {
|
|
2701
2705
|
id: "P56",
|
|
2702
2706
|
name: "Supply Shock Absorption",
|
|
2703
2707
|
category: "operations",
|
|
2704
|
-
description: "Every new-item injection shatters existing price equilibria \u2014 arbitrage spikes as participants re-price. Build
|
|
2708
|
+
description: "Every new-item injection shatters existing price equilibria \u2014 arbitrage spikes as participants re-price. Build stabilization windows for price discovery before measuring post-injection economic health.",
|
|
2705
2709
|
check(metrics, thresholds) {
|
|
2706
2710
|
const { contentDropAge, arbitrageIndex } = metrics;
|
|
2707
2711
|
if (contentDropAge > 0 && contentDropAge <= thresholds.contentDropCooldownTicks) {
|
|
@@ -2720,7 +2724,7 @@ var P56_ContentDropShock = {
|
|
|
2720
2724
|
scope: { tags: ["transaction"] },
|
|
2721
2725
|
direction: "decrease",
|
|
2722
2726
|
magnitude: 0.1,
|
|
2723
|
-
reasoning: `
|
|
2727
|
+
reasoning: `Supply injection ${contentDropAge} ticks ago \u2014 arbitrage at ${arbitrageIndex.toFixed(2)} exceeds post-injection max (${thresholds.postDropArbitrageMax}). Price discovery struggling. Lower trading friction temporarily.`
|
|
2724
2728
|
},
|
|
2725
2729
|
confidence: 0.6,
|
|
2726
2730
|
estimatedLag: 5
|
|
@@ -2731,11 +2735,11 @@ var P56_ContentDropShock = {
|
|
|
2731
2735
|
}
|
|
2732
2736
|
};
|
|
2733
2737
|
var OPERATIONS_PRINCIPLES = [
|
|
2734
|
-
|
|
2738
|
+
P51_CyclicalEngagement,
|
|
2735
2739
|
P52_EndowmentEffect,
|
|
2736
2740
|
P53_EventCompletionRate,
|
|
2737
|
-
|
|
2738
|
-
|
|
2741
|
+
P54_OperationalCadence,
|
|
2742
|
+
P56_SupplyShockAbsorption
|
|
2739
2743
|
];
|
|
2740
2744
|
|
|
2741
2745
|
// src/principles/index.ts
|
|
@@ -2773,15 +2777,24 @@ var ALL_PRINCIPLES = [
|
|
|
2773
2777
|
];
|
|
2774
2778
|
|
|
2775
2779
|
// src/Simulator.ts
|
|
2780
|
+
var DEFAULT_SIM_CONFIG = {
|
|
2781
|
+
sinkMultiplier: 0.2,
|
|
2782
|
+
faucetMultiplier: 0.15,
|
|
2783
|
+
frictionMultiplier: 0.1,
|
|
2784
|
+
frictionVelocityScale: 10,
|
|
2785
|
+
redistributionMultiplier: 0.3,
|
|
2786
|
+
neutralMultiplier: 0.05,
|
|
2787
|
+
minIterations: 100,
|
|
2788
|
+
maxProjectionTicks: 20
|
|
2789
|
+
};
|
|
2776
2790
|
var Simulator = class {
|
|
2777
|
-
constructor(registry) {
|
|
2791
|
+
constructor(registry, simConfig) {
|
|
2778
2792
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
2779
|
-
// Cache beforeViolations for the *current* tick only
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
// entries whose key differs from the incoming tick.
|
|
2783
|
-
this.beforeViolationsCache = /* @__PURE__ */ new Map();
|
|
2793
|
+
// Cache beforeViolations for the *current* tick only.
|
|
2794
|
+
this.cachedViolationsTick = -1;
|
|
2795
|
+
this.cachedViolations = /* @__PURE__ */ new Set();
|
|
2784
2796
|
this.registry = registry;
|
|
2797
|
+
this.simConfig = { ...DEFAULT_SIM_CONFIG, ...simConfig };
|
|
2785
2798
|
}
|
|
2786
2799
|
/**
|
|
2787
2800
|
* Simulate the effect of applying `action` to the current economy forward `forwardTicks`.
|
|
@@ -2805,16 +2818,13 @@ var Simulator = class {
|
|
|
2805
2818
|
const mean = this.averageMetrics(outcomes);
|
|
2806
2819
|
const netImprovement = this.checkImprovement(currentMetrics, p50, action);
|
|
2807
2820
|
const tick = currentMetrics.tick;
|
|
2808
|
-
if (this.
|
|
2809
|
-
this.
|
|
2810
|
-
}
|
|
2811
|
-
let beforeViolations = this.beforeViolationsCache.get(tick);
|
|
2812
|
-
if (!beforeViolations) {
|
|
2813
|
-
beforeViolations = new Set(
|
|
2821
|
+
if (this.cachedViolationsTick !== tick) {
|
|
2822
|
+
this.cachedViolations = new Set(
|
|
2814
2823
|
this.diagnoser.diagnose(currentMetrics, thresholds).map((d) => d.principle.id)
|
|
2815
2824
|
);
|
|
2816
|
-
this.
|
|
2825
|
+
this.cachedViolationsTick = tick;
|
|
2817
2826
|
}
|
|
2827
|
+
const beforeViolations = this.cachedViolations;
|
|
2818
2828
|
const afterViolations = new Set(
|
|
2819
2829
|
this.diagnoser.diagnose(p50, thresholds).map((d) => d.principle.id)
|
|
2820
2830
|
);
|
|
@@ -2894,25 +2904,32 @@ var Simulator = class {
|
|
|
2894
2904
|
const sign = direction === "increase" ? -1 : 1;
|
|
2895
2905
|
const roleEntries = Object.entries(metrics.populationByRole).sort((a, b) => b[1] - a[1]);
|
|
2896
2906
|
const dominantRoleCount = roleEntries[0]?.[1] ?? 0;
|
|
2897
|
-
const resolvedKey = action.resolvedParameter;
|
|
2898
2907
|
let impact;
|
|
2899
|
-
if (
|
|
2900
|
-
|
|
2908
|
+
if (this.registry) {
|
|
2909
|
+
const resolved = this.registry.resolve(action.parameterType, action.scope);
|
|
2910
|
+
if (resolved) {
|
|
2911
|
+
impact = resolved.flowImpact;
|
|
2912
|
+
}
|
|
2901
2913
|
}
|
|
2902
2914
|
if (!impact) {
|
|
2903
2915
|
impact = this.inferFlowImpact(action.parameterType);
|
|
2904
2916
|
}
|
|
2917
|
+
const cfg = this.simConfig;
|
|
2905
2918
|
switch (impact) {
|
|
2906
2919
|
case "sink":
|
|
2907
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
2920
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.sinkMultiplier;
|
|
2908
2921
|
case "faucet":
|
|
2909
|
-
return -sign * dominantRoleCount *
|
|
2922
|
+
return -sign * dominantRoleCount * cfg.redistributionMultiplier;
|
|
2910
2923
|
case "neutral":
|
|
2911
|
-
return sign * dominantRoleCount *
|
|
2924
|
+
return sign * dominantRoleCount * cfg.neutralMultiplier;
|
|
2912
2925
|
case "mixed":
|
|
2913
|
-
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) *
|
|
2926
|
+
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * cfg.faucetMultiplier;
|
|
2927
|
+
case "friction":
|
|
2928
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.frictionMultiplier;
|
|
2929
|
+
case "redistribution":
|
|
2930
|
+
return sign * dominantRoleCount * cfg.neutralMultiplier;
|
|
2914
2931
|
default:
|
|
2915
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
2932
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.frictionMultiplier;
|
|
2916
2933
|
}
|
|
2917
2934
|
}
|
|
2918
2935
|
/** Infer flow impact from parameter type when registry is unavailable */
|
|
@@ -2933,7 +2950,7 @@ var Simulator = class {
|
|
|
2933
2950
|
return "mixed";
|
|
2934
2951
|
}
|
|
2935
2952
|
}
|
|
2936
|
-
checkImprovement(before, after,
|
|
2953
|
+
checkImprovement(before, after, _action) {
|
|
2937
2954
|
const satisfactionImproved = after.avgSatisfaction >= before.avgSatisfaction - 2;
|
|
2938
2955
|
const flowMoreBalanced = before.currencies.every((curr) => {
|
|
2939
2956
|
const afterFlow = Math.abs(after.netFlowByCurrency[curr] ?? 0);
|
|
@@ -2945,7 +2962,6 @@ var Simulator = class {
|
|
|
2945
2962
|
const beforeGini = before.giniCoefficientByCurrency[curr] ?? 0;
|
|
2946
2963
|
return afterGini <= beforeGini + 0.05;
|
|
2947
2964
|
});
|
|
2948
|
-
void action;
|
|
2949
2965
|
return satisfactionImproved && flowMoreBalanced && notWorseGini;
|
|
2950
2966
|
}
|
|
2951
2967
|
averageMetrics(outcomes) {
|
|
@@ -2993,6 +3009,8 @@ var Planner = class {
|
|
|
2993
3009
|
this.constraints = /* @__PURE__ */ new Map();
|
|
2994
3010
|
this.cooldowns = /* @__PURE__ */ new Map();
|
|
2995
3011
|
// param → last-applied-tick
|
|
3012
|
+
this.typeCooldowns = /* @__PURE__ */ new Map();
|
|
3013
|
+
// type+scope key → last-applied-tick
|
|
2996
3014
|
this.activePlanCount = 0;
|
|
2997
3015
|
}
|
|
2998
3016
|
lock(param) {
|
|
@@ -3015,6 +3033,8 @@ var Planner = class {
|
|
|
3015
3033
|
*/
|
|
3016
3034
|
plan(diagnosis, metrics, simulationResult, currentParams, thresholds, registry) {
|
|
3017
3035
|
const action = diagnosis.violation.suggestedAction;
|
|
3036
|
+
const typeKey = this.typeCooldownKey(action.parameterType, action.scope);
|
|
3037
|
+
if (this.isTypeCooldown(typeKey, metrics.tick, thresholds.cooldownTicks)) return null;
|
|
3018
3038
|
let param;
|
|
3019
3039
|
let resolvedBaseline;
|
|
3020
3040
|
let scope;
|
|
@@ -3072,6 +3092,9 @@ var Planner = class {
|
|
|
3072
3092
|
}
|
|
3073
3093
|
recordApplied(plan, tick) {
|
|
3074
3094
|
this.cooldowns.set(plan.parameter, tick);
|
|
3095
|
+
const action = plan.diagnosis.violation.suggestedAction;
|
|
3096
|
+
const typeKey = this.typeCooldownKey(action.parameterType, action.scope);
|
|
3097
|
+
this.typeCooldowns.set(typeKey, tick);
|
|
3075
3098
|
this.activePlanCount++;
|
|
3076
3099
|
}
|
|
3077
3100
|
recordRolledBack(_plan) {
|
|
@@ -3088,13 +3111,35 @@ var Planner = class {
|
|
|
3088
3111
|
/** Reset all cooldowns (useful for testing) */
|
|
3089
3112
|
resetCooldowns() {
|
|
3090
3113
|
this.cooldowns.clear();
|
|
3114
|
+
this.typeCooldowns.clear();
|
|
3115
|
+
}
|
|
3116
|
+
/** V1.5.2: Reset active plan count (e.g., on system restart) */
|
|
3117
|
+
resetActivePlans() {
|
|
3118
|
+
this.activePlanCount = 0;
|
|
3119
|
+
}
|
|
3120
|
+
/** V1.5.2: Current active plan count (for diagnostics) */
|
|
3121
|
+
getActivePlanCount() {
|
|
3122
|
+
return this.activePlanCount;
|
|
3123
|
+
}
|
|
3124
|
+
typeCooldownKey(type, scope) {
|
|
3125
|
+
const parts = [type];
|
|
3126
|
+
if (scope?.system) parts.push(`sys:${scope.system}`);
|
|
3127
|
+
if (scope?.currency) parts.push(`cur:${scope.currency}`);
|
|
3128
|
+
if (scope?.tags?.length) parts.push(`tags:${scope.tags.sort().join(",")}`);
|
|
3129
|
+
return parts.join("|");
|
|
3130
|
+
}
|
|
3131
|
+
isTypeCooldown(typeKey, currentTick, cooldownTicks) {
|
|
3132
|
+
const lastApplied = this.typeCooldowns.get(typeKey);
|
|
3133
|
+
if (lastApplied === void 0) return false;
|
|
3134
|
+
return currentTick - lastApplied < cooldownTicks;
|
|
3091
3135
|
}
|
|
3092
3136
|
};
|
|
3093
3137
|
|
|
3094
3138
|
// src/Executor.ts
|
|
3095
3139
|
var Executor = class {
|
|
3096
|
-
constructor() {
|
|
3140
|
+
constructor(settlementWindowTicks = 200) {
|
|
3097
3141
|
this.activePlans = [];
|
|
3142
|
+
this.maxActiveTicks = settlementWindowTicks;
|
|
3098
3143
|
}
|
|
3099
3144
|
async apply(plan, adapter, currentParams) {
|
|
3100
3145
|
const originalValue = currentParams[plan.parameter] ?? plan.currentValue;
|
|
@@ -3113,8 +3158,7 @@ var Executor = class {
|
|
|
3113
3158
|
for (const active of this.activePlans) {
|
|
3114
3159
|
const { plan, originalValue } = active;
|
|
3115
3160
|
const rc = plan.rollbackCondition;
|
|
3116
|
-
|
|
3117
|
-
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > maxActiveTicks) {
|
|
3161
|
+
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > this.maxActiveTicks) {
|
|
3118
3162
|
settled.push(plan);
|
|
3119
3163
|
continue;
|
|
3120
3164
|
}
|
|
@@ -3181,9 +3225,9 @@ var DecisionLog = class {
|
|
|
3181
3225
|
reasoning: this.buildReasoning(diagnosis, plan, result),
|
|
3182
3226
|
metricsSnapshot: metrics
|
|
3183
3227
|
};
|
|
3184
|
-
this.entries.
|
|
3185
|
-
if (this.entries.length > this.maxEntries) {
|
|
3186
|
-
this.entries.
|
|
3228
|
+
this.entries.push(entry);
|
|
3229
|
+
if (this.entries.length > this.maxEntries * 1.5) {
|
|
3230
|
+
this.entries = this.entries.slice(-this.maxEntries);
|
|
3187
3231
|
}
|
|
3188
3232
|
return entry;
|
|
3189
3233
|
}
|
|
@@ -3198,8 +3242,10 @@ var DecisionLog = class {
|
|
|
3198
3242
|
reasoning: reason,
|
|
3199
3243
|
metricsSnapshot: metrics
|
|
3200
3244
|
};
|
|
3201
|
-
this.entries.
|
|
3202
|
-
if (this.entries.length > this.maxEntries
|
|
3245
|
+
this.entries.push(entry);
|
|
3246
|
+
if (this.entries.length > this.maxEntries * 1.5) {
|
|
3247
|
+
this.entries = this.entries.slice(-this.maxEntries);
|
|
3248
|
+
}
|
|
3203
3249
|
}
|
|
3204
3250
|
query(filter) {
|
|
3205
3251
|
return this.entries.filter((e) => {
|
|
@@ -3212,7 +3258,7 @@ var DecisionLog = class {
|
|
|
3212
3258
|
});
|
|
3213
3259
|
}
|
|
3214
3260
|
latest(n = 30) {
|
|
3215
|
-
return this.entries.slice(
|
|
3261
|
+
return this.entries.slice(-n).reverse();
|
|
3216
3262
|
}
|
|
3217
3263
|
export(format = "json") {
|
|
3218
3264
|
if (format === "text") {
|
|
@@ -3441,10 +3487,13 @@ var MetricStore = class {
|
|
|
3441
3487
|
var PersonaTracker = class {
|
|
3442
3488
|
constructor() {
|
|
3443
3489
|
this.agentHistory = /* @__PURE__ */ new Map();
|
|
3490
|
+
this.lastSeen = /* @__PURE__ */ new Map();
|
|
3444
3491
|
}
|
|
3445
3492
|
/** Ingest a state snapshot and update agent signal history */
|
|
3446
3493
|
update(state) {
|
|
3494
|
+
const tick = state.tick;
|
|
3447
3495
|
for (const agentId of Object.keys(state.agentBalances)) {
|
|
3496
|
+
this.lastSeen.set(agentId, tick);
|
|
3448
3497
|
const history = this.agentHistory.get(agentId) ?? [];
|
|
3449
3498
|
const inv = state.agentInventories[agentId] ?? {};
|
|
3450
3499
|
const uniqueItems = Object.values(inv).filter((q) => q > 0).length;
|
|
@@ -3462,6 +3511,14 @@ var PersonaTracker = class {
|
|
|
3462
3511
|
if (history.length > 50) history.shift();
|
|
3463
3512
|
this.agentHistory.set(agentId, history);
|
|
3464
3513
|
}
|
|
3514
|
+
if (tick % 50 === 0) {
|
|
3515
|
+
for (const [id, lastTick] of this.lastSeen) {
|
|
3516
|
+
if (tick - lastTick > 100) {
|
|
3517
|
+
this.agentHistory.delete(id);
|
|
3518
|
+
this.lastSeen.delete(id);
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3465
3522
|
}
|
|
3466
3523
|
/** Classify all agents and return persona distribution */
|
|
3467
3524
|
getDistribution() {
|
|
@@ -3525,25 +3582,30 @@ var ParameterRegistry = class {
|
|
|
3525
3582
|
* Resolve a parameterType + scope to a concrete RegisteredParameter.
|
|
3526
3583
|
* Returns the best match, or undefined if no match.
|
|
3527
3584
|
*
|
|
3528
|
-
* Matching rules
|
|
3529
|
-
* 1.
|
|
3530
|
-
* 2.
|
|
3531
|
-
* 3.
|
|
3532
|
-
* 4.
|
|
3585
|
+
* Matching rules:
|
|
3586
|
+
* 1. Filter candidates by type
|
|
3587
|
+
* 2. Score each by scope specificity (system +10, currency +5, tags +3 each)
|
|
3588
|
+
* 3. Mismatched scope fields disqualify (score = -Infinity)
|
|
3589
|
+
* 4. Ties broken by `priority` (higher wins), then registration order
|
|
3590
|
+
* 5. All disqualified → undefined
|
|
3533
3591
|
*/
|
|
3534
3592
|
resolve(type, scope) {
|
|
3535
3593
|
const candidates = this.findByType(type);
|
|
3536
3594
|
if (candidates.length === 0) return void 0;
|
|
3537
3595
|
if (candidates.length === 1) return candidates[0];
|
|
3538
|
-
let bestScore = -
|
|
3596
|
+
let bestScore = -Infinity;
|
|
3597
|
+
let bestPriority = -Infinity;
|
|
3539
3598
|
let best;
|
|
3540
3599
|
for (const candidate of candidates) {
|
|
3541
|
-
const score = this.
|
|
3542
|
-
|
|
3600
|
+
const score = this.scopeSpecificity(candidate.scope, scope);
|
|
3601
|
+
const prio = candidate.priority ?? 0;
|
|
3602
|
+
if (score > bestScore || score === bestScore && prio > bestPriority) {
|
|
3543
3603
|
bestScore = score;
|
|
3604
|
+
bestPriority = prio;
|
|
3544
3605
|
best = candidate;
|
|
3545
3606
|
}
|
|
3546
3607
|
}
|
|
3608
|
+
if (bestScore === -Infinity) return void 0;
|
|
3547
3609
|
return best;
|
|
3548
3610
|
}
|
|
3549
3611
|
/** Find all parameters of a given type. */
|
|
@@ -3585,28 +3647,60 @@ var ParameterRegistry = class {
|
|
|
3585
3647
|
get size() {
|
|
3586
3648
|
return this.parameters.size;
|
|
3587
3649
|
}
|
|
3650
|
+
/**
|
|
3651
|
+
* Validate the registry for common misconfigurations.
|
|
3652
|
+
* Returns warnings (non-fatal) and errors (likely broken).
|
|
3653
|
+
*/
|
|
3654
|
+
validate() {
|
|
3655
|
+
const warnings = [];
|
|
3656
|
+
const errors = [];
|
|
3657
|
+
const typeMap = /* @__PURE__ */ new Map();
|
|
3658
|
+
for (const param of this.parameters.values()) {
|
|
3659
|
+
const list = typeMap.get(param.type) ?? [];
|
|
3660
|
+
list.push(param);
|
|
3661
|
+
typeMap.set(param.type, list);
|
|
3662
|
+
}
|
|
3663
|
+
for (const [type, params] of typeMap) {
|
|
3664
|
+
if (params.length > 1) {
|
|
3665
|
+
const unscopedCount = params.filter((p) => !p.scope).length;
|
|
3666
|
+
if (unscopedCount > 1) {
|
|
3667
|
+
errors.push(
|
|
3668
|
+
`Type '${type}' has ${unscopedCount} unscoped parameters \u2014 resolve() cannot distinguish them`
|
|
3669
|
+
);
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
for (const param of this.parameters.values()) {
|
|
3674
|
+
if (!param.flowImpact) {
|
|
3675
|
+
warnings.push(`Parameter '${param.key}' has no flowImpact \u2014 Simulator will use inference`);
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
return {
|
|
3679
|
+
valid: errors.length === 0,
|
|
3680
|
+
warnings,
|
|
3681
|
+
errors
|
|
3682
|
+
};
|
|
3683
|
+
}
|
|
3588
3684
|
// ── Private ─────────────────────────────────────────────────────────────
|
|
3589
|
-
|
|
3685
|
+
scopeSpecificity(paramScope, queryScope) {
|
|
3590
3686
|
if (!queryScope) return 0;
|
|
3591
3687
|
if (!paramScope) return 0;
|
|
3592
3688
|
let score = 0;
|
|
3593
3689
|
if (queryScope.system && paramScope.system) {
|
|
3594
3690
|
if (queryScope.system === paramScope.system) score += 10;
|
|
3595
|
-
else return -
|
|
3691
|
+
else return -Infinity;
|
|
3596
3692
|
}
|
|
3597
3693
|
if (queryScope.currency && paramScope.currency) {
|
|
3598
3694
|
if (queryScope.currency === paramScope.currency) score += 5;
|
|
3599
|
-
else return -
|
|
3695
|
+
else return -Infinity;
|
|
3600
3696
|
}
|
|
3601
3697
|
if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3602
3698
|
const overlap = queryScope.tags.filter((t) => paramScope.tags.includes(t)).length;
|
|
3603
3699
|
if (overlap > 0) {
|
|
3604
3700
|
score += overlap * 3;
|
|
3605
3701
|
} else {
|
|
3606
|
-
return -
|
|
3702
|
+
return -Infinity;
|
|
3607
3703
|
}
|
|
3608
|
-
} else if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3609
|
-
return -1;
|
|
3610
3704
|
}
|
|
3611
3705
|
return score;
|
|
3612
3706
|
}
|
|
@@ -3616,7 +3710,6 @@ var ParameterRegistry = class {
|
|
|
3616
3710
|
var AgentE = class {
|
|
3617
3711
|
constructor(config) {
|
|
3618
3712
|
this.planner = new Planner();
|
|
3619
|
-
this.executor = new Executor();
|
|
3620
3713
|
this.registry = new ParameterRegistry();
|
|
3621
3714
|
// ── State ──
|
|
3622
3715
|
this.log = new DecisionLog();
|
|
@@ -3638,6 +3731,9 @@ var AgentE = class {
|
|
|
3638
3731
|
mode: this.mode,
|
|
3639
3732
|
dominantRoles: config.dominantRoles ?? [],
|
|
3640
3733
|
idealDistribution: config.idealDistribution ?? {},
|
|
3734
|
+
validateRegistry: config.validateRegistry ?? true,
|
|
3735
|
+
simulation: config.simulation ?? {},
|
|
3736
|
+
settlementWindowTicks: config.settlementWindowTicks ?? 200,
|
|
3641
3737
|
tickConfig: config.tickConfig ?? { duration: 1, unit: "tick" },
|
|
3642
3738
|
gracePeriod: config.gracePeriod ?? 50,
|
|
3643
3739
|
checkInterval: config.checkInterval ?? 5,
|
|
@@ -3658,7 +3754,13 @@ var AgentE = class {
|
|
|
3658
3754
|
if (config.parameters) {
|
|
3659
3755
|
this.registry.registerAll(config.parameters);
|
|
3660
3756
|
}
|
|
3661
|
-
|
|
3757
|
+
if (config.validateRegistry !== false && this.registry.size > 0) {
|
|
3758
|
+
const validation = this.registry.validate();
|
|
3759
|
+
for (const w of validation.warnings) console.warn(`[AgentE] Registry warning: ${w}`);
|
|
3760
|
+
for (const e of validation.errors) console.error(`[AgentE] Registry error: ${e}`);
|
|
3761
|
+
}
|
|
3762
|
+
this.executor = new Executor(config.settlementWindowTicks);
|
|
3763
|
+
this.simulator = new Simulator(this.registry, config.simulation);
|
|
3662
3764
|
if (config.onDecision) this.on("decision", config.onDecision);
|
|
3663
3765
|
if (config.onAlert) this.on("alert", config.onAlert);
|
|
3664
3766
|
if (config.onRollback) this.on("rollback", config.onRollback);
|
|
@@ -3694,7 +3796,7 @@ var AgentE = class {
|
|
|
3694
3796
|
if (!this.isRunning || this.isPaused) return;
|
|
3695
3797
|
const currentState = state ?? await Promise.resolve(this.adapter.getState());
|
|
3696
3798
|
this.currentTick = currentState.tick;
|
|
3697
|
-
const events =
|
|
3799
|
+
const events = this.eventBuffer;
|
|
3698
3800
|
this.eventBuffer = [];
|
|
3699
3801
|
let metrics;
|
|
3700
3802
|
try {
|
|
@@ -3812,7 +3914,9 @@ var AgentE = class {
|
|
|
3812
3914
|
// ── Events ──────────────────────────────────────────────────────────────────
|
|
3813
3915
|
on(event, handler) {
|
|
3814
3916
|
const list = this.handlers.get(event) ?? [];
|
|
3815
|
-
list.
|
|
3917
|
+
if (!list.includes(handler)) {
|
|
3918
|
+
list.push(handler);
|
|
3919
|
+
}
|
|
3816
3920
|
this.handlers.set(event, list);
|
|
3817
3921
|
return this;
|
|
3818
3922
|
}
|
|
@@ -3825,8 +3929,12 @@ var AgentE = class {
|
|
|
3825
3929
|
const list = this.handlers.get(event) ?? [];
|
|
3826
3930
|
let result;
|
|
3827
3931
|
for (const handler of list) {
|
|
3828
|
-
|
|
3829
|
-
|
|
3932
|
+
try {
|
|
3933
|
+
result = handler(...args);
|
|
3934
|
+
if (result === false) return false;
|
|
3935
|
+
} catch (err) {
|
|
3936
|
+
console.error(`[AgentE] Handler error on '${event}':`, err);
|
|
3937
|
+
}
|
|
3830
3938
|
}
|
|
3831
3939
|
return result;
|
|
3832
3940
|
}
|
|
@@ -3854,6 +3962,31 @@ var AgentE = class {
|
|
|
3854
3962
|
}
|
|
3855
3963
|
};
|
|
3856
3964
|
|
|
3965
|
+
// src/utils.ts
|
|
3966
|
+
function findWorstSystem(metrics, check, tolerancePercent = 0) {
|
|
3967
|
+
const systems = metrics.systems;
|
|
3968
|
+
if (systems.length === 0) return void 0;
|
|
3969
|
+
let worstSystem;
|
|
3970
|
+
let worstScore = -Infinity;
|
|
3971
|
+
let totalScore = 0;
|
|
3972
|
+
for (const sys of systems) {
|
|
3973
|
+
const score = check(sys, metrics);
|
|
3974
|
+
totalScore += score;
|
|
3975
|
+
if (score > worstScore) {
|
|
3976
|
+
worstScore = score;
|
|
3977
|
+
worstSystem = sys;
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
if (!worstSystem) return void 0;
|
|
3981
|
+
if (tolerancePercent > 0 && systems.length > 1) {
|
|
3982
|
+
const avg = totalScore / systems.length;
|
|
3983
|
+
if (avg === 0) return { system: worstSystem, score: worstScore };
|
|
3984
|
+
const excessPercent = (worstScore - avg) / Math.abs(avg) * 100;
|
|
3985
|
+
if (excessPercent < tolerancePercent) return void 0;
|
|
3986
|
+
}
|
|
3987
|
+
return { system: worstSystem, score: worstScore };
|
|
3988
|
+
}
|
|
3989
|
+
|
|
3857
3990
|
// src/StateValidator.ts
|
|
3858
3991
|
function validateEconomyState(state) {
|
|
3859
3992
|
const errors = [];
|
|
@@ -4204,7 +4337,7 @@ export {
|
|
|
4204
4337
|
OPEN_ECONOMY_PRINCIPLES,
|
|
4205
4338
|
OPERATIONS_PRINCIPLES,
|
|
4206
4339
|
Observer,
|
|
4207
|
-
|
|
4340
|
+
P10_EntryWeightingUsesInversePopulation,
|
|
4208
4341
|
P11_TwoTierPressure,
|
|
4209
4342
|
P12_OnePrimaryFaucet,
|
|
4210
4343
|
P13_PotsAreZeroSumAndSelfRegulate,
|
|
@@ -4224,9 +4357,9 @@ export {
|
|
|
4224
4357
|
P26_ContinuousPressureBeatsThresholdCuts,
|
|
4225
4358
|
P27_AdjustmentsNeedCooldowns,
|
|
4226
4359
|
P28_StructuralDominanceIsNotPathological,
|
|
4227
|
-
|
|
4360
|
+
P29_BottleneckDetection,
|
|
4228
4361
|
P2_ClosedLoopsNeedDirectHandoff,
|
|
4229
|
-
|
|
4362
|
+
P30_DynamicBottleneckRotation,
|
|
4230
4363
|
P31_AnchorValueTracking,
|
|
4231
4364
|
P32_VelocityAboveSupply,
|
|
4232
4365
|
P33_FairNotEqual,
|
|
@@ -4249,16 +4382,16 @@ export {
|
|
|
4249
4382
|
P49_IdleAssetTax,
|
|
4250
4383
|
P4_MaterialsFlowFasterThanCooldown,
|
|
4251
4384
|
P50_PayPowerRatio,
|
|
4252
|
-
|
|
4385
|
+
P51_CyclicalEngagement,
|
|
4253
4386
|
P52_EndowmentEffect,
|
|
4254
4387
|
P53_EventCompletionRate,
|
|
4255
|
-
|
|
4388
|
+
P54_OperationalCadence,
|
|
4256
4389
|
P55_ArbitrageThermometer,
|
|
4257
|
-
|
|
4390
|
+
P56_SupplyShockAbsorption,
|
|
4258
4391
|
P57_CombinatorialPriceSpace,
|
|
4259
4392
|
P58_NoNaturalNumeraire,
|
|
4260
4393
|
P59_GiftEconomyNoise,
|
|
4261
|
-
|
|
4394
|
+
P5_ProfitabilityIsRelative,
|
|
4262
4395
|
P60_SurplusDisposalAsymmetry,
|
|
4263
4396
|
P6_CrowdingMultiplierOnAllRoles,
|
|
4264
4397
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
@@ -4277,6 +4410,7 @@ export {
|
|
|
4277
4410
|
SYSTEM_DYNAMICS_PRINCIPLES,
|
|
4278
4411
|
Simulator,
|
|
4279
4412
|
emptyMetrics,
|
|
4413
|
+
findWorstSystem,
|
|
4280
4414
|
validateEconomyState
|
|
4281
4415
|
};
|
|
4282
4416
|
//# sourceMappingURL=index.mjs.map
|