@agent-e/core 1.4.4 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +143 -21
- package/dist/index.d.ts +143 -21
- package/dist/index.js +565 -201
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +555 -193
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,13 +30,13 @@ __export(index_exports, {
|
|
|
30
30
|
Executor: () => Executor,
|
|
31
31
|
FEEDBACK_LOOP_PRINCIPLES: () => FEEDBACK_LOOP_PRINCIPLES,
|
|
32
32
|
INCENTIVE_PRINCIPLES: () => INCENTIVE_PRINCIPLES,
|
|
33
|
-
LIVEOPS_PRINCIPLES: () => LIVEOPS_PRINCIPLES,
|
|
34
33
|
MARKET_DYNAMICS_PRINCIPLES: () => MARKET_DYNAMICS_PRINCIPLES,
|
|
35
34
|
MEASUREMENT_PRINCIPLES: () => MEASUREMENT_PRINCIPLES,
|
|
36
35
|
MetricStore: () => MetricStore,
|
|
37
36
|
OPEN_ECONOMY_PRINCIPLES: () => OPEN_ECONOMY_PRINCIPLES,
|
|
37
|
+
OPERATIONS_PRINCIPLES: () => OPERATIONS_PRINCIPLES,
|
|
38
38
|
Observer: () => Observer,
|
|
39
|
-
|
|
39
|
+
P10_EntryWeightingUsesInversePopulation: () => P10_EntryWeightingUsesInversePopulation,
|
|
40
40
|
P11_TwoTierPressure: () => P11_TwoTierPressure,
|
|
41
41
|
P12_OnePrimaryFaucet: () => P12_OnePrimaryFaucet,
|
|
42
42
|
P13_PotsAreZeroSumAndSelfRegulate: () => P13_PotsAreZeroSumAndSelfRegulate,
|
|
@@ -56,9 +56,9 @@ __export(index_exports, {
|
|
|
56
56
|
P26_ContinuousPressureBeatsThresholdCuts: () => P26_ContinuousPressureBeatsThresholdCuts,
|
|
57
57
|
P27_AdjustmentsNeedCooldowns: () => P27_AdjustmentsNeedCooldowns,
|
|
58
58
|
P28_StructuralDominanceIsNotPathological: () => P28_StructuralDominanceIsNotPathological,
|
|
59
|
-
|
|
59
|
+
P29_BottleneckDetection: () => P29_BottleneckDetection,
|
|
60
60
|
P2_ClosedLoopsNeedDirectHandoff: () => P2_ClosedLoopsNeedDirectHandoff,
|
|
61
|
-
|
|
61
|
+
P30_DynamicBottleneckRotation: () => P30_DynamicBottleneckRotation,
|
|
62
62
|
P31_AnchorValueTracking: () => P31_AnchorValueTracking,
|
|
63
63
|
P32_VelocityAboveSupply: () => P32_VelocityAboveSupply,
|
|
64
64
|
P33_FairNotEqual: () => P33_FairNotEqual,
|
|
@@ -81,12 +81,12 @@ __export(index_exports, {
|
|
|
81
81
|
P49_IdleAssetTax: () => P49_IdleAssetTax,
|
|
82
82
|
P4_MaterialsFlowFasterThanCooldown: () => P4_MaterialsFlowFasterThanCooldown,
|
|
83
83
|
P50_PayPowerRatio: () => P50_PayPowerRatio,
|
|
84
|
-
|
|
84
|
+
P51_CyclicalEngagement: () => P51_CyclicalEngagement,
|
|
85
85
|
P52_EndowmentEffect: () => P52_EndowmentEffect,
|
|
86
86
|
P53_EventCompletionRate: () => P53_EventCompletionRate,
|
|
87
|
-
|
|
87
|
+
P54_OperationalCadence: () => P54_OperationalCadence,
|
|
88
88
|
P55_ArbitrageThermometer: () => P55_ArbitrageThermometer,
|
|
89
|
-
|
|
89
|
+
P56_SupplyShockAbsorption: () => P56_SupplyShockAbsorption,
|
|
90
90
|
P57_CombinatorialPriceSpace: () => P57_CombinatorialPriceSpace,
|
|
91
91
|
P58_NoNaturalNumeraire: () => P58_NoNaturalNumeraire,
|
|
92
92
|
P59_GiftEconomyNoise: () => P59_GiftEconomyNoise,
|
|
@@ -96,9 +96,10 @@ __export(index_exports, {
|
|
|
96
96
|
P7_NonSpecialistsSubsidiseSpecialists: () => P7_NonSpecialistsSubsidiseSpecialists,
|
|
97
97
|
P8_RegulatorCannotFightDesign: () => P8_RegulatorCannotFightDesign,
|
|
98
98
|
P9_RoleSwitchingNeedsFriction: () => P9_RoleSwitchingNeedsFriction,
|
|
99
|
+
PARTICIPANT_EXPERIENCE_PRINCIPLES: () => PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
99
100
|
PERSONA_HEALTHY_RANGES: () => PERSONA_HEALTHY_RANGES,
|
|
100
|
-
PLAYER_EXPERIENCE_PRINCIPLES: () => PLAYER_EXPERIENCE_PRINCIPLES,
|
|
101
101
|
POPULATION_PRINCIPLES: () => POPULATION_PRINCIPLES,
|
|
102
|
+
ParameterRegistry: () => ParameterRegistry,
|
|
102
103
|
PersonaTracker: () => PersonaTracker,
|
|
103
104
|
Planner: () => Planner,
|
|
104
105
|
REGULATOR_PRINCIPLES: () => REGULATOR_PRINCIPLES,
|
|
@@ -108,6 +109,7 @@ __export(index_exports, {
|
|
|
108
109
|
SYSTEM_DYNAMICS_PRINCIPLES: () => SYSTEM_DYNAMICS_PRINCIPLES,
|
|
109
110
|
Simulator: () => Simulator,
|
|
110
111
|
emptyMetrics: () => emptyMetrics,
|
|
112
|
+
findWorstSystem: () => findWorstSystem,
|
|
111
113
|
validateEconomyState: () => validateEconomyState
|
|
112
114
|
});
|
|
113
115
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -126,11 +128,11 @@ var DEFAULT_THRESHOLDS = {
|
|
|
126
128
|
smokeTestWarning: 0.3,
|
|
127
129
|
smokeTestCritical: 0.1,
|
|
128
130
|
currencyInsulationMax: 0.5,
|
|
129
|
-
//
|
|
131
|
+
// Participant Experience (P45, P50)
|
|
130
132
|
timeBudgetRatio: 0.8,
|
|
131
133
|
payPowerRatioMax: 2,
|
|
132
134
|
payPowerRatioTarget: 1.5,
|
|
133
|
-
//
|
|
135
|
+
// Operations (P51, P53)
|
|
134
136
|
sharkToothPeakDecay: 0.95,
|
|
135
137
|
sharkToothValleyDecay: 0.9,
|
|
136
138
|
eventCompletionMin: 0.4,
|
|
@@ -184,7 +186,7 @@ var PERSONA_HEALTHY_RANGES = {
|
|
|
184
186
|
Earner: { min: 0, max: 0.15 },
|
|
185
187
|
Builder: { min: 0.05, max: 0.15 },
|
|
186
188
|
Social: { min: 0.1, max: 0.2 },
|
|
187
|
-
|
|
189
|
+
HighValue: { min: 0, max: 0.05 },
|
|
188
190
|
Influencer: { min: 0, max: 0.05 }
|
|
189
191
|
};
|
|
190
192
|
var DEFAULT_TICK_CONFIG = {
|
|
@@ -221,7 +223,7 @@ var Observer = class {
|
|
|
221
223
|
const curr = e.currency ?? defaultCurrency;
|
|
222
224
|
switch (e.type) {
|
|
223
225
|
case "mint":
|
|
224
|
-
case "
|
|
226
|
+
case "enter":
|
|
225
227
|
faucetVolumeByCurrency[curr] = (faucetVolumeByCurrency[curr] ?? 0) + (e.amount ?? 0);
|
|
226
228
|
break;
|
|
227
229
|
case "burn":
|
|
@@ -243,6 +245,46 @@ var Observer = class {
|
|
|
243
245
|
break;
|
|
244
246
|
}
|
|
245
247
|
}
|
|
248
|
+
const flowBySystem = {};
|
|
249
|
+
const activityBySystem = {};
|
|
250
|
+
const actorsBySystem = {};
|
|
251
|
+
const flowBySource = {};
|
|
252
|
+
const flowBySink = {};
|
|
253
|
+
for (const e of recentEvents) {
|
|
254
|
+
if (e.system) {
|
|
255
|
+
activityBySystem[e.system] = (activityBySystem[e.system] ?? 0) + 1;
|
|
256
|
+
if (!actorsBySystem[e.system]) actorsBySystem[e.system] = /* @__PURE__ */ new Set();
|
|
257
|
+
actorsBySystem[e.system].add(e.actor);
|
|
258
|
+
const amt = e.amount ?? 0;
|
|
259
|
+
if (e.type === "mint") {
|
|
260
|
+
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) + amt;
|
|
261
|
+
} else if (e.type === "burn" || e.type === "consume") {
|
|
262
|
+
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) - amt;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (e.sourceOrSink) {
|
|
266
|
+
const amt = e.amount ?? 0;
|
|
267
|
+
if (e.type === "mint") {
|
|
268
|
+
flowBySource[e.sourceOrSink] = (flowBySource[e.sourceOrSink] ?? 0) + amt;
|
|
269
|
+
} else if (e.type === "burn" || e.type === "consume") {
|
|
270
|
+
flowBySink[e.sourceOrSink] = (flowBySink[e.sourceOrSink] ?? 0) + amt;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const participantsBySystem = {};
|
|
275
|
+
for (const [sys, actors] of Object.entries(actorsBySystem)) {
|
|
276
|
+
participantsBySystem[sys] = actors.size;
|
|
277
|
+
}
|
|
278
|
+
const totalSourceFlow = Object.values(flowBySource).reduce((s, v) => s + v, 0);
|
|
279
|
+
const sourceShare = {};
|
|
280
|
+
for (const [src, vol] of Object.entries(flowBySource)) {
|
|
281
|
+
sourceShare[src] = totalSourceFlow > 0 ? vol / totalSourceFlow : 0;
|
|
282
|
+
}
|
|
283
|
+
const totalSinkFlow = Object.values(flowBySink).reduce((s, v) => s + v, 0);
|
|
284
|
+
const sinkShare = {};
|
|
285
|
+
for (const [snk, vol] of Object.entries(flowBySink)) {
|
|
286
|
+
sinkShare[snk] = totalSinkFlow > 0 ? vol / totalSinkFlow : 0;
|
|
287
|
+
}
|
|
246
288
|
const currencies = state.currencies;
|
|
247
289
|
const totalSupplyByCurrency = {};
|
|
248
290
|
const balancesByCurrency = {};
|
|
@@ -452,7 +494,8 @@ var Observer = class {
|
|
|
452
494
|
for (const [name, fn] of Object.entries(this.customMetricFns)) {
|
|
453
495
|
try {
|
|
454
496
|
custom[name] = fn(state);
|
|
455
|
-
} catch {
|
|
497
|
+
} catch (err) {
|
|
498
|
+
console.warn(`[AgentE] Custom metric '${name}' threw an error:`, err);
|
|
456
499
|
custom[name] = NaN;
|
|
457
500
|
}
|
|
458
501
|
}
|
|
@@ -529,6 +572,16 @@ var Observer = class {
|
|
|
529
572
|
sharkToothValleys: this.previousMetrics?.sharkToothValleys ?? [],
|
|
530
573
|
eventCompletionRate: NaN,
|
|
531
574
|
contentDropAge,
|
|
575
|
+
systems: state.systems ?? [],
|
|
576
|
+
sources: state.sources ?? [],
|
|
577
|
+
sinks: state.sinks ?? [],
|
|
578
|
+
flowBySystem,
|
|
579
|
+
activityBySystem,
|
|
580
|
+
participantsBySystem,
|
|
581
|
+
flowBySource,
|
|
582
|
+
flowBySink,
|
|
583
|
+
sourceShare,
|
|
584
|
+
sinkShare,
|
|
532
585
|
custom
|
|
533
586
|
};
|
|
534
587
|
this.previousMetrics = metrics;
|
|
@@ -671,6 +724,16 @@ function emptyMetrics(tick = 0) {
|
|
|
671
724
|
sharkToothValleys: [],
|
|
672
725
|
eventCompletionRate: NaN,
|
|
673
726
|
contentDropAge: 0,
|
|
727
|
+
systems: [],
|
|
728
|
+
sources: [],
|
|
729
|
+
sinks: [],
|
|
730
|
+
flowBySystem: {},
|
|
731
|
+
activityBySystem: {},
|
|
732
|
+
participantsBySystem: {},
|
|
733
|
+
flowBySource: {},
|
|
734
|
+
flowBySink: {},
|
|
735
|
+
sourceShare: {},
|
|
736
|
+
sinkShare: {},
|
|
674
737
|
custom: {}
|
|
675
738
|
};
|
|
676
739
|
}
|
|
@@ -703,7 +766,7 @@ var P1_ProductionMatchesConsumption = {
|
|
|
703
766
|
severity: 7,
|
|
704
767
|
evidence: { scarceResources: violations, dominantRole: dominantRole?.[0], dominantShare },
|
|
705
768
|
suggestedAction: {
|
|
706
|
-
|
|
769
|
+
parameterType: "cost",
|
|
707
770
|
direction: "decrease",
|
|
708
771
|
magnitude: 0.15,
|
|
709
772
|
reasoning: "Lower production cost to incentivise more production."
|
|
@@ -737,7 +800,8 @@ var P2_ClosedLoopsNeedDirectHandoff = {
|
|
|
737
800
|
severity: 5,
|
|
738
801
|
evidence: { backlogResources, velocity },
|
|
739
802
|
suggestedAction: {
|
|
740
|
-
|
|
803
|
+
parameterType: "fee",
|
|
804
|
+
scope: { tags: ["transaction"] },
|
|
741
805
|
direction: "increase",
|
|
742
806
|
magnitude: 0.2,
|
|
743
807
|
reasoning: "Raise market fees to discourage raw material listings. Direct hand-off at production zones is the correct channel."
|
|
@@ -767,7 +831,7 @@ var P3_BootstrapCapitalCoversFirstTransaction = {
|
|
|
767
831
|
severity: 8,
|
|
768
832
|
evidence: { resource, totalProducers, supply },
|
|
769
833
|
suggestedAction: {
|
|
770
|
-
|
|
834
|
+
parameterType: "cost",
|
|
771
835
|
direction: "decrease",
|
|
772
836
|
magnitude: 0.3,
|
|
773
837
|
reasoning: "Producers cannot complete first transaction. Lower production cost to unblock bootstrap."
|
|
@@ -786,7 +850,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
786
850
|
id: "P4",
|
|
787
851
|
name: "Materials Flow Faster Than Cooldown",
|
|
788
852
|
category: "supply_chain",
|
|
789
|
-
description: "Input delivery rate must exceed or match production cooldown rate. If producers
|
|
853
|
+
description: "Input delivery rate must exceed or match production cooldown rate. If producers produce every 5 ticks but only receive raw materials every 10 ticks, they starve regardless of supply levels.",
|
|
790
854
|
check(metrics, _thresholds) {
|
|
791
855
|
const { supplyByResource, populationByRole, velocity, totalAgents } = metrics;
|
|
792
856
|
const totalSupply = Object.values(supplyByResource).reduce((s, v) => s + v, 0);
|
|
@@ -799,7 +863,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
799
863
|
severity: 5,
|
|
800
864
|
evidence: { avgSupplyPerAgent, velocity, totalRoles },
|
|
801
865
|
suggestedAction: {
|
|
802
|
-
|
|
866
|
+
parameterType: "yield",
|
|
803
867
|
direction: "increase",
|
|
804
868
|
magnitude: 0.15,
|
|
805
869
|
reasoning: "Low supply per agent with stagnant velocity. Increase yield to compensate."
|
|
@@ -814,7 +878,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
814
878
|
severity: 4,
|
|
815
879
|
evidence: { avgSupplyPerAgent, totalSupply, totalAgents },
|
|
816
880
|
suggestedAction: {
|
|
817
|
-
|
|
881
|
+
parameterType: "yield",
|
|
818
882
|
direction: "decrease",
|
|
819
883
|
magnitude: 0.2,
|
|
820
884
|
reasoning: "Raw materials piling up. Extractors outpacing producers."
|
|
@@ -842,7 +906,7 @@ var P60_SurplusDisposalAsymmetry = {
|
|
|
842
906
|
discount: thresholds.disposalTradeWeightDiscount
|
|
843
907
|
},
|
|
844
908
|
suggestedAction: {
|
|
845
|
-
|
|
909
|
+
parameterType: "cost",
|
|
846
910
|
direction: "decrease",
|
|
847
911
|
magnitude: 0.1,
|
|
848
912
|
reasoning: `${(disposalTradeRatio * 100).toFixed(0)}% of trades are surplus disposal. Price signals unreliable as demand indicators. Lower production costs to shift balance toward deliberate production-for-sale. ADVISORY: Weight disposal-trade prices at ${thresholds.disposalTradeWeightDiscount}\xD7 in index calculations.`
|
|
@@ -885,7 +949,8 @@ var P5_ProfitabilityIsCompetitive = {
|
|
|
885
949
|
population: populationByRole[dominantRole]
|
|
886
950
|
},
|
|
887
951
|
suggestedAction: {
|
|
888
|
-
|
|
952
|
+
parameterType: "fee",
|
|
953
|
+
scope: { tags: ["transaction"] },
|
|
889
954
|
direction: "increase",
|
|
890
955
|
magnitude: thresholds.maxAdjustmentPercent,
|
|
891
956
|
reasoning: `${dominantRole} share at ${((roleShares[dominantRole] ?? 0) * 100).toFixed(0)}%. Likely stampede from non-competitive profitability formula. Raise market friction to slow role accumulation.`
|
|
@@ -911,7 +976,7 @@ var P6_CrowdingMultiplierOnAllRoles = {
|
|
|
911
976
|
severity: 5,
|
|
912
977
|
evidence: { role, share },
|
|
913
978
|
suggestedAction: {
|
|
914
|
-
|
|
979
|
+
parameterType: "cost",
|
|
915
980
|
direction: "increase",
|
|
916
981
|
magnitude: 0.1,
|
|
917
982
|
reasoning: `${role} at ${(share * 100).toFixed(0)}% \u2014 no crowding pressure detected. Apply role-specific cost increase to simulate saturation.`
|
|
@@ -946,7 +1011,8 @@ var P7_NonSpecialistsSubsidiseSpecialists = {
|
|
|
946
1011
|
severity: 6,
|
|
947
1012
|
evidence: { poolName, poolSize, dominantRole, dominantShare },
|
|
948
1013
|
suggestedAction: {
|
|
949
|
-
|
|
1014
|
+
parameterType: "fee",
|
|
1015
|
+
scope: { tags: ["entry"] },
|
|
950
1016
|
direction: "decrease",
|
|
951
1017
|
magnitude: 0.1,
|
|
952
1018
|
reasoning: `Pool "${poolName}" draining (${poolSize}) \u2014 ${dominantRole} at ${(dominantShare * 100).toFixed(0)}%. Too many specialists, not enough subsidising non-specialists. Lower entry fee to attract diverse participants.`
|
|
@@ -974,7 +1040,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
974
1040
|
severity: 4,
|
|
975
1041
|
evidence: { dominantRole: dominantRole[0], share: dominantRole[1], avgSatisfaction },
|
|
976
1042
|
suggestedAction: {
|
|
977
|
-
|
|
1043
|
+
parameterType: "reward",
|
|
978
1044
|
direction: "increase",
|
|
979
1045
|
magnitude: 0.1,
|
|
980
1046
|
reasoning: `Low satisfaction with ${dominantRole[0]} dominant. Regulator may be suppressing a structurally necessary role. Ease pressure on dominant role rewards.`
|
|
@@ -999,7 +1065,7 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
999
1065
|
id: "P9",
|
|
1000
1066
|
name: "Role Switching Needs Friction",
|
|
1001
1067
|
category: "population",
|
|
1002
|
-
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,
|
|
1068
|
+
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.",
|
|
1003
1069
|
check(metrics, thresholds) {
|
|
1004
1070
|
const { churnByRole, roleShares } = metrics;
|
|
1005
1071
|
const totalChurn = Object.values(churnByRole).reduce((s, v) => s + v, 0);
|
|
@@ -1009,7 +1075,7 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
1009
1075
|
severity: 5,
|
|
1010
1076
|
evidence: { totalChurnRate: totalChurn, churnByRole },
|
|
1011
1077
|
suggestedAction: {
|
|
1012
|
-
|
|
1078
|
+
parameterType: "cost",
|
|
1013
1079
|
direction: "increase",
|
|
1014
1080
|
magnitude: 0.05,
|
|
1015
1081
|
reasoning: `Role switch rate ${(totalChurn * 100).toFixed(1)}% exceeds friction threshold. Increase production costs to slow herd movement.`
|
|
@@ -1022,11 +1088,11 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
1022
1088
|
return { violated: false };
|
|
1023
1089
|
}
|
|
1024
1090
|
};
|
|
1025
|
-
var
|
|
1091
|
+
var P10_EntryWeightingUsesInversePopulation = {
|
|
1026
1092
|
id: "P10",
|
|
1027
|
-
name: "
|
|
1093
|
+
name: "Entry Weighting Uses Inverse Population",
|
|
1028
1094
|
category: "population",
|
|
1029
|
-
description: "New
|
|
1095
|
+
description: "New entrants should preferentially fill the least-populated roles. Flat entry probability causes initial imbalances to compound.",
|
|
1030
1096
|
check(metrics, _thresholds) {
|
|
1031
1097
|
const { roleShares } = metrics;
|
|
1032
1098
|
if (Object.keys(roleShares).length === 0) return { violated: false };
|
|
@@ -1041,7 +1107,7 @@ var P10_SpawnWeightingUsesInversePopulation = {
|
|
|
1041
1107
|
severity: 4,
|
|
1042
1108
|
evidence: { roleShares, stdDev, leastPopulatedRole: minRole?.[0] },
|
|
1043
1109
|
suggestedAction: {
|
|
1044
|
-
|
|
1110
|
+
parameterType: "yield",
|
|
1045
1111
|
direction: "increase",
|
|
1046
1112
|
magnitude: 0.05,
|
|
1047
1113
|
reasoning: `High role share variance (\u03C3=${stdDev.toFixed(2)}). Entry weighting may not be filling under-populated roles. Increasing yield makes under-populated producer roles more attractive.`
|
|
@@ -1067,7 +1133,8 @@ var P11_TwoTierPressure = {
|
|
|
1067
1133
|
severity: 6,
|
|
1068
1134
|
evidence: { role, share },
|
|
1069
1135
|
suggestedAction: {
|
|
1070
|
-
|
|
1136
|
+
parameterType: "fee",
|
|
1137
|
+
scope: { tags: ["transaction"] },
|
|
1071
1138
|
direction: "increase",
|
|
1072
1139
|
magnitude: 0.15,
|
|
1073
1140
|
reasoning: `${role} at ${(share * 100).toFixed(0)}% \u2014 continuous pressure was insufficient. Hard intervention needed alongside resumed continuous pressure.`
|
|
@@ -1095,7 +1162,7 @@ var P46_PersonaDiversity = {
|
|
|
1095
1162
|
severity: 5,
|
|
1096
1163
|
evidence: { dominantPersona: persona, share, personaDistribution },
|
|
1097
1164
|
suggestedAction: {
|
|
1098
|
-
|
|
1165
|
+
parameterType: "reward",
|
|
1099
1166
|
direction: "increase",
|
|
1100
1167
|
magnitude: 0.1,
|
|
1101
1168
|
reasoning: `${persona} persona at ${(share * 100).toFixed(0)}% \u2014 behavioral monoculture. Diversify reward structures to attract other persona types.`
|
|
@@ -1112,7 +1179,8 @@ var P46_PersonaDiversity = {
|
|
|
1112
1179
|
severity: 3,
|
|
1113
1180
|
evidence: { significantClusters, required: thresholds.personaMinClusters },
|
|
1114
1181
|
suggestedAction: {
|
|
1115
|
-
|
|
1182
|
+
parameterType: "fee",
|
|
1183
|
+
scope: { tags: ["transaction"] },
|
|
1116
1184
|
direction: "decrease",
|
|
1117
1185
|
magnitude: 0.05,
|
|
1118
1186
|
reasoning: `Only ${significantClusters} significant persona clusters (need ${thresholds.personaMinClusters}). Lower trade barriers to attract non-dominant persona types.`
|
|
@@ -1126,7 +1194,7 @@ var P46_PersonaDiversity = {
|
|
|
1126
1194
|
};
|
|
1127
1195
|
var POPULATION_PRINCIPLES = [
|
|
1128
1196
|
P9_RoleSwitchingNeedsFriction,
|
|
1129
|
-
|
|
1197
|
+
P10_EntryWeightingUsesInversePopulation,
|
|
1130
1198
|
P11_TwoTierPressure,
|
|
1131
1199
|
P46_PersonaDiversity
|
|
1132
1200
|
];
|
|
@@ -1136,7 +1204,7 @@ var P12_OnePrimaryFaucet = {
|
|
|
1136
1204
|
id: "P12",
|
|
1137
1205
|
name: "One Primary Faucet",
|
|
1138
1206
|
category: "currency",
|
|
1139
|
-
description: "Multiple independent currency sources (gathering + production +
|
|
1207
|
+
description: "Multiple independent currency sources (gathering + production + activities) each creating currency causes uncontrolled inflation. One clear primary faucet makes the economy predictable and auditable.",
|
|
1140
1208
|
check(metrics, thresholds) {
|
|
1141
1209
|
for (const curr of metrics.currencies) {
|
|
1142
1210
|
const netFlow = metrics.netFlowByCurrency[curr] ?? 0;
|
|
@@ -1148,9 +1216,9 @@ var P12_OnePrimaryFaucet = {
|
|
|
1148
1216
|
severity: 5,
|
|
1149
1217
|
evidence: { currency: curr, netFlow, faucetVolume, sinkVolume },
|
|
1150
1218
|
suggestedAction: {
|
|
1151
|
-
|
|
1219
|
+
parameterType: "cost",
|
|
1152
1220
|
direction: "increase",
|
|
1153
|
-
currency: curr,
|
|
1221
|
+
scope: { currency: curr },
|
|
1154
1222
|
magnitude: 0.15,
|
|
1155
1223
|
reasoning: `[${curr}] Net flow +${netFlow.toFixed(1)}/tick. Inflationary. Increase production cost (primary sink) to balance faucet output.`
|
|
1156
1224
|
},
|
|
@@ -1164,9 +1232,9 @@ var P12_OnePrimaryFaucet = {
|
|
|
1164
1232
|
severity: 4,
|
|
1165
1233
|
evidence: { currency: curr, netFlow, faucetVolume, sinkVolume },
|
|
1166
1234
|
suggestedAction: {
|
|
1167
|
-
|
|
1235
|
+
parameterType: "cost",
|
|
1168
1236
|
direction: "decrease",
|
|
1169
|
-
currency: curr,
|
|
1237
|
+
scope: { currency: curr },
|
|
1170
1238
|
magnitude: 0.15,
|
|
1171
1239
|
reasoning: `[${curr}] Net flow ${netFlow.toFixed(1)}/tick. Deflationary. Decrease production cost to ease sink pressure.`
|
|
1172
1240
|
},
|
|
@@ -1198,9 +1266,9 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1198
1266
|
severity: 7,
|
|
1199
1267
|
evidence: { currency: curr, pool: poolName, poolSize, participants: dominantCount, maxSustainableMultiplier },
|
|
1200
1268
|
suggestedAction: {
|
|
1201
|
-
|
|
1269
|
+
parameterType: "reward",
|
|
1202
1270
|
direction: "decrease",
|
|
1203
|
-
currency: curr,
|
|
1271
|
+
scope: { currency: curr },
|
|
1204
1272
|
magnitude: 0.15,
|
|
1205
1273
|
reasoning: `[${curr}] ${poolName} pool at ${poolSize.toFixed(0)} currency with ${dominantCount} active participants. Sustainable multiplier \u2264 ${maxSustainableMultiplier.toFixed(2)}. Reduce reward multiplier to prevent pool drain.`
|
|
1206
1274
|
},
|
|
@@ -1217,7 +1285,7 @@ var P14_TrackActualInjection = {
|
|
|
1217
1285
|
id: "P14",
|
|
1218
1286
|
name: "Track Actual Currency Injection, Not Value Creation",
|
|
1219
1287
|
category: "currency",
|
|
1220
|
-
description: 'Counting resource
|
|
1288
|
+
description: 'Counting resource extraction as "currency injected" is misleading. Currency enters through faucet mechanisms (entering, rewards). Fake metrics break every downstream decision.',
|
|
1221
1289
|
check(metrics, _thresholds) {
|
|
1222
1290
|
for (const curr of metrics.currencies) {
|
|
1223
1291
|
const faucetVolume = metrics.faucetVolumeByCurrency[curr] ?? 0;
|
|
@@ -1230,9 +1298,9 @@ var P14_TrackActualInjection = {
|
|
|
1230
1298
|
severity: 4,
|
|
1231
1299
|
evidence: { currency: curr, faucetVolume, netFlow, supplyGrowthRate },
|
|
1232
1300
|
suggestedAction: {
|
|
1233
|
-
|
|
1301
|
+
parameterType: "yield",
|
|
1234
1302
|
direction: "decrease",
|
|
1235
|
-
currency: curr,
|
|
1303
|
+
scope: { currency: curr },
|
|
1236
1304
|
magnitude: 0.1,
|
|
1237
1305
|
reasoning: `[${curr}] Supply growing at ${(supplyGrowthRate * 100).toFixed(1)}%/tick. Verify currency injection tracking. Resources should not create currency directly.`
|
|
1238
1306
|
},
|
|
@@ -1262,9 +1330,9 @@ var P15_PoolsNeedCapAndDecay = {
|
|
|
1262
1330
|
severity: 6,
|
|
1263
1331
|
evidence: { currency: curr, pool, size, shareOfSupply, cap: poolCapPercent },
|
|
1264
1332
|
suggestedAction: {
|
|
1265
|
-
|
|
1333
|
+
parameterType: "fee",
|
|
1266
1334
|
direction: "decrease",
|
|
1267
|
-
currency: curr,
|
|
1335
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1268
1336
|
magnitude: 0.1,
|
|
1269
1337
|
reasoning: `[${curr}] ${pool} pool at ${(shareOfSupply * 100).toFixed(1)}% of supply (cap: ${(poolCapPercent * 100).toFixed(0)}%). Currency frozen. Lower fees to encourage circulation over accumulation.`
|
|
1270
1338
|
},
|
|
@@ -1294,9 +1362,9 @@ var P16_WithdrawalPenaltyScales = {
|
|
|
1294
1362
|
severity: 3,
|
|
1295
1363
|
evidence: { currency: curr, pool: poolName, poolSize, estimatedStaked: stakedEstimate },
|
|
1296
1364
|
suggestedAction: {
|
|
1297
|
-
|
|
1365
|
+
parameterType: "fee",
|
|
1298
1366
|
direction: "increase",
|
|
1299
|
-
currency: curr,
|
|
1367
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1300
1368
|
magnitude: 0.05,
|
|
1301
1369
|
reasoning: `[${curr}] ${poolName} pool depleted while significant currency should be locked. Early withdrawals may be draining the pool. Ensure withdrawal penalty scales with lock duration.`
|
|
1302
1370
|
},
|
|
@@ -1326,9 +1394,9 @@ var P32_VelocityAboveSupply = {
|
|
|
1326
1394
|
severity: 4,
|
|
1327
1395
|
evidence: { currency: curr, velocity, totalSupply, totalResources },
|
|
1328
1396
|
suggestedAction: {
|
|
1329
|
-
|
|
1397
|
+
parameterType: "fee",
|
|
1330
1398
|
direction: "decrease",
|
|
1331
|
-
currency: curr,
|
|
1399
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1332
1400
|
magnitude: 0.2,
|
|
1333
1401
|
reasoning: `[${curr}] Velocity ${velocity}/t with ${totalResources} resources in system. Economy stagnant despite available supply. Lower trading friction.`
|
|
1334
1402
|
},
|
|
@@ -1368,9 +1436,9 @@ var P58_NoNaturalNumeraire = {
|
|
|
1368
1436
|
meanPrice: mean
|
|
1369
1437
|
},
|
|
1370
1438
|
suggestedAction: {
|
|
1371
|
-
|
|
1439
|
+
parameterType: "cost",
|
|
1372
1440
|
direction: "increase",
|
|
1373
|
-
currency: curr,
|
|
1441
|
+
scope: { currency: curr },
|
|
1374
1442
|
magnitude: 0.1,
|
|
1375
1443
|
reasoning: `[${curr}] Price coefficient of variation ${coeffOfVariation.toFixed(2)} with velocity ${velocity.toFixed(1)}. All items priced similarly in an active economy \u2014 no natural num\xE9raire emerging. If a designated currency exists, increase its sink demand to differentiate it.`
|
|
1376
1444
|
},
|
|
@@ -1405,7 +1473,8 @@ var P17_GracePeriodBeforeIntervention = {
|
|
|
1405
1473
|
severity: 7,
|
|
1406
1474
|
evidence: { tick: metrics.tick, avgSatisfaction: metrics.avgSatisfaction },
|
|
1407
1475
|
suggestedAction: {
|
|
1408
|
-
|
|
1476
|
+
parameterType: "fee",
|
|
1477
|
+
scope: { tags: ["entry"] },
|
|
1409
1478
|
direction: "decrease",
|
|
1410
1479
|
magnitude: 0.2,
|
|
1411
1480
|
reasoning: `Very low satisfaction at tick ${metrics.tick}. Intervention may have fired during grace period. Ease all costs to let economy bootstrap.`
|
|
@@ -1432,7 +1501,7 @@ var P18_FirstProducerNeedsStartingInventory = {
|
|
|
1432
1501
|
severity: 8,
|
|
1433
1502
|
evidence: { tick: metrics.tick, resource, supply, totalAgents: metrics.totalAgents },
|
|
1434
1503
|
suggestedAction: {
|
|
1435
|
-
|
|
1504
|
+
parameterType: "cost",
|
|
1436
1505
|
direction: "decrease",
|
|
1437
1506
|
magnitude: 0.5,
|
|
1438
1507
|
reasoning: `Bootstrap failure: ${resource} supply is 0 at tick ${metrics.tick} with ${metrics.totalAgents} agents. Drastically reduce production cost to allow immediate output.`
|
|
@@ -1471,7 +1540,7 @@ var P19_StartingSupplyExceedsDemand = {
|
|
|
1471
1540
|
resourcesPerAgent
|
|
1472
1541
|
},
|
|
1473
1542
|
suggestedAction: {
|
|
1474
|
-
|
|
1543
|
+
parameterType: "reward",
|
|
1475
1544
|
direction: "increase",
|
|
1476
1545
|
magnitude: 0.2,
|
|
1477
1546
|
reasoning: `${mostPopulatedRole} (${population} agents) has insufficient resources (${resourcesPerAgent.toFixed(2)} per agent). Cold-start scarcity. Boost competitive pool reward to attract participation despite scarcity.`
|
|
@@ -1505,7 +1574,7 @@ var P20_DecayPreventsAccumulation = {
|
|
|
1505
1574
|
severity: 4,
|
|
1506
1575
|
evidence: { totalResources, resourcesPerAgent, velocity },
|
|
1507
1576
|
suggestedAction: {
|
|
1508
|
-
|
|
1577
|
+
parameterType: "yield",
|
|
1509
1578
|
direction: "decrease",
|
|
1510
1579
|
magnitude: 0.1,
|
|
1511
1580
|
reasoning: `${totalResources.toFixed(0)} resources with velocity ${velocity}/t. Likely hoarding. Reduce yield to increase scarcity and force circulation.`
|
|
@@ -1533,7 +1602,8 @@ var P21_PriceFromGlobalSupply = {
|
|
|
1533
1602
|
severity: 3,
|
|
1534
1603
|
evidence: { resource, volatility, supply, price: prices[resource] },
|
|
1535
1604
|
suggestedAction: {
|
|
1536
|
-
|
|
1605
|
+
parameterType: "fee",
|
|
1606
|
+
scope: { tags: ["transaction"] },
|
|
1537
1607
|
direction: "increase",
|
|
1538
1608
|
magnitude: 0.05,
|
|
1539
1609
|
reasoning: `${resource} price volatile (${(volatility * 100).toFixed(0)}%) despite supply ${supply}. Price may not reflect global inventory. Increase trading friction to stabilise.`
|
|
@@ -1550,7 +1620,7 @@ var P22_MarketAwarenessPreventsSurplus = {
|
|
|
1550
1620
|
id: "P22",
|
|
1551
1621
|
name: "Market Awareness Prevents Overproduction",
|
|
1552
1622
|
category: "feedback",
|
|
1553
|
-
description: "Producers who
|
|
1623
|
+
description: "Producers who produce without checking market prices will create surpluses that crash prices. Agents need to see prices before deciding to produce.",
|
|
1554
1624
|
check(metrics, _thresholds) {
|
|
1555
1625
|
const { supplyByResource, prices, productionIndex } = metrics;
|
|
1556
1626
|
const priceValues = Object.values(prices).filter((p) => p > 0);
|
|
@@ -1574,7 +1644,7 @@ var P22_MarketAwarenessPreventsSurplus = {
|
|
|
1574
1644
|
productionIndex
|
|
1575
1645
|
},
|
|
1576
1646
|
suggestedAction: {
|
|
1577
|
-
|
|
1647
|
+
parameterType: "cost",
|
|
1578
1648
|
direction: "increase",
|
|
1579
1649
|
magnitude: 0.1,
|
|
1580
1650
|
reasoning: `${resource} price ${price.toFixed(0)} is ${(priceDeviation * 100).toFixed(0)}% of median (${medianPrice.toFixed(0)}). Supply ${supply} units but still producing. Producers appear unaware of market. Raise production cost to slow output.`
|
|
@@ -1601,7 +1671,7 @@ var P23_ProfitabilityFactorsFeasibility = {
|
|
|
1601
1671
|
severity: 5,
|
|
1602
1672
|
evidence: { blockedFraction, blockedAgentCount, avgSatisfaction },
|
|
1603
1673
|
suggestedAction: {
|
|
1604
|
-
|
|
1674
|
+
parameterType: "cost",
|
|
1605
1675
|
direction: "decrease",
|
|
1606
1676
|
magnitude: 0.15,
|
|
1607
1677
|
reasoning: `${(blockedFraction * 100).toFixed(0)}% of agents blocked with low satisfaction. Agents may have roles they cannot afford to execute. Lower production costs to restore feasibility.`
|
|
@@ -1627,7 +1697,8 @@ var P24_BlockedAgentsDecayFaster = {
|
|
|
1627
1697
|
severity: 5,
|
|
1628
1698
|
evidence: { blockedFraction, blockedAgentCount, churnRate },
|
|
1629
1699
|
suggestedAction: {
|
|
1630
|
-
|
|
1700
|
+
parameterType: "fee",
|
|
1701
|
+
scope: { tags: ["transaction"] },
|
|
1631
1702
|
direction: "decrease",
|
|
1632
1703
|
magnitude: 0.15,
|
|
1633
1704
|
reasoning: `${(blockedFraction * 100).toFixed(0)}% of agents blocked. Blocked agents churn silently, skewing metrics. Lower fees to unblock market participation.`
|
|
@@ -1672,7 +1743,7 @@ var P25_CorrectLeversForCorrectProblems = {
|
|
|
1672
1743
|
netFlow
|
|
1673
1744
|
},
|
|
1674
1745
|
suggestedAction: {
|
|
1675
|
-
|
|
1746
|
+
parameterType: "yield",
|
|
1676
1747
|
direction: "decrease",
|
|
1677
1748
|
magnitude: 0.15,
|
|
1678
1749
|
reasoning: `Inflation with ${resource} backlog (${supply} units, ${(supply / Math.max(1, avgSupply)).toFixed(1)}\xD7 average). Root cause is gathering. Correct lever: yieldRate, not fees.`
|
|
@@ -1698,7 +1769,7 @@ var P26_ContinuousPressureBeatsThresholdCuts = {
|
|
|
1698
1769
|
severity: 4,
|
|
1699
1770
|
evidence: { inflationRate },
|
|
1700
1771
|
suggestedAction: {
|
|
1701
|
-
|
|
1772
|
+
parameterType: "cost",
|
|
1702
1773
|
direction: inflationRate > 0 ? "increase" : "decrease",
|
|
1703
1774
|
magnitude: Math.min(thresholds.maxAdjustmentPercent, 0.05),
|
|
1704
1775
|
// force smaller step
|
|
@@ -1724,7 +1795,8 @@ var P27_AdjustmentsNeedCooldowns = {
|
|
|
1724
1795
|
severity: 4,
|
|
1725
1796
|
evidence: { churnRate, avgSatisfaction },
|
|
1726
1797
|
suggestedAction: {
|
|
1727
|
-
|
|
1798
|
+
parameterType: "fee",
|
|
1799
|
+
scope: { tags: ["entry"] },
|
|
1728
1800
|
direction: "decrease",
|
|
1729
1801
|
magnitude: 0.05,
|
|
1730
1802
|
reasoning: `High churn (${(churnRate * 100).toFixed(1)}%) with low satisfaction. Possible oscillation from rapid adjustments. Apply small correction only.`
|
|
@@ -1755,7 +1827,7 @@ var P28_StructuralDominanceIsNotPathological = {
|
|
|
1755
1827
|
severity: 5,
|
|
1756
1828
|
evidence: { dominantRole, dominantShare, avgSatisfaction },
|
|
1757
1829
|
suggestedAction: {
|
|
1758
|
-
|
|
1830
|
+
parameterType: "cost",
|
|
1759
1831
|
direction: "decrease",
|
|
1760
1832
|
magnitude: 0.1,
|
|
1761
1833
|
reasoning: `${dominantRole} dominant (${(dominantShare * 100).toFixed(0)}%) with low satisfaction. Pathological dominance \u2014 agents trapped, not thriving. Ease costs to allow role switching.`
|
|
@@ -1771,7 +1843,7 @@ var P38_CommunicationPreventsRevolt = {
|
|
|
1771
1843
|
id: "P38",
|
|
1772
1844
|
name: "Communication Prevents Revolt",
|
|
1773
1845
|
category: "regulator",
|
|
1774
|
-
description: "Every adjustment must be logged with reasoning. An adjustment made without explanation to
|
|
1846
|
+
description: "Every adjustment must be logged with reasoning. An adjustment made without explanation to participants causes revolt. AgentE logs every decision \u2014 this principle checks that logging is active.",
|
|
1775
1847
|
check(metrics, _thresholds) {
|
|
1776
1848
|
const { churnRate } = metrics;
|
|
1777
1849
|
if (churnRate > 0.1) {
|
|
@@ -1780,7 +1852,7 @@ var P38_CommunicationPreventsRevolt = {
|
|
|
1780
1852
|
severity: 3,
|
|
1781
1853
|
evidence: { churnRate },
|
|
1782
1854
|
suggestedAction: {
|
|
1783
|
-
|
|
1855
|
+
parameterType: "reward",
|
|
1784
1856
|
direction: "increase",
|
|
1785
1857
|
magnitude: 0.1,
|
|
1786
1858
|
reasoning: `High churn (${(churnRate * 100).toFixed(1)}%) \u2014 agents leaving. Ensure all recent adjustments are logged with reasoning to diagnose cause.`
|
|
@@ -1801,9 +1873,9 @@ var REGULATOR_PRINCIPLES = [
|
|
|
1801
1873
|
];
|
|
1802
1874
|
|
|
1803
1875
|
// src/principles/market-dynamics.ts
|
|
1804
|
-
var
|
|
1876
|
+
var P29_BottleneckDetection = {
|
|
1805
1877
|
id: "P29",
|
|
1806
|
-
name: "
|
|
1878
|
+
name: "Bottleneck Detection",
|
|
1807
1879
|
category: "market_dynamics",
|
|
1808
1880
|
description: "Every economy has a resource that constrains all downstream activity. Identify which resource is the pinch point (consumers need them, producers make them). If demand drops \u2192 oversupply. If frustration rises \u2192 undersupply.",
|
|
1809
1881
|
check(metrics, _thresholds) {
|
|
@@ -1817,7 +1889,7 @@ var P29_PinchPoint = {
|
|
|
1817
1889
|
severity: 7,
|
|
1818
1890
|
evidence: { resource, supply, demand, status },
|
|
1819
1891
|
suggestedAction: {
|
|
1820
|
-
|
|
1892
|
+
parameterType: "cost",
|
|
1821
1893
|
direction: "decrease",
|
|
1822
1894
|
magnitude: 0.15,
|
|
1823
1895
|
reasoning: `${resource} is a pinch point and currently SCARCE (supply ${supply}, demand ${demand}). Reduce production cost to increase throughput.`
|
|
@@ -1833,7 +1905,7 @@ var P29_PinchPoint = {
|
|
|
1833
1905
|
severity: 4,
|
|
1834
1906
|
evidence: { resource, supply, status },
|
|
1835
1907
|
suggestedAction: {
|
|
1836
|
-
|
|
1908
|
+
parameterType: "cost",
|
|
1837
1909
|
direction: "increase",
|
|
1838
1910
|
magnitude: 0.1,
|
|
1839
1911
|
reasoning: `${resource} is a pinch point and OVERSUPPLIED (supply ${supply}). Raise production cost to reduce surplus.`
|
|
@@ -1846,11 +1918,11 @@ var P29_PinchPoint = {
|
|
|
1846
1918
|
return { violated: false };
|
|
1847
1919
|
}
|
|
1848
1920
|
};
|
|
1849
|
-
var
|
|
1921
|
+
var P30_DynamicBottleneckRotation = {
|
|
1850
1922
|
id: "P30",
|
|
1851
|
-
name: "
|
|
1923
|
+
name: "Dynamic Bottleneck Rotation",
|
|
1852
1924
|
category: "market_dynamics",
|
|
1853
|
-
description: "
|
|
1925
|
+
description: "Participant progression shifts the demand curve. A static pinch point that works early will be cleared later. The pinch point must move with participant progression to maintain ongoing scarcity and engagement.",
|
|
1854
1926
|
check(metrics, _thresholds) {
|
|
1855
1927
|
const { capacityUsage, supplyByResource, avgSatisfaction } = metrics;
|
|
1856
1928
|
const totalResources = Object.values(supplyByResource).reduce((s, v) => s + v, 0);
|
|
@@ -1861,7 +1933,7 @@ var P30_MovingPinchPoint = {
|
|
|
1861
1933
|
severity: 3,
|
|
1862
1934
|
evidence: { capacityUsage, resourcesPerAgent, avgSatisfaction },
|
|
1863
1935
|
suggestedAction: {
|
|
1864
|
-
|
|
1936
|
+
parameterType: "cost",
|
|
1865
1937
|
direction: "increase",
|
|
1866
1938
|
magnitude: 0.1,
|
|
1867
1939
|
reasoning: "Economy operating at full capacity with abundant resources and high satisfaction. Pinch point may have been cleared. Increase production cost to restore scarcity."
|
|
@@ -1877,7 +1949,7 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1877
1949
|
id: "P57",
|
|
1878
1950
|
name: "Combinatorial Price Space",
|
|
1879
1951
|
category: "market_dynamics",
|
|
1880
|
-
description: "N tradeable items generate (N\u22121)N/2 relative prices. With thousands of items no single
|
|
1952
|
+
description: "N tradeable items generate (N\u22121)N/2 relative prices. With thousands of items no single participant can track them all. Design for distributed self-organization, not centralized pricing.",
|
|
1881
1953
|
check(metrics, thresholds) {
|
|
1882
1954
|
const { prices, priceVolatility } = metrics;
|
|
1883
1955
|
const priceKeys = Object.keys(prices);
|
|
@@ -1907,7 +1979,8 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1907
1979
|
target: thresholds.relativePriceConvergenceTarget
|
|
1908
1980
|
},
|
|
1909
1981
|
suggestedAction: {
|
|
1910
|
-
|
|
1982
|
+
parameterType: "fee",
|
|
1983
|
+
scope: { tags: ["transaction"] },
|
|
1911
1984
|
direction: "decrease",
|
|
1912
1985
|
magnitude: 0.1,
|
|
1913
1986
|
reasoning: `Only ${(convergenceRate * 100).toFixed(0)}% of ${relativePriceCount} relative prices have converged (target: ${(thresholds.relativePriceConvergenceTarget * 100).toFixed(0)}%). Price space too complex for distributed discovery. Lower friction to help.`
|
|
@@ -1920,8 +1993,8 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1920
1993
|
}
|
|
1921
1994
|
};
|
|
1922
1995
|
var MARKET_DYNAMICS_PRINCIPLES = [
|
|
1923
|
-
|
|
1924
|
-
|
|
1996
|
+
P29_BottleneckDetection,
|
|
1997
|
+
P30_DynamicBottleneckRotation,
|
|
1925
1998
|
P57_CombinatorialPriceSpace
|
|
1926
1999
|
];
|
|
1927
2000
|
|
|
@@ -1939,7 +2012,7 @@ var P31_AnchorValueTracking = {
|
|
|
1939
2012
|
severity: 5,
|
|
1940
2013
|
evidence: { anchorRatioDrift, inflationRate },
|
|
1941
2014
|
suggestedAction: {
|
|
1942
|
-
|
|
2015
|
+
parameterType: "cost",
|
|
1943
2016
|
direction: anchorRatioDrift > 0 ? "increase" : "decrease",
|
|
1944
2017
|
magnitude: 0.1,
|
|
1945
2018
|
reasoning: `Anchor ratio has drifted ${(anchorRatioDrift * 100).toFixed(0)}% from baseline. Time-to-value for participants is changing. Adjust production costs to restore.`
|
|
@@ -1964,7 +2037,8 @@ var P41_MultiResolutionMonitoring = {
|
|
|
1964
2037
|
severity: 4,
|
|
1965
2038
|
evidence: { giniCoefficient, avgSatisfaction },
|
|
1966
2039
|
suggestedAction: {
|
|
1967
|
-
|
|
2040
|
+
parameterType: "fee",
|
|
2041
|
+
scope: { tags: ["transaction"] },
|
|
1968
2042
|
direction: "increase",
|
|
1969
2043
|
magnitude: 0.1,
|
|
1970
2044
|
reasoning: `Gini ${giniCoefficient.toFixed(2)} rising despite okay satisfaction. Early warning from fine-resolution monitoring. Raise trading fees to slow wealth concentration before it hurts satisfaction.`
|
|
@@ -1993,7 +2067,8 @@ var P55_ArbitrageThermometer = {
|
|
|
1993
2067
|
critical: thresholds.arbitrageIndexCritical
|
|
1994
2068
|
},
|
|
1995
2069
|
suggestedAction: {
|
|
1996
|
-
|
|
2070
|
+
parameterType: "fee",
|
|
2071
|
+
scope: { tags: ["transaction"] },
|
|
1997
2072
|
direction: "decrease",
|
|
1998
2073
|
magnitude: 0.15,
|
|
1999
2074
|
reasoning: `Arbitrage index ${arbitrageIndex.toFixed(2)} exceeds critical threshold (${thresholds.arbitrageIndexCritical}). Relative prices are diverging \u2014 economy destabilizing. Lower trading friction to accelerate price convergence.`
|
|
@@ -2011,7 +2086,8 @@ var P55_ArbitrageThermometer = {
|
|
|
2011
2086
|
warning: thresholds.arbitrageIndexWarning
|
|
2012
2087
|
},
|
|
2013
2088
|
suggestedAction: {
|
|
2014
|
-
|
|
2089
|
+
parameterType: "fee",
|
|
2090
|
+
scope: { tags: ["transaction"] },
|
|
2015
2091
|
direction: "decrease",
|
|
2016
2092
|
magnitude: 0.08,
|
|
2017
2093
|
reasoning: `Arbitrage index ${arbitrageIndex.toFixed(2)} above warning threshold (${thresholds.arbitrageIndexWarning}). Early sign of price divergence. Gently reduce friction to support self-correction.`
|
|
@@ -2039,7 +2115,8 @@ var P59_GiftEconomyNoise = {
|
|
|
2039
2115
|
threshold: thresholds.giftTradeFilterRatio
|
|
2040
2116
|
},
|
|
2041
2117
|
suggestedAction: {
|
|
2042
|
-
|
|
2118
|
+
parameterType: "fee",
|
|
2119
|
+
scope: { tags: ["transaction"] },
|
|
2043
2120
|
direction: "increase",
|
|
2044
2121
|
magnitude: 0.05,
|
|
2045
2122
|
reasoning: `${(giftTradeRatio * 100).toFixed(0)}% of trades are gift-like (price = 0 or <30% market). Exceeds filter threshold (${(thresholds.giftTradeFilterRatio * 100).toFixed(0)}%). Price signals contaminated. Slightly raise trading fees to discourage zero-value listings. ADVISORY: Consider filtering sub-market trades from price index computation.`
|
|
@@ -2082,9 +2159,9 @@ var P42_TheMedianPrinciple = {
|
|
|
2082
2159
|
medianBalance
|
|
2083
2160
|
},
|
|
2084
2161
|
suggestedAction: {
|
|
2085
|
-
|
|
2162
|
+
parameterType: "fee",
|
|
2163
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2086
2164
|
direction: "increase",
|
|
2087
|
-
currency: curr,
|
|
2088
2165
|
magnitude: 0.15,
|
|
2089
2166
|
reasoning: `[${curr}] Mean/median divergence ${(meanMedianDivergence * 100).toFixed(0)}% (threshold: ${(thresholds.meanMedianDivergenceMax * 100).toFixed(0)}%). Economy has outliers skewing metrics. Use median for decisions. Raise transaction fees to redistribute wealth.`
|
|
2090
2167
|
},
|
|
@@ -2109,7 +2186,7 @@ var P43_SimulationMinimum = {
|
|
|
2109
2186
|
severity: 3,
|
|
2110
2187
|
evidence: { inflationRate, minIterations: thresholds.simulationMinIterations },
|
|
2111
2188
|
suggestedAction: {
|
|
2112
|
-
|
|
2189
|
+
parameterType: "cost",
|
|
2113
2190
|
direction: inflationRate > 0 ? "increase" : "decrease",
|
|
2114
2191
|
magnitude: 0.05,
|
|
2115
2192
|
reasoning: `Large inflation rate swing (${(inflationRate * 100).toFixed(0)}%). Ensure all decisions use \u2265${thresholds.simulationMinIterations} simulation iterations. Apply conservative correction.`
|
|
@@ -2147,7 +2224,7 @@ var P39_TheLagPrinciple = {
|
|
|
2147
2224
|
severity: 5,
|
|
2148
2225
|
evidence: { inflationRate, netFlow, lagRange: [lagMin, lagMax] },
|
|
2149
2226
|
suggestedAction: {
|
|
2150
|
-
|
|
2227
|
+
parameterType: "cost",
|
|
2151
2228
|
direction: "increase",
|
|
2152
2229
|
magnitude: 0.03,
|
|
2153
2230
|
// very small — oscillation means over-adjusting
|
|
@@ -2174,7 +2251,8 @@ var P44_ComplexityBudget = {
|
|
|
2174
2251
|
severity: 3,
|
|
2175
2252
|
evidence: { customMetricCount, budgetMax: thresholds.complexityBudgetMax },
|
|
2176
2253
|
suggestedAction: {
|
|
2177
|
-
|
|
2254
|
+
parameterType: "fee",
|
|
2255
|
+
scope: { tags: ["transaction"] },
|
|
2178
2256
|
direction: "decrease",
|
|
2179
2257
|
magnitude: 0.01,
|
|
2180
2258
|
reasoning: `${customMetricCount} custom metrics tracked (budget: ${thresholds.complexityBudgetMax}). Consider pruning low-impact parameters. Applying minimal correction to avoid adding complexity.`
|
|
@@ -2206,7 +2284,8 @@ var P35_DestructionCreatesValue = {
|
|
|
2206
2284
|
severity: 6,
|
|
2207
2285
|
evidence: { resource, supply, sinkVolume, netFlow },
|
|
2208
2286
|
suggestedAction: {
|
|
2209
|
-
|
|
2287
|
+
parameterType: "fee",
|
|
2288
|
+
scope: { tags: ["entry"] },
|
|
2210
2289
|
direction: "decrease",
|
|
2211
2290
|
magnitude: 0.1,
|
|
2212
2291
|
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower competitive pool entry to increase resource usage.`
|
|
@@ -2223,7 +2302,7 @@ var P40_ReplacementRate = {
|
|
|
2223
2302
|
id: "P40",
|
|
2224
2303
|
name: "Replacement Rate \u2265 2\xD7 Consumption",
|
|
2225
2304
|
category: "resource",
|
|
2226
|
-
description: "
|
|
2305
|
+
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.",
|
|
2227
2306
|
check(metrics, thresholds) {
|
|
2228
2307
|
const { productionIndex, sinkVolume } = metrics;
|
|
2229
2308
|
if (sinkVolume > 0 && productionIndex > 0) {
|
|
@@ -2234,7 +2313,7 @@ var P40_ReplacementRate = {
|
|
|
2234
2313
|
severity: 6,
|
|
2235
2314
|
evidence: { productionIndex, sinkVolume, replacementRatio },
|
|
2236
2315
|
suggestedAction: {
|
|
2237
|
-
|
|
2316
|
+
parameterType: "yield",
|
|
2238
2317
|
direction: "increase",
|
|
2239
2318
|
magnitude: 0.15,
|
|
2240
2319
|
reasoning: `Replacement rate ${replacementRatio.toFixed(2)} (need \u2265${thresholds.replacementRateMultiplier}). Production below consumption. Resources will deplete. Increase yield.`
|
|
@@ -2248,7 +2327,7 @@ var P40_ReplacementRate = {
|
|
|
2248
2327
|
severity: 3,
|
|
2249
2328
|
evidence: { productionIndex, sinkVolume, replacementRatio },
|
|
2250
2329
|
suggestedAction: {
|
|
2251
|
-
|
|
2330
|
+
parameterType: "yield",
|
|
2252
2331
|
direction: "decrease",
|
|
2253
2332
|
magnitude: 0.1,
|
|
2254
2333
|
reasoning: `Replacement rate ${replacementRatio.toFixed(2)} \u2014 overproducing. Production far exceeds consumption. Reduce yield to prevent glut.`
|
|
@@ -2274,7 +2353,8 @@ var P49_IdleAssetTax = {
|
|
|
2274
2353
|
severity: 5,
|
|
2275
2354
|
evidence: { giniCoefficient, top10PctShare, velocity },
|
|
2276
2355
|
suggestedAction: {
|
|
2277
|
-
|
|
2356
|
+
parameterType: "fee",
|
|
2357
|
+
scope: { tags: ["transaction"] },
|
|
2278
2358
|
direction: "increase",
|
|
2279
2359
|
magnitude: 0.15,
|
|
2280
2360
|
reasoning: `Gini ${giniCoefficient.toFixed(2)}, top 10% hold ${(top10PctShare * 100).toFixed(0)}%, velocity ${velocity}. Wealth concentrated in idle assets. Raise trading costs to simulate holding tax.`
|
|
@@ -2292,11 +2372,11 @@ var RESOURCE_MGMT_PRINCIPLES = [
|
|
|
2292
2372
|
P49_IdleAssetTax
|
|
2293
2373
|
];
|
|
2294
2374
|
|
|
2295
|
-
// src/principles/
|
|
2375
|
+
// src/principles/participant-experience.ts
|
|
2296
2376
|
var P33_FairNotEqual = {
|
|
2297
2377
|
id: "P33",
|
|
2298
2378
|
name: "Fair \u2260 Equal",
|
|
2299
|
-
category: "
|
|
2379
|
+
category: "participant_experience",
|
|
2300
2380
|
description: "Gini = 0 is boring \u2014 everyone has the same and there is nothing to strive for. Healthy inequality from skill/effort is fine. Inequality from money (pay-to-win) is toxic. Target Gini 0.3-0.45: meaningful spread, not oligarchy.",
|
|
2301
2381
|
check(metrics, thresholds) {
|
|
2302
2382
|
for (const curr of metrics.currencies) {
|
|
@@ -2307,9 +2387,9 @@ var P33_FairNotEqual = {
|
|
|
2307
2387
|
severity: 3,
|
|
2308
2388
|
evidence: { currency: curr, giniCoefficient },
|
|
2309
2389
|
suggestedAction: {
|
|
2310
|
-
|
|
2390
|
+
parameterType: "reward",
|
|
2311
2391
|
direction: "increase",
|
|
2312
|
-
currency: curr,
|
|
2392
|
+
scope: { currency: curr },
|
|
2313
2393
|
magnitude: 0.1,
|
|
2314
2394
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 near-perfect equality. Economy lacks stakes. Increase winner rewards to create meaningful spread.`
|
|
2315
2395
|
},
|
|
@@ -2323,9 +2403,9 @@ var P33_FairNotEqual = {
|
|
|
2323
2403
|
severity: 7,
|
|
2324
2404
|
evidence: { currency: curr, giniCoefficient },
|
|
2325
2405
|
suggestedAction: {
|
|
2326
|
-
|
|
2406
|
+
parameterType: "fee",
|
|
2327
2407
|
direction: "increase",
|
|
2328
|
-
currency: curr,
|
|
2408
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2329
2409
|
magnitude: 0.2,
|
|
2330
2410
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 oligarchy level. Toxic inequality. Raise transaction fees to redistribute wealth from rich to pool.`
|
|
2331
2411
|
},
|
|
@@ -2339,9 +2419,9 @@ var P33_FairNotEqual = {
|
|
|
2339
2419
|
severity: 4,
|
|
2340
2420
|
evidence: { currency: curr, giniCoefficient },
|
|
2341
2421
|
suggestedAction: {
|
|
2342
|
-
|
|
2422
|
+
parameterType: "fee",
|
|
2343
2423
|
direction: "increase",
|
|
2344
|
-
currency: curr,
|
|
2424
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2345
2425
|
magnitude: 0.1,
|
|
2346
2426
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 high inequality warning. Gently raise fees to slow wealth concentration.`
|
|
2347
2427
|
},
|
|
@@ -2355,9 +2435,9 @@ var P33_FairNotEqual = {
|
|
|
2355
2435
|
};
|
|
2356
2436
|
var P36_MechanicFrictionDetector = {
|
|
2357
2437
|
id: "P36",
|
|
2358
|
-
name: "
|
|
2359
|
-
category: "
|
|
2360
|
-
description: "Deterministic + probabilistic systems \u2192 expectation mismatch. When
|
|
2438
|
+
name: "Mechanism Friction Detector",
|
|
2439
|
+
category: "participant_experience",
|
|
2440
|
+
description: "Deterministic + probabilistic systems \u2192 expectation mismatch. When production is guaranteed but competition is random, participants feel betrayed by the random side. Mix mechanisms carefully or segregate them entirely.",
|
|
2361
2441
|
check(metrics, _thresholds) {
|
|
2362
2442
|
const { avgSatisfaction, churnRate, velocity } = metrics;
|
|
2363
2443
|
if (churnRate > 0.1 && avgSatisfaction < 50 && velocity > 3) {
|
|
@@ -2366,10 +2446,10 @@ var P36_MechanicFrictionDetector = {
|
|
|
2366
2446
|
severity: 5,
|
|
2367
2447
|
evidence: { churnRate, avgSatisfaction, velocity },
|
|
2368
2448
|
suggestedAction: {
|
|
2369
|
-
|
|
2449
|
+
parameterType: "reward",
|
|
2370
2450
|
direction: "increase",
|
|
2371
2451
|
magnitude: 0.15,
|
|
2372
|
-
reasoning: `Churn ${(churnRate * 100).toFixed(1)}% with satisfaction ${avgSatisfaction.toFixed(0)} despite active economy (velocity ` + velocity.toFixed(1) + "). Suggests
|
|
2452
|
+
reasoning: `Churn ${(churnRate * 100).toFixed(1)}% with satisfaction ${avgSatisfaction.toFixed(0)} despite active economy (velocity ` + velocity.toFixed(1) + "). Suggests mechanism friction (deterministic vs random systems). Increase rewards to compensate for perceived unfairness. ADVISORY: Review if mixing guaranteed and probabilistic mechanisms."
|
|
2373
2453
|
},
|
|
2374
2454
|
confidence: 0.55,
|
|
2375
2455
|
estimatedLag: 15
|
|
@@ -2380,8 +2460,8 @@ var P36_MechanicFrictionDetector = {
|
|
|
2380
2460
|
};
|
|
2381
2461
|
var P37_LatecommerProblem = {
|
|
2382
2462
|
id: "P37",
|
|
2383
|
-
name: "
|
|
2384
|
-
category: "
|
|
2463
|
+
name: "Late Entrant Problem",
|
|
2464
|
+
category: "participant_experience",
|
|
2385
2465
|
description: "A new participant must reach viability in reasonable time. If all the good roles are saturated and prices are high, new agents cannot contribute and churn immediately.",
|
|
2386
2466
|
check(metrics, _thresholds) {
|
|
2387
2467
|
const { timeToValue, avgSatisfaction, churnRate } = metrics;
|
|
@@ -2391,7 +2471,7 @@ var P37_LatecommerProblem = {
|
|
|
2391
2471
|
severity: 6,
|
|
2392
2472
|
evidence: { timeToValue, avgSatisfaction, churnRate },
|
|
2393
2473
|
suggestedAction: {
|
|
2394
|
-
|
|
2474
|
+
parameterType: "cost",
|
|
2395
2475
|
direction: "decrease",
|
|
2396
2476
|
magnitude: 0.15,
|
|
2397
2477
|
reasoning: `New agents taking ${timeToValue} ticks to reach viability. Churn ${(churnRate * 100).toFixed(1)}%, satisfaction ${avgSatisfaction.toFixed(0)}. Lower production costs to help new participants contribute faster.`
|
|
@@ -2406,7 +2486,7 @@ var P37_LatecommerProblem = {
|
|
|
2406
2486
|
var P45_TimeBudget = {
|
|
2407
2487
|
id: "P45",
|
|
2408
2488
|
name: "Time Budget",
|
|
2409
|
-
category: "
|
|
2489
|
+
category: "participant_experience",
|
|
2410
2490
|
description: "required_time \u2264 available_time \xD7 0.8. If the economy requires more engagement than participants can realistically give, it is a disguised paywall. The 0.8 buffer accounts for real life.",
|
|
2411
2491
|
check(metrics, thresholds) {
|
|
2412
2492
|
const { timeToValue, avgSatisfaction } = metrics;
|
|
@@ -2418,8 +2498,9 @@ var P45_TimeBudget = {
|
|
|
2418
2498
|
severity: 5,
|
|
2419
2499
|
evidence: { timeToValue, avgSatisfaction, timeBudgetRatio: thresholds.timeBudgetRatio },
|
|
2420
2500
|
suggestedAction: {
|
|
2421
|
-
|
|
2501
|
+
parameterType: "fee",
|
|
2422
2502
|
direction: "decrease",
|
|
2503
|
+
scope: { tags: ["entry"] },
|
|
2423
2504
|
magnitude: 0.15,
|
|
2424
2505
|
reasoning: `Time-to-value ${timeToValue} ticks with ${avgSatisfaction.toFixed(0)} satisfaction. Economy requires too much time investment. Lower barriers to participation.`
|
|
2425
2506
|
},
|
|
@@ -2433,7 +2514,7 @@ var P45_TimeBudget = {
|
|
|
2433
2514
|
var P50_PayPowerRatio = {
|
|
2434
2515
|
id: "P50",
|
|
2435
2516
|
name: "Pay-Power Ratio",
|
|
2436
|
-
category: "
|
|
2517
|
+
category: "participant_experience",
|
|
2437
2518
|
description: "spender / non-spender power ratio > 2.0 = pay-to-win territory. Target 1.5 (meaningful advantage without shutting out non-payers). Above 2.0, non-paying participants start leaving.",
|
|
2438
2519
|
check(metrics, thresholds) {
|
|
2439
2520
|
const { top10PctShare, giniCoefficient } = metrics;
|
|
@@ -2448,8 +2529,9 @@ var P50_PayPowerRatio = {
|
|
|
2448
2529
|
threshold: thresholds.payPowerRatioMax
|
|
2449
2530
|
},
|
|
2450
2531
|
suggestedAction: {
|
|
2451
|
-
|
|
2532
|
+
parameterType: "fee",
|
|
2452
2533
|
direction: "increase",
|
|
2534
|
+
scope: { tags: ["transaction"] },
|
|
2453
2535
|
magnitude: 0.2,
|
|
2454
2536
|
reasoning: `Top 10% hold ${(top10PctShare * 100).toFixed(0)}% of wealth (Gini ${giniCoefficient.toFixed(2)}). Wealth advantage may exceed pay-power ratio threshold. Redistribute via higher trading fees.`
|
|
2455
2537
|
},
|
|
@@ -2460,7 +2542,7 @@ var P50_PayPowerRatio = {
|
|
|
2460
2542
|
return { violated: false };
|
|
2461
2543
|
}
|
|
2462
2544
|
};
|
|
2463
|
-
var
|
|
2545
|
+
var PARTICIPANT_EXPERIENCE_PRINCIPLES = [
|
|
2464
2546
|
P33_FairNotEqual,
|
|
2465
2547
|
P36_MechanicFrictionDetector,
|
|
2466
2548
|
P37_LatecommerProblem,
|
|
@@ -2483,7 +2565,8 @@ var P34_ExtractionRatio = {
|
|
|
2483
2565
|
severity: 8,
|
|
2484
2566
|
evidence: { extractionRatio, threshold: thresholds.extractionRatioRed },
|
|
2485
2567
|
suggestedAction: {
|
|
2486
|
-
|
|
2568
|
+
parameterType: "fee",
|
|
2569
|
+
scope: { tags: ["transaction"] },
|
|
2487
2570
|
direction: "increase",
|
|
2488
2571
|
magnitude: 0.25,
|
|
2489
2572
|
reasoning: `Extraction ratio ${(extractionRatio * 100).toFixed(0)}% (critical: ${(thresholds.extractionRatioRed * 100).toFixed(0)}%). Economy is extraction-heavy and subsidy-dependent. Raise fees to increase the cost of extraction.`
|
|
@@ -2498,7 +2581,8 @@ var P34_ExtractionRatio = {
|
|
|
2498
2581
|
severity: 5,
|
|
2499
2582
|
evidence: { extractionRatio, threshold: thresholds.extractionRatioYellow },
|
|
2500
2583
|
suggestedAction: {
|
|
2501
|
-
|
|
2584
|
+
parameterType: "fee",
|
|
2585
|
+
scope: { tags: ["transaction"] },
|
|
2502
2586
|
direction: "increase",
|
|
2503
2587
|
magnitude: 0.1,
|
|
2504
2588
|
reasoning: `Extraction ratio ${(extractionRatio * 100).toFixed(0)}% (warning: ${(thresholds.extractionRatioYellow * 100).toFixed(0)}%). Economy trending toward extraction-heavy. Apply early pressure.`
|
|
@@ -2524,7 +2608,7 @@ var P47_SmokeTest = {
|
|
|
2524
2608
|
severity: 9,
|
|
2525
2609
|
evidence: { smokeTestRatio, threshold: thresholds.smokeTestCritical },
|
|
2526
2610
|
suggestedAction: {
|
|
2527
|
-
|
|
2611
|
+
parameterType: "reward",
|
|
2528
2612
|
direction: "increase",
|
|
2529
2613
|
magnitude: 0.2,
|
|
2530
2614
|
reasoning: `Utility/market ratio ${(smokeTestRatio * 100).toFixed(0)}% (critical). Economy is >90% speculative. Collapse risk is extreme. Increase utility rewards to anchor real value.`
|
|
@@ -2539,7 +2623,7 @@ var P47_SmokeTest = {
|
|
|
2539
2623
|
severity: 6,
|
|
2540
2624
|
evidence: { smokeTestRatio, threshold: thresholds.smokeTestWarning },
|
|
2541
2625
|
suggestedAction: {
|
|
2542
|
-
|
|
2626
|
+
parameterType: "reward",
|
|
2543
2627
|
direction: "increase",
|
|
2544
2628
|
magnitude: 0.1,
|
|
2545
2629
|
reasoning: `Utility/market ratio ${(smokeTestRatio * 100).toFixed(0)}% (warning). Economy is >70% speculative. Boost utility rewards to restore intrinsic value anchor.`
|
|
@@ -2565,7 +2649,8 @@ var P48_CurrencyInsulation = {
|
|
|
2565
2649
|
severity: 6,
|
|
2566
2650
|
evidence: { currencyInsulation, threshold: thresholds.currencyInsulationMax },
|
|
2567
2651
|
suggestedAction: {
|
|
2568
|
-
|
|
2652
|
+
parameterType: "fee",
|
|
2653
|
+
scope: { tags: ["transaction"] },
|
|
2569
2654
|
direction: "increase",
|
|
2570
2655
|
magnitude: 0.1,
|
|
2571
2656
|
reasoning: `Currency correlation with external market: ${(currencyInsulation * 100).toFixed(0)}% (max: ${(thresholds.currencyInsulationMax * 100).toFixed(0)}%). Economy is exposed to external market shocks. Increase internal friction to reduce external correlation.`
|
|
@@ -2583,12 +2668,12 @@ var OPEN_ECONOMY_PRINCIPLES = [
|
|
|
2583
2668
|
P48_CurrencyInsulation
|
|
2584
2669
|
];
|
|
2585
2670
|
|
|
2586
|
-
// src/principles/
|
|
2587
|
-
var
|
|
2671
|
+
// src/principles/operations.ts
|
|
2672
|
+
var P51_CyclicalEngagement = {
|
|
2588
2673
|
id: "P51",
|
|
2589
|
-
name: "
|
|
2590
|
-
category: "
|
|
2591
|
-
description: "Each
|
|
2674
|
+
name: "Cyclical Engagement Pattern",
|
|
2675
|
+
category: "operations",
|
|
2676
|
+
description: "Each activity peak should be >=95% of the previous peak. If peaks are shrinking (cyclical engagement becoming flat), activity fatigue is setting in. If valleys are deepening, the off-activity economy is failing to sustain engagement.",
|
|
2592
2677
|
check(metrics, thresholds) {
|
|
2593
2678
|
const { sharkToothPeaks, sharkToothValleys } = metrics;
|
|
2594
2679
|
if (sharkToothPeaks.length < 2) return { violated: false };
|
|
@@ -2605,10 +2690,10 @@ var P51_SharkTooth = {
|
|
|
2605
2690
|
threshold: thresholds.sharkToothPeakDecay
|
|
2606
2691
|
},
|
|
2607
2692
|
suggestedAction: {
|
|
2608
|
-
|
|
2693
|
+
parameterType: "reward",
|
|
2609
2694
|
direction: "increase",
|
|
2610
2695
|
magnitude: 0.1,
|
|
2611
|
-
reasoning: `Peak engagement dropped to ${(lastPeak / prevPeak * 100).toFixed(0)}% of previous peak (threshold: ${(thresholds.sharkToothPeakDecay * 100).toFixed(0)}%).
|
|
2696
|
+
reasoning: `Peak engagement dropped to ${(lastPeak / prevPeak * 100).toFixed(0)}% of previous peak (threshold: ${(thresholds.sharkToothPeakDecay * 100).toFixed(0)}%). Activity fatigue detected. Boost activity rewards to restore peak engagement.`
|
|
2612
2697
|
},
|
|
2613
2698
|
confidence: 0.75,
|
|
2614
2699
|
estimatedLag: 30
|
|
@@ -2623,10 +2708,10 @@ var P51_SharkTooth = {
|
|
|
2623
2708
|
severity: 4,
|
|
2624
2709
|
evidence: { lastValley, prevValley, ratio: lastValley / prevValley },
|
|
2625
2710
|
suggestedAction: {
|
|
2626
|
-
|
|
2711
|
+
parameterType: "cost",
|
|
2627
2712
|
direction: "decrease",
|
|
2628
2713
|
magnitude: 0.1,
|
|
2629
|
-
reasoning: "Between-
|
|
2714
|
+
reasoning: "Between-activity engagement declining (deepening valleys). Base economy not sustaining participants between activities. Lower production costs to improve off-activity value."
|
|
2630
2715
|
},
|
|
2631
2716
|
confidence: 0.65,
|
|
2632
2717
|
estimatedLag: 20
|
|
@@ -2639,8 +2724,8 @@ var P51_SharkTooth = {
|
|
|
2639
2724
|
var P52_EndowmentEffect = {
|
|
2640
2725
|
id: "P52",
|
|
2641
2726
|
name: "Endowment Effect",
|
|
2642
|
-
category: "
|
|
2643
|
-
description: "Participants who never owned premium
|
|
2727
|
+
category: "operations",
|
|
2728
|
+
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).",
|
|
2644
2729
|
check(metrics, _thresholds) {
|
|
2645
2730
|
const { avgSatisfaction, churnRate } = metrics;
|
|
2646
2731
|
const { eventCompletionRate } = metrics;
|
|
@@ -2651,10 +2736,10 @@ var P52_EndowmentEffect = {
|
|
|
2651
2736
|
severity: 4,
|
|
2652
2737
|
evidence: { eventCompletionRate, avgSatisfaction, churnRate },
|
|
2653
2738
|
suggestedAction: {
|
|
2654
|
-
|
|
2739
|
+
parameterType: "reward",
|
|
2655
2740
|
direction: "increase",
|
|
2656
2741
|
magnitude: 0.15,
|
|
2657
|
-
reasoning: `${(eventCompletionRate * 100).toFixed(0)}%
|
|
2742
|
+
reasoning: `${(eventCompletionRate * 100).toFixed(0)}% activity completion but satisfaction only ${avgSatisfaction.toFixed(0)}. Activities not creating perceived value. Increase reward quality/quantity.`
|
|
2658
2743
|
},
|
|
2659
2744
|
confidence: 0.6,
|
|
2660
2745
|
estimatedLag: 20
|
|
@@ -2665,8 +2750,8 @@ var P52_EndowmentEffect = {
|
|
|
2665
2750
|
};
|
|
2666
2751
|
var P53_EventCompletionRate = {
|
|
2667
2752
|
id: "P53",
|
|
2668
|
-
name: "
|
|
2669
|
-
category: "
|
|
2753
|
+
name: "Activity Completion Rate Sweet Spot",
|
|
2754
|
+
category: "operations",
|
|
2670
2755
|
description: "Free completion at 60-80% is the sweet spot. <40% = predatory design. >80% = no monetization pressure. 100% free = zero reason to ever spend.",
|
|
2671
2756
|
check(metrics, thresholds) {
|
|
2672
2757
|
const { eventCompletionRate } = metrics;
|
|
@@ -2681,10 +2766,10 @@ var P53_EventCompletionRate = {
|
|
|
2681
2766
|
max: thresholds.eventCompletionMax
|
|
2682
2767
|
},
|
|
2683
2768
|
suggestedAction: {
|
|
2684
|
-
|
|
2769
|
+
parameterType: "cost",
|
|
2685
2770
|
direction: "decrease",
|
|
2686
2771
|
magnitude: 0.15,
|
|
2687
|
-
reasoning: `
|
|
2772
|
+
reasoning: `Activity completion rate ${(eventCompletionRate * 100).toFixed(0)}% \u2014 predatory territory (min: ${(thresholds.eventCompletionMin * 100).toFixed(0)}%). Too hard for free participants. Lower barriers to participation.`
|
|
2688
2773
|
},
|
|
2689
2774
|
confidence: 0.8,
|
|
2690
2775
|
estimatedLag: 10
|
|
@@ -2696,10 +2781,11 @@ var P53_EventCompletionRate = {
|
|
|
2696
2781
|
severity: 3,
|
|
2697
2782
|
evidence: { eventCompletionRate, max: thresholds.eventCompletionMax },
|
|
2698
2783
|
suggestedAction: {
|
|
2699
|
-
|
|
2784
|
+
parameterType: "fee",
|
|
2785
|
+
scope: { tags: ["entry"] },
|
|
2700
2786
|
direction: "increase",
|
|
2701
2787
|
magnitude: 0.05,
|
|
2702
|
-
reasoning: `
|
|
2788
|
+
reasoning: `Activity completion rate ${(eventCompletionRate * 100).toFixed(0)}% \u2014 no monetization pressure (max: ${(thresholds.eventCompletionMax * 100).toFixed(0)}%). Slightly raise costs to create meaningful premium differentiation.`
|
|
2703
2789
|
},
|
|
2704
2790
|
confidence: 0.55,
|
|
2705
2791
|
estimatedLag: 10
|
|
@@ -2708,11 +2794,11 @@ var P53_EventCompletionRate = {
|
|
|
2708
2794
|
return { violated: false };
|
|
2709
2795
|
}
|
|
2710
2796
|
};
|
|
2711
|
-
var
|
|
2797
|
+
var P54_OperationalCadence = {
|
|
2712
2798
|
id: "P54",
|
|
2713
|
-
name: "
|
|
2714
|
-
category: "
|
|
2715
|
-
description: ">50% of
|
|
2799
|
+
name: "Operational Cadence",
|
|
2800
|
+
category: "operations",
|
|
2801
|
+
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.",
|
|
2716
2802
|
check(metrics, _thresholds) {
|
|
2717
2803
|
const { velocity, avgSatisfaction } = metrics;
|
|
2718
2804
|
if (velocity < 2 && avgSatisfaction < 55 && metrics.tick > 100) {
|
|
@@ -2721,10 +2807,10 @@ var P54_LiveOpsCadence = {
|
|
|
2721
2807
|
severity: 3,
|
|
2722
2808
|
evidence: { velocity, avgSatisfaction, tick: metrics.tick },
|
|
2723
2809
|
suggestedAction: {
|
|
2724
|
-
|
|
2810
|
+
parameterType: "reward",
|
|
2725
2811
|
direction: "increase",
|
|
2726
2812
|
magnitude: 0.1,
|
|
2727
|
-
reasoning: "Low velocity and satisfaction after long runtime. Possible
|
|
2813
|
+
reasoning: "Low velocity and satisfaction after long runtime. Possible supply stagnation. Increase rewards as bridge while new supply is developed (developer action required)."
|
|
2728
2814
|
},
|
|
2729
2815
|
confidence: 0.4,
|
|
2730
2816
|
estimatedLag: 30
|
|
@@ -2733,11 +2819,11 @@ var P54_LiveOpsCadence = {
|
|
|
2733
2819
|
return { violated: false };
|
|
2734
2820
|
}
|
|
2735
2821
|
};
|
|
2736
|
-
var
|
|
2822
|
+
var P56_SupplyShockAbsorption = {
|
|
2737
2823
|
id: "P56",
|
|
2738
|
-
name: "
|
|
2739
|
-
category: "
|
|
2740
|
-
description: "Every new-item injection shatters existing price equilibria \u2014 arbitrage spikes as participants re-price. Build
|
|
2824
|
+
name: "Supply Shock Absorption",
|
|
2825
|
+
category: "operations",
|
|
2826
|
+
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.",
|
|
2741
2827
|
check(metrics, thresholds) {
|
|
2742
2828
|
const { contentDropAge, arbitrageIndex } = metrics;
|
|
2743
2829
|
if (contentDropAge > 0 && contentDropAge <= thresholds.contentDropCooldownTicks) {
|
|
@@ -2752,10 +2838,11 @@ var P56_ContentDropShock = {
|
|
|
2752
2838
|
postDropMax: thresholds.postDropArbitrageMax
|
|
2753
2839
|
},
|
|
2754
2840
|
suggestedAction: {
|
|
2755
|
-
|
|
2841
|
+
parameterType: "fee",
|
|
2842
|
+
scope: { tags: ["transaction"] },
|
|
2756
2843
|
direction: "decrease",
|
|
2757
2844
|
magnitude: 0.1,
|
|
2758
|
-
reasoning: `
|
|
2845
|
+
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.`
|
|
2759
2846
|
},
|
|
2760
2847
|
confidence: 0.6,
|
|
2761
2848
|
estimatedLag: 5
|
|
@@ -2765,12 +2852,12 @@ var P56_ContentDropShock = {
|
|
|
2765
2852
|
return { violated: false };
|
|
2766
2853
|
}
|
|
2767
2854
|
};
|
|
2768
|
-
var
|
|
2769
|
-
|
|
2855
|
+
var OPERATIONS_PRINCIPLES = [
|
|
2856
|
+
P51_CyclicalEngagement,
|
|
2770
2857
|
P52_EndowmentEffect,
|
|
2771
2858
|
P53_EventCompletionRate,
|
|
2772
|
-
|
|
2773
|
-
|
|
2859
|
+
P54_OperationalCadence,
|
|
2860
|
+
P56_SupplyShockAbsorption
|
|
2774
2861
|
];
|
|
2775
2862
|
|
|
2776
2863
|
// src/principles/index.ts
|
|
@@ -2799,23 +2886,24 @@ var ALL_PRINCIPLES = [
|
|
|
2799
2886
|
// P39, P44
|
|
2800
2887
|
...RESOURCE_MGMT_PRINCIPLES,
|
|
2801
2888
|
// P35, P40, P49
|
|
2802
|
-
...
|
|
2889
|
+
...PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
2803
2890
|
// P33, P36, P37, P45, P50
|
|
2804
2891
|
...OPEN_ECONOMY_PRINCIPLES,
|
|
2805
2892
|
// P34, P47-P48
|
|
2806
|
-
...
|
|
2893
|
+
...OPERATIONS_PRINCIPLES
|
|
2807
2894
|
// P51-P54, P56
|
|
2808
2895
|
];
|
|
2809
2896
|
|
|
2810
2897
|
// src/Simulator.ts
|
|
2811
2898
|
var Simulator = class {
|
|
2812
|
-
constructor() {
|
|
2899
|
+
constructor(registry) {
|
|
2813
2900
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
2814
2901
|
// Cache beforeViolations for the *current* tick only (one entry max).
|
|
2815
2902
|
// Using a Map here is intentional but the cache must be bounded — we only
|
|
2816
2903
|
// care about the tick that is currently being evaluated, so we evict any
|
|
2817
2904
|
// entries whose key differs from the incoming tick.
|
|
2818
2905
|
this.beforeViolationsCache = /* @__PURE__ */ new Map();
|
|
2906
|
+
this.registry = registry;
|
|
2819
2907
|
}
|
|
2820
2908
|
/**
|
|
2821
2909
|
* Simulate the effect of applying `action` to the current economy forward `forwardTicks`.
|
|
@@ -2882,7 +2970,7 @@ var Simulator = class {
|
|
|
2882
2970
|
const multiplier = this.actionMultiplier(action);
|
|
2883
2971
|
const noise = () => 1 + (Math.random() - 0.5) * 0.1;
|
|
2884
2972
|
const currencies = metrics.currencies;
|
|
2885
|
-
const targetCurrency = action.currency;
|
|
2973
|
+
const targetCurrency = action.scope?.currency;
|
|
2886
2974
|
const supplies = { ...metrics.totalSupplyByCurrency };
|
|
2887
2975
|
const netFlows = { ...metrics.netFlowByCurrency };
|
|
2888
2976
|
const ginis = { ...metrics.giniCoefficientByCurrency };
|
|
@@ -2924,26 +3012,54 @@ var Simulator = class {
|
|
|
2924
3012
|
return action.direction === "increase" ? 1 + base : 1 - base;
|
|
2925
3013
|
}
|
|
2926
3014
|
flowEffect(action, metrics, currency) {
|
|
2927
|
-
const {
|
|
3015
|
+
const { direction } = action;
|
|
2928
3016
|
const sign = direction === "increase" ? -1 : 1;
|
|
2929
3017
|
const roleEntries = Object.entries(metrics.populationByRole).sort((a, b) => b[1] - a[1]);
|
|
2930
3018
|
const dominantRoleCount = roleEntries[0]?.[1] ?? 0;
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
if (parameter === "entryFee") {
|
|
2938
|
-
return sign * dominantRoleCount * 0.5;
|
|
2939
|
-
}
|
|
2940
|
-
if (parameter === "rewardRate") {
|
|
2941
|
-
return -sign * dominantRoleCount * 0.3;
|
|
3019
|
+
let impact;
|
|
3020
|
+
if (this.registry) {
|
|
3021
|
+
const resolved = this.registry.resolve(action.parameterType, action.scope);
|
|
3022
|
+
if (resolved) {
|
|
3023
|
+
impact = resolved.flowImpact;
|
|
3024
|
+
}
|
|
2942
3025
|
}
|
|
2943
|
-
if (
|
|
2944
|
-
|
|
3026
|
+
if (!impact) {
|
|
3027
|
+
impact = this.inferFlowImpact(action.parameterType);
|
|
3028
|
+
}
|
|
3029
|
+
switch (impact) {
|
|
3030
|
+
case "sink":
|
|
3031
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.2;
|
|
3032
|
+
case "faucet":
|
|
3033
|
+
return -sign * dominantRoleCount * 0.3;
|
|
3034
|
+
case "neutral":
|
|
3035
|
+
return sign * dominantRoleCount * 0.5;
|
|
3036
|
+
case "mixed":
|
|
3037
|
+
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * 0.15;
|
|
3038
|
+
case "friction":
|
|
3039
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
3040
|
+
case "redistribution":
|
|
3041
|
+
return sign * dominantRoleCount * 0.05;
|
|
3042
|
+
default:
|
|
3043
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
/** Infer flow impact from parameter type when registry is unavailable */
|
|
3047
|
+
inferFlowImpact(parameterType) {
|
|
3048
|
+
switch (parameterType) {
|
|
3049
|
+
case "cost":
|
|
3050
|
+
case "fee":
|
|
3051
|
+
case "penalty":
|
|
3052
|
+
return "sink";
|
|
3053
|
+
case "reward":
|
|
3054
|
+
return "faucet";
|
|
3055
|
+
case "yield":
|
|
3056
|
+
return "mixed";
|
|
3057
|
+
case "cap":
|
|
3058
|
+
case "multiplier":
|
|
3059
|
+
return "neutral";
|
|
3060
|
+
default:
|
|
3061
|
+
return "mixed";
|
|
2945
3062
|
}
|
|
2946
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
2947
3063
|
}
|
|
2948
3064
|
checkImprovement(before, after, action) {
|
|
2949
3065
|
const satisfactionImproved = after.avgSatisfaction >= before.avgSatisfaction - 2;
|
|
@@ -3005,6 +3121,8 @@ var Planner = class {
|
|
|
3005
3121
|
this.constraints = /* @__PURE__ */ new Map();
|
|
3006
3122
|
this.cooldowns = /* @__PURE__ */ new Map();
|
|
3007
3123
|
// param → last-applied-tick
|
|
3124
|
+
this.typeCooldowns = /* @__PURE__ */ new Map();
|
|
3125
|
+
// type+scope key → last-applied-tick
|
|
3008
3126
|
this.activePlanCount = 0;
|
|
3009
3127
|
}
|
|
3010
3128
|
lock(param) {
|
|
@@ -3023,16 +3141,32 @@ var Planner = class {
|
|
|
3023
3141
|
* - parameter is still in cooldown
|
|
3024
3142
|
* - simulation result failed
|
|
3025
3143
|
* - complexity budget exceeded
|
|
3144
|
+
* - no matching parameter in registry
|
|
3026
3145
|
*/
|
|
3027
|
-
plan(diagnosis, metrics, simulationResult, currentParams, thresholds) {
|
|
3146
|
+
plan(diagnosis, metrics, simulationResult, currentParams, thresholds, registry) {
|
|
3028
3147
|
const action = diagnosis.violation.suggestedAction;
|
|
3029
|
-
const
|
|
3148
|
+
const typeKey = this.typeCooldownKey(action.parameterType, action.scope);
|
|
3149
|
+
if (this.isTypeCooldown(typeKey, metrics.tick, thresholds.cooldownTicks)) return null;
|
|
3150
|
+
let param;
|
|
3151
|
+
let resolvedBaseline;
|
|
3152
|
+
let scope;
|
|
3153
|
+
if (registry) {
|
|
3154
|
+
const resolved = registry.resolve(action.parameterType, action.scope);
|
|
3155
|
+
if (!resolved) return null;
|
|
3156
|
+
param = resolved.key;
|
|
3157
|
+
resolvedBaseline = resolved.currentValue;
|
|
3158
|
+
scope = resolved.scope;
|
|
3159
|
+
action.resolvedParameter = param;
|
|
3160
|
+
} else {
|
|
3161
|
+
param = action.resolvedParameter ?? action.parameterType;
|
|
3162
|
+
scope = action.scope;
|
|
3163
|
+
}
|
|
3030
3164
|
if (this.lockedParams.has(param)) return null;
|
|
3031
3165
|
if (this.isOnCooldown(param, metrics.tick, thresholds.cooldownTicks)) return null;
|
|
3032
3166
|
if (!simulationResult.netImprovement) return null;
|
|
3033
3167
|
if (!simulationResult.noNewProblems) return null;
|
|
3034
3168
|
if (this.activePlanCount >= thresholds.complexityBudgetMax) return null;
|
|
3035
|
-
const currentValue = currentParams[param] ?? 1;
|
|
3169
|
+
const currentValue = resolvedBaseline ?? currentParams[param] ?? action.absoluteValue ?? 1;
|
|
3036
3170
|
const magnitude = Math.min(action.magnitude ?? 0.1, thresholds.maxAdjustmentPercent);
|
|
3037
3171
|
let targetValue;
|
|
3038
3172
|
if (action.direction === "set" && action.absoluteValue !== void 0) {
|
|
@@ -3052,7 +3186,7 @@ var Planner = class {
|
|
|
3052
3186
|
id: `plan_${metrics.tick}_${param}`,
|
|
3053
3187
|
diagnosis,
|
|
3054
3188
|
parameter: param,
|
|
3055
|
-
...
|
|
3189
|
+
...scope !== void 0 ? { scope } : {},
|
|
3056
3190
|
currentValue,
|
|
3057
3191
|
targetValue,
|
|
3058
3192
|
maxChangePercent: thresholds.maxAdjustmentPercent,
|
|
@@ -3061,7 +3195,6 @@ var Planner = class {
|
|
|
3061
3195
|
metric: "avgSatisfaction",
|
|
3062
3196
|
direction: "below",
|
|
3063
3197
|
threshold: Math.max(20, metrics.avgSatisfaction - 10),
|
|
3064
|
-
// rollback if sat drops >10 pts
|
|
3065
3198
|
checkAfterTick: metrics.tick + estimatedLag + 3
|
|
3066
3199
|
},
|
|
3067
3200
|
simulationResult,
|
|
@@ -3071,11 +3204,17 @@ var Planner = class {
|
|
|
3071
3204
|
}
|
|
3072
3205
|
recordApplied(plan, tick) {
|
|
3073
3206
|
this.cooldowns.set(plan.parameter, tick);
|
|
3207
|
+
const action = plan.diagnosis.violation.suggestedAction;
|
|
3208
|
+
const typeKey = this.typeCooldownKey(action.parameterType, action.scope);
|
|
3209
|
+
this.typeCooldowns.set(typeKey, tick);
|
|
3074
3210
|
this.activePlanCount++;
|
|
3075
3211
|
}
|
|
3076
3212
|
recordRolledBack(_plan) {
|
|
3077
3213
|
this.activePlanCount = Math.max(0, this.activePlanCount - 1);
|
|
3078
3214
|
}
|
|
3215
|
+
recordSettled(_plan) {
|
|
3216
|
+
this.activePlanCount = Math.max(0, this.activePlanCount - 1);
|
|
3217
|
+
}
|
|
3079
3218
|
isOnCooldown(param, currentTick, cooldownTicks) {
|
|
3080
3219
|
const lastApplied = this.cooldowns.get(param);
|
|
3081
3220
|
if (lastApplied === void 0) return false;
|
|
@@ -3084,6 +3223,19 @@ var Planner = class {
|
|
|
3084
3223
|
/** Reset all cooldowns (useful for testing) */
|
|
3085
3224
|
resetCooldowns() {
|
|
3086
3225
|
this.cooldowns.clear();
|
|
3226
|
+
this.typeCooldowns.clear();
|
|
3227
|
+
}
|
|
3228
|
+
typeCooldownKey(type, scope) {
|
|
3229
|
+
const parts = [type];
|
|
3230
|
+
if (scope?.system) parts.push(`sys:${scope.system}`);
|
|
3231
|
+
if (scope?.currency) parts.push(`cur:${scope.currency}`);
|
|
3232
|
+
if (scope?.tags?.length) parts.push(`tags:${scope.tags.sort().join(",")}`);
|
|
3233
|
+
return parts.join("|");
|
|
3234
|
+
}
|
|
3235
|
+
isTypeCooldown(typeKey, currentTick, cooldownTicks) {
|
|
3236
|
+
const lastApplied = this.typeCooldowns.get(typeKey);
|
|
3237
|
+
if (lastApplied === void 0) return false;
|
|
3238
|
+
return currentTick - lastApplied < cooldownTicks;
|
|
3087
3239
|
}
|
|
3088
3240
|
};
|
|
3089
3241
|
|
|
@@ -3094,40 +3246,54 @@ var Executor = class {
|
|
|
3094
3246
|
}
|
|
3095
3247
|
async apply(plan, adapter, currentParams) {
|
|
3096
3248
|
const originalValue = currentParams[plan.parameter] ?? plan.currentValue;
|
|
3097
|
-
await adapter.setParam(plan.parameter, plan.targetValue, plan.
|
|
3249
|
+
await adapter.setParam(plan.parameter, plan.targetValue, plan.scope);
|
|
3098
3250
|
plan.appliedAt = plan.diagnosis.tick;
|
|
3099
3251
|
this.activePlans.push({ plan, originalValue });
|
|
3100
3252
|
}
|
|
3101
3253
|
/**
|
|
3102
3254
|
* Check all active plans for rollback conditions.
|
|
3103
|
-
*
|
|
3104
|
-
* Returns list of plans that were rolled back.
|
|
3255
|
+
* Returns { rolledBack, settled } — plans that were undone and plans that passed their window.
|
|
3105
3256
|
*/
|
|
3106
3257
|
async checkRollbacks(metrics, adapter) {
|
|
3107
3258
|
const rolledBack = [];
|
|
3259
|
+
const settled = [];
|
|
3108
3260
|
const remaining = [];
|
|
3109
3261
|
for (const active of this.activePlans) {
|
|
3110
3262
|
const { plan, originalValue } = active;
|
|
3111
3263
|
const rc = plan.rollbackCondition;
|
|
3264
|
+
const maxActiveTicks = 200;
|
|
3265
|
+
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > maxActiveTicks) {
|
|
3266
|
+
settled.push(plan);
|
|
3267
|
+
continue;
|
|
3268
|
+
}
|
|
3112
3269
|
if (metrics.tick < rc.checkAfterTick) {
|
|
3113
3270
|
remaining.push(active);
|
|
3114
3271
|
continue;
|
|
3115
3272
|
}
|
|
3116
3273
|
const metricValue = this.getMetricValue(metrics, rc.metric);
|
|
3274
|
+
if (Number.isNaN(metricValue)) {
|
|
3275
|
+
console.warn(
|
|
3276
|
+
`[AgentE] Rollback check: metric path '${rc.metric}' resolved to NaN for plan '${plan.id}'. Triggering rollback as fail-safe.`
|
|
3277
|
+
);
|
|
3278
|
+
await adapter.setParam(plan.parameter, originalValue, plan.scope);
|
|
3279
|
+
rolledBack.push(plan);
|
|
3280
|
+
continue;
|
|
3281
|
+
}
|
|
3117
3282
|
const shouldRollback = rc.direction === "below" ? metricValue < rc.threshold : metricValue > rc.threshold;
|
|
3118
3283
|
if (shouldRollback) {
|
|
3119
|
-
await adapter.setParam(plan.parameter, originalValue, plan.
|
|
3284
|
+
await adapter.setParam(plan.parameter, originalValue, plan.scope);
|
|
3120
3285
|
rolledBack.push(plan);
|
|
3121
3286
|
} else {
|
|
3122
3287
|
const settledTick = rc.checkAfterTick + 10;
|
|
3123
3288
|
if (metrics.tick > settledTick) {
|
|
3289
|
+
settled.push(plan);
|
|
3124
3290
|
} else {
|
|
3125
3291
|
remaining.push(active);
|
|
3126
3292
|
}
|
|
3127
3293
|
}
|
|
3128
3294
|
}
|
|
3129
3295
|
this.activePlans = remaining;
|
|
3130
|
-
return rolledBack;
|
|
3296
|
+
return { rolledBack, settled };
|
|
3131
3297
|
}
|
|
3132
3298
|
getMetricValue(metrics, metricPath) {
|
|
3133
3299
|
const parts = metricPath.split(".");
|
|
@@ -3216,7 +3382,8 @@ var DecisionLog = class {
|
|
|
3216
3382
|
return {
|
|
3217
3383
|
id: `stub_${metrics.tick}`,
|
|
3218
3384
|
diagnosis,
|
|
3219
|
-
parameter: action.
|
|
3385
|
+
parameter: action.resolvedParameter ?? action.parameterType,
|
|
3386
|
+
...action.scope !== void 0 ? { scope: action.scope } : {},
|
|
3220
3387
|
currentValue: 1,
|
|
3221
3388
|
targetValue: 1,
|
|
3222
3389
|
maxChangePercent: 0,
|
|
@@ -3454,13 +3621,13 @@ var PersonaTracker = class {
|
|
|
3454
3621
|
Earner: 0,
|
|
3455
3622
|
Builder: 0,
|
|
3456
3623
|
Social: 0,
|
|
3457
|
-
|
|
3624
|
+
HighValue: 0,
|
|
3458
3625
|
Influencer: 0
|
|
3459
3626
|
};
|
|
3460
3627
|
let total = 0;
|
|
3461
3628
|
for (const [, history] of this.agentHistory) {
|
|
3462
3629
|
const persona = this.classify(history);
|
|
3463
|
-
counts[persona]
|
|
3630
|
+
counts[persona] = (counts[persona] ?? 0) + 1;
|
|
3464
3631
|
total++;
|
|
3465
3632
|
}
|
|
3466
3633
|
if (total === 0) return {};
|
|
@@ -3480,7 +3647,7 @@ var PersonaTracker = class {
|
|
|
3480
3647
|
const extraction = avg("netExtraction");
|
|
3481
3648
|
const uniqueItems = avg("uniqueItemsHeld");
|
|
3482
3649
|
const spend = avg("spendAmount");
|
|
3483
|
-
if (spend > 1e3) return "
|
|
3650
|
+
if (spend > 1e3) return "HighValue";
|
|
3484
3651
|
if (txRate > 10) return "Trader";
|
|
3485
3652
|
if (uniqueItems > 5 && extraction < 0) return "Collector";
|
|
3486
3653
|
if (extraction > 100) return "Earner";
|
|
@@ -3489,12 +3656,153 @@ var PersonaTracker = class {
|
|
|
3489
3656
|
}
|
|
3490
3657
|
};
|
|
3491
3658
|
|
|
3659
|
+
// src/ParameterRegistry.ts
|
|
3660
|
+
var ParameterRegistry = class {
|
|
3661
|
+
constructor() {
|
|
3662
|
+
this.parameters = /* @__PURE__ */ new Map();
|
|
3663
|
+
}
|
|
3664
|
+
/** Register a parameter. Overwrites if key already exists. */
|
|
3665
|
+
register(param) {
|
|
3666
|
+
this.parameters.set(param.key, { ...param });
|
|
3667
|
+
}
|
|
3668
|
+
/** Register multiple parameters at once. */
|
|
3669
|
+
registerAll(params) {
|
|
3670
|
+
for (const p of params) this.register(p);
|
|
3671
|
+
}
|
|
3672
|
+
/**
|
|
3673
|
+
* Resolve a parameterType + scope to a concrete RegisteredParameter.
|
|
3674
|
+
* Returns the best match, or undefined if no match.
|
|
3675
|
+
*
|
|
3676
|
+
* Matching rules:
|
|
3677
|
+
* 1. Filter candidates by type
|
|
3678
|
+
* 2. Score each by scope specificity (system +10, currency +5, tags +3 each)
|
|
3679
|
+
* 3. Mismatched scope fields disqualify (score = -Infinity)
|
|
3680
|
+
* 4. Ties broken by `priority` (higher wins), then registration order
|
|
3681
|
+
* 5. All disqualified → undefined
|
|
3682
|
+
*/
|
|
3683
|
+
resolve(type, scope) {
|
|
3684
|
+
const candidates = this.findByType(type);
|
|
3685
|
+
if (candidates.length === 0) return void 0;
|
|
3686
|
+
if (candidates.length === 1) return candidates[0];
|
|
3687
|
+
let bestScore = -Infinity;
|
|
3688
|
+
let bestPriority = -Infinity;
|
|
3689
|
+
let best;
|
|
3690
|
+
for (const candidate of candidates) {
|
|
3691
|
+
const score = this.scopeSpecificity(candidate.scope, scope);
|
|
3692
|
+
const prio = candidate.priority ?? 0;
|
|
3693
|
+
if (score > bestScore || score === bestScore && prio > bestPriority) {
|
|
3694
|
+
bestScore = score;
|
|
3695
|
+
bestPriority = prio;
|
|
3696
|
+
best = candidate;
|
|
3697
|
+
}
|
|
3698
|
+
}
|
|
3699
|
+
if (bestScore === -Infinity) return void 0;
|
|
3700
|
+
return best;
|
|
3701
|
+
}
|
|
3702
|
+
/** Find all parameters of a given type. */
|
|
3703
|
+
findByType(type) {
|
|
3704
|
+
const results = [];
|
|
3705
|
+
for (const param of this.parameters.values()) {
|
|
3706
|
+
if (param.type === type) results.push(param);
|
|
3707
|
+
}
|
|
3708
|
+
return results;
|
|
3709
|
+
}
|
|
3710
|
+
/** Find all parameters belonging to a given system. */
|
|
3711
|
+
findBySystem(system) {
|
|
3712
|
+
const results = [];
|
|
3713
|
+
for (const param of this.parameters.values()) {
|
|
3714
|
+
if (param.scope?.system === system) results.push(param);
|
|
3715
|
+
}
|
|
3716
|
+
return results;
|
|
3717
|
+
}
|
|
3718
|
+
/** Get a parameter by its concrete key. */
|
|
3719
|
+
get(key) {
|
|
3720
|
+
return this.parameters.get(key);
|
|
3721
|
+
}
|
|
3722
|
+
/** Get the flow impact of a parameter by its concrete key. */
|
|
3723
|
+
getFlowImpact(key) {
|
|
3724
|
+
return this.parameters.get(key)?.flowImpact;
|
|
3725
|
+
}
|
|
3726
|
+
/** Update the current value of a registered parameter. */
|
|
3727
|
+
updateValue(key, value) {
|
|
3728
|
+
const param = this.parameters.get(key);
|
|
3729
|
+
if (param) {
|
|
3730
|
+
param.currentValue = value;
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
/** Get all registered parameters. */
|
|
3734
|
+
getAll() {
|
|
3735
|
+
return [...this.parameters.values()];
|
|
3736
|
+
}
|
|
3737
|
+
/** Number of registered parameters. */
|
|
3738
|
+
get size() {
|
|
3739
|
+
return this.parameters.size;
|
|
3740
|
+
}
|
|
3741
|
+
/**
|
|
3742
|
+
* Validate the registry for common misconfigurations.
|
|
3743
|
+
* Returns warnings (non-fatal) and errors (likely broken).
|
|
3744
|
+
*/
|
|
3745
|
+
validate() {
|
|
3746
|
+
const warnings = [];
|
|
3747
|
+
const errors = [];
|
|
3748
|
+
const typeMap = /* @__PURE__ */ new Map();
|
|
3749
|
+
for (const param of this.parameters.values()) {
|
|
3750
|
+
const list = typeMap.get(param.type) ?? [];
|
|
3751
|
+
list.push(param);
|
|
3752
|
+
typeMap.set(param.type, list);
|
|
3753
|
+
}
|
|
3754
|
+
for (const [type, params] of typeMap) {
|
|
3755
|
+
if (params.length > 1) {
|
|
3756
|
+
const unscopedCount = params.filter((p) => !p.scope).length;
|
|
3757
|
+
if (unscopedCount > 1) {
|
|
3758
|
+
errors.push(
|
|
3759
|
+
`Type '${type}' has ${unscopedCount} unscoped parameters \u2014 resolve() cannot distinguish them`
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
for (const param of this.parameters.values()) {
|
|
3765
|
+
if (!param.flowImpact) {
|
|
3766
|
+
warnings.push(`Parameter '${param.key}' has no flowImpact \u2014 Simulator will use inference`);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
return {
|
|
3770
|
+
valid: errors.length === 0,
|
|
3771
|
+
warnings,
|
|
3772
|
+
errors
|
|
3773
|
+
};
|
|
3774
|
+
}
|
|
3775
|
+
// ── Private ─────────────────────────────────────────────────────────────
|
|
3776
|
+
scopeSpecificity(paramScope, queryScope) {
|
|
3777
|
+
if (!queryScope) return 0;
|
|
3778
|
+
if (!paramScope) return 0;
|
|
3779
|
+
let score = 0;
|
|
3780
|
+
if (queryScope.system && paramScope.system) {
|
|
3781
|
+
if (queryScope.system === paramScope.system) score += 10;
|
|
3782
|
+
else return -Infinity;
|
|
3783
|
+
}
|
|
3784
|
+
if (queryScope.currency && paramScope.currency) {
|
|
3785
|
+
if (queryScope.currency === paramScope.currency) score += 5;
|
|
3786
|
+
else return -Infinity;
|
|
3787
|
+
}
|
|
3788
|
+
if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3789
|
+
const overlap = queryScope.tags.filter((t) => paramScope.tags.includes(t)).length;
|
|
3790
|
+
if (overlap > 0) {
|
|
3791
|
+
score += overlap * 3;
|
|
3792
|
+
} else {
|
|
3793
|
+
return -Infinity;
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
return score;
|
|
3797
|
+
}
|
|
3798
|
+
};
|
|
3799
|
+
|
|
3492
3800
|
// src/AgentE.ts
|
|
3493
3801
|
var AgentE = class {
|
|
3494
3802
|
constructor(config) {
|
|
3495
|
-
this.simulator = new Simulator();
|
|
3496
3803
|
this.planner = new Planner();
|
|
3497
3804
|
this.executor = new Executor();
|
|
3805
|
+
this.registry = new ParameterRegistry();
|
|
3498
3806
|
// ── State ──
|
|
3499
3807
|
this.log = new DecisionLog();
|
|
3500
3808
|
this.personaTracker = new PersonaTracker();
|
|
@@ -3515,11 +3823,13 @@ var AgentE = class {
|
|
|
3515
3823
|
mode: this.mode,
|
|
3516
3824
|
dominantRoles: config.dominantRoles ?? [],
|
|
3517
3825
|
idealDistribution: config.idealDistribution ?? {},
|
|
3826
|
+
validateRegistry: config.validateRegistry ?? true,
|
|
3518
3827
|
tickConfig: config.tickConfig ?? { duration: 1, unit: "tick" },
|
|
3519
3828
|
gracePeriod: config.gracePeriod ?? 50,
|
|
3520
3829
|
checkInterval: config.checkInterval ?? 5,
|
|
3521
3830
|
maxAdjustmentPercent: config.maxAdjustmentPercent ?? 0.15,
|
|
3522
|
-
cooldownTicks: config.cooldownTicks ?? 15
|
|
3831
|
+
cooldownTicks: config.cooldownTicks ?? 15,
|
|
3832
|
+
parameters: config.parameters ?? []
|
|
3523
3833
|
};
|
|
3524
3834
|
this.thresholds = {
|
|
3525
3835
|
...DEFAULT_THRESHOLDS,
|
|
@@ -3531,6 +3841,15 @@ var AgentE = class {
|
|
|
3531
3841
|
this.observer = new Observer(tickConfig);
|
|
3532
3842
|
this.store = new MetricStore(tickConfig);
|
|
3533
3843
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
3844
|
+
if (config.parameters) {
|
|
3845
|
+
this.registry.registerAll(config.parameters);
|
|
3846
|
+
}
|
|
3847
|
+
if (config.validateRegistry !== false && this.registry.size > 0) {
|
|
3848
|
+
const validation = this.registry.validate();
|
|
3849
|
+
for (const w of validation.warnings) console.warn(`[AgentE] Registry warning: ${w}`);
|
|
3850
|
+
for (const e of validation.errors) console.error(`[AgentE] Registry error: ${e}`);
|
|
3851
|
+
}
|
|
3852
|
+
this.simulator = new Simulator(this.registry);
|
|
3534
3853
|
if (config.onDecision) this.on("decision", config.onDecision);
|
|
3535
3854
|
if (config.onAlert) this.on("alert", config.onAlert);
|
|
3536
3855
|
if (config.onRollback) this.on("rollback", config.onRollback);
|
|
@@ -3568,15 +3887,24 @@ var AgentE = class {
|
|
|
3568
3887
|
this.currentTick = currentState.tick;
|
|
3569
3888
|
const events = [...this.eventBuffer];
|
|
3570
3889
|
this.eventBuffer = [];
|
|
3571
|
-
|
|
3890
|
+
let metrics;
|
|
3891
|
+
try {
|
|
3892
|
+
metrics = this.observer.compute(currentState, events);
|
|
3893
|
+
} catch (err) {
|
|
3894
|
+
console.error(`[AgentE] Observer.compute() failed at tick ${currentState.tick}:`, err);
|
|
3895
|
+
return;
|
|
3896
|
+
}
|
|
3572
3897
|
this.store.record(metrics);
|
|
3573
3898
|
this.personaTracker.update(currentState);
|
|
3574
3899
|
metrics.personaDistribution = this.personaTracker.getDistribution();
|
|
3575
|
-
const rolledBack = await this.executor.checkRollbacks(metrics, this.adapter);
|
|
3900
|
+
const { rolledBack, settled } = await this.executor.checkRollbacks(metrics, this.adapter);
|
|
3576
3901
|
for (const plan2 of rolledBack) {
|
|
3577
3902
|
this.planner.recordRolledBack(plan2);
|
|
3578
3903
|
this.emit("rollback", plan2, "rollback condition triggered");
|
|
3579
3904
|
}
|
|
3905
|
+
for (const plan2 of settled) {
|
|
3906
|
+
this.planner.recordSettled(plan2);
|
|
3907
|
+
}
|
|
3580
3908
|
if (metrics.tick < this.config.gracePeriod) return;
|
|
3581
3909
|
if (metrics.tick % this.config.checkInterval !== 0) return;
|
|
3582
3910
|
const diagnoses = this.diagnoser.diagnose(metrics, this.thresholds);
|
|
@@ -3598,7 +3926,8 @@ var AgentE = class {
|
|
|
3598
3926
|
metrics,
|
|
3599
3927
|
simulationResult,
|
|
3600
3928
|
this.params,
|
|
3601
|
-
this.thresholds
|
|
3929
|
+
this.thresholds,
|
|
3930
|
+
this.registry
|
|
3602
3931
|
);
|
|
3603
3932
|
if (!plan) {
|
|
3604
3933
|
let reason = "skipped_cooldown";
|
|
@@ -3618,6 +3947,7 @@ var AgentE = class {
|
|
|
3618
3947
|
}
|
|
3619
3948
|
await this.executor.apply(plan, this.adapter, this.params);
|
|
3620
3949
|
this.params[plan.parameter] = plan.targetValue;
|
|
3950
|
+
this.registry.updateValue(plan.parameter, plan.targetValue);
|
|
3621
3951
|
this.planner.recordApplied(plan, metrics.tick);
|
|
3622
3952
|
const entry = this.log.record(topDiagnosis, plan, "applied", metrics);
|
|
3623
3953
|
this.emit("decision", entry);
|
|
@@ -3627,6 +3957,7 @@ var AgentE = class {
|
|
|
3627
3957
|
async apply(plan) {
|
|
3628
3958
|
await this.executor.apply(plan, this.adapter, this.params);
|
|
3629
3959
|
this.params[plan.parameter] = plan.targetValue;
|
|
3960
|
+
this.registry.updateValue(plan.parameter, plan.targetValue);
|
|
3630
3961
|
this.planner.recordApplied(plan, this.currentTick);
|
|
3631
3962
|
}
|
|
3632
3963
|
// ── Developer API ───────────────────────────────────────────────────────────
|
|
@@ -3651,6 +3982,12 @@ var AgentE = class {
|
|
|
3651
3982
|
removePrinciple(id) {
|
|
3652
3983
|
this.diagnoser.removePrinciple(id);
|
|
3653
3984
|
}
|
|
3985
|
+
registerParameter(param) {
|
|
3986
|
+
this.registry.register(param);
|
|
3987
|
+
}
|
|
3988
|
+
getRegistry() {
|
|
3989
|
+
return this.registry;
|
|
3990
|
+
}
|
|
3654
3991
|
registerCustomMetric(name, fn) {
|
|
3655
3992
|
this.observer.registerCustomMetric(name, fn);
|
|
3656
3993
|
}
|
|
@@ -3708,6 +4045,31 @@ var AgentE = class {
|
|
|
3708
4045
|
}
|
|
3709
4046
|
};
|
|
3710
4047
|
|
|
4048
|
+
// src/utils.ts
|
|
4049
|
+
function findWorstSystem(metrics, check, tolerancePercent = 0) {
|
|
4050
|
+
const systems = metrics.systems;
|
|
4051
|
+
if (systems.length === 0) return void 0;
|
|
4052
|
+
let worstSystem;
|
|
4053
|
+
let worstScore = -Infinity;
|
|
4054
|
+
let totalScore = 0;
|
|
4055
|
+
for (const sys of systems) {
|
|
4056
|
+
const score = check(sys, metrics);
|
|
4057
|
+
totalScore += score;
|
|
4058
|
+
if (score > worstScore) {
|
|
4059
|
+
worstScore = score;
|
|
4060
|
+
worstSystem = sys;
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
if (!worstSystem) return void 0;
|
|
4064
|
+
if (tolerancePercent > 0 && systems.length > 1) {
|
|
4065
|
+
const avg = totalScore / systems.length;
|
|
4066
|
+
if (avg === 0) return { system: worstSystem, score: worstScore };
|
|
4067
|
+
const excessPercent = (worstScore - avg) / Math.abs(avg) * 100;
|
|
4068
|
+
if (excessPercent < tolerancePercent) return void 0;
|
|
4069
|
+
}
|
|
4070
|
+
return { system: worstSystem, score: worstScore };
|
|
4071
|
+
}
|
|
4072
|
+
|
|
3711
4073
|
// src/StateValidator.ts
|
|
3712
4074
|
function validateEconomyState(state) {
|
|
3713
4075
|
const errors = [];
|
|
@@ -4053,13 +4415,13 @@ function describeValue(value) {
|
|
|
4053
4415
|
Executor,
|
|
4054
4416
|
FEEDBACK_LOOP_PRINCIPLES,
|
|
4055
4417
|
INCENTIVE_PRINCIPLES,
|
|
4056
|
-
LIVEOPS_PRINCIPLES,
|
|
4057
4418
|
MARKET_DYNAMICS_PRINCIPLES,
|
|
4058
4419
|
MEASUREMENT_PRINCIPLES,
|
|
4059
4420
|
MetricStore,
|
|
4060
4421
|
OPEN_ECONOMY_PRINCIPLES,
|
|
4422
|
+
OPERATIONS_PRINCIPLES,
|
|
4061
4423
|
Observer,
|
|
4062
|
-
|
|
4424
|
+
P10_EntryWeightingUsesInversePopulation,
|
|
4063
4425
|
P11_TwoTierPressure,
|
|
4064
4426
|
P12_OnePrimaryFaucet,
|
|
4065
4427
|
P13_PotsAreZeroSumAndSelfRegulate,
|
|
@@ -4079,9 +4441,9 @@ function describeValue(value) {
|
|
|
4079
4441
|
P26_ContinuousPressureBeatsThresholdCuts,
|
|
4080
4442
|
P27_AdjustmentsNeedCooldowns,
|
|
4081
4443
|
P28_StructuralDominanceIsNotPathological,
|
|
4082
|
-
|
|
4444
|
+
P29_BottleneckDetection,
|
|
4083
4445
|
P2_ClosedLoopsNeedDirectHandoff,
|
|
4084
|
-
|
|
4446
|
+
P30_DynamicBottleneckRotation,
|
|
4085
4447
|
P31_AnchorValueTracking,
|
|
4086
4448
|
P32_VelocityAboveSupply,
|
|
4087
4449
|
P33_FairNotEqual,
|
|
@@ -4104,12 +4466,12 @@ function describeValue(value) {
|
|
|
4104
4466
|
P49_IdleAssetTax,
|
|
4105
4467
|
P4_MaterialsFlowFasterThanCooldown,
|
|
4106
4468
|
P50_PayPowerRatio,
|
|
4107
|
-
|
|
4469
|
+
P51_CyclicalEngagement,
|
|
4108
4470
|
P52_EndowmentEffect,
|
|
4109
4471
|
P53_EventCompletionRate,
|
|
4110
|
-
|
|
4472
|
+
P54_OperationalCadence,
|
|
4111
4473
|
P55_ArbitrageThermometer,
|
|
4112
|
-
|
|
4474
|
+
P56_SupplyShockAbsorption,
|
|
4113
4475
|
P57_CombinatorialPriceSpace,
|
|
4114
4476
|
P58_NoNaturalNumeraire,
|
|
4115
4477
|
P59_GiftEconomyNoise,
|
|
@@ -4119,9 +4481,10 @@ function describeValue(value) {
|
|
|
4119
4481
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
4120
4482
|
P8_RegulatorCannotFightDesign,
|
|
4121
4483
|
P9_RoleSwitchingNeedsFriction,
|
|
4484
|
+
PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
4122
4485
|
PERSONA_HEALTHY_RANGES,
|
|
4123
|
-
PLAYER_EXPERIENCE_PRINCIPLES,
|
|
4124
4486
|
POPULATION_PRINCIPLES,
|
|
4487
|
+
ParameterRegistry,
|
|
4125
4488
|
PersonaTracker,
|
|
4126
4489
|
Planner,
|
|
4127
4490
|
REGULATOR_PRINCIPLES,
|
|
@@ -4131,6 +4494,7 @@ function describeValue(value) {
|
|
|
4131
4494
|
SYSTEM_DYNAMICS_PRINCIPLES,
|
|
4132
4495
|
Simulator,
|
|
4133
4496
|
emptyMetrics,
|
|
4497
|
+
findWorstSystem,
|
|
4134
4498
|
validateEconomyState
|
|
4135
4499
|
});
|
|
4136
4500
|
//# sourceMappingURL=index.js.map
|