@agent-e/core 1.5.1 → 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 +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.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;
|
|
@@ -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,7 +452,7 @@ 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,
|
|
459
457
|
systems: state.systems ?? [],
|
|
460
458
|
sources: state.sources ?? [],
|
|
@@ -486,7 +484,7 @@ function computeGini(sorted) {
|
|
|
486
484
|
for (let i = 0; i < n; i++) {
|
|
487
485
|
numerator += (2 * (i + 1) - n - 1) * (sorted[i] ?? 0);
|
|
488
486
|
}
|
|
489
|
-
return Math.abs(numerator) / (n * sum);
|
|
487
|
+
return Math.min(1, Math.abs(numerator) / (n * sum));
|
|
490
488
|
}
|
|
491
489
|
|
|
492
490
|
// src/Diagnoser.ts
|
|
@@ -582,10 +580,10 @@ function emptyMetrics(tick = 0) {
|
|
|
582
580
|
prices: {},
|
|
583
581
|
priceVolatility: {},
|
|
584
582
|
poolSizes: {},
|
|
585
|
-
extractionRatio:
|
|
586
|
-
newUserDependency:
|
|
587
|
-
smokeTestRatio:
|
|
588
|
-
currencyInsulation:
|
|
583
|
+
extractionRatio: 0,
|
|
584
|
+
newUserDependency: 0,
|
|
585
|
+
smokeTestRatio: 0,
|
|
586
|
+
currencyInsulation: 0,
|
|
589
587
|
arbitrageIndex: 0,
|
|
590
588
|
giftTradeRatio: 0,
|
|
591
589
|
disposalTradeRatio: 0,
|
|
@@ -606,7 +604,7 @@ function emptyMetrics(tick = 0) {
|
|
|
606
604
|
timeToValue: 0,
|
|
607
605
|
sharkToothPeaks: [],
|
|
608
606
|
sharkToothValleys: [],
|
|
609
|
-
eventCompletionRate:
|
|
607
|
+
eventCompletionRate: 0,
|
|
610
608
|
contentDropAge: 0,
|
|
611
609
|
systems: [],
|
|
612
610
|
sources: [],
|
|
@@ -811,9 +809,9 @@ var SUPPLY_CHAIN_PRINCIPLES = [
|
|
|
811
809
|
];
|
|
812
810
|
|
|
813
811
|
// src/principles/incentives.ts
|
|
814
|
-
var
|
|
812
|
+
var P5_ProfitabilityIsRelative = {
|
|
815
813
|
id: "P5",
|
|
816
|
-
name: "Profitability Is
|
|
814
|
+
name: "Profitability Is Relative, Not Absolute",
|
|
817
815
|
category: "incentive",
|
|
818
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.",
|
|
819
817
|
check(metrics, thresholds) {
|
|
@@ -877,7 +875,7 @@ var P7_NonSpecialistsSubsidiseSpecialists = {
|
|
|
877
875
|
id: "P7",
|
|
878
876
|
name: "Non-Specialists Subsidise Specialists in Zero-Sum Games",
|
|
879
877
|
category: "incentive",
|
|
880
|
-
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.",
|
|
881
879
|
check(metrics, _thresholds) {
|
|
882
880
|
const { poolSizes } = metrics;
|
|
883
881
|
for (const [poolName, poolSize] of Object.entries(poolSizes)) {
|
|
@@ -913,7 +911,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
913
911
|
id: "P8",
|
|
914
912
|
name: "Regulator Cannot Fight the Design",
|
|
915
913
|
category: "incentive",
|
|
916
|
-
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.",
|
|
917
915
|
check(metrics, _thresholds) {
|
|
918
916
|
const { roleShares, avgSatisfaction } = metrics;
|
|
919
917
|
if (avgSatisfaction < 45) {
|
|
@@ -938,7 +936,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
938
936
|
}
|
|
939
937
|
};
|
|
940
938
|
var INCENTIVE_PRINCIPLES = [
|
|
941
|
-
|
|
939
|
+
P5_ProfitabilityIsRelative,
|
|
942
940
|
P6_CrowdingMultiplierOnAllRoles,
|
|
943
941
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
944
942
|
P8_RegulatorCannotFightDesign
|
|
@@ -1134,7 +1132,7 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1134
1132
|
id: "P13",
|
|
1135
1133
|
name: "Pots Self-Regulate with Correct Multiplier",
|
|
1136
1134
|
category: "currency",
|
|
1137
|
-
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.",
|
|
1138
1136
|
check(metrics, thresholds) {
|
|
1139
1137
|
const { populationByRole } = metrics;
|
|
1140
1138
|
const roleEntries = Object.entries(populationByRole).sort((a, b) => b[1] - a[1]);
|
|
@@ -1143,8 +1141,8 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1143
1141
|
for (const curr of metrics.currencies) {
|
|
1144
1142
|
const poolSize = currencyAmounts[curr] ?? 0;
|
|
1145
1143
|
if (dominantCount > 5 && poolSize < 50) {
|
|
1146
|
-
const { poolWinRate,
|
|
1147
|
-
const maxSustainableMultiplier = (1 -
|
|
1144
|
+
const { poolWinRate, poolOperatorShare } = thresholds;
|
|
1145
|
+
const maxSustainableMultiplier = (1 - poolOperatorShare) / poolWinRate;
|
|
1148
1146
|
return {
|
|
1149
1147
|
violated: true,
|
|
1150
1148
|
severity: 7,
|
|
@@ -1427,7 +1425,7 @@ var P19_StartingSupplyExceedsDemand = {
|
|
|
1427
1425
|
parameterType: "reward",
|
|
1428
1426
|
direction: "increase",
|
|
1429
1427
|
magnitude: 0.2,
|
|
1430
|
-
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.`
|
|
1431
1429
|
},
|
|
1432
1430
|
confidence: 0.75,
|
|
1433
1431
|
estimatedLag: 5
|
|
@@ -2172,7 +2170,7 @@ var P35_DestructionCreatesValue = {
|
|
|
2172
2170
|
scope: { tags: ["entry"] },
|
|
2173
2171
|
direction: "decrease",
|
|
2174
2172
|
magnitude: 0.1,
|
|
2175
|
-
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.`
|
|
2176
2174
|
},
|
|
2177
2175
|
confidence: 0.7,
|
|
2178
2176
|
estimatedLag: 5
|
|
@@ -2779,15 +2777,24 @@ var ALL_PRINCIPLES = [
|
|
|
2779
2777
|
];
|
|
2780
2778
|
|
|
2781
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
|
+
};
|
|
2782
2790
|
var Simulator = class {
|
|
2783
|
-
constructor(registry) {
|
|
2791
|
+
constructor(registry, simConfig) {
|
|
2784
2792
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
2785
|
-
// Cache beforeViolations for the *current* tick only
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
// entries whose key differs from the incoming tick.
|
|
2789
|
-
this.beforeViolationsCache = /* @__PURE__ */ new Map();
|
|
2793
|
+
// Cache beforeViolations for the *current* tick only.
|
|
2794
|
+
this.cachedViolationsTick = -1;
|
|
2795
|
+
this.cachedViolations = /* @__PURE__ */ new Set();
|
|
2790
2796
|
this.registry = registry;
|
|
2797
|
+
this.simConfig = { ...DEFAULT_SIM_CONFIG, ...simConfig };
|
|
2791
2798
|
}
|
|
2792
2799
|
/**
|
|
2793
2800
|
* Simulate the effect of applying `action` to the current economy forward `forwardTicks`.
|
|
@@ -2811,16 +2818,13 @@ var Simulator = class {
|
|
|
2811
2818
|
const mean = this.averageMetrics(outcomes);
|
|
2812
2819
|
const netImprovement = this.checkImprovement(currentMetrics, p50, action);
|
|
2813
2820
|
const tick = currentMetrics.tick;
|
|
2814
|
-
if (this.
|
|
2815
|
-
this.
|
|
2816
|
-
}
|
|
2817
|
-
let beforeViolations = this.beforeViolationsCache.get(tick);
|
|
2818
|
-
if (!beforeViolations) {
|
|
2819
|
-
beforeViolations = new Set(
|
|
2821
|
+
if (this.cachedViolationsTick !== tick) {
|
|
2822
|
+
this.cachedViolations = new Set(
|
|
2820
2823
|
this.diagnoser.diagnose(currentMetrics, thresholds).map((d) => d.principle.id)
|
|
2821
2824
|
);
|
|
2822
|
-
this.
|
|
2825
|
+
this.cachedViolationsTick = tick;
|
|
2823
2826
|
}
|
|
2827
|
+
const beforeViolations = this.cachedViolations;
|
|
2824
2828
|
const afterViolations = new Set(
|
|
2825
2829
|
this.diagnoser.diagnose(p50, thresholds).map((d) => d.principle.id)
|
|
2826
2830
|
);
|
|
@@ -2910,21 +2914,22 @@ var Simulator = class {
|
|
|
2910
2914
|
if (!impact) {
|
|
2911
2915
|
impact = this.inferFlowImpact(action.parameterType);
|
|
2912
2916
|
}
|
|
2917
|
+
const cfg = this.simConfig;
|
|
2913
2918
|
switch (impact) {
|
|
2914
2919
|
case "sink":
|
|
2915
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
2920
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.sinkMultiplier;
|
|
2916
2921
|
case "faucet":
|
|
2917
|
-
return -sign * dominantRoleCount *
|
|
2922
|
+
return -sign * dominantRoleCount * cfg.redistributionMultiplier;
|
|
2918
2923
|
case "neutral":
|
|
2919
|
-
return sign * dominantRoleCount *
|
|
2924
|
+
return sign * dominantRoleCount * cfg.neutralMultiplier;
|
|
2920
2925
|
case "mixed":
|
|
2921
|
-
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) *
|
|
2926
|
+
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * cfg.faucetMultiplier;
|
|
2922
2927
|
case "friction":
|
|
2923
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
2928
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.frictionMultiplier;
|
|
2924
2929
|
case "redistribution":
|
|
2925
|
-
return sign * dominantRoleCount *
|
|
2930
|
+
return sign * dominantRoleCount * cfg.neutralMultiplier;
|
|
2926
2931
|
default:
|
|
2927
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) *
|
|
2932
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * cfg.frictionMultiplier;
|
|
2928
2933
|
}
|
|
2929
2934
|
}
|
|
2930
2935
|
/** Infer flow impact from parameter type when registry is unavailable */
|
|
@@ -2945,7 +2950,7 @@ var Simulator = class {
|
|
|
2945
2950
|
return "mixed";
|
|
2946
2951
|
}
|
|
2947
2952
|
}
|
|
2948
|
-
checkImprovement(before, after,
|
|
2953
|
+
checkImprovement(before, after, _action) {
|
|
2949
2954
|
const satisfactionImproved = after.avgSatisfaction >= before.avgSatisfaction - 2;
|
|
2950
2955
|
const flowMoreBalanced = before.currencies.every((curr) => {
|
|
2951
2956
|
const afterFlow = Math.abs(after.netFlowByCurrency[curr] ?? 0);
|
|
@@ -2957,7 +2962,6 @@ var Simulator = class {
|
|
|
2957
2962
|
const beforeGini = before.giniCoefficientByCurrency[curr] ?? 0;
|
|
2958
2963
|
return afterGini <= beforeGini + 0.05;
|
|
2959
2964
|
});
|
|
2960
|
-
void action;
|
|
2961
2965
|
return satisfactionImproved && flowMoreBalanced && notWorseGini;
|
|
2962
2966
|
}
|
|
2963
2967
|
averageMetrics(outcomes) {
|
|
@@ -3109,6 +3113,14 @@ var Planner = class {
|
|
|
3109
3113
|
this.cooldowns.clear();
|
|
3110
3114
|
this.typeCooldowns.clear();
|
|
3111
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
|
+
}
|
|
3112
3124
|
typeCooldownKey(type, scope) {
|
|
3113
3125
|
const parts = [type];
|
|
3114
3126
|
if (scope?.system) parts.push(`sys:${scope.system}`);
|
|
@@ -3125,8 +3137,9 @@ var Planner = class {
|
|
|
3125
3137
|
|
|
3126
3138
|
// src/Executor.ts
|
|
3127
3139
|
var Executor = class {
|
|
3128
|
-
constructor() {
|
|
3140
|
+
constructor(settlementWindowTicks = 200) {
|
|
3129
3141
|
this.activePlans = [];
|
|
3142
|
+
this.maxActiveTicks = settlementWindowTicks;
|
|
3130
3143
|
}
|
|
3131
3144
|
async apply(plan, adapter, currentParams) {
|
|
3132
3145
|
const originalValue = currentParams[plan.parameter] ?? plan.currentValue;
|
|
@@ -3145,8 +3158,7 @@ var Executor = class {
|
|
|
3145
3158
|
for (const active of this.activePlans) {
|
|
3146
3159
|
const { plan, originalValue } = active;
|
|
3147
3160
|
const rc = plan.rollbackCondition;
|
|
3148
|
-
|
|
3149
|
-
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > maxActiveTicks) {
|
|
3161
|
+
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > this.maxActiveTicks) {
|
|
3150
3162
|
settled.push(plan);
|
|
3151
3163
|
continue;
|
|
3152
3164
|
}
|
|
@@ -3213,9 +3225,9 @@ var DecisionLog = class {
|
|
|
3213
3225
|
reasoning: this.buildReasoning(diagnosis, plan, result),
|
|
3214
3226
|
metricsSnapshot: metrics
|
|
3215
3227
|
};
|
|
3216
|
-
this.entries.
|
|
3217
|
-
if (this.entries.length > this.maxEntries) {
|
|
3218
|
-
this.entries.
|
|
3228
|
+
this.entries.push(entry);
|
|
3229
|
+
if (this.entries.length > this.maxEntries * 1.5) {
|
|
3230
|
+
this.entries = this.entries.slice(-this.maxEntries);
|
|
3219
3231
|
}
|
|
3220
3232
|
return entry;
|
|
3221
3233
|
}
|
|
@@ -3230,8 +3242,10 @@ var DecisionLog = class {
|
|
|
3230
3242
|
reasoning: reason,
|
|
3231
3243
|
metricsSnapshot: metrics
|
|
3232
3244
|
};
|
|
3233
|
-
this.entries.
|
|
3234
|
-
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
|
+
}
|
|
3235
3249
|
}
|
|
3236
3250
|
query(filter) {
|
|
3237
3251
|
return this.entries.filter((e) => {
|
|
@@ -3244,7 +3258,7 @@ var DecisionLog = class {
|
|
|
3244
3258
|
});
|
|
3245
3259
|
}
|
|
3246
3260
|
latest(n = 30) {
|
|
3247
|
-
return this.entries.slice(
|
|
3261
|
+
return this.entries.slice(-n).reverse();
|
|
3248
3262
|
}
|
|
3249
3263
|
export(format = "json") {
|
|
3250
3264
|
if (format === "text") {
|
|
@@ -3473,10 +3487,13 @@ var MetricStore = class {
|
|
|
3473
3487
|
var PersonaTracker = class {
|
|
3474
3488
|
constructor() {
|
|
3475
3489
|
this.agentHistory = /* @__PURE__ */ new Map();
|
|
3490
|
+
this.lastSeen = /* @__PURE__ */ new Map();
|
|
3476
3491
|
}
|
|
3477
3492
|
/** Ingest a state snapshot and update agent signal history */
|
|
3478
3493
|
update(state) {
|
|
3494
|
+
const tick = state.tick;
|
|
3479
3495
|
for (const agentId of Object.keys(state.agentBalances)) {
|
|
3496
|
+
this.lastSeen.set(agentId, tick);
|
|
3480
3497
|
const history = this.agentHistory.get(agentId) ?? [];
|
|
3481
3498
|
const inv = state.agentInventories[agentId] ?? {};
|
|
3482
3499
|
const uniqueItems = Object.values(inv).filter((q) => q > 0).length;
|
|
@@ -3494,6 +3511,14 @@ var PersonaTracker = class {
|
|
|
3494
3511
|
if (history.length > 50) history.shift();
|
|
3495
3512
|
this.agentHistory.set(agentId, history);
|
|
3496
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
|
+
}
|
|
3497
3522
|
}
|
|
3498
3523
|
/** Classify all agents and return persona distribution */
|
|
3499
3524
|
getDistribution() {
|
|
@@ -3685,7 +3710,6 @@ var ParameterRegistry = class {
|
|
|
3685
3710
|
var AgentE = class {
|
|
3686
3711
|
constructor(config) {
|
|
3687
3712
|
this.planner = new Planner();
|
|
3688
|
-
this.executor = new Executor();
|
|
3689
3713
|
this.registry = new ParameterRegistry();
|
|
3690
3714
|
// ── State ──
|
|
3691
3715
|
this.log = new DecisionLog();
|
|
@@ -3708,6 +3732,8 @@ var AgentE = class {
|
|
|
3708
3732
|
dominantRoles: config.dominantRoles ?? [],
|
|
3709
3733
|
idealDistribution: config.idealDistribution ?? {},
|
|
3710
3734
|
validateRegistry: config.validateRegistry ?? true,
|
|
3735
|
+
simulation: config.simulation ?? {},
|
|
3736
|
+
settlementWindowTicks: config.settlementWindowTicks ?? 200,
|
|
3711
3737
|
tickConfig: config.tickConfig ?? { duration: 1, unit: "tick" },
|
|
3712
3738
|
gracePeriod: config.gracePeriod ?? 50,
|
|
3713
3739
|
checkInterval: config.checkInterval ?? 5,
|
|
@@ -3733,7 +3759,8 @@ var AgentE = class {
|
|
|
3733
3759
|
for (const w of validation.warnings) console.warn(`[AgentE] Registry warning: ${w}`);
|
|
3734
3760
|
for (const e of validation.errors) console.error(`[AgentE] Registry error: ${e}`);
|
|
3735
3761
|
}
|
|
3736
|
-
this.
|
|
3762
|
+
this.executor = new Executor(config.settlementWindowTicks);
|
|
3763
|
+
this.simulator = new Simulator(this.registry, config.simulation);
|
|
3737
3764
|
if (config.onDecision) this.on("decision", config.onDecision);
|
|
3738
3765
|
if (config.onAlert) this.on("alert", config.onAlert);
|
|
3739
3766
|
if (config.onRollback) this.on("rollback", config.onRollback);
|
|
@@ -3769,7 +3796,7 @@ var AgentE = class {
|
|
|
3769
3796
|
if (!this.isRunning || this.isPaused) return;
|
|
3770
3797
|
const currentState = state ?? await Promise.resolve(this.adapter.getState());
|
|
3771
3798
|
this.currentTick = currentState.tick;
|
|
3772
|
-
const events =
|
|
3799
|
+
const events = this.eventBuffer;
|
|
3773
3800
|
this.eventBuffer = [];
|
|
3774
3801
|
let metrics;
|
|
3775
3802
|
try {
|
|
@@ -3887,7 +3914,9 @@ var AgentE = class {
|
|
|
3887
3914
|
// ── Events ──────────────────────────────────────────────────────────────────
|
|
3888
3915
|
on(event, handler) {
|
|
3889
3916
|
const list = this.handlers.get(event) ?? [];
|
|
3890
|
-
list.
|
|
3917
|
+
if (!list.includes(handler)) {
|
|
3918
|
+
list.push(handler);
|
|
3919
|
+
}
|
|
3891
3920
|
this.handlers.set(event, list);
|
|
3892
3921
|
return this;
|
|
3893
3922
|
}
|
|
@@ -3900,8 +3929,12 @@ var AgentE = class {
|
|
|
3900
3929
|
const list = this.handlers.get(event) ?? [];
|
|
3901
3930
|
let result;
|
|
3902
3931
|
for (const handler of list) {
|
|
3903
|
-
|
|
3904
|
-
|
|
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
|
+
}
|
|
3905
3938
|
}
|
|
3906
3939
|
return result;
|
|
3907
3940
|
}
|
|
@@ -4358,7 +4391,7 @@ export {
|
|
|
4358
4391
|
P57_CombinatorialPriceSpace,
|
|
4359
4392
|
P58_NoNaturalNumeraire,
|
|
4360
4393
|
P59_GiftEconomyNoise,
|
|
4361
|
-
|
|
4394
|
+
P5_ProfitabilityIsRelative,
|
|
4362
4395
|
P60_SurplusDisposalAsymmetry,
|
|
4363
4396
|
P6_CrowdingMultiplierOnAllRoles,
|
|
4364
4397
|
P7_NonSpecialistsSubsidiseSpecialists,
|