@agent-e/core 1.5.1 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -72
- package/dist/index.d.mts +27 -5
- package/dist/index.d.ts +27 -5
- package/dist/index.js +114 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -80
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -90,7 +90,7 @@ __export(index_exports, {
|
|
|
90
90
|
P57_CombinatorialPriceSpace: () => P57_CombinatorialPriceSpace,
|
|
91
91
|
P58_NoNaturalNumeraire: () => P58_NoNaturalNumeraire,
|
|
92
92
|
P59_GiftEconomyNoise: () => P59_GiftEconomyNoise,
|
|
93
|
-
|
|
93
|
+
P5_ProfitabilityIsRelative: () => P5_ProfitabilityIsRelative,
|
|
94
94
|
P60_SurplusDisposalAsymmetry: () => P60_SurplusDisposalAsymmetry,
|
|
95
95
|
P6_CrowdingMultiplierOnAllRoles: () => P6_CrowdingMultiplierOnAllRoles,
|
|
96
96
|
P7_NonSpecialistsSubsidiseSpecialists: () => P7_NonSpecialistsSubsidiseSpecialists,
|
|
@@ -148,7 +148,7 @@ var DEFAULT_THRESHOLDS = {
|
|
|
148
148
|
cooldownTicks: 15,
|
|
149
149
|
// Currency (P13)
|
|
150
150
|
poolWinRate: 0.65,
|
|
151
|
-
|
|
151
|
+
poolOperatorShare: 0.1,
|
|
152
152
|
// Population balance (P9)
|
|
153
153
|
roleSwitchFrictionMax: 0.05,
|
|
154
154
|
// >5% of population switching in one period = herd
|
|
@@ -209,6 +209,12 @@ var Observer = class {
|
|
|
209
209
|
this.customMetricFns[name] = fn;
|
|
210
210
|
}
|
|
211
211
|
compute(state, recentEvents) {
|
|
212
|
+
if (!state.currencies || state.currencies.length === 0) {
|
|
213
|
+
console.warn("[AgentE] Warning: state.currencies is empty. Metrics will be zeroed.");
|
|
214
|
+
}
|
|
215
|
+
if (!state.agentBalances || Object.keys(state.agentBalances).length === 0) {
|
|
216
|
+
console.warn("[AgentE] Warning: state.agentBalances is empty.");
|
|
217
|
+
}
|
|
212
218
|
const tick = state.tick;
|
|
213
219
|
const roles = Object.values(state.agentRoles);
|
|
214
220
|
const totalAgents = Object.keys(state.agentBalances).length;
|
|
@@ -303,7 +309,7 @@ var Observer = class {
|
|
|
303
309
|
const faucet = faucetVolumeByCurrency[curr] ?? 0;
|
|
304
310
|
const sink = sinkVolumeByCurrency[curr] ?? 0;
|
|
305
311
|
netFlowByCurrency[curr] = faucet - sink;
|
|
306
|
-
tapSinkRatioByCurrency[curr] = sink > 0 ? faucet / sink : faucet > 0 ?
|
|
312
|
+
tapSinkRatioByCurrency[curr] = sink > 0 ? Math.min(faucet / sink, 100) : faucet > 0 ? 100 : 1;
|
|
307
313
|
const prevSupply = this.previousMetrics?.totalSupplyByCurrency?.[curr] ?? totalSupplyByCurrency[curr] ?? 0;
|
|
308
314
|
const currSupply = totalSupplyByCurrency[curr] ?? 0;
|
|
309
315
|
inflationRateByCurrency[curr] = prevSupply > 0 ? (currSupply - prevSupply) / prevSupply : 0;
|
|
@@ -338,7 +344,7 @@ var Observer = class {
|
|
|
338
344
|
const faucetVolume = Object.values(faucetVolumeByCurrency).reduce((s, v) => s + v, 0);
|
|
339
345
|
const sinkVolume = Object.values(sinkVolumeByCurrency).reduce((s, v) => s + v, 0);
|
|
340
346
|
const netFlow = faucetVolume - sinkVolume;
|
|
341
|
-
const tapSinkRatio = sinkVolume > 0 ? faucetVolume / sinkVolume : faucetVolume > 0 ?
|
|
347
|
+
const tapSinkRatio = sinkVolume > 0 ? Math.min(faucetVolume / sinkVolume, 100) : faucetVolume > 0 ? 100 : 1;
|
|
342
348
|
const velocity = totalSupply > 0 ? tradeEvents.length / totalSupply : 0;
|
|
343
349
|
const prevTotalSupply = this.previousMetrics?.totalSupply ?? totalSupply;
|
|
344
350
|
const inflationRate = prevTotalSupply > 0 ? (totalSupply - prevTotalSupply) / prevTotalSupply : 0;
|
|
@@ -376,7 +382,9 @@ var Observer = class {
|
|
|
376
382
|
const pVals = Object.values(resourcePrices);
|
|
377
383
|
priceIndexByCurrency[curr] = pVals.length > 0 ? pVals.reduce((s, p) => s + p, 0) / pVals.length : 0;
|
|
378
384
|
}
|
|
379
|
-
this.previousPricesByCurrency =
|
|
385
|
+
this.previousPricesByCurrency = Object.fromEntries(
|
|
386
|
+
Object.entries(pricesByCurrency).map(([c, p]) => [c, { ...p }])
|
|
387
|
+
);
|
|
380
388
|
const prices = pricesByCurrency[defaultCurrency] ?? {};
|
|
381
389
|
const priceVolatility = priceVolatilityByCurrency[defaultCurrency] ?? {};
|
|
382
390
|
const priceIndex = priceIndexByCurrency[defaultCurrency] ?? 0;
|
|
@@ -396,9 +404,9 @@ var Observer = class {
|
|
|
396
404
|
for (const resource of /* @__PURE__ */ new Set([...Object.keys(supplyByResource), ...Object.keys(demandSignals)])) {
|
|
397
405
|
const s = supplyByResource[resource] ?? 0;
|
|
398
406
|
const d = demandSignals[resource] ?? 0;
|
|
399
|
-
if (d > 2 && s / d < 0.5) {
|
|
407
|
+
if (d > 0 && d > 2 && s / d < 0.5) {
|
|
400
408
|
pinchPoints[resource] = "scarce";
|
|
401
|
-
} else if (
|
|
409
|
+
} else if (d > 0 && s > 3 && s / d > 3) {
|
|
402
410
|
pinchPoints[resource] = "oversupplied";
|
|
403
411
|
} else {
|
|
404
412
|
pinchPoints[resource] = "optimal";
|
|
@@ -444,21 +452,11 @@ var Observer = class {
|
|
|
444
452
|
const arbitrageIndexByCurrency = {};
|
|
445
453
|
for (const curr of currencies) {
|
|
446
454
|
const cPrices = pricesByCurrency[curr] ?? {};
|
|
447
|
-
const
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
for (let j = i + 1; j < priceKeys.length; j++) {
|
|
453
|
-
const pA = cPrices[priceKeys[i]];
|
|
454
|
-
const pB = cPrices[priceKeys[j]];
|
|
455
|
-
let ratio = pA / pB;
|
|
456
|
-
ratio = Math.max(1e-3, Math.min(1e3, ratio));
|
|
457
|
-
totalDivergence += Math.abs(Math.log(ratio));
|
|
458
|
-
pairCount++;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
arbitrageIndexByCurrency[curr] = pairCount > 0 ? Math.min(1, totalDivergence / pairCount) : 0;
|
|
455
|
+
const logPrices = Object.values(cPrices).filter((p) => p > 0).map((p) => Math.log(p));
|
|
456
|
+
if (logPrices.length >= 2) {
|
|
457
|
+
const mean = logPrices.reduce((s, v) => s + v, 0) / logPrices.length;
|
|
458
|
+
const variance = logPrices.reduce((s, v) => s + (v - mean) ** 2, 0) / logPrices.length;
|
|
459
|
+
arbitrageIndexByCurrency[curr] = Math.min(1, Math.sqrt(variance));
|
|
462
460
|
} else {
|
|
463
461
|
arbitrageIndexByCurrency[curr] = 0;
|
|
464
462
|
}
|
|
@@ -545,10 +543,10 @@ var Observer = class {
|
|
|
545
543
|
prices,
|
|
546
544
|
priceVolatility,
|
|
547
545
|
poolSizes: poolSizesAggregate,
|
|
548
|
-
extractionRatio:
|
|
549
|
-
newUserDependency:
|
|
550
|
-
smokeTestRatio:
|
|
551
|
-
currencyInsulation:
|
|
546
|
+
extractionRatio: 0,
|
|
547
|
+
newUserDependency: 0,
|
|
548
|
+
smokeTestRatio: 0,
|
|
549
|
+
currencyInsulation: 0,
|
|
552
550
|
arbitrageIndex,
|
|
553
551
|
giftTradeRatio,
|
|
554
552
|
disposalTradeRatio,
|
|
@@ -570,7 +568,7 @@ var Observer = class {
|
|
|
570
568
|
timeToValue,
|
|
571
569
|
sharkToothPeaks: this.previousMetrics?.sharkToothPeaks ?? [],
|
|
572
570
|
sharkToothValleys: this.previousMetrics?.sharkToothValleys ?? [],
|
|
573
|
-
eventCompletionRate:
|
|
571
|
+
eventCompletionRate: 0,
|
|
574
572
|
contentDropAge,
|
|
575
573
|
systems: state.systems ?? [],
|
|
576
574
|
sources: state.sources ?? [],
|
|
@@ -602,7 +600,7 @@ function computeGini(sorted) {
|
|
|
602
600
|
for (let i = 0; i < n; i++) {
|
|
603
601
|
numerator += (2 * (i + 1) - n - 1) * (sorted[i] ?? 0);
|
|
604
602
|
}
|
|
605
|
-
return Math.abs(numerator) / (n * sum);
|
|
603
|
+
return Math.min(1, Math.abs(numerator) / (n * sum));
|
|
606
604
|
}
|
|
607
605
|
|
|
608
606
|
// src/Diagnoser.ts
|
|
@@ -698,10 +696,10 @@ function emptyMetrics(tick = 0) {
|
|
|
698
696
|
prices: {},
|
|
699
697
|
priceVolatility: {},
|
|
700
698
|
poolSizes: {},
|
|
701
|
-
extractionRatio:
|
|
702
|
-
newUserDependency:
|
|
703
|
-
smokeTestRatio:
|
|
704
|
-
currencyInsulation:
|
|
699
|
+
extractionRatio: 0,
|
|
700
|
+
newUserDependency: 0,
|
|
701
|
+
smokeTestRatio: 0,
|
|
702
|
+
currencyInsulation: 0,
|
|
705
703
|
arbitrageIndex: 0,
|
|
706
704
|
giftTradeRatio: 0,
|
|
707
705
|
disposalTradeRatio: 0,
|
|
@@ -722,7 +720,7 @@ function emptyMetrics(tick = 0) {
|
|
|
722
720
|
timeToValue: 0,
|
|
723
721
|
sharkToothPeaks: [],
|
|
724
722
|
sharkToothValleys: [],
|
|
725
|
-
eventCompletionRate:
|
|
723
|
+
eventCompletionRate: 0,
|
|
726
724
|
contentDropAge: 0,
|
|
727
725
|
systems: [],
|
|
728
726
|
sources: [],
|
|
@@ -927,9 +925,9 @@ var SUPPLY_CHAIN_PRINCIPLES = [
|
|
|
927
925
|
];
|
|
928
926
|
|
|
929
927
|
// src/principles/incentives.ts
|
|
930
|
-
var
|
|
928
|
+
var P5_ProfitabilityIsRelative = {
|
|
931
929
|
id: "P5",
|
|
932
|
-
name: "Profitability Is
|
|
930
|
+
name: "Profitability Is Relative, Not Absolute",
|
|
933
931
|
category: "incentive",
|
|
934
932
|
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.",
|
|
935
933
|
check(metrics, thresholds) {
|
|
@@ -993,7 +991,7 @@ var P7_NonSpecialistsSubsidiseSpecialists = {
|
|
|
993
991
|
id: "P7",
|
|
994
992
|
name: "Non-Specialists Subsidise Specialists in Zero-Sum Games",
|
|
995
993
|
category: "incentive",
|
|
996
|
-
description: "In zero-sum pools (
|
|
994
|
+
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.",
|
|
997
995
|
check(metrics, _thresholds) {
|
|
998
996
|
const { poolSizes } = metrics;
|
|
999
997
|
for (const [poolName, poolSize] of Object.entries(poolSizes)) {
|
|
@@ -1029,7 +1027,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
1029
1027
|
id: "P8",
|
|
1030
1028
|
name: "Regulator Cannot Fight the Design",
|
|
1031
1029
|
category: "incentive",
|
|
1032
|
-
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
|
|
1030
|
+
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.",
|
|
1033
1031
|
check(metrics, _thresholds) {
|
|
1034
1032
|
const { roleShares, avgSatisfaction } = metrics;
|
|
1035
1033
|
if (avgSatisfaction < 45) {
|
|
@@ -1054,7 +1052,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
1054
1052
|
}
|
|
1055
1053
|
};
|
|
1056
1054
|
var INCENTIVE_PRINCIPLES = [
|
|
1057
|
-
|
|
1055
|
+
P5_ProfitabilityIsRelative,
|
|
1058
1056
|
P6_CrowdingMultiplierOnAllRoles,
|
|
1059
1057
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
1060
1058
|
P8_RegulatorCannotFightDesign
|
|
@@ -1250,7 +1248,7 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1250
1248
|
id: "P13",
|
|
1251
1249
|
name: "Pots Self-Regulate with Correct Multiplier",
|
|
1252
1250
|
category: "currency",
|
|
1253
|
-
description: "
|
|
1251
|
+
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.",
|
|
1254
1252
|
check(metrics, thresholds) {
|
|
1255
1253
|
const { populationByRole } = metrics;
|
|
1256
1254
|
const roleEntries = Object.entries(populationByRole).sort((a, b) => b[1] - a[1]);
|
|
@@ -1259,8 +1257,8 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1259
1257
|
for (const curr of metrics.currencies) {
|
|
1260
1258
|
const poolSize = currencyAmounts[curr] ?? 0;
|
|
1261
1259
|
if (dominantCount > 5 && poolSize < 50) {
|
|
1262
|
-
const { poolWinRate,
|
|
1263
|
-
const maxSustainableMultiplier = (1 -
|
|
1260
|
+
const { poolWinRate, poolOperatorShare } = thresholds;
|
|
1261
|
+
const maxSustainableMultiplier = (1 - poolOperatorShare) / poolWinRate;
|
|
1264
1262
|
return {
|
|
1265
1263
|
violated: true,
|
|
1266
1264
|
severity: 7,
|
|
@@ -1543,7 +1541,7 @@ var P19_StartingSupplyExceedsDemand = {
|
|
|
1543
1541
|
parameterType: "reward",
|
|
1544
1542
|
direction: "increase",
|
|
1545
1543
|
magnitude: 0.2,
|
|
1546
|
-
reasoning: `${mostPopulatedRole} (${population} agents) has insufficient resources (${resourcesPerAgent.toFixed(2)} per agent). Cold-start scarcity. Boost
|
|
1544
|
+
reasoning: `${mostPopulatedRole} (${population} agents) has insufficient resources (${resourcesPerAgent.toFixed(2)} per agent). Cold-start scarcity. Boost pool reward to attract participation despite scarcity.`
|
|
1547
1545
|
},
|
|
1548
1546
|
confidence: 0.75,
|
|
1549
1547
|
estimatedLag: 5
|
|
@@ -2288,7 +2286,7 @@ var P35_DestructionCreatesValue = {
|
|
|
2288
2286
|
scope: { tags: ["entry"] },
|
|
2289
2287
|
direction: "decrease",
|
|
2290
2288
|
magnitude: 0.1,
|
|
2291
|
-
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower
|
|
2289
|
+
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower pool entry to increase resource usage.`
|
|
2292
2290
|
},
|
|
2293
2291
|
confidence: 0.7,
|
|
2294
2292
|
estimatedLag: 5
|
|
@@ -2895,15 +2893,24 @@ var ALL_PRINCIPLES = [
|
|
|
2895
2893
|
];
|
|
2896
2894
|
|
|
2897
2895
|
// src/Simulator.ts
|
|
2896
|
+
var DEFAULT_SIM_CONFIG = {
|
|
2897
|
+
sinkMultiplier: 0.2,
|
|
2898
|
+
faucetMultiplier: 0.15,
|
|
2899
|
+
frictionMultiplier: 0.1,
|
|
2900
|
+
frictionVelocityScale: 10,
|
|
2901
|
+
redistributionMultiplier: 0.3,
|
|
2902
|
+
neutralMultiplier: 0.05,
|
|
2903
|
+
minIterations: 100,
|
|
2904
|
+
maxProjectionTicks: 20
|
|
2905
|
+
};
|
|
2898
2906
|
var Simulator = class {
|
|
2899
|
-
constructor(registry) {
|
|
2907
|
+
constructor(registry, simConfig) {
|
|
2900
2908
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
2901
|
-
// Cache beforeViolations for the *current* tick only
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
// entries whose key differs from the incoming tick.
|
|
2905
|
-
this.beforeViolationsCache = /* @__PURE__ */ new Map();
|
|
2909
|
+
// Cache beforeViolations for the *current* tick only.
|
|
2910
|
+
this.cachedViolationsTick = -1;
|
|
2911
|
+
this.cachedViolations = /* @__PURE__ */ new Set();
|
|
2906
2912
|
this.registry = registry;
|
|
2913
|
+
this.simConfig = { ...DEFAULT_SIM_CONFIG, ...simConfig };
|
|
2907
2914
|
}
|
|
2908
2915
|
/**
|
|
2909
2916
|
* Simulate the effect of applying `action` to the current economy forward `forwardTicks`.
|
|
@@ -2927,16 +2934,13 @@ var Simulator = class {
|
|
|
2927
2934
|
const mean = this.averageMetrics(outcomes);
|
|
2928
2935
|
const netImprovement = this.checkImprovement(currentMetrics, p50, action);
|
|
2929
2936
|
const tick = currentMetrics.tick;
|
|
2930
|
-
if (this.
|
|
2931
|
-
this.
|
|
2932
|
-
}
|
|
2933
|
-
let beforeViolations = this.beforeViolationsCache.get(tick);
|
|
2934
|
-
if (!beforeViolations) {
|
|
2935
|
-
beforeViolations = new Set(
|
|
2937
|
+
if (this.cachedViolationsTick !== tick) {
|
|
2938
|
+
this.cachedViolations = new Set(
|
|
2936
2939
|
this.diagnoser.diagnose(currentMetrics, thresholds).map((d) => d.principle.id)
|
|
2937
2940
|
);
|
|
2938
|
-
this.
|
|
2941
|
+
this.cachedViolationsTick = tick;
|
|
2939
2942
|
}
|
|
2943
|
+
const beforeViolations = this.cachedViolations;
|
|
2940
2944
|
const afterViolations = new Set(
|
|
2941
2945
|
this.diagnoser.diagnose(p50, thresholds).map((d) => d.principle.id)
|
|
2942
2946
|
);
|
|
@@ -3026,21 +3030,22 @@ var Simulator = class {
|
|
|
3026
3030
|
if (!impact) {
|
|
3027
3031
|
impact = this.inferFlowImpact(action.parameterType);
|
|
3028
3032
|
}
|
|
3033
|
+
const cfg = this.simConfig;
|
|
3029
3034
|
switch (impact) {
|
|
3030
3035
|
case "sink":
|
|
3031
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
3036
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.sinkMultiplier;
|
|
3032
3037
|
case "faucet":
|
|
3033
|
-
return -sign * dominantRoleCount *
|
|
3038
|
+
return -sign * dominantRoleCount * cfg.redistributionMultiplier;
|
|
3034
3039
|
case "neutral":
|
|
3035
|
-
return sign * dominantRoleCount *
|
|
3040
|
+
return sign * dominantRoleCount * cfg.neutralMultiplier;
|
|
3036
3041
|
case "mixed":
|
|
3037
|
-
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) *
|
|
3042
|
+
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * cfg.faucetMultiplier;
|
|
3038
3043
|
case "friction":
|
|
3039
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
3044
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.frictionMultiplier;
|
|
3040
3045
|
case "redistribution":
|
|
3041
|
-
return sign * dominantRoleCount *
|
|
3046
|
+
return sign * dominantRoleCount * cfg.neutralMultiplier;
|
|
3042
3047
|
default:
|
|
3043
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
3048
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.frictionMultiplier;
|
|
3044
3049
|
}
|
|
3045
3050
|
}
|
|
3046
3051
|
/** Infer flow impact from parameter type when registry is unavailable */
|
|
@@ -3061,7 +3066,7 @@ var Simulator = class {
|
|
|
3061
3066
|
return "mixed";
|
|
3062
3067
|
}
|
|
3063
3068
|
}
|
|
3064
|
-
checkImprovement(before, after,
|
|
3069
|
+
checkImprovement(before, after, _action) {
|
|
3065
3070
|
const satisfactionImproved = after.avgSatisfaction >= before.avgSatisfaction - 2;
|
|
3066
3071
|
const flowMoreBalanced = before.currencies.every((curr) => {
|
|
3067
3072
|
const afterFlow = Math.abs(after.netFlowByCurrency[curr] ?? 0);
|
|
@@ -3073,7 +3078,6 @@ var Simulator = class {
|
|
|
3073
3078
|
const beforeGini = before.giniCoefficientByCurrency[curr] ?? 0;
|
|
3074
3079
|
return afterGini <= beforeGini + 0.05;
|
|
3075
3080
|
});
|
|
3076
|
-
void action;
|
|
3077
3081
|
return satisfactionImproved && flowMoreBalanced && notWorseGini;
|
|
3078
3082
|
}
|
|
3079
3083
|
averageMetrics(outcomes) {
|
|
@@ -3225,6 +3229,14 @@ var Planner = class {
|
|
|
3225
3229
|
this.cooldowns.clear();
|
|
3226
3230
|
this.typeCooldowns.clear();
|
|
3227
3231
|
}
|
|
3232
|
+
/** V1.5.2: Reset active plan count (e.g., on system restart) */
|
|
3233
|
+
resetActivePlans() {
|
|
3234
|
+
this.activePlanCount = 0;
|
|
3235
|
+
}
|
|
3236
|
+
/** V1.5.2: Current active plan count (for diagnostics) */
|
|
3237
|
+
getActivePlanCount() {
|
|
3238
|
+
return this.activePlanCount;
|
|
3239
|
+
}
|
|
3228
3240
|
typeCooldownKey(type, scope) {
|
|
3229
3241
|
const parts = [type];
|
|
3230
3242
|
if (scope?.system) parts.push(`sys:${scope.system}`);
|
|
@@ -3241,8 +3253,9 @@ var Planner = class {
|
|
|
3241
3253
|
|
|
3242
3254
|
// src/Executor.ts
|
|
3243
3255
|
var Executor = class {
|
|
3244
|
-
constructor() {
|
|
3256
|
+
constructor(settlementWindowTicks = 200) {
|
|
3245
3257
|
this.activePlans = [];
|
|
3258
|
+
this.maxActiveTicks = settlementWindowTicks;
|
|
3246
3259
|
}
|
|
3247
3260
|
async apply(plan, adapter, currentParams) {
|
|
3248
3261
|
const originalValue = currentParams[plan.parameter] ?? plan.currentValue;
|
|
@@ -3261,8 +3274,7 @@ var Executor = class {
|
|
|
3261
3274
|
for (const active of this.activePlans) {
|
|
3262
3275
|
const { plan, originalValue } = active;
|
|
3263
3276
|
const rc = plan.rollbackCondition;
|
|
3264
|
-
|
|
3265
|
-
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > maxActiveTicks) {
|
|
3277
|
+
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > this.maxActiveTicks) {
|
|
3266
3278
|
settled.push(plan);
|
|
3267
3279
|
continue;
|
|
3268
3280
|
}
|
|
@@ -3329,9 +3341,9 @@ var DecisionLog = class {
|
|
|
3329
3341
|
reasoning: this.buildReasoning(diagnosis, plan, result),
|
|
3330
3342
|
metricsSnapshot: metrics
|
|
3331
3343
|
};
|
|
3332
|
-
this.entries.
|
|
3333
|
-
if (this.entries.length > this.maxEntries) {
|
|
3334
|
-
this.entries.
|
|
3344
|
+
this.entries.push(entry);
|
|
3345
|
+
if (this.entries.length > this.maxEntries * 1.5) {
|
|
3346
|
+
this.entries = this.entries.slice(-this.maxEntries);
|
|
3335
3347
|
}
|
|
3336
3348
|
return entry;
|
|
3337
3349
|
}
|
|
@@ -3346,8 +3358,10 @@ var DecisionLog = class {
|
|
|
3346
3358
|
reasoning: reason,
|
|
3347
3359
|
metricsSnapshot: metrics
|
|
3348
3360
|
};
|
|
3349
|
-
this.entries.
|
|
3350
|
-
if (this.entries.length > this.maxEntries
|
|
3361
|
+
this.entries.push(entry);
|
|
3362
|
+
if (this.entries.length > this.maxEntries * 1.5) {
|
|
3363
|
+
this.entries = this.entries.slice(-this.maxEntries);
|
|
3364
|
+
}
|
|
3351
3365
|
}
|
|
3352
3366
|
query(filter) {
|
|
3353
3367
|
return this.entries.filter((e) => {
|
|
@@ -3360,7 +3374,7 @@ var DecisionLog = class {
|
|
|
3360
3374
|
});
|
|
3361
3375
|
}
|
|
3362
3376
|
latest(n = 30) {
|
|
3363
|
-
return this.entries.slice(
|
|
3377
|
+
return this.entries.slice(-n).reverse();
|
|
3364
3378
|
}
|
|
3365
3379
|
export(format = "json") {
|
|
3366
3380
|
if (format === "text") {
|
|
@@ -3589,10 +3603,13 @@ var MetricStore = class {
|
|
|
3589
3603
|
var PersonaTracker = class {
|
|
3590
3604
|
constructor() {
|
|
3591
3605
|
this.agentHistory = /* @__PURE__ */ new Map();
|
|
3606
|
+
this.lastSeen = /* @__PURE__ */ new Map();
|
|
3592
3607
|
}
|
|
3593
3608
|
/** Ingest a state snapshot and update agent signal history */
|
|
3594
3609
|
update(state) {
|
|
3610
|
+
const tick = state.tick;
|
|
3595
3611
|
for (const agentId of Object.keys(state.agentBalances)) {
|
|
3612
|
+
this.lastSeen.set(agentId, tick);
|
|
3596
3613
|
const history = this.agentHistory.get(agentId) ?? [];
|
|
3597
3614
|
const inv = state.agentInventories[agentId] ?? {};
|
|
3598
3615
|
const uniqueItems = Object.values(inv).filter((q) => q > 0).length;
|
|
@@ -3610,6 +3627,14 @@ var PersonaTracker = class {
|
|
|
3610
3627
|
if (history.length > 50) history.shift();
|
|
3611
3628
|
this.agentHistory.set(agentId, history);
|
|
3612
3629
|
}
|
|
3630
|
+
if (tick % 50 === 0) {
|
|
3631
|
+
for (const [id, lastTick] of this.lastSeen) {
|
|
3632
|
+
if (tick - lastTick > 100) {
|
|
3633
|
+
this.agentHistory.delete(id);
|
|
3634
|
+
this.lastSeen.delete(id);
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3613
3638
|
}
|
|
3614
3639
|
/** Classify all agents and return persona distribution */
|
|
3615
3640
|
getDistribution() {
|
|
@@ -3801,7 +3826,6 @@ var ParameterRegistry = class {
|
|
|
3801
3826
|
var AgentE = class {
|
|
3802
3827
|
constructor(config) {
|
|
3803
3828
|
this.planner = new Planner();
|
|
3804
|
-
this.executor = new Executor();
|
|
3805
3829
|
this.registry = new ParameterRegistry();
|
|
3806
3830
|
// ── State ──
|
|
3807
3831
|
this.log = new DecisionLog();
|
|
@@ -3824,6 +3848,8 @@ var AgentE = class {
|
|
|
3824
3848
|
dominantRoles: config.dominantRoles ?? [],
|
|
3825
3849
|
idealDistribution: config.idealDistribution ?? {},
|
|
3826
3850
|
validateRegistry: config.validateRegistry ?? true,
|
|
3851
|
+
simulation: config.simulation ?? {},
|
|
3852
|
+
settlementWindowTicks: config.settlementWindowTicks ?? 200,
|
|
3827
3853
|
tickConfig: config.tickConfig ?? { duration: 1, unit: "tick" },
|
|
3828
3854
|
gracePeriod: config.gracePeriod ?? 50,
|
|
3829
3855
|
checkInterval: config.checkInterval ?? 5,
|
|
@@ -3849,7 +3875,8 @@ var AgentE = class {
|
|
|
3849
3875
|
for (const w of validation.warnings) console.warn(`[AgentE] Registry warning: ${w}`);
|
|
3850
3876
|
for (const e of validation.errors) console.error(`[AgentE] Registry error: ${e}`);
|
|
3851
3877
|
}
|
|
3852
|
-
this.
|
|
3878
|
+
this.executor = new Executor(config.settlementWindowTicks);
|
|
3879
|
+
this.simulator = new Simulator(this.registry, config.simulation);
|
|
3853
3880
|
if (config.onDecision) this.on("decision", config.onDecision);
|
|
3854
3881
|
if (config.onAlert) this.on("alert", config.onAlert);
|
|
3855
3882
|
if (config.onRollback) this.on("rollback", config.onRollback);
|
|
@@ -3885,7 +3912,7 @@ var AgentE = class {
|
|
|
3885
3912
|
if (!this.isRunning || this.isPaused) return;
|
|
3886
3913
|
const currentState = state ?? await Promise.resolve(this.adapter.getState());
|
|
3887
3914
|
this.currentTick = currentState.tick;
|
|
3888
|
-
const events =
|
|
3915
|
+
const events = this.eventBuffer;
|
|
3889
3916
|
this.eventBuffer = [];
|
|
3890
3917
|
let metrics;
|
|
3891
3918
|
try {
|
|
@@ -4003,7 +4030,9 @@ var AgentE = class {
|
|
|
4003
4030
|
// ── Events ──────────────────────────────────────────────────────────────────
|
|
4004
4031
|
on(event, handler) {
|
|
4005
4032
|
const list = this.handlers.get(event) ?? [];
|
|
4006
|
-
list.
|
|
4033
|
+
if (!list.includes(handler)) {
|
|
4034
|
+
list.push(handler);
|
|
4035
|
+
}
|
|
4007
4036
|
this.handlers.set(event, list);
|
|
4008
4037
|
return this;
|
|
4009
4038
|
}
|
|
@@ -4016,8 +4045,12 @@ var AgentE = class {
|
|
|
4016
4045
|
const list = this.handlers.get(event) ?? [];
|
|
4017
4046
|
let result;
|
|
4018
4047
|
for (const handler of list) {
|
|
4019
|
-
|
|
4020
|
-
|
|
4048
|
+
try {
|
|
4049
|
+
result = handler(...args);
|
|
4050
|
+
if (result === false) return false;
|
|
4051
|
+
} catch (err) {
|
|
4052
|
+
console.error(`[AgentE] Handler error on '${event}':`, err);
|
|
4053
|
+
}
|
|
4021
4054
|
}
|
|
4022
4055
|
return result;
|
|
4023
4056
|
}
|
|
@@ -4475,7 +4508,7 @@ function describeValue(value) {
|
|
|
4475
4508
|
P57_CombinatorialPriceSpace,
|
|
4476
4509
|
P58_NoNaturalNumeraire,
|
|
4477
4510
|
P59_GiftEconomyNoise,
|
|
4478
|
-
|
|
4511
|
+
P5_ProfitabilityIsRelative,
|
|
4479
4512
|
P60_SurplusDisposalAsymmetry,
|
|
4480
4513
|
P6_CrowdingMultiplierOnAllRoles,
|
|
4481
4514
|
P7_NonSpecialistsSubsidiseSpecialists,
|