@agent-e/core 1.4.0 → 1.5.0
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 +99 -15
- package/dist/index.d.ts +99 -15
- package/dist/index.js +435 -173
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +432 -171
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,11 +30,11 @@ __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_SpawnWeightingUsesInversePopulation: () => P10_SpawnWeightingUsesInversePopulation,
|
|
40
40
|
P11_TwoTierPressure: () => P11_TwoTierPressure,
|
|
@@ -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,
|
|
@@ -126,11 +127,11 @@ var DEFAULT_THRESHOLDS = {
|
|
|
126
127
|
smokeTestWarning: 0.3,
|
|
127
128
|
smokeTestCritical: 0.1,
|
|
128
129
|
currencyInsulationMax: 0.5,
|
|
129
|
-
//
|
|
130
|
+
// Participant Experience (P45, P50)
|
|
130
131
|
timeBudgetRatio: 0.8,
|
|
131
132
|
payPowerRatioMax: 2,
|
|
132
133
|
payPowerRatioTarget: 1.5,
|
|
133
|
-
//
|
|
134
|
+
// Operations (P51, P53)
|
|
134
135
|
sharkToothPeakDecay: 0.95,
|
|
135
136
|
sharkToothValleyDecay: 0.9,
|
|
136
137
|
eventCompletionMin: 0.4,
|
|
@@ -184,7 +185,7 @@ var PERSONA_HEALTHY_RANGES = {
|
|
|
184
185
|
Earner: { min: 0, max: 0.15 },
|
|
185
186
|
Builder: { min: 0.05, max: 0.15 },
|
|
186
187
|
Social: { min: 0.1, max: 0.2 },
|
|
187
|
-
|
|
188
|
+
HighValue: { min: 0, max: 0.05 },
|
|
188
189
|
Influencer: { min: 0, max: 0.05 }
|
|
189
190
|
};
|
|
190
191
|
var DEFAULT_TICK_CONFIG = {
|
|
@@ -221,7 +222,7 @@ var Observer = class {
|
|
|
221
222
|
const curr = e.currency ?? defaultCurrency;
|
|
222
223
|
switch (e.type) {
|
|
223
224
|
case "mint":
|
|
224
|
-
case "
|
|
225
|
+
case "enter":
|
|
225
226
|
faucetVolumeByCurrency[curr] = (faucetVolumeByCurrency[curr] ?? 0) + (e.amount ?? 0);
|
|
226
227
|
break;
|
|
227
228
|
case "burn":
|
|
@@ -243,6 +244,46 @@ var Observer = class {
|
|
|
243
244
|
break;
|
|
244
245
|
}
|
|
245
246
|
}
|
|
247
|
+
const flowBySystem = {};
|
|
248
|
+
const activityBySystem = {};
|
|
249
|
+
const actorsBySystem = {};
|
|
250
|
+
const flowBySource = {};
|
|
251
|
+
const flowBySink = {};
|
|
252
|
+
for (const e of recentEvents) {
|
|
253
|
+
if (e.system) {
|
|
254
|
+
activityBySystem[e.system] = (activityBySystem[e.system] ?? 0) + 1;
|
|
255
|
+
if (!actorsBySystem[e.system]) actorsBySystem[e.system] = /* @__PURE__ */ new Set();
|
|
256
|
+
actorsBySystem[e.system].add(e.actor);
|
|
257
|
+
const amt = e.amount ?? 0;
|
|
258
|
+
if (e.type === "mint" || e.type === "enter") {
|
|
259
|
+
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) + amt;
|
|
260
|
+
} else if (e.type === "burn" || e.type === "consume") {
|
|
261
|
+
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) - amt;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (e.sourceOrSink) {
|
|
265
|
+
const amt = e.amount ?? 0;
|
|
266
|
+
if (e.type === "mint" || e.type === "enter") {
|
|
267
|
+
flowBySource[e.sourceOrSink] = (flowBySource[e.sourceOrSink] ?? 0) + amt;
|
|
268
|
+
} else if (e.type === "burn" || e.type === "consume") {
|
|
269
|
+
flowBySink[e.sourceOrSink] = (flowBySink[e.sourceOrSink] ?? 0) + amt;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const participantsBySystem = {};
|
|
274
|
+
for (const [sys, actors] of Object.entries(actorsBySystem)) {
|
|
275
|
+
participantsBySystem[sys] = actors.size;
|
|
276
|
+
}
|
|
277
|
+
const totalSourceFlow = Object.values(flowBySource).reduce((s, v) => s + v, 0);
|
|
278
|
+
const sourceShare = {};
|
|
279
|
+
for (const [src, vol] of Object.entries(flowBySource)) {
|
|
280
|
+
sourceShare[src] = totalSourceFlow > 0 ? vol / totalSourceFlow : 0;
|
|
281
|
+
}
|
|
282
|
+
const totalSinkFlow = Object.values(flowBySink).reduce((s, v) => s + v, 0);
|
|
283
|
+
const sinkShare = {};
|
|
284
|
+
for (const [snk, vol] of Object.entries(flowBySink)) {
|
|
285
|
+
sinkShare[snk] = totalSinkFlow > 0 ? vol / totalSinkFlow : 0;
|
|
286
|
+
}
|
|
246
287
|
const currencies = state.currencies;
|
|
247
288
|
const totalSupplyByCurrency = {};
|
|
248
289
|
const balancesByCurrency = {};
|
|
@@ -452,7 +493,8 @@ var Observer = class {
|
|
|
452
493
|
for (const [name, fn] of Object.entries(this.customMetricFns)) {
|
|
453
494
|
try {
|
|
454
495
|
custom[name] = fn(state);
|
|
455
|
-
} catch {
|
|
496
|
+
} catch (err) {
|
|
497
|
+
console.warn(`[AgentE] Custom metric '${name}' threw an error:`, err);
|
|
456
498
|
custom[name] = NaN;
|
|
457
499
|
}
|
|
458
500
|
}
|
|
@@ -529,6 +571,13 @@ var Observer = class {
|
|
|
529
571
|
sharkToothValleys: this.previousMetrics?.sharkToothValleys ?? [],
|
|
530
572
|
eventCompletionRate: NaN,
|
|
531
573
|
contentDropAge,
|
|
574
|
+
flowBySystem,
|
|
575
|
+
activityBySystem,
|
|
576
|
+
participantsBySystem,
|
|
577
|
+
flowBySource,
|
|
578
|
+
flowBySink,
|
|
579
|
+
sourceShare,
|
|
580
|
+
sinkShare,
|
|
532
581
|
custom
|
|
533
582
|
};
|
|
534
583
|
this.previousMetrics = metrics;
|
|
@@ -671,6 +720,13 @@ function emptyMetrics(tick = 0) {
|
|
|
671
720
|
sharkToothValleys: [],
|
|
672
721
|
eventCompletionRate: NaN,
|
|
673
722
|
contentDropAge: 0,
|
|
723
|
+
flowBySystem: {},
|
|
724
|
+
activityBySystem: {},
|
|
725
|
+
participantsBySystem: {},
|
|
726
|
+
flowBySource: {},
|
|
727
|
+
flowBySink: {},
|
|
728
|
+
sourceShare: {},
|
|
729
|
+
sinkShare: {},
|
|
674
730
|
custom: {}
|
|
675
731
|
};
|
|
676
732
|
}
|
|
@@ -703,7 +759,7 @@ var P1_ProductionMatchesConsumption = {
|
|
|
703
759
|
severity: 7,
|
|
704
760
|
evidence: { scarceResources: violations, dominantRole: dominantRole?.[0], dominantShare },
|
|
705
761
|
suggestedAction: {
|
|
706
|
-
|
|
762
|
+
parameterType: "cost",
|
|
707
763
|
direction: "decrease",
|
|
708
764
|
magnitude: 0.15,
|
|
709
765
|
reasoning: "Lower production cost to incentivise more production."
|
|
@@ -737,7 +793,8 @@ var P2_ClosedLoopsNeedDirectHandoff = {
|
|
|
737
793
|
severity: 5,
|
|
738
794
|
evidence: { backlogResources, velocity },
|
|
739
795
|
suggestedAction: {
|
|
740
|
-
|
|
796
|
+
parameterType: "fee",
|
|
797
|
+
scope: { tags: ["transaction"] },
|
|
741
798
|
direction: "increase",
|
|
742
799
|
magnitude: 0.2,
|
|
743
800
|
reasoning: "Raise market fees to discourage raw material listings. Direct hand-off at production zones is the correct channel."
|
|
@@ -767,7 +824,7 @@ var P3_BootstrapCapitalCoversFirstTransaction = {
|
|
|
767
824
|
severity: 8,
|
|
768
825
|
evidence: { resource, totalProducers, supply },
|
|
769
826
|
suggestedAction: {
|
|
770
|
-
|
|
827
|
+
parameterType: "cost",
|
|
771
828
|
direction: "decrease",
|
|
772
829
|
magnitude: 0.3,
|
|
773
830
|
reasoning: "Producers cannot complete first transaction. Lower production cost to unblock bootstrap."
|
|
@@ -786,7 +843,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
786
843
|
id: "P4",
|
|
787
844
|
name: "Materials Flow Faster Than Cooldown",
|
|
788
845
|
category: "supply_chain",
|
|
789
|
-
description: "Input delivery rate must exceed or match production cooldown rate. If producers
|
|
846
|
+
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
847
|
check(metrics, _thresholds) {
|
|
791
848
|
const { supplyByResource, populationByRole, velocity, totalAgents } = metrics;
|
|
792
849
|
const totalSupply = Object.values(supplyByResource).reduce((s, v) => s + v, 0);
|
|
@@ -799,7 +856,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
799
856
|
severity: 5,
|
|
800
857
|
evidence: { avgSupplyPerAgent, velocity, totalRoles },
|
|
801
858
|
suggestedAction: {
|
|
802
|
-
|
|
859
|
+
parameterType: "yield",
|
|
803
860
|
direction: "increase",
|
|
804
861
|
magnitude: 0.15,
|
|
805
862
|
reasoning: "Low supply per agent with stagnant velocity. Increase yield to compensate."
|
|
@@ -814,7 +871,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
814
871
|
severity: 4,
|
|
815
872
|
evidence: { avgSupplyPerAgent, totalSupply, totalAgents },
|
|
816
873
|
suggestedAction: {
|
|
817
|
-
|
|
874
|
+
parameterType: "yield",
|
|
818
875
|
direction: "decrease",
|
|
819
876
|
magnitude: 0.2,
|
|
820
877
|
reasoning: "Raw materials piling up. Extractors outpacing producers."
|
|
@@ -842,7 +899,7 @@ var P60_SurplusDisposalAsymmetry = {
|
|
|
842
899
|
discount: thresholds.disposalTradeWeightDiscount
|
|
843
900
|
},
|
|
844
901
|
suggestedAction: {
|
|
845
|
-
|
|
902
|
+
parameterType: "cost",
|
|
846
903
|
direction: "decrease",
|
|
847
904
|
magnitude: 0.1,
|
|
848
905
|
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 +942,8 @@ var P5_ProfitabilityIsCompetitive = {
|
|
|
885
942
|
population: populationByRole[dominantRole]
|
|
886
943
|
},
|
|
887
944
|
suggestedAction: {
|
|
888
|
-
|
|
945
|
+
parameterType: "fee",
|
|
946
|
+
scope: { tags: ["transaction"] },
|
|
889
947
|
direction: "increase",
|
|
890
948
|
magnitude: thresholds.maxAdjustmentPercent,
|
|
891
949
|
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 +969,7 @@ var P6_CrowdingMultiplierOnAllRoles = {
|
|
|
911
969
|
severity: 5,
|
|
912
970
|
evidence: { role, share },
|
|
913
971
|
suggestedAction: {
|
|
914
|
-
|
|
972
|
+
parameterType: "cost",
|
|
915
973
|
direction: "increase",
|
|
916
974
|
magnitude: 0.1,
|
|
917
975
|
reasoning: `${role} at ${(share * 100).toFixed(0)}% \u2014 no crowding pressure detected. Apply role-specific cost increase to simulate saturation.`
|
|
@@ -946,7 +1004,8 @@ var P7_NonSpecialistsSubsidiseSpecialists = {
|
|
|
946
1004
|
severity: 6,
|
|
947
1005
|
evidence: { poolName, poolSize, dominantRole, dominantShare },
|
|
948
1006
|
suggestedAction: {
|
|
949
|
-
|
|
1007
|
+
parameterType: "fee",
|
|
1008
|
+
scope: { tags: ["entry"] },
|
|
950
1009
|
direction: "decrease",
|
|
951
1010
|
magnitude: 0.1,
|
|
952
1011
|
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 +1033,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
974
1033
|
severity: 4,
|
|
975
1034
|
evidence: { dominantRole: dominantRole[0], share: dominantRole[1], avgSatisfaction },
|
|
976
1035
|
suggestedAction: {
|
|
977
|
-
|
|
1036
|
+
parameterType: "reward",
|
|
978
1037
|
direction: "increase",
|
|
979
1038
|
magnitude: 0.1,
|
|
980
1039
|
reasoning: `Low satisfaction with ${dominantRole[0]} dominant. Regulator may be suppressing a structurally necessary role. Ease pressure on dominant role rewards.`
|
|
@@ -1009,7 +1068,7 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
1009
1068
|
severity: 5,
|
|
1010
1069
|
evidence: { totalChurnRate: totalChurn, churnByRole },
|
|
1011
1070
|
suggestedAction: {
|
|
1012
|
-
|
|
1071
|
+
parameterType: "cost",
|
|
1013
1072
|
direction: "increase",
|
|
1014
1073
|
magnitude: 0.05,
|
|
1015
1074
|
reasoning: `Role switch rate ${(totalChurn * 100).toFixed(1)}% exceeds friction threshold. Increase production costs to slow herd movement.`
|
|
@@ -1024,9 +1083,9 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
1024
1083
|
};
|
|
1025
1084
|
var P10_SpawnWeightingUsesInversePopulation = {
|
|
1026
1085
|
id: "P10",
|
|
1027
|
-
name: "
|
|
1086
|
+
name: "Entry Weighting Uses Inverse Population",
|
|
1028
1087
|
category: "population",
|
|
1029
|
-
description: "New
|
|
1088
|
+
description: "New entrants should preferentially fill the least-populated roles. Flat entry probability causes initial imbalances to compound.",
|
|
1030
1089
|
check(metrics, _thresholds) {
|
|
1031
1090
|
const { roleShares } = metrics;
|
|
1032
1091
|
if (Object.keys(roleShares).length === 0) return { violated: false };
|
|
@@ -1041,7 +1100,7 @@ var P10_SpawnWeightingUsesInversePopulation = {
|
|
|
1041
1100
|
severity: 4,
|
|
1042
1101
|
evidence: { roleShares, stdDev, leastPopulatedRole: minRole?.[0] },
|
|
1043
1102
|
suggestedAction: {
|
|
1044
|
-
|
|
1103
|
+
parameterType: "yield",
|
|
1045
1104
|
direction: "increase",
|
|
1046
1105
|
magnitude: 0.05,
|
|
1047
1106
|
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 +1126,8 @@ var P11_TwoTierPressure = {
|
|
|
1067
1126
|
severity: 6,
|
|
1068
1127
|
evidence: { role, share },
|
|
1069
1128
|
suggestedAction: {
|
|
1070
|
-
|
|
1129
|
+
parameterType: "fee",
|
|
1130
|
+
scope: { tags: ["transaction"] },
|
|
1071
1131
|
direction: "increase",
|
|
1072
1132
|
magnitude: 0.15,
|
|
1073
1133
|
reasoning: `${role} at ${(share * 100).toFixed(0)}% \u2014 continuous pressure was insufficient. Hard intervention needed alongside resumed continuous pressure.`
|
|
@@ -1095,7 +1155,7 @@ var P46_PersonaDiversity = {
|
|
|
1095
1155
|
severity: 5,
|
|
1096
1156
|
evidence: { dominantPersona: persona, share, personaDistribution },
|
|
1097
1157
|
suggestedAction: {
|
|
1098
|
-
|
|
1158
|
+
parameterType: "reward",
|
|
1099
1159
|
direction: "increase",
|
|
1100
1160
|
magnitude: 0.1,
|
|
1101
1161
|
reasoning: `${persona} persona at ${(share * 100).toFixed(0)}% \u2014 behavioral monoculture. Diversify reward structures to attract other persona types.`
|
|
@@ -1112,7 +1172,8 @@ var P46_PersonaDiversity = {
|
|
|
1112
1172
|
severity: 3,
|
|
1113
1173
|
evidence: { significantClusters, required: thresholds.personaMinClusters },
|
|
1114
1174
|
suggestedAction: {
|
|
1115
|
-
|
|
1175
|
+
parameterType: "fee",
|
|
1176
|
+
scope: { tags: ["transaction"] },
|
|
1116
1177
|
direction: "decrease",
|
|
1117
1178
|
magnitude: 0.05,
|
|
1118
1179
|
reasoning: `Only ${significantClusters} significant persona clusters (need ${thresholds.personaMinClusters}). Lower trade barriers to attract non-dominant persona types.`
|
|
@@ -1136,7 +1197,7 @@ var P12_OnePrimaryFaucet = {
|
|
|
1136
1197
|
id: "P12",
|
|
1137
1198
|
name: "One Primary Faucet",
|
|
1138
1199
|
category: "currency",
|
|
1139
|
-
description: "Multiple independent currency sources (gathering + production +
|
|
1200
|
+
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
1201
|
check(metrics, thresholds) {
|
|
1141
1202
|
for (const curr of metrics.currencies) {
|
|
1142
1203
|
const netFlow = metrics.netFlowByCurrency[curr] ?? 0;
|
|
@@ -1148,9 +1209,9 @@ var P12_OnePrimaryFaucet = {
|
|
|
1148
1209
|
severity: 5,
|
|
1149
1210
|
evidence: { currency: curr, netFlow, faucetVolume, sinkVolume },
|
|
1150
1211
|
suggestedAction: {
|
|
1151
|
-
|
|
1212
|
+
parameterType: "cost",
|
|
1152
1213
|
direction: "increase",
|
|
1153
|
-
currency: curr,
|
|
1214
|
+
scope: { currency: curr },
|
|
1154
1215
|
magnitude: 0.15,
|
|
1155
1216
|
reasoning: `[${curr}] Net flow +${netFlow.toFixed(1)}/tick. Inflationary. Increase production cost (primary sink) to balance faucet output.`
|
|
1156
1217
|
},
|
|
@@ -1164,9 +1225,9 @@ var P12_OnePrimaryFaucet = {
|
|
|
1164
1225
|
severity: 4,
|
|
1165
1226
|
evidence: { currency: curr, netFlow, faucetVolume, sinkVolume },
|
|
1166
1227
|
suggestedAction: {
|
|
1167
|
-
|
|
1228
|
+
parameterType: "cost",
|
|
1168
1229
|
direction: "decrease",
|
|
1169
|
-
currency: curr,
|
|
1230
|
+
scope: { currency: curr },
|
|
1170
1231
|
magnitude: 0.15,
|
|
1171
1232
|
reasoning: `[${curr}] Net flow ${netFlow.toFixed(1)}/tick. Deflationary. Decrease production cost to ease sink pressure.`
|
|
1172
1233
|
},
|
|
@@ -1198,9 +1259,9 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1198
1259
|
severity: 7,
|
|
1199
1260
|
evidence: { currency: curr, pool: poolName, poolSize, participants: dominantCount, maxSustainableMultiplier },
|
|
1200
1261
|
suggestedAction: {
|
|
1201
|
-
|
|
1262
|
+
parameterType: "reward",
|
|
1202
1263
|
direction: "decrease",
|
|
1203
|
-
currency: curr,
|
|
1264
|
+
scope: { currency: curr },
|
|
1204
1265
|
magnitude: 0.15,
|
|
1205
1266
|
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
1267
|
},
|
|
@@ -1217,7 +1278,7 @@ var P14_TrackActualInjection = {
|
|
|
1217
1278
|
id: "P14",
|
|
1218
1279
|
name: "Track Actual Currency Injection, Not Value Creation",
|
|
1219
1280
|
category: "currency",
|
|
1220
|
-
description: 'Counting resource gathering as "currency injected" is misleading. Currency enters through faucet mechanisms (
|
|
1281
|
+
description: 'Counting resource gathering as "currency injected" is misleading. Currency enters through faucet mechanisms (entering, rewards). Fake metrics break every downstream decision.',
|
|
1221
1282
|
check(metrics, _thresholds) {
|
|
1222
1283
|
for (const curr of metrics.currencies) {
|
|
1223
1284
|
const faucetVolume = metrics.faucetVolumeByCurrency[curr] ?? 0;
|
|
@@ -1230,9 +1291,9 @@ var P14_TrackActualInjection = {
|
|
|
1230
1291
|
severity: 4,
|
|
1231
1292
|
evidence: { currency: curr, faucetVolume, netFlow, supplyGrowthRate },
|
|
1232
1293
|
suggestedAction: {
|
|
1233
|
-
|
|
1294
|
+
parameterType: "yield",
|
|
1234
1295
|
direction: "decrease",
|
|
1235
|
-
currency: curr,
|
|
1296
|
+
scope: { currency: curr },
|
|
1236
1297
|
magnitude: 0.1,
|
|
1237
1298
|
reasoning: `[${curr}] Supply growing at ${(supplyGrowthRate * 100).toFixed(1)}%/tick. Verify currency injection tracking. Resources should not create currency directly.`
|
|
1238
1299
|
},
|
|
@@ -1262,9 +1323,9 @@ var P15_PoolsNeedCapAndDecay = {
|
|
|
1262
1323
|
severity: 6,
|
|
1263
1324
|
evidence: { currency: curr, pool, size, shareOfSupply, cap: poolCapPercent },
|
|
1264
1325
|
suggestedAction: {
|
|
1265
|
-
|
|
1326
|
+
parameterType: "fee",
|
|
1266
1327
|
direction: "decrease",
|
|
1267
|
-
currency: curr,
|
|
1328
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1268
1329
|
magnitude: 0.1,
|
|
1269
1330
|
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
1331
|
},
|
|
@@ -1294,9 +1355,9 @@ var P16_WithdrawalPenaltyScales = {
|
|
|
1294
1355
|
severity: 3,
|
|
1295
1356
|
evidence: { currency: curr, pool: poolName, poolSize, estimatedStaked: stakedEstimate },
|
|
1296
1357
|
suggestedAction: {
|
|
1297
|
-
|
|
1358
|
+
parameterType: "fee",
|
|
1298
1359
|
direction: "increase",
|
|
1299
|
-
currency: curr,
|
|
1360
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1300
1361
|
magnitude: 0.05,
|
|
1301
1362
|
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
1363
|
},
|
|
@@ -1326,9 +1387,9 @@ var P32_VelocityAboveSupply = {
|
|
|
1326
1387
|
severity: 4,
|
|
1327
1388
|
evidence: { currency: curr, velocity, totalSupply, totalResources },
|
|
1328
1389
|
suggestedAction: {
|
|
1329
|
-
|
|
1390
|
+
parameterType: "fee",
|
|
1330
1391
|
direction: "decrease",
|
|
1331
|
-
currency: curr,
|
|
1392
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1332
1393
|
magnitude: 0.2,
|
|
1333
1394
|
reasoning: `[${curr}] Velocity ${velocity}/t with ${totalResources} resources in system. Economy stagnant despite available supply. Lower trading friction.`
|
|
1334
1395
|
},
|
|
@@ -1368,9 +1429,9 @@ var P58_NoNaturalNumeraire = {
|
|
|
1368
1429
|
meanPrice: mean
|
|
1369
1430
|
},
|
|
1370
1431
|
suggestedAction: {
|
|
1371
|
-
|
|
1432
|
+
parameterType: "cost",
|
|
1372
1433
|
direction: "increase",
|
|
1373
|
-
currency: curr,
|
|
1434
|
+
scope: { currency: curr },
|
|
1374
1435
|
magnitude: 0.1,
|
|
1375
1436
|
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
1437
|
},
|
|
@@ -1405,7 +1466,8 @@ var P17_GracePeriodBeforeIntervention = {
|
|
|
1405
1466
|
severity: 7,
|
|
1406
1467
|
evidence: { tick: metrics.tick, avgSatisfaction: metrics.avgSatisfaction },
|
|
1407
1468
|
suggestedAction: {
|
|
1408
|
-
|
|
1469
|
+
parameterType: "fee",
|
|
1470
|
+
scope: { tags: ["entry"] },
|
|
1409
1471
|
direction: "decrease",
|
|
1410
1472
|
magnitude: 0.2,
|
|
1411
1473
|
reasoning: `Very low satisfaction at tick ${metrics.tick}. Intervention may have fired during grace period. Ease all costs to let economy bootstrap.`
|
|
@@ -1432,7 +1494,7 @@ var P18_FirstProducerNeedsStartingInventory = {
|
|
|
1432
1494
|
severity: 8,
|
|
1433
1495
|
evidence: { tick: metrics.tick, resource, supply, totalAgents: metrics.totalAgents },
|
|
1434
1496
|
suggestedAction: {
|
|
1435
|
-
|
|
1497
|
+
parameterType: "cost",
|
|
1436
1498
|
direction: "decrease",
|
|
1437
1499
|
magnitude: 0.5,
|
|
1438
1500
|
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 +1533,7 @@ var P19_StartingSupplyExceedsDemand = {
|
|
|
1471
1533
|
resourcesPerAgent
|
|
1472
1534
|
},
|
|
1473
1535
|
suggestedAction: {
|
|
1474
|
-
|
|
1536
|
+
parameterType: "reward",
|
|
1475
1537
|
direction: "increase",
|
|
1476
1538
|
magnitude: 0.2,
|
|
1477
1539
|
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 +1567,7 @@ var P20_DecayPreventsAccumulation = {
|
|
|
1505
1567
|
severity: 4,
|
|
1506
1568
|
evidence: { totalResources, resourcesPerAgent, velocity },
|
|
1507
1569
|
suggestedAction: {
|
|
1508
|
-
|
|
1570
|
+
parameterType: "yield",
|
|
1509
1571
|
direction: "decrease",
|
|
1510
1572
|
magnitude: 0.1,
|
|
1511
1573
|
reasoning: `${totalResources.toFixed(0)} resources with velocity ${velocity}/t. Likely hoarding. Reduce yield to increase scarcity and force circulation.`
|
|
@@ -1533,7 +1595,8 @@ var P21_PriceFromGlobalSupply = {
|
|
|
1533
1595
|
severity: 3,
|
|
1534
1596
|
evidence: { resource, volatility, supply, price: prices[resource] },
|
|
1535
1597
|
suggestedAction: {
|
|
1536
|
-
|
|
1598
|
+
parameterType: "fee",
|
|
1599
|
+
scope: { tags: ["transaction"] },
|
|
1537
1600
|
direction: "increase",
|
|
1538
1601
|
magnitude: 0.05,
|
|
1539
1602
|
reasoning: `${resource} price volatile (${(volatility * 100).toFixed(0)}%) despite supply ${supply}. Price may not reflect global inventory. Increase trading friction to stabilise.`
|
|
@@ -1550,7 +1613,7 @@ var P22_MarketAwarenessPreventsSurplus = {
|
|
|
1550
1613
|
id: "P22",
|
|
1551
1614
|
name: "Market Awareness Prevents Overproduction",
|
|
1552
1615
|
category: "feedback",
|
|
1553
|
-
description: "Producers who
|
|
1616
|
+
description: "Producers who produce without checking market prices will create surpluses that crash prices. Agents need to see prices before deciding to produce.",
|
|
1554
1617
|
check(metrics, _thresholds) {
|
|
1555
1618
|
const { supplyByResource, prices, productionIndex } = metrics;
|
|
1556
1619
|
const priceValues = Object.values(prices).filter((p) => p > 0);
|
|
@@ -1574,7 +1637,7 @@ var P22_MarketAwarenessPreventsSurplus = {
|
|
|
1574
1637
|
productionIndex
|
|
1575
1638
|
},
|
|
1576
1639
|
suggestedAction: {
|
|
1577
|
-
|
|
1640
|
+
parameterType: "cost",
|
|
1578
1641
|
direction: "increase",
|
|
1579
1642
|
magnitude: 0.1,
|
|
1580
1643
|
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 +1664,7 @@ var P23_ProfitabilityFactorsFeasibility = {
|
|
|
1601
1664
|
severity: 5,
|
|
1602
1665
|
evidence: { blockedFraction, blockedAgentCount, avgSatisfaction },
|
|
1603
1666
|
suggestedAction: {
|
|
1604
|
-
|
|
1667
|
+
parameterType: "cost",
|
|
1605
1668
|
direction: "decrease",
|
|
1606
1669
|
magnitude: 0.15,
|
|
1607
1670
|
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 +1690,8 @@ var P24_BlockedAgentsDecayFaster = {
|
|
|
1627
1690
|
severity: 5,
|
|
1628
1691
|
evidence: { blockedFraction, blockedAgentCount, churnRate },
|
|
1629
1692
|
suggestedAction: {
|
|
1630
|
-
|
|
1693
|
+
parameterType: "fee",
|
|
1694
|
+
scope: { tags: ["transaction"] },
|
|
1631
1695
|
direction: "decrease",
|
|
1632
1696
|
magnitude: 0.15,
|
|
1633
1697
|
reasoning: `${(blockedFraction * 100).toFixed(0)}% of agents blocked. Blocked agents churn silently, skewing metrics. Lower fees to unblock market participation.`
|
|
@@ -1672,7 +1736,7 @@ var P25_CorrectLeversForCorrectProblems = {
|
|
|
1672
1736
|
netFlow
|
|
1673
1737
|
},
|
|
1674
1738
|
suggestedAction: {
|
|
1675
|
-
|
|
1739
|
+
parameterType: "yield",
|
|
1676
1740
|
direction: "decrease",
|
|
1677
1741
|
magnitude: 0.15,
|
|
1678
1742
|
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 +1762,7 @@ var P26_ContinuousPressureBeatsThresholdCuts = {
|
|
|
1698
1762
|
severity: 4,
|
|
1699
1763
|
evidence: { inflationRate },
|
|
1700
1764
|
suggestedAction: {
|
|
1701
|
-
|
|
1765
|
+
parameterType: "cost",
|
|
1702
1766
|
direction: inflationRate > 0 ? "increase" : "decrease",
|
|
1703
1767
|
magnitude: Math.min(thresholds.maxAdjustmentPercent, 0.05),
|
|
1704
1768
|
// force smaller step
|
|
@@ -1724,7 +1788,8 @@ var P27_AdjustmentsNeedCooldowns = {
|
|
|
1724
1788
|
severity: 4,
|
|
1725
1789
|
evidence: { churnRate, avgSatisfaction },
|
|
1726
1790
|
suggestedAction: {
|
|
1727
|
-
|
|
1791
|
+
parameterType: "fee",
|
|
1792
|
+
scope: { tags: ["entry"] },
|
|
1728
1793
|
direction: "decrease",
|
|
1729
1794
|
magnitude: 0.05,
|
|
1730
1795
|
reasoning: `High churn (${(churnRate * 100).toFixed(1)}%) with low satisfaction. Possible oscillation from rapid adjustments. Apply small correction only.`
|
|
@@ -1755,7 +1820,7 @@ var P28_StructuralDominanceIsNotPathological = {
|
|
|
1755
1820
|
severity: 5,
|
|
1756
1821
|
evidence: { dominantRole, dominantShare, avgSatisfaction },
|
|
1757
1822
|
suggestedAction: {
|
|
1758
|
-
|
|
1823
|
+
parameterType: "cost",
|
|
1759
1824
|
direction: "decrease",
|
|
1760
1825
|
magnitude: 0.1,
|
|
1761
1826
|
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 +1836,7 @@ var P38_CommunicationPreventsRevolt = {
|
|
|
1771
1836
|
id: "P38",
|
|
1772
1837
|
name: "Communication Prevents Revolt",
|
|
1773
1838
|
category: "regulator",
|
|
1774
|
-
description: "Every adjustment must be logged with reasoning. An adjustment made without explanation to
|
|
1839
|
+
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
1840
|
check(metrics, _thresholds) {
|
|
1776
1841
|
const { churnRate } = metrics;
|
|
1777
1842
|
if (churnRate > 0.1) {
|
|
@@ -1780,7 +1845,7 @@ var P38_CommunicationPreventsRevolt = {
|
|
|
1780
1845
|
severity: 3,
|
|
1781
1846
|
evidence: { churnRate },
|
|
1782
1847
|
suggestedAction: {
|
|
1783
|
-
|
|
1848
|
+
parameterType: "reward",
|
|
1784
1849
|
direction: "increase",
|
|
1785
1850
|
magnitude: 0.1,
|
|
1786
1851
|
reasoning: `High churn (${(churnRate * 100).toFixed(1)}%) \u2014 agents leaving. Ensure all recent adjustments are logged with reasoning to diagnose cause.`
|
|
@@ -1803,7 +1868,7 @@ var REGULATOR_PRINCIPLES = [
|
|
|
1803
1868
|
// src/principles/market-dynamics.ts
|
|
1804
1869
|
var P29_PinchPoint = {
|
|
1805
1870
|
id: "P29",
|
|
1806
|
-
name: "
|
|
1871
|
+
name: "Bottleneck Detection",
|
|
1807
1872
|
category: "market_dynamics",
|
|
1808
1873
|
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
1874
|
check(metrics, _thresholds) {
|
|
@@ -1817,7 +1882,7 @@ var P29_PinchPoint = {
|
|
|
1817
1882
|
severity: 7,
|
|
1818
1883
|
evidence: { resource, supply, demand, status },
|
|
1819
1884
|
suggestedAction: {
|
|
1820
|
-
|
|
1885
|
+
parameterType: "cost",
|
|
1821
1886
|
direction: "decrease",
|
|
1822
1887
|
magnitude: 0.15,
|
|
1823
1888
|
reasoning: `${resource} is a pinch point and currently SCARCE (supply ${supply}, demand ${demand}). Reduce production cost to increase throughput.`
|
|
@@ -1833,7 +1898,7 @@ var P29_PinchPoint = {
|
|
|
1833
1898
|
severity: 4,
|
|
1834
1899
|
evidence: { resource, supply, status },
|
|
1835
1900
|
suggestedAction: {
|
|
1836
|
-
|
|
1901
|
+
parameterType: "cost",
|
|
1837
1902
|
direction: "increase",
|
|
1838
1903
|
magnitude: 0.1,
|
|
1839
1904
|
reasoning: `${resource} is a pinch point and OVERSUPPLIED (supply ${supply}). Raise production cost to reduce surplus.`
|
|
@@ -1848,9 +1913,9 @@ var P29_PinchPoint = {
|
|
|
1848
1913
|
};
|
|
1849
1914
|
var P30_MovingPinchPoint = {
|
|
1850
1915
|
id: "P30",
|
|
1851
|
-
name: "
|
|
1916
|
+
name: "Dynamic Bottleneck Rotation",
|
|
1852
1917
|
category: "market_dynamics",
|
|
1853
|
-
description: "
|
|
1918
|
+
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
1919
|
check(metrics, _thresholds) {
|
|
1855
1920
|
const { capacityUsage, supplyByResource, avgSatisfaction } = metrics;
|
|
1856
1921
|
const totalResources = Object.values(supplyByResource).reduce((s, v) => s + v, 0);
|
|
@@ -1861,7 +1926,7 @@ var P30_MovingPinchPoint = {
|
|
|
1861
1926
|
severity: 3,
|
|
1862
1927
|
evidence: { capacityUsage, resourcesPerAgent, avgSatisfaction },
|
|
1863
1928
|
suggestedAction: {
|
|
1864
|
-
|
|
1929
|
+
parameterType: "cost",
|
|
1865
1930
|
direction: "increase",
|
|
1866
1931
|
magnitude: 0.1,
|
|
1867
1932
|
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 +1942,7 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1877
1942
|
id: "P57",
|
|
1878
1943
|
name: "Combinatorial Price Space",
|
|
1879
1944
|
category: "market_dynamics",
|
|
1880
|
-
description: "N tradeable items generate (N\u22121)N/2 relative prices. With thousands of items no single
|
|
1945
|
+
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
1946
|
check(metrics, thresholds) {
|
|
1882
1947
|
const { prices, priceVolatility } = metrics;
|
|
1883
1948
|
const priceKeys = Object.keys(prices);
|
|
@@ -1907,7 +1972,8 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1907
1972
|
target: thresholds.relativePriceConvergenceTarget
|
|
1908
1973
|
},
|
|
1909
1974
|
suggestedAction: {
|
|
1910
|
-
|
|
1975
|
+
parameterType: "fee",
|
|
1976
|
+
scope: { tags: ["transaction"] },
|
|
1911
1977
|
direction: "decrease",
|
|
1912
1978
|
magnitude: 0.1,
|
|
1913
1979
|
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.`
|
|
@@ -1939,7 +2005,7 @@ var P31_AnchorValueTracking = {
|
|
|
1939
2005
|
severity: 5,
|
|
1940
2006
|
evidence: { anchorRatioDrift, inflationRate },
|
|
1941
2007
|
suggestedAction: {
|
|
1942
|
-
|
|
2008
|
+
parameterType: "cost",
|
|
1943
2009
|
direction: anchorRatioDrift > 0 ? "increase" : "decrease",
|
|
1944
2010
|
magnitude: 0.1,
|
|
1945
2011
|
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 +2030,8 @@ var P41_MultiResolutionMonitoring = {
|
|
|
1964
2030
|
severity: 4,
|
|
1965
2031
|
evidence: { giniCoefficient, avgSatisfaction },
|
|
1966
2032
|
suggestedAction: {
|
|
1967
|
-
|
|
2033
|
+
parameterType: "fee",
|
|
2034
|
+
scope: { tags: ["transaction"] },
|
|
1968
2035
|
direction: "increase",
|
|
1969
2036
|
magnitude: 0.1,
|
|
1970
2037
|
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 +2060,8 @@ var P55_ArbitrageThermometer = {
|
|
|
1993
2060
|
critical: thresholds.arbitrageIndexCritical
|
|
1994
2061
|
},
|
|
1995
2062
|
suggestedAction: {
|
|
1996
|
-
|
|
2063
|
+
parameterType: "fee",
|
|
2064
|
+
scope: { tags: ["transaction"] },
|
|
1997
2065
|
direction: "decrease",
|
|
1998
2066
|
magnitude: 0.15,
|
|
1999
2067
|
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 +2079,8 @@ var P55_ArbitrageThermometer = {
|
|
|
2011
2079
|
warning: thresholds.arbitrageIndexWarning
|
|
2012
2080
|
},
|
|
2013
2081
|
suggestedAction: {
|
|
2014
|
-
|
|
2082
|
+
parameterType: "fee",
|
|
2083
|
+
scope: { tags: ["transaction"] },
|
|
2015
2084
|
direction: "decrease",
|
|
2016
2085
|
magnitude: 0.08,
|
|
2017
2086
|
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 +2108,8 @@ var P59_GiftEconomyNoise = {
|
|
|
2039
2108
|
threshold: thresholds.giftTradeFilterRatio
|
|
2040
2109
|
},
|
|
2041
2110
|
suggestedAction: {
|
|
2042
|
-
|
|
2111
|
+
parameterType: "fee",
|
|
2112
|
+
scope: { tags: ["transaction"] },
|
|
2043
2113
|
direction: "increase",
|
|
2044
2114
|
magnitude: 0.05,
|
|
2045
2115
|
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 +2152,9 @@ var P42_TheMedianPrinciple = {
|
|
|
2082
2152
|
medianBalance
|
|
2083
2153
|
},
|
|
2084
2154
|
suggestedAction: {
|
|
2085
|
-
|
|
2155
|
+
parameterType: "fee",
|
|
2156
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2086
2157
|
direction: "increase",
|
|
2087
|
-
currency: curr,
|
|
2088
2158
|
magnitude: 0.15,
|
|
2089
2159
|
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
2160
|
},
|
|
@@ -2109,7 +2179,7 @@ var P43_SimulationMinimum = {
|
|
|
2109
2179
|
severity: 3,
|
|
2110
2180
|
evidence: { inflationRate, minIterations: thresholds.simulationMinIterations },
|
|
2111
2181
|
suggestedAction: {
|
|
2112
|
-
|
|
2182
|
+
parameterType: "cost",
|
|
2113
2183
|
direction: inflationRate > 0 ? "increase" : "decrease",
|
|
2114
2184
|
magnitude: 0.05,
|
|
2115
2185
|
reasoning: `Large inflation rate swing (${(inflationRate * 100).toFixed(0)}%). Ensure all decisions use \u2265${thresholds.simulationMinIterations} simulation iterations. Apply conservative correction.`
|
|
@@ -2147,7 +2217,7 @@ var P39_TheLagPrinciple = {
|
|
|
2147
2217
|
severity: 5,
|
|
2148
2218
|
evidence: { inflationRate, netFlow, lagRange: [lagMin, lagMax] },
|
|
2149
2219
|
suggestedAction: {
|
|
2150
|
-
|
|
2220
|
+
parameterType: "cost",
|
|
2151
2221
|
direction: "increase",
|
|
2152
2222
|
magnitude: 0.03,
|
|
2153
2223
|
// very small — oscillation means over-adjusting
|
|
@@ -2174,7 +2244,8 @@ var P44_ComplexityBudget = {
|
|
|
2174
2244
|
severity: 3,
|
|
2175
2245
|
evidence: { customMetricCount, budgetMax: thresholds.complexityBudgetMax },
|
|
2176
2246
|
suggestedAction: {
|
|
2177
|
-
|
|
2247
|
+
parameterType: "fee",
|
|
2248
|
+
scope: { tags: ["transaction"] },
|
|
2178
2249
|
direction: "decrease",
|
|
2179
2250
|
magnitude: 0.01,
|
|
2180
2251
|
reasoning: `${customMetricCount} custom metrics tracked (budget: ${thresholds.complexityBudgetMax}). Consider pruning low-impact parameters. Applying minimal correction to avoid adding complexity.`
|
|
@@ -2206,7 +2277,8 @@ var P35_DestructionCreatesValue = {
|
|
|
2206
2277
|
severity: 6,
|
|
2207
2278
|
evidence: { resource, supply, sinkVolume, netFlow },
|
|
2208
2279
|
suggestedAction: {
|
|
2209
|
-
|
|
2280
|
+
parameterType: "fee",
|
|
2281
|
+
scope: { tags: ["entry"] },
|
|
2210
2282
|
direction: "decrease",
|
|
2211
2283
|
magnitude: 0.1,
|
|
2212
2284
|
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower competitive pool entry to increase resource usage.`
|
|
@@ -2234,7 +2306,7 @@ var P40_ReplacementRate = {
|
|
|
2234
2306
|
severity: 6,
|
|
2235
2307
|
evidence: { productionIndex, sinkVolume, replacementRatio },
|
|
2236
2308
|
suggestedAction: {
|
|
2237
|
-
|
|
2309
|
+
parameterType: "yield",
|
|
2238
2310
|
direction: "increase",
|
|
2239
2311
|
magnitude: 0.15,
|
|
2240
2312
|
reasoning: `Replacement rate ${replacementRatio.toFixed(2)} (need \u2265${thresholds.replacementRateMultiplier}). Production below consumption. Resources will deplete. Increase yield.`
|
|
@@ -2248,7 +2320,7 @@ var P40_ReplacementRate = {
|
|
|
2248
2320
|
severity: 3,
|
|
2249
2321
|
evidence: { productionIndex, sinkVolume, replacementRatio },
|
|
2250
2322
|
suggestedAction: {
|
|
2251
|
-
|
|
2323
|
+
parameterType: "yield",
|
|
2252
2324
|
direction: "decrease",
|
|
2253
2325
|
magnitude: 0.1,
|
|
2254
2326
|
reasoning: `Replacement rate ${replacementRatio.toFixed(2)} \u2014 overproducing. Production far exceeds consumption. Reduce yield to prevent glut.`
|
|
@@ -2274,7 +2346,8 @@ var P49_IdleAssetTax = {
|
|
|
2274
2346
|
severity: 5,
|
|
2275
2347
|
evidence: { giniCoefficient, top10PctShare, velocity },
|
|
2276
2348
|
suggestedAction: {
|
|
2277
|
-
|
|
2349
|
+
parameterType: "fee",
|
|
2350
|
+
scope: { tags: ["transaction"] },
|
|
2278
2351
|
direction: "increase",
|
|
2279
2352
|
magnitude: 0.15,
|
|
2280
2353
|
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 +2365,11 @@ var RESOURCE_MGMT_PRINCIPLES = [
|
|
|
2292
2365
|
P49_IdleAssetTax
|
|
2293
2366
|
];
|
|
2294
2367
|
|
|
2295
|
-
// src/principles/
|
|
2368
|
+
// src/principles/participant-experience.ts
|
|
2296
2369
|
var P33_FairNotEqual = {
|
|
2297
2370
|
id: "P33",
|
|
2298
2371
|
name: "Fair \u2260 Equal",
|
|
2299
|
-
category: "
|
|
2372
|
+
category: "participant_experience",
|
|
2300
2373
|
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
2374
|
check(metrics, thresholds) {
|
|
2302
2375
|
for (const curr of metrics.currencies) {
|
|
@@ -2307,9 +2380,9 @@ var P33_FairNotEqual = {
|
|
|
2307
2380
|
severity: 3,
|
|
2308
2381
|
evidence: { currency: curr, giniCoefficient },
|
|
2309
2382
|
suggestedAction: {
|
|
2310
|
-
|
|
2383
|
+
parameterType: "reward",
|
|
2311
2384
|
direction: "increase",
|
|
2312
|
-
currency: curr,
|
|
2385
|
+
scope: { currency: curr },
|
|
2313
2386
|
magnitude: 0.1,
|
|
2314
2387
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 near-perfect equality. Economy lacks stakes. Increase winner rewards to create meaningful spread.`
|
|
2315
2388
|
},
|
|
@@ -2323,9 +2396,9 @@ var P33_FairNotEqual = {
|
|
|
2323
2396
|
severity: 7,
|
|
2324
2397
|
evidence: { currency: curr, giniCoefficient },
|
|
2325
2398
|
suggestedAction: {
|
|
2326
|
-
|
|
2399
|
+
parameterType: "fee",
|
|
2327
2400
|
direction: "increase",
|
|
2328
|
-
currency: curr,
|
|
2401
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2329
2402
|
magnitude: 0.2,
|
|
2330
2403
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 oligarchy level. Toxic inequality. Raise transaction fees to redistribute wealth from rich to pool.`
|
|
2331
2404
|
},
|
|
@@ -2339,9 +2412,9 @@ var P33_FairNotEqual = {
|
|
|
2339
2412
|
severity: 4,
|
|
2340
2413
|
evidence: { currency: curr, giniCoefficient },
|
|
2341
2414
|
suggestedAction: {
|
|
2342
|
-
|
|
2415
|
+
parameterType: "fee",
|
|
2343
2416
|
direction: "increase",
|
|
2344
|
-
currency: curr,
|
|
2417
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2345
2418
|
magnitude: 0.1,
|
|
2346
2419
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 high inequality warning. Gently raise fees to slow wealth concentration.`
|
|
2347
2420
|
},
|
|
@@ -2355,9 +2428,9 @@ var P33_FairNotEqual = {
|
|
|
2355
2428
|
};
|
|
2356
2429
|
var P36_MechanicFrictionDetector = {
|
|
2357
2430
|
id: "P36",
|
|
2358
|
-
name: "
|
|
2359
|
-
category: "
|
|
2360
|
-
description: "Deterministic + probabilistic systems \u2192 expectation mismatch. When
|
|
2431
|
+
name: "Mechanism Friction Detector",
|
|
2432
|
+
category: "participant_experience",
|
|
2433
|
+
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
2434
|
check(metrics, _thresholds) {
|
|
2362
2435
|
const { avgSatisfaction, churnRate, velocity } = metrics;
|
|
2363
2436
|
if (churnRate > 0.1 && avgSatisfaction < 50 && velocity > 3) {
|
|
@@ -2366,10 +2439,10 @@ var P36_MechanicFrictionDetector = {
|
|
|
2366
2439
|
severity: 5,
|
|
2367
2440
|
evidence: { churnRate, avgSatisfaction, velocity },
|
|
2368
2441
|
suggestedAction: {
|
|
2369
|
-
|
|
2442
|
+
parameterType: "reward",
|
|
2370
2443
|
direction: "increase",
|
|
2371
2444
|
magnitude: 0.15,
|
|
2372
|
-
reasoning: `Churn ${(churnRate * 100).toFixed(1)}% with satisfaction ${avgSatisfaction.toFixed(0)} despite active economy (velocity ` + velocity.toFixed(1) + "). Suggests
|
|
2445
|
+
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
2446
|
},
|
|
2374
2447
|
confidence: 0.55,
|
|
2375
2448
|
estimatedLag: 15
|
|
@@ -2380,8 +2453,8 @@ var P36_MechanicFrictionDetector = {
|
|
|
2380
2453
|
};
|
|
2381
2454
|
var P37_LatecommerProblem = {
|
|
2382
2455
|
id: "P37",
|
|
2383
|
-
name: "
|
|
2384
|
-
category: "
|
|
2456
|
+
name: "Late Entrant Problem",
|
|
2457
|
+
category: "participant_experience",
|
|
2385
2458
|
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
2459
|
check(metrics, _thresholds) {
|
|
2387
2460
|
const { timeToValue, avgSatisfaction, churnRate } = metrics;
|
|
@@ -2391,7 +2464,7 @@ var P37_LatecommerProblem = {
|
|
|
2391
2464
|
severity: 6,
|
|
2392
2465
|
evidence: { timeToValue, avgSatisfaction, churnRate },
|
|
2393
2466
|
suggestedAction: {
|
|
2394
|
-
|
|
2467
|
+
parameterType: "cost",
|
|
2395
2468
|
direction: "decrease",
|
|
2396
2469
|
magnitude: 0.15,
|
|
2397
2470
|
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 +2479,7 @@ var P37_LatecommerProblem = {
|
|
|
2406
2479
|
var P45_TimeBudget = {
|
|
2407
2480
|
id: "P45",
|
|
2408
2481
|
name: "Time Budget",
|
|
2409
|
-
category: "
|
|
2482
|
+
category: "participant_experience",
|
|
2410
2483
|
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
2484
|
check(metrics, thresholds) {
|
|
2412
2485
|
const { timeToValue, avgSatisfaction } = metrics;
|
|
@@ -2418,8 +2491,9 @@ var P45_TimeBudget = {
|
|
|
2418
2491
|
severity: 5,
|
|
2419
2492
|
evidence: { timeToValue, avgSatisfaction, timeBudgetRatio: thresholds.timeBudgetRatio },
|
|
2420
2493
|
suggestedAction: {
|
|
2421
|
-
|
|
2494
|
+
parameterType: "fee",
|
|
2422
2495
|
direction: "decrease",
|
|
2496
|
+
scope: { tags: ["entry"] },
|
|
2423
2497
|
magnitude: 0.15,
|
|
2424
2498
|
reasoning: `Time-to-value ${timeToValue} ticks with ${avgSatisfaction.toFixed(0)} satisfaction. Economy requires too much time investment. Lower barriers to participation.`
|
|
2425
2499
|
},
|
|
@@ -2433,7 +2507,7 @@ var P45_TimeBudget = {
|
|
|
2433
2507
|
var P50_PayPowerRatio = {
|
|
2434
2508
|
id: "P50",
|
|
2435
2509
|
name: "Pay-Power Ratio",
|
|
2436
|
-
category: "
|
|
2510
|
+
category: "participant_experience",
|
|
2437
2511
|
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
2512
|
check(metrics, thresholds) {
|
|
2439
2513
|
const { top10PctShare, giniCoefficient } = metrics;
|
|
@@ -2448,8 +2522,9 @@ var P50_PayPowerRatio = {
|
|
|
2448
2522
|
threshold: thresholds.payPowerRatioMax
|
|
2449
2523
|
},
|
|
2450
2524
|
suggestedAction: {
|
|
2451
|
-
|
|
2525
|
+
parameterType: "fee",
|
|
2452
2526
|
direction: "increase",
|
|
2527
|
+
scope: { tags: ["transaction"] },
|
|
2453
2528
|
magnitude: 0.2,
|
|
2454
2529
|
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
2530
|
},
|
|
@@ -2460,7 +2535,7 @@ var P50_PayPowerRatio = {
|
|
|
2460
2535
|
return { violated: false };
|
|
2461
2536
|
}
|
|
2462
2537
|
};
|
|
2463
|
-
var
|
|
2538
|
+
var PARTICIPANT_EXPERIENCE_PRINCIPLES = [
|
|
2464
2539
|
P33_FairNotEqual,
|
|
2465
2540
|
P36_MechanicFrictionDetector,
|
|
2466
2541
|
P37_LatecommerProblem,
|
|
@@ -2483,7 +2558,8 @@ var P34_ExtractionRatio = {
|
|
|
2483
2558
|
severity: 8,
|
|
2484
2559
|
evidence: { extractionRatio, threshold: thresholds.extractionRatioRed },
|
|
2485
2560
|
suggestedAction: {
|
|
2486
|
-
|
|
2561
|
+
parameterType: "fee",
|
|
2562
|
+
scope: { tags: ["transaction"] },
|
|
2487
2563
|
direction: "increase",
|
|
2488
2564
|
magnitude: 0.25,
|
|
2489
2565
|
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 +2574,8 @@ var P34_ExtractionRatio = {
|
|
|
2498
2574
|
severity: 5,
|
|
2499
2575
|
evidence: { extractionRatio, threshold: thresholds.extractionRatioYellow },
|
|
2500
2576
|
suggestedAction: {
|
|
2501
|
-
|
|
2577
|
+
parameterType: "fee",
|
|
2578
|
+
scope: { tags: ["transaction"] },
|
|
2502
2579
|
direction: "increase",
|
|
2503
2580
|
magnitude: 0.1,
|
|
2504
2581
|
reasoning: `Extraction ratio ${(extractionRatio * 100).toFixed(0)}% (warning: ${(thresholds.extractionRatioYellow * 100).toFixed(0)}%). Economy trending toward extraction-heavy. Apply early pressure.`
|
|
@@ -2524,7 +2601,7 @@ var P47_SmokeTest = {
|
|
|
2524
2601
|
severity: 9,
|
|
2525
2602
|
evidence: { smokeTestRatio, threshold: thresholds.smokeTestCritical },
|
|
2526
2603
|
suggestedAction: {
|
|
2527
|
-
|
|
2604
|
+
parameterType: "reward",
|
|
2528
2605
|
direction: "increase",
|
|
2529
2606
|
magnitude: 0.2,
|
|
2530
2607
|
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 +2616,7 @@ var P47_SmokeTest = {
|
|
|
2539
2616
|
severity: 6,
|
|
2540
2617
|
evidence: { smokeTestRatio, threshold: thresholds.smokeTestWarning },
|
|
2541
2618
|
suggestedAction: {
|
|
2542
|
-
|
|
2619
|
+
parameterType: "reward",
|
|
2543
2620
|
direction: "increase",
|
|
2544
2621
|
magnitude: 0.1,
|
|
2545
2622
|
reasoning: `Utility/market ratio ${(smokeTestRatio * 100).toFixed(0)}% (warning). Economy is >70% speculative. Boost utility rewards to restore intrinsic value anchor.`
|
|
@@ -2565,7 +2642,8 @@ var P48_CurrencyInsulation = {
|
|
|
2565
2642
|
severity: 6,
|
|
2566
2643
|
evidence: { currencyInsulation, threshold: thresholds.currencyInsulationMax },
|
|
2567
2644
|
suggestedAction: {
|
|
2568
|
-
|
|
2645
|
+
parameterType: "fee",
|
|
2646
|
+
scope: { tags: ["transaction"] },
|
|
2569
2647
|
direction: "increase",
|
|
2570
2648
|
magnitude: 0.1,
|
|
2571
2649
|
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 +2661,12 @@ var OPEN_ECONOMY_PRINCIPLES = [
|
|
|
2583
2661
|
P48_CurrencyInsulation
|
|
2584
2662
|
];
|
|
2585
2663
|
|
|
2586
|
-
// src/principles/
|
|
2664
|
+
// src/principles/operations.ts
|
|
2587
2665
|
var P51_SharkTooth = {
|
|
2588
2666
|
id: "P51",
|
|
2589
|
-
name: "
|
|
2590
|
-
category: "
|
|
2591
|
-
description: "Each
|
|
2667
|
+
name: "Cyclical Engagement Pattern",
|
|
2668
|
+
category: "operations",
|
|
2669
|
+
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
2670
|
check(metrics, thresholds) {
|
|
2593
2671
|
const { sharkToothPeaks, sharkToothValleys } = metrics;
|
|
2594
2672
|
if (sharkToothPeaks.length < 2) return { violated: false };
|
|
@@ -2605,10 +2683,10 @@ var P51_SharkTooth = {
|
|
|
2605
2683
|
threshold: thresholds.sharkToothPeakDecay
|
|
2606
2684
|
},
|
|
2607
2685
|
suggestedAction: {
|
|
2608
|
-
|
|
2686
|
+
parameterType: "reward",
|
|
2609
2687
|
direction: "increase",
|
|
2610
2688
|
magnitude: 0.1,
|
|
2611
|
-
reasoning: `Peak engagement dropped to ${(lastPeak / prevPeak * 100).toFixed(0)}% of previous peak (threshold: ${(thresholds.sharkToothPeakDecay * 100).toFixed(0)}%).
|
|
2689
|
+
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
2690
|
},
|
|
2613
2691
|
confidence: 0.75,
|
|
2614
2692
|
estimatedLag: 30
|
|
@@ -2623,10 +2701,10 @@ var P51_SharkTooth = {
|
|
|
2623
2701
|
severity: 4,
|
|
2624
2702
|
evidence: { lastValley, prevValley, ratio: lastValley / prevValley },
|
|
2625
2703
|
suggestedAction: {
|
|
2626
|
-
|
|
2704
|
+
parameterType: "cost",
|
|
2627
2705
|
direction: "decrease",
|
|
2628
2706
|
magnitude: 0.1,
|
|
2629
|
-
reasoning: "Between-
|
|
2707
|
+
reasoning: "Between-activity engagement declining (deepening valleys). Base economy not sustaining participants between activities. Lower production costs to improve off-activity value."
|
|
2630
2708
|
},
|
|
2631
2709
|
confidence: 0.65,
|
|
2632
2710
|
estimatedLag: 20
|
|
@@ -2639,8 +2717,8 @@ var P51_SharkTooth = {
|
|
|
2639
2717
|
var P52_EndowmentEffect = {
|
|
2640
2718
|
id: "P52",
|
|
2641
2719
|
name: "Endowment Effect",
|
|
2642
|
-
category: "
|
|
2643
|
-
description: "Participants who never owned premium items do not value them. Free trial
|
|
2720
|
+
category: "operations",
|
|
2721
|
+
description: "Participants who never owned premium items do not value them. Free trial activities that let participants experience premium items drive conversions because ownership creates perceived value (endowment effect).",
|
|
2644
2722
|
check(metrics, _thresholds) {
|
|
2645
2723
|
const { avgSatisfaction, churnRate } = metrics;
|
|
2646
2724
|
const { eventCompletionRate } = metrics;
|
|
@@ -2651,10 +2729,10 @@ var P52_EndowmentEffect = {
|
|
|
2651
2729
|
severity: 4,
|
|
2652
2730
|
evidence: { eventCompletionRate, avgSatisfaction, churnRate },
|
|
2653
2731
|
suggestedAction: {
|
|
2654
|
-
|
|
2732
|
+
parameterType: "reward",
|
|
2655
2733
|
direction: "increase",
|
|
2656
2734
|
magnitude: 0.15,
|
|
2657
|
-
reasoning: `${(eventCompletionRate * 100).toFixed(0)}%
|
|
2735
|
+
reasoning: `${(eventCompletionRate * 100).toFixed(0)}% activity completion but satisfaction only ${avgSatisfaction.toFixed(0)}. Activities not creating perceived value. Increase reward quality/quantity.`
|
|
2658
2736
|
},
|
|
2659
2737
|
confidence: 0.6,
|
|
2660
2738
|
estimatedLag: 20
|
|
@@ -2665,8 +2743,8 @@ var P52_EndowmentEffect = {
|
|
|
2665
2743
|
};
|
|
2666
2744
|
var P53_EventCompletionRate = {
|
|
2667
2745
|
id: "P53",
|
|
2668
|
-
name: "
|
|
2669
|
-
category: "
|
|
2746
|
+
name: "Activity Completion Rate Sweet Spot",
|
|
2747
|
+
category: "operations",
|
|
2670
2748
|
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
2749
|
check(metrics, thresholds) {
|
|
2672
2750
|
const { eventCompletionRate } = metrics;
|
|
@@ -2681,10 +2759,10 @@ var P53_EventCompletionRate = {
|
|
|
2681
2759
|
max: thresholds.eventCompletionMax
|
|
2682
2760
|
},
|
|
2683
2761
|
suggestedAction: {
|
|
2684
|
-
|
|
2762
|
+
parameterType: "cost",
|
|
2685
2763
|
direction: "decrease",
|
|
2686
2764
|
magnitude: 0.15,
|
|
2687
|
-
reasoning: `
|
|
2765
|
+
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
2766
|
},
|
|
2689
2767
|
confidence: 0.8,
|
|
2690
2768
|
estimatedLag: 10
|
|
@@ -2696,10 +2774,11 @@ var P53_EventCompletionRate = {
|
|
|
2696
2774
|
severity: 3,
|
|
2697
2775
|
evidence: { eventCompletionRate, max: thresholds.eventCompletionMax },
|
|
2698
2776
|
suggestedAction: {
|
|
2699
|
-
|
|
2777
|
+
parameterType: "fee",
|
|
2778
|
+
scope: { tags: ["entry"] },
|
|
2700
2779
|
direction: "increase",
|
|
2701
2780
|
magnitude: 0.05,
|
|
2702
|
-
reasoning: `
|
|
2781
|
+
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
2782
|
},
|
|
2704
2783
|
confidence: 0.55,
|
|
2705
2784
|
estimatedLag: 10
|
|
@@ -2710,9 +2789,9 @@ var P53_EventCompletionRate = {
|
|
|
2710
2789
|
};
|
|
2711
2790
|
var P54_LiveOpsCadence = {
|
|
2712
2791
|
id: "P54",
|
|
2713
|
-
name: "
|
|
2714
|
-
category: "
|
|
2715
|
-
description: ">50% of
|
|
2792
|
+
name: "Operational Cadence",
|
|
2793
|
+
category: "operations",
|
|
2794
|
+
description: ">50% of activities that are re-wrapped existing content \u2192 staleness. The cadence must include genuinely new content at regular intervals. This is an advisory principle \u2014 AgentE can flag but cannot fix content.",
|
|
2716
2795
|
check(metrics, _thresholds) {
|
|
2717
2796
|
const { velocity, avgSatisfaction } = metrics;
|
|
2718
2797
|
if (velocity < 2 && avgSatisfaction < 55 && metrics.tick > 100) {
|
|
@@ -2721,7 +2800,7 @@ var P54_LiveOpsCadence = {
|
|
|
2721
2800
|
severity: 3,
|
|
2722
2801
|
evidence: { velocity, avgSatisfaction, tick: metrics.tick },
|
|
2723
2802
|
suggestedAction: {
|
|
2724
|
-
|
|
2803
|
+
parameterType: "reward",
|
|
2725
2804
|
direction: "increase",
|
|
2726
2805
|
magnitude: 0.1,
|
|
2727
2806
|
reasoning: "Low velocity and satisfaction after long runtime. Possible content staleness. Increase rewards as bridge while new content is developed (developer action required)."
|
|
@@ -2735,8 +2814,8 @@ var P54_LiveOpsCadence = {
|
|
|
2735
2814
|
};
|
|
2736
2815
|
var P56_ContentDropShock = {
|
|
2737
2816
|
id: "P56",
|
|
2738
|
-
name: "
|
|
2739
|
-
category: "
|
|
2817
|
+
name: "Supply Shock Absorption",
|
|
2818
|
+
category: "operations",
|
|
2740
2819
|
description: "Every new-item injection shatters existing price equilibria \u2014 arbitrage spikes as participants re-price. Build cooldown windows for price discovery before measuring post-drop economic health.",
|
|
2741
2820
|
check(metrics, thresholds) {
|
|
2742
2821
|
const { contentDropAge, arbitrageIndex } = metrics;
|
|
@@ -2752,7 +2831,8 @@ var P56_ContentDropShock = {
|
|
|
2752
2831
|
postDropMax: thresholds.postDropArbitrageMax
|
|
2753
2832
|
},
|
|
2754
2833
|
suggestedAction: {
|
|
2755
|
-
|
|
2834
|
+
parameterType: "fee",
|
|
2835
|
+
scope: { tags: ["transaction"] },
|
|
2756
2836
|
direction: "decrease",
|
|
2757
2837
|
magnitude: 0.1,
|
|
2758
2838
|
reasoning: `Content drop ${contentDropAge} ticks ago \u2014 arbitrage at ${arbitrageIndex.toFixed(2)} exceeds post-drop max (${thresholds.postDropArbitrageMax}). Price discovery struggling. Lower trading friction temporarily.`
|
|
@@ -2765,7 +2845,7 @@ var P56_ContentDropShock = {
|
|
|
2765
2845
|
return { violated: false };
|
|
2766
2846
|
}
|
|
2767
2847
|
};
|
|
2768
|
-
var
|
|
2848
|
+
var OPERATIONS_PRINCIPLES = [
|
|
2769
2849
|
P51_SharkTooth,
|
|
2770
2850
|
P52_EndowmentEffect,
|
|
2771
2851
|
P53_EventCompletionRate,
|
|
@@ -2799,23 +2879,24 @@ var ALL_PRINCIPLES = [
|
|
|
2799
2879
|
// P39, P44
|
|
2800
2880
|
...RESOURCE_MGMT_PRINCIPLES,
|
|
2801
2881
|
// P35, P40, P49
|
|
2802
|
-
...
|
|
2882
|
+
...PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
2803
2883
|
// P33, P36, P37, P45, P50
|
|
2804
2884
|
...OPEN_ECONOMY_PRINCIPLES,
|
|
2805
2885
|
// P34, P47-P48
|
|
2806
|
-
...
|
|
2886
|
+
...OPERATIONS_PRINCIPLES
|
|
2807
2887
|
// P51-P54, P56
|
|
2808
2888
|
];
|
|
2809
2889
|
|
|
2810
2890
|
// src/Simulator.ts
|
|
2811
2891
|
var Simulator = class {
|
|
2812
|
-
constructor() {
|
|
2892
|
+
constructor(registry) {
|
|
2813
2893
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
2814
2894
|
// Cache beforeViolations for the *current* tick only (one entry max).
|
|
2815
2895
|
// Using a Map here is intentional but the cache must be bounded — we only
|
|
2816
2896
|
// care about the tick that is currently being evaluated, so we evict any
|
|
2817
2897
|
// entries whose key differs from the incoming tick.
|
|
2818
2898
|
this.beforeViolationsCache = /* @__PURE__ */ new Map();
|
|
2899
|
+
this.registry = registry;
|
|
2819
2900
|
}
|
|
2820
2901
|
/**
|
|
2821
2902
|
* Simulate the effect of applying `action` to the current economy forward `forwardTicks`.
|
|
@@ -2882,7 +2963,7 @@ var Simulator = class {
|
|
|
2882
2963
|
const multiplier = this.actionMultiplier(action);
|
|
2883
2964
|
const noise = () => 1 + (Math.random() - 0.5) * 0.1;
|
|
2884
2965
|
const currencies = metrics.currencies;
|
|
2885
|
-
const targetCurrency = action.currency;
|
|
2966
|
+
const targetCurrency = action.scope?.currency;
|
|
2886
2967
|
const supplies = { ...metrics.totalSupplyByCurrency };
|
|
2887
2968
|
const netFlows = { ...metrics.netFlowByCurrency };
|
|
2888
2969
|
const ginis = { ...metrics.giniCoefficientByCurrency };
|
|
@@ -2924,26 +3005,48 @@ var Simulator = class {
|
|
|
2924
3005
|
return action.direction === "increase" ? 1 + base : 1 - base;
|
|
2925
3006
|
}
|
|
2926
3007
|
flowEffect(action, metrics, currency) {
|
|
2927
|
-
const {
|
|
3008
|
+
const { direction } = action;
|
|
2928
3009
|
const sign = direction === "increase" ? -1 : 1;
|
|
2929
3010
|
const roleEntries = Object.entries(metrics.populationByRole).sort((a, b) => b[1] - a[1]);
|
|
2930
3011
|
const dominantRoleCount = roleEntries[0]?.[1] ?? 0;
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
3012
|
+
const resolvedKey = action.resolvedParameter;
|
|
3013
|
+
let impact;
|
|
3014
|
+
if (resolvedKey && this.registry) {
|
|
3015
|
+
impact = this.registry.getFlowImpact(resolvedKey);
|
|
3016
|
+
}
|
|
3017
|
+
if (!impact) {
|
|
3018
|
+
impact = this.inferFlowImpact(action.parameterType);
|
|
3019
|
+
}
|
|
3020
|
+
switch (impact) {
|
|
3021
|
+
case "sink":
|
|
3022
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.2;
|
|
3023
|
+
case "faucet":
|
|
3024
|
+
return -sign * dominantRoleCount * 0.3;
|
|
3025
|
+
case "neutral":
|
|
3026
|
+
return sign * dominantRoleCount * 0.5;
|
|
3027
|
+
case "mixed":
|
|
3028
|
+
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * 0.15;
|
|
3029
|
+
default:
|
|
3030
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
/** Infer flow impact from parameter type when registry is unavailable */
|
|
3034
|
+
inferFlowImpact(parameterType) {
|
|
3035
|
+
switch (parameterType) {
|
|
3036
|
+
case "cost":
|
|
3037
|
+
case "fee":
|
|
3038
|
+
case "penalty":
|
|
3039
|
+
return "sink";
|
|
3040
|
+
case "reward":
|
|
3041
|
+
return "faucet";
|
|
3042
|
+
case "yield":
|
|
3043
|
+
return "mixed";
|
|
3044
|
+
case "cap":
|
|
3045
|
+
case "multiplier":
|
|
3046
|
+
return "neutral";
|
|
3047
|
+
default:
|
|
3048
|
+
return "mixed";
|
|
2939
3049
|
}
|
|
2940
|
-
if (parameter === "rewardRate") {
|
|
2941
|
-
return -sign * dominantRoleCount * 0.3;
|
|
2942
|
-
}
|
|
2943
|
-
if (parameter === "yieldRate") {
|
|
2944
|
-
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * 0.15;
|
|
2945
|
-
}
|
|
2946
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
2947
3050
|
}
|
|
2948
3051
|
checkImprovement(before, after, action) {
|
|
2949
3052
|
const satisfactionImproved = after.avgSatisfaction >= before.avgSatisfaction - 2;
|
|
@@ -3023,16 +3126,30 @@ var Planner = class {
|
|
|
3023
3126
|
* - parameter is still in cooldown
|
|
3024
3127
|
* - simulation result failed
|
|
3025
3128
|
* - complexity budget exceeded
|
|
3129
|
+
* - no matching parameter in registry
|
|
3026
3130
|
*/
|
|
3027
|
-
plan(diagnosis, metrics, simulationResult, currentParams, thresholds) {
|
|
3131
|
+
plan(diagnosis, metrics, simulationResult, currentParams, thresholds, registry) {
|
|
3028
3132
|
const action = diagnosis.violation.suggestedAction;
|
|
3029
|
-
|
|
3133
|
+
let param;
|
|
3134
|
+
let resolvedBaseline;
|
|
3135
|
+
let scope;
|
|
3136
|
+
if (registry) {
|
|
3137
|
+
const resolved = registry.resolve(action.parameterType, action.scope);
|
|
3138
|
+
if (!resolved) return null;
|
|
3139
|
+
param = resolved.key;
|
|
3140
|
+
resolvedBaseline = resolved.currentValue;
|
|
3141
|
+
scope = resolved.scope;
|
|
3142
|
+
action.resolvedParameter = param;
|
|
3143
|
+
} else {
|
|
3144
|
+
param = action.resolvedParameter ?? action.parameterType;
|
|
3145
|
+
scope = action.scope;
|
|
3146
|
+
}
|
|
3030
3147
|
if (this.lockedParams.has(param)) return null;
|
|
3031
3148
|
if (this.isOnCooldown(param, metrics.tick, thresholds.cooldownTicks)) return null;
|
|
3032
3149
|
if (!simulationResult.netImprovement) return null;
|
|
3033
3150
|
if (!simulationResult.noNewProblems) return null;
|
|
3034
3151
|
if (this.activePlanCount >= thresholds.complexityBudgetMax) return null;
|
|
3035
|
-
const currentValue = currentParams[param] ?? 1;
|
|
3152
|
+
const currentValue = resolvedBaseline ?? currentParams[param] ?? action.absoluteValue ?? 1;
|
|
3036
3153
|
const magnitude = Math.min(action.magnitude ?? 0.1, thresholds.maxAdjustmentPercent);
|
|
3037
3154
|
let targetValue;
|
|
3038
3155
|
if (action.direction === "set" && action.absoluteValue !== void 0) {
|
|
@@ -3052,7 +3169,7 @@ var Planner = class {
|
|
|
3052
3169
|
id: `plan_${metrics.tick}_${param}`,
|
|
3053
3170
|
diagnosis,
|
|
3054
3171
|
parameter: param,
|
|
3055
|
-
...
|
|
3172
|
+
...scope !== void 0 ? { scope } : {},
|
|
3056
3173
|
currentValue,
|
|
3057
3174
|
targetValue,
|
|
3058
3175
|
maxChangePercent: thresholds.maxAdjustmentPercent,
|
|
@@ -3061,7 +3178,6 @@ var Planner = class {
|
|
|
3061
3178
|
metric: "avgSatisfaction",
|
|
3062
3179
|
direction: "below",
|
|
3063
3180
|
threshold: Math.max(20, metrics.avgSatisfaction - 10),
|
|
3064
|
-
// rollback if sat drops >10 pts
|
|
3065
3181
|
checkAfterTick: metrics.tick + estimatedLag + 3
|
|
3066
3182
|
},
|
|
3067
3183
|
simulationResult,
|
|
@@ -3076,6 +3192,9 @@ var Planner = class {
|
|
|
3076
3192
|
recordRolledBack(_plan) {
|
|
3077
3193
|
this.activePlanCount = Math.max(0, this.activePlanCount - 1);
|
|
3078
3194
|
}
|
|
3195
|
+
recordSettled(_plan) {
|
|
3196
|
+
this.activePlanCount = Math.max(0, this.activePlanCount - 1);
|
|
3197
|
+
}
|
|
3079
3198
|
isOnCooldown(param, currentTick, cooldownTicks) {
|
|
3080
3199
|
const lastApplied = this.cooldowns.get(param);
|
|
3081
3200
|
if (lastApplied === void 0) return false;
|
|
@@ -3094,40 +3213,54 @@ var Executor = class {
|
|
|
3094
3213
|
}
|
|
3095
3214
|
async apply(plan, adapter, currentParams) {
|
|
3096
3215
|
const originalValue = currentParams[plan.parameter] ?? plan.currentValue;
|
|
3097
|
-
await adapter.setParam(plan.parameter, plan.targetValue, plan.
|
|
3216
|
+
await adapter.setParam(plan.parameter, plan.targetValue, plan.scope);
|
|
3098
3217
|
plan.appliedAt = plan.diagnosis.tick;
|
|
3099
3218
|
this.activePlans.push({ plan, originalValue });
|
|
3100
3219
|
}
|
|
3101
3220
|
/**
|
|
3102
3221
|
* Check all active plans for rollback conditions.
|
|
3103
|
-
*
|
|
3104
|
-
* Returns list of plans that were rolled back.
|
|
3222
|
+
* Returns { rolledBack, settled } — plans that were undone and plans that passed their window.
|
|
3105
3223
|
*/
|
|
3106
3224
|
async checkRollbacks(metrics, adapter) {
|
|
3107
3225
|
const rolledBack = [];
|
|
3226
|
+
const settled = [];
|
|
3108
3227
|
const remaining = [];
|
|
3109
3228
|
for (const active of this.activePlans) {
|
|
3110
3229
|
const { plan, originalValue } = active;
|
|
3111
3230
|
const rc = plan.rollbackCondition;
|
|
3231
|
+
const maxActiveTicks = 200;
|
|
3232
|
+
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > maxActiveTicks) {
|
|
3233
|
+
settled.push(plan);
|
|
3234
|
+
continue;
|
|
3235
|
+
}
|
|
3112
3236
|
if (metrics.tick < rc.checkAfterTick) {
|
|
3113
3237
|
remaining.push(active);
|
|
3114
3238
|
continue;
|
|
3115
3239
|
}
|
|
3116
3240
|
const metricValue = this.getMetricValue(metrics, rc.metric);
|
|
3241
|
+
if (Number.isNaN(metricValue)) {
|
|
3242
|
+
console.warn(
|
|
3243
|
+
`[AgentE] Rollback check: metric path '${rc.metric}' resolved to NaN for plan '${plan.id}'. Triggering rollback as fail-safe.`
|
|
3244
|
+
);
|
|
3245
|
+
await adapter.setParam(plan.parameter, originalValue, plan.scope);
|
|
3246
|
+
rolledBack.push(plan);
|
|
3247
|
+
continue;
|
|
3248
|
+
}
|
|
3117
3249
|
const shouldRollback = rc.direction === "below" ? metricValue < rc.threshold : metricValue > rc.threshold;
|
|
3118
3250
|
if (shouldRollback) {
|
|
3119
|
-
await adapter.setParam(plan.parameter, originalValue, plan.
|
|
3251
|
+
await adapter.setParam(plan.parameter, originalValue, plan.scope);
|
|
3120
3252
|
rolledBack.push(plan);
|
|
3121
3253
|
} else {
|
|
3122
3254
|
const settledTick = rc.checkAfterTick + 10;
|
|
3123
3255
|
if (metrics.tick > settledTick) {
|
|
3256
|
+
settled.push(plan);
|
|
3124
3257
|
} else {
|
|
3125
3258
|
remaining.push(active);
|
|
3126
3259
|
}
|
|
3127
3260
|
}
|
|
3128
3261
|
}
|
|
3129
3262
|
this.activePlans = remaining;
|
|
3130
|
-
return rolledBack;
|
|
3263
|
+
return { rolledBack, settled };
|
|
3131
3264
|
}
|
|
3132
3265
|
getMetricValue(metrics, metricPath) {
|
|
3133
3266
|
const parts = metricPath.split(".");
|
|
@@ -3216,7 +3349,8 @@ var DecisionLog = class {
|
|
|
3216
3349
|
return {
|
|
3217
3350
|
id: `stub_${metrics.tick}`,
|
|
3218
3351
|
diagnosis,
|
|
3219
|
-
parameter: action.
|
|
3352
|
+
parameter: action.resolvedParameter ?? action.parameterType,
|
|
3353
|
+
...action.scope !== void 0 ? { scope: action.scope } : {},
|
|
3220
3354
|
currentValue: 1,
|
|
3221
3355
|
targetValue: 1,
|
|
3222
3356
|
maxChangePercent: 0,
|
|
@@ -3454,13 +3588,13 @@ var PersonaTracker = class {
|
|
|
3454
3588
|
Earner: 0,
|
|
3455
3589
|
Builder: 0,
|
|
3456
3590
|
Social: 0,
|
|
3457
|
-
|
|
3591
|
+
HighValue: 0,
|
|
3458
3592
|
Influencer: 0
|
|
3459
3593
|
};
|
|
3460
3594
|
let total = 0;
|
|
3461
3595
|
for (const [, history] of this.agentHistory) {
|
|
3462
3596
|
const persona = this.classify(history);
|
|
3463
|
-
counts[persona]
|
|
3597
|
+
counts[persona] = (counts[persona] ?? 0) + 1;
|
|
3464
3598
|
total++;
|
|
3465
3599
|
}
|
|
3466
3600
|
if (total === 0) return {};
|
|
@@ -3480,7 +3614,7 @@ var PersonaTracker = class {
|
|
|
3480
3614
|
const extraction = avg("netExtraction");
|
|
3481
3615
|
const uniqueItems = avg("uniqueItemsHeld");
|
|
3482
3616
|
const spend = avg("spendAmount");
|
|
3483
|
-
if (spend > 1e3) return "
|
|
3617
|
+
if (spend > 1e3) return "HighValue";
|
|
3484
3618
|
if (txRate > 10) return "Trader";
|
|
3485
3619
|
if (uniqueItems > 5 && extraction < 0) return "Collector";
|
|
3486
3620
|
if (extraction > 100) return "Earner";
|
|
@@ -3489,12 +3623,116 @@ var PersonaTracker = class {
|
|
|
3489
3623
|
}
|
|
3490
3624
|
};
|
|
3491
3625
|
|
|
3626
|
+
// src/ParameterRegistry.ts
|
|
3627
|
+
var ParameterRegistry = class {
|
|
3628
|
+
constructor() {
|
|
3629
|
+
this.parameters = /* @__PURE__ */ new Map();
|
|
3630
|
+
}
|
|
3631
|
+
/** Register a parameter. Overwrites if key already exists. */
|
|
3632
|
+
register(param) {
|
|
3633
|
+
this.parameters.set(param.key, { ...param });
|
|
3634
|
+
}
|
|
3635
|
+
/** Register multiple parameters at once. */
|
|
3636
|
+
registerAll(params) {
|
|
3637
|
+
for (const p of params) this.register(p);
|
|
3638
|
+
}
|
|
3639
|
+
/**
|
|
3640
|
+
* Resolve a parameterType + scope to a concrete RegisteredParameter.
|
|
3641
|
+
* Returns the best match, or undefined if no match.
|
|
3642
|
+
*
|
|
3643
|
+
* Matching rules (in priority order):
|
|
3644
|
+
* 1. Exact type match + all scope fields match
|
|
3645
|
+
* 2. Exact type match + partial scope match (tags overlap)
|
|
3646
|
+
* 3. Exact type match + no scope constraints
|
|
3647
|
+
* 4. undefined (no match)
|
|
3648
|
+
*/
|
|
3649
|
+
resolve(type, scope) {
|
|
3650
|
+
const candidates = this.findByType(type);
|
|
3651
|
+
if (candidates.length === 0) return void 0;
|
|
3652
|
+
if (candidates.length === 1) return candidates[0];
|
|
3653
|
+
let bestScore = -1;
|
|
3654
|
+
let best;
|
|
3655
|
+
for (const candidate of candidates) {
|
|
3656
|
+
const score = this.scopeMatchScore(candidate.scope, scope);
|
|
3657
|
+
if (score > bestScore) {
|
|
3658
|
+
bestScore = score;
|
|
3659
|
+
best = candidate;
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
return best;
|
|
3663
|
+
}
|
|
3664
|
+
/** Find all parameters of a given type. */
|
|
3665
|
+
findByType(type) {
|
|
3666
|
+
const results = [];
|
|
3667
|
+
for (const param of this.parameters.values()) {
|
|
3668
|
+
if (param.type === type) results.push(param);
|
|
3669
|
+
}
|
|
3670
|
+
return results;
|
|
3671
|
+
}
|
|
3672
|
+
/** Find all parameters belonging to a given system. */
|
|
3673
|
+
findBySystem(system) {
|
|
3674
|
+
const results = [];
|
|
3675
|
+
for (const param of this.parameters.values()) {
|
|
3676
|
+
if (param.scope?.system === system) results.push(param);
|
|
3677
|
+
}
|
|
3678
|
+
return results;
|
|
3679
|
+
}
|
|
3680
|
+
/** Get a parameter by its concrete key. */
|
|
3681
|
+
get(key) {
|
|
3682
|
+
return this.parameters.get(key);
|
|
3683
|
+
}
|
|
3684
|
+
/** Get the flow impact of a parameter by its concrete key. */
|
|
3685
|
+
getFlowImpact(key) {
|
|
3686
|
+
return this.parameters.get(key)?.flowImpact;
|
|
3687
|
+
}
|
|
3688
|
+
/** Update the current value of a registered parameter. */
|
|
3689
|
+
updateValue(key, value) {
|
|
3690
|
+
const param = this.parameters.get(key);
|
|
3691
|
+
if (param) {
|
|
3692
|
+
param.currentValue = value;
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
/** Get all registered parameters. */
|
|
3696
|
+
getAll() {
|
|
3697
|
+
return [...this.parameters.values()];
|
|
3698
|
+
}
|
|
3699
|
+
/** Number of registered parameters. */
|
|
3700
|
+
get size() {
|
|
3701
|
+
return this.parameters.size;
|
|
3702
|
+
}
|
|
3703
|
+
// ── Private ─────────────────────────────────────────────────────────────
|
|
3704
|
+
scopeMatchScore(paramScope, queryScope) {
|
|
3705
|
+
if (!queryScope) return 0;
|
|
3706
|
+
if (!paramScope) return 0;
|
|
3707
|
+
let score = 0;
|
|
3708
|
+
if (queryScope.system && paramScope.system) {
|
|
3709
|
+
if (queryScope.system === paramScope.system) score += 10;
|
|
3710
|
+
else return -1;
|
|
3711
|
+
}
|
|
3712
|
+
if (queryScope.currency && paramScope.currency) {
|
|
3713
|
+
if (queryScope.currency === paramScope.currency) score += 5;
|
|
3714
|
+
else return -1;
|
|
3715
|
+
}
|
|
3716
|
+
if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3717
|
+
const overlap = queryScope.tags.filter((t) => paramScope.tags.includes(t)).length;
|
|
3718
|
+
if (overlap > 0) {
|
|
3719
|
+
score += overlap * 3;
|
|
3720
|
+
} else {
|
|
3721
|
+
return -1;
|
|
3722
|
+
}
|
|
3723
|
+
} else if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3724
|
+
return -1;
|
|
3725
|
+
}
|
|
3726
|
+
return score;
|
|
3727
|
+
}
|
|
3728
|
+
};
|
|
3729
|
+
|
|
3492
3730
|
// src/AgentE.ts
|
|
3493
3731
|
var AgentE = class {
|
|
3494
3732
|
constructor(config) {
|
|
3495
|
-
this.simulator = new Simulator();
|
|
3496
3733
|
this.planner = new Planner();
|
|
3497
3734
|
this.executor = new Executor();
|
|
3735
|
+
this.registry = new ParameterRegistry();
|
|
3498
3736
|
// ── State ──
|
|
3499
3737
|
this.log = new DecisionLog();
|
|
3500
3738
|
this.personaTracker = new PersonaTracker();
|
|
@@ -3519,7 +3757,8 @@ var AgentE = class {
|
|
|
3519
3757
|
gracePeriod: config.gracePeriod ?? 50,
|
|
3520
3758
|
checkInterval: config.checkInterval ?? 5,
|
|
3521
3759
|
maxAdjustmentPercent: config.maxAdjustmentPercent ?? 0.15,
|
|
3522
|
-
cooldownTicks: config.cooldownTicks ?? 15
|
|
3760
|
+
cooldownTicks: config.cooldownTicks ?? 15,
|
|
3761
|
+
parameters: config.parameters ?? []
|
|
3523
3762
|
};
|
|
3524
3763
|
this.thresholds = {
|
|
3525
3764
|
...DEFAULT_THRESHOLDS,
|
|
@@ -3531,6 +3770,10 @@ var AgentE = class {
|
|
|
3531
3770
|
this.observer = new Observer(tickConfig);
|
|
3532
3771
|
this.store = new MetricStore(tickConfig);
|
|
3533
3772
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
3773
|
+
if (config.parameters) {
|
|
3774
|
+
this.registry.registerAll(config.parameters);
|
|
3775
|
+
}
|
|
3776
|
+
this.simulator = new Simulator(this.registry);
|
|
3534
3777
|
if (config.onDecision) this.on("decision", config.onDecision);
|
|
3535
3778
|
if (config.onAlert) this.on("alert", config.onAlert);
|
|
3536
3779
|
if (config.onRollback) this.on("rollback", config.onRollback);
|
|
@@ -3568,15 +3811,24 @@ var AgentE = class {
|
|
|
3568
3811
|
this.currentTick = currentState.tick;
|
|
3569
3812
|
const events = [...this.eventBuffer];
|
|
3570
3813
|
this.eventBuffer = [];
|
|
3571
|
-
|
|
3814
|
+
let metrics;
|
|
3815
|
+
try {
|
|
3816
|
+
metrics = this.observer.compute(currentState, events);
|
|
3817
|
+
} catch (err) {
|
|
3818
|
+
console.error(`[AgentE] Observer.compute() failed at tick ${currentState.tick}:`, err);
|
|
3819
|
+
return;
|
|
3820
|
+
}
|
|
3572
3821
|
this.store.record(metrics);
|
|
3573
3822
|
this.personaTracker.update(currentState);
|
|
3574
3823
|
metrics.personaDistribution = this.personaTracker.getDistribution();
|
|
3575
|
-
const rolledBack = await this.executor.checkRollbacks(metrics, this.adapter);
|
|
3824
|
+
const { rolledBack, settled } = await this.executor.checkRollbacks(metrics, this.adapter);
|
|
3576
3825
|
for (const plan2 of rolledBack) {
|
|
3577
3826
|
this.planner.recordRolledBack(plan2);
|
|
3578
3827
|
this.emit("rollback", plan2, "rollback condition triggered");
|
|
3579
3828
|
}
|
|
3829
|
+
for (const plan2 of settled) {
|
|
3830
|
+
this.planner.recordSettled(plan2);
|
|
3831
|
+
}
|
|
3580
3832
|
if (metrics.tick < this.config.gracePeriod) return;
|
|
3581
3833
|
if (metrics.tick % this.config.checkInterval !== 0) return;
|
|
3582
3834
|
const diagnoses = this.diagnoser.diagnose(metrics, this.thresholds);
|
|
@@ -3598,7 +3850,8 @@ var AgentE = class {
|
|
|
3598
3850
|
metrics,
|
|
3599
3851
|
simulationResult,
|
|
3600
3852
|
this.params,
|
|
3601
|
-
this.thresholds
|
|
3853
|
+
this.thresholds,
|
|
3854
|
+
this.registry
|
|
3602
3855
|
);
|
|
3603
3856
|
if (!plan) {
|
|
3604
3857
|
let reason = "skipped_cooldown";
|
|
@@ -3618,6 +3871,7 @@ var AgentE = class {
|
|
|
3618
3871
|
}
|
|
3619
3872
|
await this.executor.apply(plan, this.adapter, this.params);
|
|
3620
3873
|
this.params[plan.parameter] = plan.targetValue;
|
|
3874
|
+
this.registry.updateValue(plan.parameter, plan.targetValue);
|
|
3621
3875
|
this.planner.recordApplied(plan, metrics.tick);
|
|
3622
3876
|
const entry = this.log.record(topDiagnosis, plan, "applied", metrics);
|
|
3623
3877
|
this.emit("decision", entry);
|
|
@@ -3627,6 +3881,7 @@ var AgentE = class {
|
|
|
3627
3881
|
async apply(plan) {
|
|
3628
3882
|
await this.executor.apply(plan, this.adapter, this.params);
|
|
3629
3883
|
this.params[plan.parameter] = plan.targetValue;
|
|
3884
|
+
this.registry.updateValue(plan.parameter, plan.targetValue);
|
|
3630
3885
|
this.planner.recordApplied(plan, this.currentTick);
|
|
3631
3886
|
}
|
|
3632
3887
|
// ── Developer API ───────────────────────────────────────────────────────────
|
|
@@ -3651,6 +3906,12 @@ var AgentE = class {
|
|
|
3651
3906
|
removePrinciple(id) {
|
|
3652
3907
|
this.diagnoser.removePrinciple(id);
|
|
3653
3908
|
}
|
|
3909
|
+
registerParameter(param) {
|
|
3910
|
+
this.registry.register(param);
|
|
3911
|
+
}
|
|
3912
|
+
getRegistry() {
|
|
3913
|
+
return this.registry;
|
|
3914
|
+
}
|
|
3654
3915
|
registerCustomMetric(name, fn) {
|
|
3655
3916
|
this.observer.registerCustomMetric(name, fn);
|
|
3656
3917
|
}
|
|
@@ -4053,11 +4314,11 @@ function describeValue(value) {
|
|
|
4053
4314
|
Executor,
|
|
4054
4315
|
FEEDBACK_LOOP_PRINCIPLES,
|
|
4055
4316
|
INCENTIVE_PRINCIPLES,
|
|
4056
|
-
LIVEOPS_PRINCIPLES,
|
|
4057
4317
|
MARKET_DYNAMICS_PRINCIPLES,
|
|
4058
4318
|
MEASUREMENT_PRINCIPLES,
|
|
4059
4319
|
MetricStore,
|
|
4060
4320
|
OPEN_ECONOMY_PRINCIPLES,
|
|
4321
|
+
OPERATIONS_PRINCIPLES,
|
|
4061
4322
|
Observer,
|
|
4062
4323
|
P10_SpawnWeightingUsesInversePopulation,
|
|
4063
4324
|
P11_TwoTierPressure,
|
|
@@ -4119,9 +4380,10 @@ function describeValue(value) {
|
|
|
4119
4380
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
4120
4381
|
P8_RegulatorCannotFightDesign,
|
|
4121
4382
|
P9_RoleSwitchingNeedsFriction,
|
|
4383
|
+
PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
4122
4384
|
PERSONA_HEALTHY_RANGES,
|
|
4123
|
-
PLAYER_EXPERIENCE_PRINCIPLES,
|
|
4124
4385
|
POPULATION_PRINCIPLES,
|
|
4386
|
+
ParameterRegistry,
|
|
4125
4387
|
PersonaTracker,
|
|
4126
4388
|
Planner,
|
|
4127
4389
|
REGULATOR_PRINCIPLES,
|