@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.mjs
CHANGED
|
@@ -12,11 +12,11 @@ var DEFAULT_THRESHOLDS = {
|
|
|
12
12
|
smokeTestWarning: 0.3,
|
|
13
13
|
smokeTestCritical: 0.1,
|
|
14
14
|
currencyInsulationMax: 0.5,
|
|
15
|
-
//
|
|
15
|
+
// Participant Experience (P45, P50)
|
|
16
16
|
timeBudgetRatio: 0.8,
|
|
17
17
|
payPowerRatioMax: 2,
|
|
18
18
|
payPowerRatioTarget: 1.5,
|
|
19
|
-
//
|
|
19
|
+
// Operations (P51, P53)
|
|
20
20
|
sharkToothPeakDecay: 0.95,
|
|
21
21
|
sharkToothValleyDecay: 0.9,
|
|
22
22
|
eventCompletionMin: 0.4,
|
|
@@ -70,7 +70,7 @@ var PERSONA_HEALTHY_RANGES = {
|
|
|
70
70
|
Earner: { min: 0, max: 0.15 },
|
|
71
71
|
Builder: { min: 0.05, max: 0.15 },
|
|
72
72
|
Social: { min: 0.1, max: 0.2 },
|
|
73
|
-
|
|
73
|
+
HighValue: { min: 0, max: 0.05 },
|
|
74
74
|
Influencer: { min: 0, max: 0.05 }
|
|
75
75
|
};
|
|
76
76
|
var DEFAULT_TICK_CONFIG = {
|
|
@@ -107,7 +107,7 @@ var Observer = class {
|
|
|
107
107
|
const curr = e.currency ?? defaultCurrency;
|
|
108
108
|
switch (e.type) {
|
|
109
109
|
case "mint":
|
|
110
|
-
case "
|
|
110
|
+
case "enter":
|
|
111
111
|
faucetVolumeByCurrency[curr] = (faucetVolumeByCurrency[curr] ?? 0) + (e.amount ?? 0);
|
|
112
112
|
break;
|
|
113
113
|
case "burn":
|
|
@@ -129,6 +129,46 @@ var Observer = class {
|
|
|
129
129
|
break;
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
+
const flowBySystem = {};
|
|
133
|
+
const activityBySystem = {};
|
|
134
|
+
const actorsBySystem = {};
|
|
135
|
+
const flowBySource = {};
|
|
136
|
+
const flowBySink = {};
|
|
137
|
+
for (const e of recentEvents) {
|
|
138
|
+
if (e.system) {
|
|
139
|
+
activityBySystem[e.system] = (activityBySystem[e.system] ?? 0) + 1;
|
|
140
|
+
if (!actorsBySystem[e.system]) actorsBySystem[e.system] = /* @__PURE__ */ new Set();
|
|
141
|
+
actorsBySystem[e.system].add(e.actor);
|
|
142
|
+
const amt = e.amount ?? 0;
|
|
143
|
+
if (e.type === "mint" || e.type === "enter") {
|
|
144
|
+
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) + amt;
|
|
145
|
+
} else if (e.type === "burn" || e.type === "consume") {
|
|
146
|
+
flowBySystem[e.system] = (flowBySystem[e.system] ?? 0) - amt;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (e.sourceOrSink) {
|
|
150
|
+
const amt = e.amount ?? 0;
|
|
151
|
+
if (e.type === "mint" || e.type === "enter") {
|
|
152
|
+
flowBySource[e.sourceOrSink] = (flowBySource[e.sourceOrSink] ?? 0) + amt;
|
|
153
|
+
} else if (e.type === "burn" || e.type === "consume") {
|
|
154
|
+
flowBySink[e.sourceOrSink] = (flowBySink[e.sourceOrSink] ?? 0) + amt;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const participantsBySystem = {};
|
|
159
|
+
for (const [sys, actors] of Object.entries(actorsBySystem)) {
|
|
160
|
+
participantsBySystem[sys] = actors.size;
|
|
161
|
+
}
|
|
162
|
+
const totalSourceFlow = Object.values(flowBySource).reduce((s, v) => s + v, 0);
|
|
163
|
+
const sourceShare = {};
|
|
164
|
+
for (const [src, vol] of Object.entries(flowBySource)) {
|
|
165
|
+
sourceShare[src] = totalSourceFlow > 0 ? vol / totalSourceFlow : 0;
|
|
166
|
+
}
|
|
167
|
+
const totalSinkFlow = Object.values(flowBySink).reduce((s, v) => s + v, 0);
|
|
168
|
+
const sinkShare = {};
|
|
169
|
+
for (const [snk, vol] of Object.entries(flowBySink)) {
|
|
170
|
+
sinkShare[snk] = totalSinkFlow > 0 ? vol / totalSinkFlow : 0;
|
|
171
|
+
}
|
|
132
172
|
const currencies = state.currencies;
|
|
133
173
|
const totalSupplyByCurrency = {};
|
|
134
174
|
const balancesByCurrency = {};
|
|
@@ -338,7 +378,8 @@ var Observer = class {
|
|
|
338
378
|
for (const [name, fn] of Object.entries(this.customMetricFns)) {
|
|
339
379
|
try {
|
|
340
380
|
custom[name] = fn(state);
|
|
341
|
-
} catch {
|
|
381
|
+
} catch (err) {
|
|
382
|
+
console.warn(`[AgentE] Custom metric '${name}' threw an error:`, err);
|
|
342
383
|
custom[name] = NaN;
|
|
343
384
|
}
|
|
344
385
|
}
|
|
@@ -415,6 +456,13 @@ var Observer = class {
|
|
|
415
456
|
sharkToothValleys: this.previousMetrics?.sharkToothValleys ?? [],
|
|
416
457
|
eventCompletionRate: NaN,
|
|
417
458
|
contentDropAge,
|
|
459
|
+
flowBySystem,
|
|
460
|
+
activityBySystem,
|
|
461
|
+
participantsBySystem,
|
|
462
|
+
flowBySource,
|
|
463
|
+
flowBySink,
|
|
464
|
+
sourceShare,
|
|
465
|
+
sinkShare,
|
|
418
466
|
custom
|
|
419
467
|
};
|
|
420
468
|
this.previousMetrics = metrics;
|
|
@@ -557,6 +605,13 @@ function emptyMetrics(tick = 0) {
|
|
|
557
605
|
sharkToothValleys: [],
|
|
558
606
|
eventCompletionRate: NaN,
|
|
559
607
|
contentDropAge: 0,
|
|
608
|
+
flowBySystem: {},
|
|
609
|
+
activityBySystem: {},
|
|
610
|
+
participantsBySystem: {},
|
|
611
|
+
flowBySource: {},
|
|
612
|
+
flowBySink: {},
|
|
613
|
+
sourceShare: {},
|
|
614
|
+
sinkShare: {},
|
|
560
615
|
custom: {}
|
|
561
616
|
};
|
|
562
617
|
}
|
|
@@ -589,7 +644,7 @@ var P1_ProductionMatchesConsumption = {
|
|
|
589
644
|
severity: 7,
|
|
590
645
|
evidence: { scarceResources: violations, dominantRole: dominantRole?.[0], dominantShare },
|
|
591
646
|
suggestedAction: {
|
|
592
|
-
|
|
647
|
+
parameterType: "cost",
|
|
593
648
|
direction: "decrease",
|
|
594
649
|
magnitude: 0.15,
|
|
595
650
|
reasoning: "Lower production cost to incentivise more production."
|
|
@@ -623,7 +678,8 @@ var P2_ClosedLoopsNeedDirectHandoff = {
|
|
|
623
678
|
severity: 5,
|
|
624
679
|
evidence: { backlogResources, velocity },
|
|
625
680
|
suggestedAction: {
|
|
626
|
-
|
|
681
|
+
parameterType: "fee",
|
|
682
|
+
scope: { tags: ["transaction"] },
|
|
627
683
|
direction: "increase",
|
|
628
684
|
magnitude: 0.2,
|
|
629
685
|
reasoning: "Raise market fees to discourage raw material listings. Direct hand-off at production zones is the correct channel."
|
|
@@ -653,7 +709,7 @@ var P3_BootstrapCapitalCoversFirstTransaction = {
|
|
|
653
709
|
severity: 8,
|
|
654
710
|
evidence: { resource, totalProducers, supply },
|
|
655
711
|
suggestedAction: {
|
|
656
|
-
|
|
712
|
+
parameterType: "cost",
|
|
657
713
|
direction: "decrease",
|
|
658
714
|
magnitude: 0.3,
|
|
659
715
|
reasoning: "Producers cannot complete first transaction. Lower production cost to unblock bootstrap."
|
|
@@ -672,7 +728,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
672
728
|
id: "P4",
|
|
673
729
|
name: "Materials Flow Faster Than Cooldown",
|
|
674
730
|
category: "supply_chain",
|
|
675
|
-
description: "Input delivery rate must exceed or match production cooldown rate. If producers
|
|
731
|
+
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.",
|
|
676
732
|
check(metrics, _thresholds) {
|
|
677
733
|
const { supplyByResource, populationByRole, velocity, totalAgents } = metrics;
|
|
678
734
|
const totalSupply = Object.values(supplyByResource).reduce((s, v) => s + v, 0);
|
|
@@ -685,7 +741,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
685
741
|
severity: 5,
|
|
686
742
|
evidence: { avgSupplyPerAgent, velocity, totalRoles },
|
|
687
743
|
suggestedAction: {
|
|
688
|
-
|
|
744
|
+
parameterType: "yield",
|
|
689
745
|
direction: "increase",
|
|
690
746
|
magnitude: 0.15,
|
|
691
747
|
reasoning: "Low supply per agent with stagnant velocity. Increase yield to compensate."
|
|
@@ -700,7 +756,7 @@ var P4_MaterialsFlowFasterThanCooldown = {
|
|
|
700
756
|
severity: 4,
|
|
701
757
|
evidence: { avgSupplyPerAgent, totalSupply, totalAgents },
|
|
702
758
|
suggestedAction: {
|
|
703
|
-
|
|
759
|
+
parameterType: "yield",
|
|
704
760
|
direction: "decrease",
|
|
705
761
|
magnitude: 0.2,
|
|
706
762
|
reasoning: "Raw materials piling up. Extractors outpacing producers."
|
|
@@ -728,7 +784,7 @@ var P60_SurplusDisposalAsymmetry = {
|
|
|
728
784
|
discount: thresholds.disposalTradeWeightDiscount
|
|
729
785
|
},
|
|
730
786
|
suggestedAction: {
|
|
731
|
-
|
|
787
|
+
parameterType: "cost",
|
|
732
788
|
direction: "decrease",
|
|
733
789
|
magnitude: 0.1,
|
|
734
790
|
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.`
|
|
@@ -771,7 +827,8 @@ var P5_ProfitabilityIsCompetitive = {
|
|
|
771
827
|
population: populationByRole[dominantRole]
|
|
772
828
|
},
|
|
773
829
|
suggestedAction: {
|
|
774
|
-
|
|
830
|
+
parameterType: "fee",
|
|
831
|
+
scope: { tags: ["transaction"] },
|
|
775
832
|
direction: "increase",
|
|
776
833
|
magnitude: thresholds.maxAdjustmentPercent,
|
|
777
834
|
reasoning: `${dominantRole} share at ${((roleShares[dominantRole] ?? 0) * 100).toFixed(0)}%. Likely stampede from non-competitive profitability formula. Raise market friction to slow role accumulation.`
|
|
@@ -797,7 +854,7 @@ var P6_CrowdingMultiplierOnAllRoles = {
|
|
|
797
854
|
severity: 5,
|
|
798
855
|
evidence: { role, share },
|
|
799
856
|
suggestedAction: {
|
|
800
|
-
|
|
857
|
+
parameterType: "cost",
|
|
801
858
|
direction: "increase",
|
|
802
859
|
magnitude: 0.1,
|
|
803
860
|
reasoning: `${role} at ${(share * 100).toFixed(0)}% \u2014 no crowding pressure detected. Apply role-specific cost increase to simulate saturation.`
|
|
@@ -832,7 +889,8 @@ var P7_NonSpecialistsSubsidiseSpecialists = {
|
|
|
832
889
|
severity: 6,
|
|
833
890
|
evidence: { poolName, poolSize, dominantRole, dominantShare },
|
|
834
891
|
suggestedAction: {
|
|
835
|
-
|
|
892
|
+
parameterType: "fee",
|
|
893
|
+
scope: { tags: ["entry"] },
|
|
836
894
|
direction: "decrease",
|
|
837
895
|
magnitude: 0.1,
|
|
838
896
|
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.`
|
|
@@ -860,7 +918,7 @@ var P8_RegulatorCannotFightDesign = {
|
|
|
860
918
|
severity: 4,
|
|
861
919
|
evidence: { dominantRole: dominantRole[0], share: dominantRole[1], avgSatisfaction },
|
|
862
920
|
suggestedAction: {
|
|
863
|
-
|
|
921
|
+
parameterType: "reward",
|
|
864
922
|
direction: "increase",
|
|
865
923
|
magnitude: 0.1,
|
|
866
924
|
reasoning: `Low satisfaction with ${dominantRole[0]} dominant. Regulator may be suppressing a structurally necessary role. Ease pressure on dominant role rewards.`
|
|
@@ -895,7 +953,7 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
895
953
|
severity: 5,
|
|
896
954
|
evidence: { totalChurnRate: totalChurn, churnByRole },
|
|
897
955
|
suggestedAction: {
|
|
898
|
-
|
|
956
|
+
parameterType: "cost",
|
|
899
957
|
direction: "increase",
|
|
900
958
|
magnitude: 0.05,
|
|
901
959
|
reasoning: `Role switch rate ${(totalChurn * 100).toFixed(1)}% exceeds friction threshold. Increase production costs to slow herd movement.`
|
|
@@ -910,9 +968,9 @@ var P9_RoleSwitchingNeedsFriction = {
|
|
|
910
968
|
};
|
|
911
969
|
var P10_SpawnWeightingUsesInversePopulation = {
|
|
912
970
|
id: "P10",
|
|
913
|
-
name: "
|
|
971
|
+
name: "Entry Weighting Uses Inverse Population",
|
|
914
972
|
category: "population",
|
|
915
|
-
description: "New
|
|
973
|
+
description: "New entrants should preferentially fill the least-populated roles. Flat entry probability causes initial imbalances to compound.",
|
|
916
974
|
check(metrics, _thresholds) {
|
|
917
975
|
const { roleShares } = metrics;
|
|
918
976
|
if (Object.keys(roleShares).length === 0) return { violated: false };
|
|
@@ -927,7 +985,7 @@ var P10_SpawnWeightingUsesInversePopulation = {
|
|
|
927
985
|
severity: 4,
|
|
928
986
|
evidence: { roleShares, stdDev, leastPopulatedRole: minRole?.[0] },
|
|
929
987
|
suggestedAction: {
|
|
930
|
-
|
|
988
|
+
parameterType: "yield",
|
|
931
989
|
direction: "increase",
|
|
932
990
|
magnitude: 0.05,
|
|
933
991
|
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.`
|
|
@@ -953,7 +1011,8 @@ var P11_TwoTierPressure = {
|
|
|
953
1011
|
severity: 6,
|
|
954
1012
|
evidence: { role, share },
|
|
955
1013
|
suggestedAction: {
|
|
956
|
-
|
|
1014
|
+
parameterType: "fee",
|
|
1015
|
+
scope: { tags: ["transaction"] },
|
|
957
1016
|
direction: "increase",
|
|
958
1017
|
magnitude: 0.15,
|
|
959
1018
|
reasoning: `${role} at ${(share * 100).toFixed(0)}% \u2014 continuous pressure was insufficient. Hard intervention needed alongside resumed continuous pressure.`
|
|
@@ -981,7 +1040,7 @@ var P46_PersonaDiversity = {
|
|
|
981
1040
|
severity: 5,
|
|
982
1041
|
evidence: { dominantPersona: persona, share, personaDistribution },
|
|
983
1042
|
suggestedAction: {
|
|
984
|
-
|
|
1043
|
+
parameterType: "reward",
|
|
985
1044
|
direction: "increase",
|
|
986
1045
|
magnitude: 0.1,
|
|
987
1046
|
reasoning: `${persona} persona at ${(share * 100).toFixed(0)}% \u2014 behavioral monoculture. Diversify reward structures to attract other persona types.`
|
|
@@ -998,7 +1057,8 @@ var P46_PersonaDiversity = {
|
|
|
998
1057
|
severity: 3,
|
|
999
1058
|
evidence: { significantClusters, required: thresholds.personaMinClusters },
|
|
1000
1059
|
suggestedAction: {
|
|
1001
|
-
|
|
1060
|
+
parameterType: "fee",
|
|
1061
|
+
scope: { tags: ["transaction"] },
|
|
1002
1062
|
direction: "decrease",
|
|
1003
1063
|
magnitude: 0.05,
|
|
1004
1064
|
reasoning: `Only ${significantClusters} significant persona clusters (need ${thresholds.personaMinClusters}). Lower trade barriers to attract non-dominant persona types.`
|
|
@@ -1022,7 +1082,7 @@ var P12_OnePrimaryFaucet = {
|
|
|
1022
1082
|
id: "P12",
|
|
1023
1083
|
name: "One Primary Faucet",
|
|
1024
1084
|
category: "currency",
|
|
1025
|
-
description: "Multiple independent currency sources (gathering + production +
|
|
1085
|
+
description: "Multiple independent currency sources (gathering + production + activities) each creating currency causes uncontrolled inflation. One clear primary faucet makes the economy predictable and auditable.",
|
|
1026
1086
|
check(metrics, thresholds) {
|
|
1027
1087
|
for (const curr of metrics.currencies) {
|
|
1028
1088
|
const netFlow = metrics.netFlowByCurrency[curr] ?? 0;
|
|
@@ -1034,9 +1094,9 @@ var P12_OnePrimaryFaucet = {
|
|
|
1034
1094
|
severity: 5,
|
|
1035
1095
|
evidence: { currency: curr, netFlow, faucetVolume, sinkVolume },
|
|
1036
1096
|
suggestedAction: {
|
|
1037
|
-
|
|
1097
|
+
parameterType: "cost",
|
|
1038
1098
|
direction: "increase",
|
|
1039
|
-
currency: curr,
|
|
1099
|
+
scope: { currency: curr },
|
|
1040
1100
|
magnitude: 0.15,
|
|
1041
1101
|
reasoning: `[${curr}] Net flow +${netFlow.toFixed(1)}/tick. Inflationary. Increase production cost (primary sink) to balance faucet output.`
|
|
1042
1102
|
},
|
|
@@ -1050,9 +1110,9 @@ var P12_OnePrimaryFaucet = {
|
|
|
1050
1110
|
severity: 4,
|
|
1051
1111
|
evidence: { currency: curr, netFlow, faucetVolume, sinkVolume },
|
|
1052
1112
|
suggestedAction: {
|
|
1053
|
-
|
|
1113
|
+
parameterType: "cost",
|
|
1054
1114
|
direction: "decrease",
|
|
1055
|
-
currency: curr,
|
|
1115
|
+
scope: { currency: curr },
|
|
1056
1116
|
magnitude: 0.15,
|
|
1057
1117
|
reasoning: `[${curr}] Net flow ${netFlow.toFixed(1)}/tick. Deflationary. Decrease production cost to ease sink pressure.`
|
|
1058
1118
|
},
|
|
@@ -1084,9 +1144,9 @@ var P13_PotsAreZeroSumAndSelfRegulate = {
|
|
|
1084
1144
|
severity: 7,
|
|
1085
1145
|
evidence: { currency: curr, pool: poolName, poolSize, participants: dominantCount, maxSustainableMultiplier },
|
|
1086
1146
|
suggestedAction: {
|
|
1087
|
-
|
|
1147
|
+
parameterType: "reward",
|
|
1088
1148
|
direction: "decrease",
|
|
1089
|
-
currency: curr,
|
|
1149
|
+
scope: { currency: curr },
|
|
1090
1150
|
magnitude: 0.15,
|
|
1091
1151
|
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.`
|
|
1092
1152
|
},
|
|
@@ -1103,7 +1163,7 @@ var P14_TrackActualInjection = {
|
|
|
1103
1163
|
id: "P14",
|
|
1104
1164
|
name: "Track Actual Currency Injection, Not Value Creation",
|
|
1105
1165
|
category: "currency",
|
|
1106
|
-
description: 'Counting resource gathering as "currency injected" is misleading. Currency enters through faucet mechanisms (
|
|
1166
|
+
description: 'Counting resource gathering as "currency injected" is misleading. Currency enters through faucet mechanisms (entering, rewards). Fake metrics break every downstream decision.',
|
|
1107
1167
|
check(metrics, _thresholds) {
|
|
1108
1168
|
for (const curr of metrics.currencies) {
|
|
1109
1169
|
const faucetVolume = metrics.faucetVolumeByCurrency[curr] ?? 0;
|
|
@@ -1116,9 +1176,9 @@ var P14_TrackActualInjection = {
|
|
|
1116
1176
|
severity: 4,
|
|
1117
1177
|
evidence: { currency: curr, faucetVolume, netFlow, supplyGrowthRate },
|
|
1118
1178
|
suggestedAction: {
|
|
1119
|
-
|
|
1179
|
+
parameterType: "yield",
|
|
1120
1180
|
direction: "decrease",
|
|
1121
|
-
currency: curr,
|
|
1181
|
+
scope: { currency: curr },
|
|
1122
1182
|
magnitude: 0.1,
|
|
1123
1183
|
reasoning: `[${curr}] Supply growing at ${(supplyGrowthRate * 100).toFixed(1)}%/tick. Verify currency injection tracking. Resources should not create currency directly.`
|
|
1124
1184
|
},
|
|
@@ -1148,9 +1208,9 @@ var P15_PoolsNeedCapAndDecay = {
|
|
|
1148
1208
|
severity: 6,
|
|
1149
1209
|
evidence: { currency: curr, pool, size, shareOfSupply, cap: poolCapPercent },
|
|
1150
1210
|
suggestedAction: {
|
|
1151
|
-
|
|
1211
|
+
parameterType: "fee",
|
|
1152
1212
|
direction: "decrease",
|
|
1153
|
-
currency: curr,
|
|
1213
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1154
1214
|
magnitude: 0.1,
|
|
1155
1215
|
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.`
|
|
1156
1216
|
},
|
|
@@ -1180,9 +1240,9 @@ var P16_WithdrawalPenaltyScales = {
|
|
|
1180
1240
|
severity: 3,
|
|
1181
1241
|
evidence: { currency: curr, pool: poolName, poolSize, estimatedStaked: stakedEstimate },
|
|
1182
1242
|
suggestedAction: {
|
|
1183
|
-
|
|
1243
|
+
parameterType: "fee",
|
|
1184
1244
|
direction: "increase",
|
|
1185
|
-
currency: curr,
|
|
1245
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1186
1246
|
magnitude: 0.05,
|
|
1187
1247
|
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.`
|
|
1188
1248
|
},
|
|
@@ -1212,9 +1272,9 @@ var P32_VelocityAboveSupply = {
|
|
|
1212
1272
|
severity: 4,
|
|
1213
1273
|
evidence: { currency: curr, velocity, totalSupply, totalResources },
|
|
1214
1274
|
suggestedAction: {
|
|
1215
|
-
|
|
1275
|
+
parameterType: "fee",
|
|
1216
1276
|
direction: "decrease",
|
|
1217
|
-
currency: curr,
|
|
1277
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1218
1278
|
magnitude: 0.2,
|
|
1219
1279
|
reasoning: `[${curr}] Velocity ${velocity}/t with ${totalResources} resources in system. Economy stagnant despite available supply. Lower trading friction.`
|
|
1220
1280
|
},
|
|
@@ -1254,9 +1314,9 @@ var P58_NoNaturalNumeraire = {
|
|
|
1254
1314
|
meanPrice: mean
|
|
1255
1315
|
},
|
|
1256
1316
|
suggestedAction: {
|
|
1257
|
-
|
|
1317
|
+
parameterType: "cost",
|
|
1258
1318
|
direction: "increase",
|
|
1259
|
-
currency: curr,
|
|
1319
|
+
scope: { currency: curr },
|
|
1260
1320
|
magnitude: 0.1,
|
|
1261
1321
|
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.`
|
|
1262
1322
|
},
|
|
@@ -1291,7 +1351,8 @@ var P17_GracePeriodBeforeIntervention = {
|
|
|
1291
1351
|
severity: 7,
|
|
1292
1352
|
evidence: { tick: metrics.tick, avgSatisfaction: metrics.avgSatisfaction },
|
|
1293
1353
|
suggestedAction: {
|
|
1294
|
-
|
|
1354
|
+
parameterType: "fee",
|
|
1355
|
+
scope: { tags: ["entry"] },
|
|
1295
1356
|
direction: "decrease",
|
|
1296
1357
|
magnitude: 0.2,
|
|
1297
1358
|
reasoning: `Very low satisfaction at tick ${metrics.tick}. Intervention may have fired during grace period. Ease all costs to let economy bootstrap.`
|
|
@@ -1318,7 +1379,7 @@ var P18_FirstProducerNeedsStartingInventory = {
|
|
|
1318
1379
|
severity: 8,
|
|
1319
1380
|
evidence: { tick: metrics.tick, resource, supply, totalAgents: metrics.totalAgents },
|
|
1320
1381
|
suggestedAction: {
|
|
1321
|
-
|
|
1382
|
+
parameterType: "cost",
|
|
1322
1383
|
direction: "decrease",
|
|
1323
1384
|
magnitude: 0.5,
|
|
1324
1385
|
reasoning: `Bootstrap failure: ${resource} supply is 0 at tick ${metrics.tick} with ${metrics.totalAgents} agents. Drastically reduce production cost to allow immediate output.`
|
|
@@ -1357,7 +1418,7 @@ var P19_StartingSupplyExceedsDemand = {
|
|
|
1357
1418
|
resourcesPerAgent
|
|
1358
1419
|
},
|
|
1359
1420
|
suggestedAction: {
|
|
1360
|
-
|
|
1421
|
+
parameterType: "reward",
|
|
1361
1422
|
direction: "increase",
|
|
1362
1423
|
magnitude: 0.2,
|
|
1363
1424
|
reasoning: `${mostPopulatedRole} (${population} agents) has insufficient resources (${resourcesPerAgent.toFixed(2)} per agent). Cold-start scarcity. Boost competitive pool reward to attract participation despite scarcity.`
|
|
@@ -1391,7 +1452,7 @@ var P20_DecayPreventsAccumulation = {
|
|
|
1391
1452
|
severity: 4,
|
|
1392
1453
|
evidence: { totalResources, resourcesPerAgent, velocity },
|
|
1393
1454
|
suggestedAction: {
|
|
1394
|
-
|
|
1455
|
+
parameterType: "yield",
|
|
1395
1456
|
direction: "decrease",
|
|
1396
1457
|
magnitude: 0.1,
|
|
1397
1458
|
reasoning: `${totalResources.toFixed(0)} resources with velocity ${velocity}/t. Likely hoarding. Reduce yield to increase scarcity and force circulation.`
|
|
@@ -1419,7 +1480,8 @@ var P21_PriceFromGlobalSupply = {
|
|
|
1419
1480
|
severity: 3,
|
|
1420
1481
|
evidence: { resource, volatility, supply, price: prices[resource] },
|
|
1421
1482
|
suggestedAction: {
|
|
1422
|
-
|
|
1483
|
+
parameterType: "fee",
|
|
1484
|
+
scope: { tags: ["transaction"] },
|
|
1423
1485
|
direction: "increase",
|
|
1424
1486
|
magnitude: 0.05,
|
|
1425
1487
|
reasoning: `${resource} price volatile (${(volatility * 100).toFixed(0)}%) despite supply ${supply}. Price may not reflect global inventory. Increase trading friction to stabilise.`
|
|
@@ -1436,7 +1498,7 @@ var P22_MarketAwarenessPreventsSurplus = {
|
|
|
1436
1498
|
id: "P22",
|
|
1437
1499
|
name: "Market Awareness Prevents Overproduction",
|
|
1438
1500
|
category: "feedback",
|
|
1439
|
-
description: "Producers who
|
|
1501
|
+
description: "Producers who produce without checking market prices will create surpluses that crash prices. Agents need to see prices before deciding to produce.",
|
|
1440
1502
|
check(metrics, _thresholds) {
|
|
1441
1503
|
const { supplyByResource, prices, productionIndex } = metrics;
|
|
1442
1504
|
const priceValues = Object.values(prices).filter((p) => p > 0);
|
|
@@ -1460,7 +1522,7 @@ var P22_MarketAwarenessPreventsSurplus = {
|
|
|
1460
1522
|
productionIndex
|
|
1461
1523
|
},
|
|
1462
1524
|
suggestedAction: {
|
|
1463
|
-
|
|
1525
|
+
parameterType: "cost",
|
|
1464
1526
|
direction: "increase",
|
|
1465
1527
|
magnitude: 0.1,
|
|
1466
1528
|
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.`
|
|
@@ -1487,7 +1549,7 @@ var P23_ProfitabilityFactorsFeasibility = {
|
|
|
1487
1549
|
severity: 5,
|
|
1488
1550
|
evidence: { blockedFraction, blockedAgentCount, avgSatisfaction },
|
|
1489
1551
|
suggestedAction: {
|
|
1490
|
-
|
|
1552
|
+
parameterType: "cost",
|
|
1491
1553
|
direction: "decrease",
|
|
1492
1554
|
magnitude: 0.15,
|
|
1493
1555
|
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.`
|
|
@@ -1513,7 +1575,8 @@ var P24_BlockedAgentsDecayFaster = {
|
|
|
1513
1575
|
severity: 5,
|
|
1514
1576
|
evidence: { blockedFraction, blockedAgentCount, churnRate },
|
|
1515
1577
|
suggestedAction: {
|
|
1516
|
-
|
|
1578
|
+
parameterType: "fee",
|
|
1579
|
+
scope: { tags: ["transaction"] },
|
|
1517
1580
|
direction: "decrease",
|
|
1518
1581
|
magnitude: 0.15,
|
|
1519
1582
|
reasoning: `${(blockedFraction * 100).toFixed(0)}% of agents blocked. Blocked agents churn silently, skewing metrics. Lower fees to unblock market participation.`
|
|
@@ -1558,7 +1621,7 @@ var P25_CorrectLeversForCorrectProblems = {
|
|
|
1558
1621
|
netFlow
|
|
1559
1622
|
},
|
|
1560
1623
|
suggestedAction: {
|
|
1561
|
-
|
|
1624
|
+
parameterType: "yield",
|
|
1562
1625
|
direction: "decrease",
|
|
1563
1626
|
magnitude: 0.15,
|
|
1564
1627
|
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.`
|
|
@@ -1584,7 +1647,7 @@ var P26_ContinuousPressureBeatsThresholdCuts = {
|
|
|
1584
1647
|
severity: 4,
|
|
1585
1648
|
evidence: { inflationRate },
|
|
1586
1649
|
suggestedAction: {
|
|
1587
|
-
|
|
1650
|
+
parameterType: "cost",
|
|
1588
1651
|
direction: inflationRate > 0 ? "increase" : "decrease",
|
|
1589
1652
|
magnitude: Math.min(thresholds.maxAdjustmentPercent, 0.05),
|
|
1590
1653
|
// force smaller step
|
|
@@ -1610,7 +1673,8 @@ var P27_AdjustmentsNeedCooldowns = {
|
|
|
1610
1673
|
severity: 4,
|
|
1611
1674
|
evidence: { churnRate, avgSatisfaction },
|
|
1612
1675
|
suggestedAction: {
|
|
1613
|
-
|
|
1676
|
+
parameterType: "fee",
|
|
1677
|
+
scope: { tags: ["entry"] },
|
|
1614
1678
|
direction: "decrease",
|
|
1615
1679
|
magnitude: 0.05,
|
|
1616
1680
|
reasoning: `High churn (${(churnRate * 100).toFixed(1)}%) with low satisfaction. Possible oscillation from rapid adjustments. Apply small correction only.`
|
|
@@ -1641,7 +1705,7 @@ var P28_StructuralDominanceIsNotPathological = {
|
|
|
1641
1705
|
severity: 5,
|
|
1642
1706
|
evidence: { dominantRole, dominantShare, avgSatisfaction },
|
|
1643
1707
|
suggestedAction: {
|
|
1644
|
-
|
|
1708
|
+
parameterType: "cost",
|
|
1645
1709
|
direction: "decrease",
|
|
1646
1710
|
magnitude: 0.1,
|
|
1647
1711
|
reasoning: `${dominantRole} dominant (${(dominantShare * 100).toFixed(0)}%) with low satisfaction. Pathological dominance \u2014 agents trapped, not thriving. Ease costs to allow role switching.`
|
|
@@ -1657,7 +1721,7 @@ var P38_CommunicationPreventsRevolt = {
|
|
|
1657
1721
|
id: "P38",
|
|
1658
1722
|
name: "Communication Prevents Revolt",
|
|
1659
1723
|
category: "regulator",
|
|
1660
|
-
description: "Every adjustment must be logged with reasoning. An adjustment made without explanation to
|
|
1724
|
+
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.",
|
|
1661
1725
|
check(metrics, _thresholds) {
|
|
1662
1726
|
const { churnRate } = metrics;
|
|
1663
1727
|
if (churnRate > 0.1) {
|
|
@@ -1666,7 +1730,7 @@ var P38_CommunicationPreventsRevolt = {
|
|
|
1666
1730
|
severity: 3,
|
|
1667
1731
|
evidence: { churnRate },
|
|
1668
1732
|
suggestedAction: {
|
|
1669
|
-
|
|
1733
|
+
parameterType: "reward",
|
|
1670
1734
|
direction: "increase",
|
|
1671
1735
|
magnitude: 0.1,
|
|
1672
1736
|
reasoning: `High churn (${(churnRate * 100).toFixed(1)}%) \u2014 agents leaving. Ensure all recent adjustments are logged with reasoning to diagnose cause.`
|
|
@@ -1689,7 +1753,7 @@ var REGULATOR_PRINCIPLES = [
|
|
|
1689
1753
|
// src/principles/market-dynamics.ts
|
|
1690
1754
|
var P29_PinchPoint = {
|
|
1691
1755
|
id: "P29",
|
|
1692
|
-
name: "
|
|
1756
|
+
name: "Bottleneck Detection",
|
|
1693
1757
|
category: "market_dynamics",
|
|
1694
1758
|
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.",
|
|
1695
1759
|
check(metrics, _thresholds) {
|
|
@@ -1703,7 +1767,7 @@ var P29_PinchPoint = {
|
|
|
1703
1767
|
severity: 7,
|
|
1704
1768
|
evidence: { resource, supply, demand, status },
|
|
1705
1769
|
suggestedAction: {
|
|
1706
|
-
|
|
1770
|
+
parameterType: "cost",
|
|
1707
1771
|
direction: "decrease",
|
|
1708
1772
|
magnitude: 0.15,
|
|
1709
1773
|
reasoning: `${resource} is a pinch point and currently SCARCE (supply ${supply}, demand ${demand}). Reduce production cost to increase throughput.`
|
|
@@ -1719,7 +1783,7 @@ var P29_PinchPoint = {
|
|
|
1719
1783
|
severity: 4,
|
|
1720
1784
|
evidence: { resource, supply, status },
|
|
1721
1785
|
suggestedAction: {
|
|
1722
|
-
|
|
1786
|
+
parameterType: "cost",
|
|
1723
1787
|
direction: "increase",
|
|
1724
1788
|
magnitude: 0.1,
|
|
1725
1789
|
reasoning: `${resource} is a pinch point and OVERSUPPLIED (supply ${supply}). Raise production cost to reduce surplus.`
|
|
@@ -1734,9 +1798,9 @@ var P29_PinchPoint = {
|
|
|
1734
1798
|
};
|
|
1735
1799
|
var P30_MovingPinchPoint = {
|
|
1736
1800
|
id: "P30",
|
|
1737
|
-
name: "
|
|
1801
|
+
name: "Dynamic Bottleneck Rotation",
|
|
1738
1802
|
category: "market_dynamics",
|
|
1739
|
-
description: "
|
|
1803
|
+
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.",
|
|
1740
1804
|
check(metrics, _thresholds) {
|
|
1741
1805
|
const { capacityUsage, supplyByResource, avgSatisfaction } = metrics;
|
|
1742
1806
|
const totalResources = Object.values(supplyByResource).reduce((s, v) => s + v, 0);
|
|
@@ -1747,7 +1811,7 @@ var P30_MovingPinchPoint = {
|
|
|
1747
1811
|
severity: 3,
|
|
1748
1812
|
evidence: { capacityUsage, resourcesPerAgent, avgSatisfaction },
|
|
1749
1813
|
suggestedAction: {
|
|
1750
|
-
|
|
1814
|
+
parameterType: "cost",
|
|
1751
1815
|
direction: "increase",
|
|
1752
1816
|
magnitude: 0.1,
|
|
1753
1817
|
reasoning: "Economy operating at full capacity with abundant resources and high satisfaction. Pinch point may have been cleared. Increase production cost to restore scarcity."
|
|
@@ -1763,7 +1827,7 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1763
1827
|
id: "P57",
|
|
1764
1828
|
name: "Combinatorial Price Space",
|
|
1765
1829
|
category: "market_dynamics",
|
|
1766
|
-
description: "N tradeable items generate (N\u22121)N/2 relative prices. With thousands of items no single
|
|
1830
|
+
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.",
|
|
1767
1831
|
check(metrics, thresholds) {
|
|
1768
1832
|
const { prices, priceVolatility } = metrics;
|
|
1769
1833
|
const priceKeys = Object.keys(prices);
|
|
@@ -1793,7 +1857,8 @@ var P57_CombinatorialPriceSpace = {
|
|
|
1793
1857
|
target: thresholds.relativePriceConvergenceTarget
|
|
1794
1858
|
},
|
|
1795
1859
|
suggestedAction: {
|
|
1796
|
-
|
|
1860
|
+
parameterType: "fee",
|
|
1861
|
+
scope: { tags: ["transaction"] },
|
|
1797
1862
|
direction: "decrease",
|
|
1798
1863
|
magnitude: 0.1,
|
|
1799
1864
|
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.`
|
|
@@ -1825,7 +1890,7 @@ var P31_AnchorValueTracking = {
|
|
|
1825
1890
|
severity: 5,
|
|
1826
1891
|
evidence: { anchorRatioDrift, inflationRate },
|
|
1827
1892
|
suggestedAction: {
|
|
1828
|
-
|
|
1893
|
+
parameterType: "cost",
|
|
1829
1894
|
direction: anchorRatioDrift > 0 ? "increase" : "decrease",
|
|
1830
1895
|
magnitude: 0.1,
|
|
1831
1896
|
reasoning: `Anchor ratio has drifted ${(anchorRatioDrift * 100).toFixed(0)}% from baseline. Time-to-value for participants is changing. Adjust production costs to restore.`
|
|
@@ -1850,7 +1915,8 @@ var P41_MultiResolutionMonitoring = {
|
|
|
1850
1915
|
severity: 4,
|
|
1851
1916
|
evidence: { giniCoefficient, avgSatisfaction },
|
|
1852
1917
|
suggestedAction: {
|
|
1853
|
-
|
|
1918
|
+
parameterType: "fee",
|
|
1919
|
+
scope: { tags: ["transaction"] },
|
|
1854
1920
|
direction: "increase",
|
|
1855
1921
|
magnitude: 0.1,
|
|
1856
1922
|
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.`
|
|
@@ -1879,7 +1945,8 @@ var P55_ArbitrageThermometer = {
|
|
|
1879
1945
|
critical: thresholds.arbitrageIndexCritical
|
|
1880
1946
|
},
|
|
1881
1947
|
suggestedAction: {
|
|
1882
|
-
|
|
1948
|
+
parameterType: "fee",
|
|
1949
|
+
scope: { tags: ["transaction"] },
|
|
1883
1950
|
direction: "decrease",
|
|
1884
1951
|
magnitude: 0.15,
|
|
1885
1952
|
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.`
|
|
@@ -1897,7 +1964,8 @@ var P55_ArbitrageThermometer = {
|
|
|
1897
1964
|
warning: thresholds.arbitrageIndexWarning
|
|
1898
1965
|
},
|
|
1899
1966
|
suggestedAction: {
|
|
1900
|
-
|
|
1967
|
+
parameterType: "fee",
|
|
1968
|
+
scope: { tags: ["transaction"] },
|
|
1901
1969
|
direction: "decrease",
|
|
1902
1970
|
magnitude: 0.08,
|
|
1903
1971
|
reasoning: `Arbitrage index ${arbitrageIndex.toFixed(2)} above warning threshold (${thresholds.arbitrageIndexWarning}). Early sign of price divergence. Gently reduce friction to support self-correction.`
|
|
@@ -1925,7 +1993,8 @@ var P59_GiftEconomyNoise = {
|
|
|
1925
1993
|
threshold: thresholds.giftTradeFilterRatio
|
|
1926
1994
|
},
|
|
1927
1995
|
suggestedAction: {
|
|
1928
|
-
|
|
1996
|
+
parameterType: "fee",
|
|
1997
|
+
scope: { tags: ["transaction"] },
|
|
1929
1998
|
direction: "increase",
|
|
1930
1999
|
magnitude: 0.05,
|
|
1931
2000
|
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.`
|
|
@@ -1968,9 +2037,9 @@ var P42_TheMedianPrinciple = {
|
|
|
1968
2037
|
medianBalance
|
|
1969
2038
|
},
|
|
1970
2039
|
suggestedAction: {
|
|
1971
|
-
|
|
2040
|
+
parameterType: "fee",
|
|
2041
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
1972
2042
|
direction: "increase",
|
|
1973
|
-
currency: curr,
|
|
1974
2043
|
magnitude: 0.15,
|
|
1975
2044
|
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.`
|
|
1976
2045
|
},
|
|
@@ -1995,7 +2064,7 @@ var P43_SimulationMinimum = {
|
|
|
1995
2064
|
severity: 3,
|
|
1996
2065
|
evidence: { inflationRate, minIterations: thresholds.simulationMinIterations },
|
|
1997
2066
|
suggestedAction: {
|
|
1998
|
-
|
|
2067
|
+
parameterType: "cost",
|
|
1999
2068
|
direction: inflationRate > 0 ? "increase" : "decrease",
|
|
2000
2069
|
magnitude: 0.05,
|
|
2001
2070
|
reasoning: `Large inflation rate swing (${(inflationRate * 100).toFixed(0)}%). Ensure all decisions use \u2265${thresholds.simulationMinIterations} simulation iterations. Apply conservative correction.`
|
|
@@ -2033,7 +2102,7 @@ var P39_TheLagPrinciple = {
|
|
|
2033
2102
|
severity: 5,
|
|
2034
2103
|
evidence: { inflationRate, netFlow, lagRange: [lagMin, lagMax] },
|
|
2035
2104
|
suggestedAction: {
|
|
2036
|
-
|
|
2105
|
+
parameterType: "cost",
|
|
2037
2106
|
direction: "increase",
|
|
2038
2107
|
magnitude: 0.03,
|
|
2039
2108
|
// very small — oscillation means over-adjusting
|
|
@@ -2060,7 +2129,8 @@ var P44_ComplexityBudget = {
|
|
|
2060
2129
|
severity: 3,
|
|
2061
2130
|
evidence: { customMetricCount, budgetMax: thresholds.complexityBudgetMax },
|
|
2062
2131
|
suggestedAction: {
|
|
2063
|
-
|
|
2132
|
+
parameterType: "fee",
|
|
2133
|
+
scope: { tags: ["transaction"] },
|
|
2064
2134
|
direction: "decrease",
|
|
2065
2135
|
magnitude: 0.01,
|
|
2066
2136
|
reasoning: `${customMetricCount} custom metrics tracked (budget: ${thresholds.complexityBudgetMax}). Consider pruning low-impact parameters. Applying minimal correction to avoid adding complexity.`
|
|
@@ -2092,7 +2162,8 @@ var P35_DestructionCreatesValue = {
|
|
|
2092
2162
|
severity: 6,
|
|
2093
2163
|
evidence: { resource, supply, sinkVolume, netFlow },
|
|
2094
2164
|
suggestedAction: {
|
|
2095
|
-
|
|
2165
|
+
parameterType: "fee",
|
|
2166
|
+
scope: { tags: ["entry"] },
|
|
2096
2167
|
direction: "decrease",
|
|
2097
2168
|
magnitude: 0.1,
|
|
2098
2169
|
reasoning: `${resource} supply at ${supply} units with low destruction (sink ${sinkVolume}/t). Resources not being consumed. Lower competitive pool entry to increase resource usage.`
|
|
@@ -2120,7 +2191,7 @@ var P40_ReplacementRate = {
|
|
|
2120
2191
|
severity: 6,
|
|
2121
2192
|
evidence: { productionIndex, sinkVolume, replacementRatio },
|
|
2122
2193
|
suggestedAction: {
|
|
2123
|
-
|
|
2194
|
+
parameterType: "yield",
|
|
2124
2195
|
direction: "increase",
|
|
2125
2196
|
magnitude: 0.15,
|
|
2126
2197
|
reasoning: `Replacement rate ${replacementRatio.toFixed(2)} (need \u2265${thresholds.replacementRateMultiplier}). Production below consumption. Resources will deplete. Increase yield.`
|
|
@@ -2134,7 +2205,7 @@ var P40_ReplacementRate = {
|
|
|
2134
2205
|
severity: 3,
|
|
2135
2206
|
evidence: { productionIndex, sinkVolume, replacementRatio },
|
|
2136
2207
|
suggestedAction: {
|
|
2137
|
-
|
|
2208
|
+
parameterType: "yield",
|
|
2138
2209
|
direction: "decrease",
|
|
2139
2210
|
magnitude: 0.1,
|
|
2140
2211
|
reasoning: `Replacement rate ${replacementRatio.toFixed(2)} \u2014 overproducing. Production far exceeds consumption. Reduce yield to prevent glut.`
|
|
@@ -2160,7 +2231,8 @@ var P49_IdleAssetTax = {
|
|
|
2160
2231
|
severity: 5,
|
|
2161
2232
|
evidence: { giniCoefficient, top10PctShare, velocity },
|
|
2162
2233
|
suggestedAction: {
|
|
2163
|
-
|
|
2234
|
+
parameterType: "fee",
|
|
2235
|
+
scope: { tags: ["transaction"] },
|
|
2164
2236
|
direction: "increase",
|
|
2165
2237
|
magnitude: 0.15,
|
|
2166
2238
|
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.`
|
|
@@ -2178,11 +2250,11 @@ var RESOURCE_MGMT_PRINCIPLES = [
|
|
|
2178
2250
|
P49_IdleAssetTax
|
|
2179
2251
|
];
|
|
2180
2252
|
|
|
2181
|
-
// src/principles/
|
|
2253
|
+
// src/principles/participant-experience.ts
|
|
2182
2254
|
var P33_FairNotEqual = {
|
|
2183
2255
|
id: "P33",
|
|
2184
2256
|
name: "Fair \u2260 Equal",
|
|
2185
|
-
category: "
|
|
2257
|
+
category: "participant_experience",
|
|
2186
2258
|
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.",
|
|
2187
2259
|
check(metrics, thresholds) {
|
|
2188
2260
|
for (const curr of metrics.currencies) {
|
|
@@ -2193,9 +2265,9 @@ var P33_FairNotEqual = {
|
|
|
2193
2265
|
severity: 3,
|
|
2194
2266
|
evidence: { currency: curr, giniCoefficient },
|
|
2195
2267
|
suggestedAction: {
|
|
2196
|
-
|
|
2268
|
+
parameterType: "reward",
|
|
2197
2269
|
direction: "increase",
|
|
2198
|
-
currency: curr,
|
|
2270
|
+
scope: { currency: curr },
|
|
2199
2271
|
magnitude: 0.1,
|
|
2200
2272
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 near-perfect equality. Economy lacks stakes. Increase winner rewards to create meaningful spread.`
|
|
2201
2273
|
},
|
|
@@ -2209,9 +2281,9 @@ var P33_FairNotEqual = {
|
|
|
2209
2281
|
severity: 7,
|
|
2210
2282
|
evidence: { currency: curr, giniCoefficient },
|
|
2211
2283
|
suggestedAction: {
|
|
2212
|
-
|
|
2284
|
+
parameterType: "fee",
|
|
2213
2285
|
direction: "increase",
|
|
2214
|
-
currency: curr,
|
|
2286
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2215
2287
|
magnitude: 0.2,
|
|
2216
2288
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 oligarchy level. Toxic inequality. Raise transaction fees to redistribute wealth from rich to pool.`
|
|
2217
2289
|
},
|
|
@@ -2225,9 +2297,9 @@ var P33_FairNotEqual = {
|
|
|
2225
2297
|
severity: 4,
|
|
2226
2298
|
evidence: { currency: curr, giniCoefficient },
|
|
2227
2299
|
suggestedAction: {
|
|
2228
|
-
|
|
2300
|
+
parameterType: "fee",
|
|
2229
2301
|
direction: "increase",
|
|
2230
|
-
currency: curr,
|
|
2302
|
+
scope: { tags: ["transaction"], currency: curr },
|
|
2231
2303
|
magnitude: 0.1,
|
|
2232
2304
|
reasoning: `[${curr}] Gini ${giniCoefficient.toFixed(2)} \u2014 high inequality warning. Gently raise fees to slow wealth concentration.`
|
|
2233
2305
|
},
|
|
@@ -2241,9 +2313,9 @@ var P33_FairNotEqual = {
|
|
|
2241
2313
|
};
|
|
2242
2314
|
var P36_MechanicFrictionDetector = {
|
|
2243
2315
|
id: "P36",
|
|
2244
|
-
name: "
|
|
2245
|
-
category: "
|
|
2246
|
-
description: "Deterministic + probabilistic systems \u2192 expectation mismatch. When
|
|
2316
|
+
name: "Mechanism Friction Detector",
|
|
2317
|
+
category: "participant_experience",
|
|
2318
|
+
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.",
|
|
2247
2319
|
check(metrics, _thresholds) {
|
|
2248
2320
|
const { avgSatisfaction, churnRate, velocity } = metrics;
|
|
2249
2321
|
if (churnRate > 0.1 && avgSatisfaction < 50 && velocity > 3) {
|
|
@@ -2252,10 +2324,10 @@ var P36_MechanicFrictionDetector = {
|
|
|
2252
2324
|
severity: 5,
|
|
2253
2325
|
evidence: { churnRate, avgSatisfaction, velocity },
|
|
2254
2326
|
suggestedAction: {
|
|
2255
|
-
|
|
2327
|
+
parameterType: "reward",
|
|
2256
2328
|
direction: "increase",
|
|
2257
2329
|
magnitude: 0.15,
|
|
2258
|
-
reasoning: `Churn ${(churnRate * 100).toFixed(1)}% with satisfaction ${avgSatisfaction.toFixed(0)} despite active economy (velocity ` + velocity.toFixed(1) + "). Suggests
|
|
2330
|
+
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."
|
|
2259
2331
|
},
|
|
2260
2332
|
confidence: 0.55,
|
|
2261
2333
|
estimatedLag: 15
|
|
@@ -2266,8 +2338,8 @@ var P36_MechanicFrictionDetector = {
|
|
|
2266
2338
|
};
|
|
2267
2339
|
var P37_LatecommerProblem = {
|
|
2268
2340
|
id: "P37",
|
|
2269
|
-
name: "
|
|
2270
|
-
category: "
|
|
2341
|
+
name: "Late Entrant Problem",
|
|
2342
|
+
category: "participant_experience",
|
|
2271
2343
|
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.",
|
|
2272
2344
|
check(metrics, _thresholds) {
|
|
2273
2345
|
const { timeToValue, avgSatisfaction, churnRate } = metrics;
|
|
@@ -2277,7 +2349,7 @@ var P37_LatecommerProblem = {
|
|
|
2277
2349
|
severity: 6,
|
|
2278
2350
|
evidence: { timeToValue, avgSatisfaction, churnRate },
|
|
2279
2351
|
suggestedAction: {
|
|
2280
|
-
|
|
2352
|
+
parameterType: "cost",
|
|
2281
2353
|
direction: "decrease",
|
|
2282
2354
|
magnitude: 0.15,
|
|
2283
2355
|
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.`
|
|
@@ -2292,7 +2364,7 @@ var P37_LatecommerProblem = {
|
|
|
2292
2364
|
var P45_TimeBudget = {
|
|
2293
2365
|
id: "P45",
|
|
2294
2366
|
name: "Time Budget",
|
|
2295
|
-
category: "
|
|
2367
|
+
category: "participant_experience",
|
|
2296
2368
|
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.",
|
|
2297
2369
|
check(metrics, thresholds) {
|
|
2298
2370
|
const { timeToValue, avgSatisfaction } = metrics;
|
|
@@ -2304,8 +2376,9 @@ var P45_TimeBudget = {
|
|
|
2304
2376
|
severity: 5,
|
|
2305
2377
|
evidence: { timeToValue, avgSatisfaction, timeBudgetRatio: thresholds.timeBudgetRatio },
|
|
2306
2378
|
suggestedAction: {
|
|
2307
|
-
|
|
2379
|
+
parameterType: "fee",
|
|
2308
2380
|
direction: "decrease",
|
|
2381
|
+
scope: { tags: ["entry"] },
|
|
2309
2382
|
magnitude: 0.15,
|
|
2310
2383
|
reasoning: `Time-to-value ${timeToValue} ticks with ${avgSatisfaction.toFixed(0)} satisfaction. Economy requires too much time investment. Lower barriers to participation.`
|
|
2311
2384
|
},
|
|
@@ -2319,7 +2392,7 @@ var P45_TimeBudget = {
|
|
|
2319
2392
|
var P50_PayPowerRatio = {
|
|
2320
2393
|
id: "P50",
|
|
2321
2394
|
name: "Pay-Power Ratio",
|
|
2322
|
-
category: "
|
|
2395
|
+
category: "participant_experience",
|
|
2323
2396
|
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.",
|
|
2324
2397
|
check(metrics, thresholds) {
|
|
2325
2398
|
const { top10PctShare, giniCoefficient } = metrics;
|
|
@@ -2334,8 +2407,9 @@ var P50_PayPowerRatio = {
|
|
|
2334
2407
|
threshold: thresholds.payPowerRatioMax
|
|
2335
2408
|
},
|
|
2336
2409
|
suggestedAction: {
|
|
2337
|
-
|
|
2410
|
+
parameterType: "fee",
|
|
2338
2411
|
direction: "increase",
|
|
2412
|
+
scope: { tags: ["transaction"] },
|
|
2339
2413
|
magnitude: 0.2,
|
|
2340
2414
|
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.`
|
|
2341
2415
|
},
|
|
@@ -2346,7 +2420,7 @@ var P50_PayPowerRatio = {
|
|
|
2346
2420
|
return { violated: false };
|
|
2347
2421
|
}
|
|
2348
2422
|
};
|
|
2349
|
-
var
|
|
2423
|
+
var PARTICIPANT_EXPERIENCE_PRINCIPLES = [
|
|
2350
2424
|
P33_FairNotEqual,
|
|
2351
2425
|
P36_MechanicFrictionDetector,
|
|
2352
2426
|
P37_LatecommerProblem,
|
|
@@ -2369,7 +2443,8 @@ var P34_ExtractionRatio = {
|
|
|
2369
2443
|
severity: 8,
|
|
2370
2444
|
evidence: { extractionRatio, threshold: thresholds.extractionRatioRed },
|
|
2371
2445
|
suggestedAction: {
|
|
2372
|
-
|
|
2446
|
+
parameterType: "fee",
|
|
2447
|
+
scope: { tags: ["transaction"] },
|
|
2373
2448
|
direction: "increase",
|
|
2374
2449
|
magnitude: 0.25,
|
|
2375
2450
|
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.`
|
|
@@ -2384,7 +2459,8 @@ var P34_ExtractionRatio = {
|
|
|
2384
2459
|
severity: 5,
|
|
2385
2460
|
evidence: { extractionRatio, threshold: thresholds.extractionRatioYellow },
|
|
2386
2461
|
suggestedAction: {
|
|
2387
|
-
|
|
2462
|
+
parameterType: "fee",
|
|
2463
|
+
scope: { tags: ["transaction"] },
|
|
2388
2464
|
direction: "increase",
|
|
2389
2465
|
magnitude: 0.1,
|
|
2390
2466
|
reasoning: `Extraction ratio ${(extractionRatio * 100).toFixed(0)}% (warning: ${(thresholds.extractionRatioYellow * 100).toFixed(0)}%). Economy trending toward extraction-heavy. Apply early pressure.`
|
|
@@ -2410,7 +2486,7 @@ var P47_SmokeTest = {
|
|
|
2410
2486
|
severity: 9,
|
|
2411
2487
|
evidence: { smokeTestRatio, threshold: thresholds.smokeTestCritical },
|
|
2412
2488
|
suggestedAction: {
|
|
2413
|
-
|
|
2489
|
+
parameterType: "reward",
|
|
2414
2490
|
direction: "increase",
|
|
2415
2491
|
magnitude: 0.2,
|
|
2416
2492
|
reasoning: `Utility/market ratio ${(smokeTestRatio * 100).toFixed(0)}% (critical). Economy is >90% speculative. Collapse risk is extreme. Increase utility rewards to anchor real value.`
|
|
@@ -2425,7 +2501,7 @@ var P47_SmokeTest = {
|
|
|
2425
2501
|
severity: 6,
|
|
2426
2502
|
evidence: { smokeTestRatio, threshold: thresholds.smokeTestWarning },
|
|
2427
2503
|
suggestedAction: {
|
|
2428
|
-
|
|
2504
|
+
parameterType: "reward",
|
|
2429
2505
|
direction: "increase",
|
|
2430
2506
|
magnitude: 0.1,
|
|
2431
2507
|
reasoning: `Utility/market ratio ${(smokeTestRatio * 100).toFixed(0)}% (warning). Economy is >70% speculative. Boost utility rewards to restore intrinsic value anchor.`
|
|
@@ -2451,7 +2527,8 @@ var P48_CurrencyInsulation = {
|
|
|
2451
2527
|
severity: 6,
|
|
2452
2528
|
evidence: { currencyInsulation, threshold: thresholds.currencyInsulationMax },
|
|
2453
2529
|
suggestedAction: {
|
|
2454
|
-
|
|
2530
|
+
parameterType: "fee",
|
|
2531
|
+
scope: { tags: ["transaction"] },
|
|
2455
2532
|
direction: "increase",
|
|
2456
2533
|
magnitude: 0.1,
|
|
2457
2534
|
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.`
|
|
@@ -2469,12 +2546,12 @@ var OPEN_ECONOMY_PRINCIPLES = [
|
|
|
2469
2546
|
P48_CurrencyInsulation
|
|
2470
2547
|
];
|
|
2471
2548
|
|
|
2472
|
-
// src/principles/
|
|
2549
|
+
// src/principles/operations.ts
|
|
2473
2550
|
var P51_SharkTooth = {
|
|
2474
2551
|
id: "P51",
|
|
2475
|
-
name: "
|
|
2476
|
-
category: "
|
|
2477
|
-
description: "Each
|
|
2552
|
+
name: "Cyclical Engagement Pattern",
|
|
2553
|
+
category: "operations",
|
|
2554
|
+
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.",
|
|
2478
2555
|
check(metrics, thresholds) {
|
|
2479
2556
|
const { sharkToothPeaks, sharkToothValleys } = metrics;
|
|
2480
2557
|
if (sharkToothPeaks.length < 2) return { violated: false };
|
|
@@ -2491,10 +2568,10 @@ var P51_SharkTooth = {
|
|
|
2491
2568
|
threshold: thresholds.sharkToothPeakDecay
|
|
2492
2569
|
},
|
|
2493
2570
|
suggestedAction: {
|
|
2494
|
-
|
|
2571
|
+
parameterType: "reward",
|
|
2495
2572
|
direction: "increase",
|
|
2496
2573
|
magnitude: 0.1,
|
|
2497
|
-
reasoning: `Peak engagement dropped to ${(lastPeak / prevPeak * 100).toFixed(0)}% of previous peak (threshold: ${(thresholds.sharkToothPeakDecay * 100).toFixed(0)}%).
|
|
2574
|
+
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.`
|
|
2498
2575
|
},
|
|
2499
2576
|
confidence: 0.75,
|
|
2500
2577
|
estimatedLag: 30
|
|
@@ -2509,10 +2586,10 @@ var P51_SharkTooth = {
|
|
|
2509
2586
|
severity: 4,
|
|
2510
2587
|
evidence: { lastValley, prevValley, ratio: lastValley / prevValley },
|
|
2511
2588
|
suggestedAction: {
|
|
2512
|
-
|
|
2589
|
+
parameterType: "cost",
|
|
2513
2590
|
direction: "decrease",
|
|
2514
2591
|
magnitude: 0.1,
|
|
2515
|
-
reasoning: "Between-
|
|
2592
|
+
reasoning: "Between-activity engagement declining (deepening valleys). Base economy not sustaining participants between activities. Lower production costs to improve off-activity value."
|
|
2516
2593
|
},
|
|
2517
2594
|
confidence: 0.65,
|
|
2518
2595
|
estimatedLag: 20
|
|
@@ -2525,8 +2602,8 @@ var P51_SharkTooth = {
|
|
|
2525
2602
|
var P52_EndowmentEffect = {
|
|
2526
2603
|
id: "P52",
|
|
2527
2604
|
name: "Endowment Effect",
|
|
2528
|
-
category: "
|
|
2529
|
-
description: "Participants who never owned premium items do not value them. Free trial
|
|
2605
|
+
category: "operations",
|
|
2606
|
+
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).",
|
|
2530
2607
|
check(metrics, _thresholds) {
|
|
2531
2608
|
const { avgSatisfaction, churnRate } = metrics;
|
|
2532
2609
|
const { eventCompletionRate } = metrics;
|
|
@@ -2537,10 +2614,10 @@ var P52_EndowmentEffect = {
|
|
|
2537
2614
|
severity: 4,
|
|
2538
2615
|
evidence: { eventCompletionRate, avgSatisfaction, churnRate },
|
|
2539
2616
|
suggestedAction: {
|
|
2540
|
-
|
|
2617
|
+
parameterType: "reward",
|
|
2541
2618
|
direction: "increase",
|
|
2542
2619
|
magnitude: 0.15,
|
|
2543
|
-
reasoning: `${(eventCompletionRate * 100).toFixed(0)}%
|
|
2620
|
+
reasoning: `${(eventCompletionRate * 100).toFixed(0)}% activity completion but satisfaction only ${avgSatisfaction.toFixed(0)}. Activities not creating perceived value. Increase reward quality/quantity.`
|
|
2544
2621
|
},
|
|
2545
2622
|
confidence: 0.6,
|
|
2546
2623
|
estimatedLag: 20
|
|
@@ -2551,8 +2628,8 @@ var P52_EndowmentEffect = {
|
|
|
2551
2628
|
};
|
|
2552
2629
|
var P53_EventCompletionRate = {
|
|
2553
2630
|
id: "P53",
|
|
2554
|
-
name: "
|
|
2555
|
-
category: "
|
|
2631
|
+
name: "Activity Completion Rate Sweet Spot",
|
|
2632
|
+
category: "operations",
|
|
2556
2633
|
description: "Free completion at 60-80% is the sweet spot. <40% = predatory design. >80% = no monetization pressure. 100% free = zero reason to ever spend.",
|
|
2557
2634
|
check(metrics, thresholds) {
|
|
2558
2635
|
const { eventCompletionRate } = metrics;
|
|
@@ -2567,10 +2644,10 @@ var P53_EventCompletionRate = {
|
|
|
2567
2644
|
max: thresholds.eventCompletionMax
|
|
2568
2645
|
},
|
|
2569
2646
|
suggestedAction: {
|
|
2570
|
-
|
|
2647
|
+
parameterType: "cost",
|
|
2571
2648
|
direction: "decrease",
|
|
2572
2649
|
magnitude: 0.15,
|
|
2573
|
-
reasoning: `
|
|
2650
|
+
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.`
|
|
2574
2651
|
},
|
|
2575
2652
|
confidence: 0.8,
|
|
2576
2653
|
estimatedLag: 10
|
|
@@ -2582,10 +2659,11 @@ var P53_EventCompletionRate = {
|
|
|
2582
2659
|
severity: 3,
|
|
2583
2660
|
evidence: { eventCompletionRate, max: thresholds.eventCompletionMax },
|
|
2584
2661
|
suggestedAction: {
|
|
2585
|
-
|
|
2662
|
+
parameterType: "fee",
|
|
2663
|
+
scope: { tags: ["entry"] },
|
|
2586
2664
|
direction: "increase",
|
|
2587
2665
|
magnitude: 0.05,
|
|
2588
|
-
reasoning: `
|
|
2666
|
+
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.`
|
|
2589
2667
|
},
|
|
2590
2668
|
confidence: 0.55,
|
|
2591
2669
|
estimatedLag: 10
|
|
@@ -2596,9 +2674,9 @@ var P53_EventCompletionRate = {
|
|
|
2596
2674
|
};
|
|
2597
2675
|
var P54_LiveOpsCadence = {
|
|
2598
2676
|
id: "P54",
|
|
2599
|
-
name: "
|
|
2600
|
-
category: "
|
|
2601
|
-
description: ">50% of
|
|
2677
|
+
name: "Operational Cadence",
|
|
2678
|
+
category: "operations",
|
|
2679
|
+
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.",
|
|
2602
2680
|
check(metrics, _thresholds) {
|
|
2603
2681
|
const { velocity, avgSatisfaction } = metrics;
|
|
2604
2682
|
if (velocity < 2 && avgSatisfaction < 55 && metrics.tick > 100) {
|
|
@@ -2607,7 +2685,7 @@ var P54_LiveOpsCadence = {
|
|
|
2607
2685
|
severity: 3,
|
|
2608
2686
|
evidence: { velocity, avgSatisfaction, tick: metrics.tick },
|
|
2609
2687
|
suggestedAction: {
|
|
2610
|
-
|
|
2688
|
+
parameterType: "reward",
|
|
2611
2689
|
direction: "increase",
|
|
2612
2690
|
magnitude: 0.1,
|
|
2613
2691
|
reasoning: "Low velocity and satisfaction after long runtime. Possible content staleness. Increase rewards as bridge while new content is developed (developer action required)."
|
|
@@ -2621,8 +2699,8 @@ var P54_LiveOpsCadence = {
|
|
|
2621
2699
|
};
|
|
2622
2700
|
var P56_ContentDropShock = {
|
|
2623
2701
|
id: "P56",
|
|
2624
|
-
name: "
|
|
2625
|
-
category: "
|
|
2702
|
+
name: "Supply Shock Absorption",
|
|
2703
|
+
category: "operations",
|
|
2626
2704
|
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.",
|
|
2627
2705
|
check(metrics, thresholds) {
|
|
2628
2706
|
const { contentDropAge, arbitrageIndex } = metrics;
|
|
@@ -2638,7 +2716,8 @@ var P56_ContentDropShock = {
|
|
|
2638
2716
|
postDropMax: thresholds.postDropArbitrageMax
|
|
2639
2717
|
},
|
|
2640
2718
|
suggestedAction: {
|
|
2641
|
-
|
|
2719
|
+
parameterType: "fee",
|
|
2720
|
+
scope: { tags: ["transaction"] },
|
|
2642
2721
|
direction: "decrease",
|
|
2643
2722
|
magnitude: 0.1,
|
|
2644
2723
|
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.`
|
|
@@ -2651,7 +2730,7 @@ var P56_ContentDropShock = {
|
|
|
2651
2730
|
return { violated: false };
|
|
2652
2731
|
}
|
|
2653
2732
|
};
|
|
2654
|
-
var
|
|
2733
|
+
var OPERATIONS_PRINCIPLES = [
|
|
2655
2734
|
P51_SharkTooth,
|
|
2656
2735
|
P52_EndowmentEffect,
|
|
2657
2736
|
P53_EventCompletionRate,
|
|
@@ -2685,23 +2764,24 @@ var ALL_PRINCIPLES = [
|
|
|
2685
2764
|
// P39, P44
|
|
2686
2765
|
...RESOURCE_MGMT_PRINCIPLES,
|
|
2687
2766
|
// P35, P40, P49
|
|
2688
|
-
...
|
|
2767
|
+
...PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
2689
2768
|
// P33, P36, P37, P45, P50
|
|
2690
2769
|
...OPEN_ECONOMY_PRINCIPLES,
|
|
2691
2770
|
// P34, P47-P48
|
|
2692
|
-
...
|
|
2771
|
+
...OPERATIONS_PRINCIPLES
|
|
2693
2772
|
// P51-P54, P56
|
|
2694
2773
|
];
|
|
2695
2774
|
|
|
2696
2775
|
// src/Simulator.ts
|
|
2697
2776
|
var Simulator = class {
|
|
2698
|
-
constructor() {
|
|
2777
|
+
constructor(registry) {
|
|
2699
2778
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
2700
2779
|
// Cache beforeViolations for the *current* tick only (one entry max).
|
|
2701
2780
|
// Using a Map here is intentional but the cache must be bounded — we only
|
|
2702
2781
|
// care about the tick that is currently being evaluated, so we evict any
|
|
2703
2782
|
// entries whose key differs from the incoming tick.
|
|
2704
2783
|
this.beforeViolationsCache = /* @__PURE__ */ new Map();
|
|
2784
|
+
this.registry = registry;
|
|
2705
2785
|
}
|
|
2706
2786
|
/**
|
|
2707
2787
|
* Simulate the effect of applying `action` to the current economy forward `forwardTicks`.
|
|
@@ -2768,7 +2848,7 @@ var Simulator = class {
|
|
|
2768
2848
|
const multiplier = this.actionMultiplier(action);
|
|
2769
2849
|
const noise = () => 1 + (Math.random() - 0.5) * 0.1;
|
|
2770
2850
|
const currencies = metrics.currencies;
|
|
2771
|
-
const targetCurrency = action.currency;
|
|
2851
|
+
const targetCurrency = action.scope?.currency;
|
|
2772
2852
|
const supplies = { ...metrics.totalSupplyByCurrency };
|
|
2773
2853
|
const netFlows = { ...metrics.netFlowByCurrency };
|
|
2774
2854
|
const ginis = { ...metrics.giniCoefficientByCurrency };
|
|
@@ -2810,26 +2890,48 @@ var Simulator = class {
|
|
|
2810
2890
|
return action.direction === "increase" ? 1 + base : 1 - base;
|
|
2811
2891
|
}
|
|
2812
2892
|
flowEffect(action, metrics, currency) {
|
|
2813
|
-
const {
|
|
2893
|
+
const { direction } = action;
|
|
2814
2894
|
const sign = direction === "increase" ? -1 : 1;
|
|
2815
2895
|
const roleEntries = Object.entries(metrics.populationByRole).sort((a, b) => b[1] - a[1]);
|
|
2816
2896
|
const dominantRoleCount = roleEntries[0]?.[1] ?? 0;
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2897
|
+
const resolvedKey = action.resolvedParameter;
|
|
2898
|
+
let impact;
|
|
2899
|
+
if (resolvedKey && this.registry) {
|
|
2900
|
+
impact = this.registry.getFlowImpact(resolvedKey);
|
|
2901
|
+
}
|
|
2902
|
+
if (!impact) {
|
|
2903
|
+
impact = this.inferFlowImpact(action.parameterType);
|
|
2904
|
+
}
|
|
2905
|
+
switch (impact) {
|
|
2906
|
+
case "sink":
|
|
2907
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.2;
|
|
2908
|
+
case "faucet":
|
|
2909
|
+
return -sign * dominantRoleCount * 0.3;
|
|
2910
|
+
case "neutral":
|
|
2911
|
+
return sign * dominantRoleCount * 0.5;
|
|
2912
|
+
case "mixed":
|
|
2913
|
+
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * 0.15;
|
|
2914
|
+
default:
|
|
2915
|
+
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
/** Infer flow impact from parameter type when registry is unavailable */
|
|
2919
|
+
inferFlowImpact(parameterType) {
|
|
2920
|
+
switch (parameterType) {
|
|
2921
|
+
case "cost":
|
|
2922
|
+
case "fee":
|
|
2923
|
+
case "penalty":
|
|
2924
|
+
return "sink";
|
|
2925
|
+
case "reward":
|
|
2926
|
+
return "faucet";
|
|
2927
|
+
case "yield":
|
|
2928
|
+
return "mixed";
|
|
2929
|
+
case "cap":
|
|
2930
|
+
case "multiplier":
|
|
2931
|
+
return "neutral";
|
|
2932
|
+
default:
|
|
2933
|
+
return "mixed";
|
|
2825
2934
|
}
|
|
2826
|
-
if (parameter === "rewardRate") {
|
|
2827
|
-
return -sign * dominantRoleCount * 0.3;
|
|
2828
|
-
}
|
|
2829
|
-
if (parameter === "yieldRate") {
|
|
2830
|
-
return sign * (metrics.faucetVolumeByCurrency[currency] ?? 0) * 0.15;
|
|
2831
|
-
}
|
|
2832
|
-
return sign * (metrics.netFlowByCurrency[currency] ?? 0) * 0.1;
|
|
2833
2935
|
}
|
|
2834
2936
|
checkImprovement(before, after, action) {
|
|
2835
2937
|
const satisfactionImproved = after.avgSatisfaction >= before.avgSatisfaction - 2;
|
|
@@ -2909,16 +3011,30 @@ var Planner = class {
|
|
|
2909
3011
|
* - parameter is still in cooldown
|
|
2910
3012
|
* - simulation result failed
|
|
2911
3013
|
* - complexity budget exceeded
|
|
3014
|
+
* - no matching parameter in registry
|
|
2912
3015
|
*/
|
|
2913
|
-
plan(diagnosis, metrics, simulationResult, currentParams, thresholds) {
|
|
3016
|
+
plan(diagnosis, metrics, simulationResult, currentParams, thresholds, registry) {
|
|
2914
3017
|
const action = diagnosis.violation.suggestedAction;
|
|
2915
|
-
|
|
3018
|
+
let param;
|
|
3019
|
+
let resolvedBaseline;
|
|
3020
|
+
let scope;
|
|
3021
|
+
if (registry) {
|
|
3022
|
+
const resolved = registry.resolve(action.parameterType, action.scope);
|
|
3023
|
+
if (!resolved) return null;
|
|
3024
|
+
param = resolved.key;
|
|
3025
|
+
resolvedBaseline = resolved.currentValue;
|
|
3026
|
+
scope = resolved.scope;
|
|
3027
|
+
action.resolvedParameter = param;
|
|
3028
|
+
} else {
|
|
3029
|
+
param = action.resolvedParameter ?? action.parameterType;
|
|
3030
|
+
scope = action.scope;
|
|
3031
|
+
}
|
|
2916
3032
|
if (this.lockedParams.has(param)) return null;
|
|
2917
3033
|
if (this.isOnCooldown(param, metrics.tick, thresholds.cooldownTicks)) return null;
|
|
2918
3034
|
if (!simulationResult.netImprovement) return null;
|
|
2919
3035
|
if (!simulationResult.noNewProblems) return null;
|
|
2920
3036
|
if (this.activePlanCount >= thresholds.complexityBudgetMax) return null;
|
|
2921
|
-
const currentValue = currentParams[param] ?? 1;
|
|
3037
|
+
const currentValue = resolvedBaseline ?? currentParams[param] ?? action.absoluteValue ?? 1;
|
|
2922
3038
|
const magnitude = Math.min(action.magnitude ?? 0.1, thresholds.maxAdjustmentPercent);
|
|
2923
3039
|
let targetValue;
|
|
2924
3040
|
if (action.direction === "set" && action.absoluteValue !== void 0) {
|
|
@@ -2938,7 +3054,7 @@ var Planner = class {
|
|
|
2938
3054
|
id: `plan_${metrics.tick}_${param}`,
|
|
2939
3055
|
diagnosis,
|
|
2940
3056
|
parameter: param,
|
|
2941
|
-
...
|
|
3057
|
+
...scope !== void 0 ? { scope } : {},
|
|
2942
3058
|
currentValue,
|
|
2943
3059
|
targetValue,
|
|
2944
3060
|
maxChangePercent: thresholds.maxAdjustmentPercent,
|
|
@@ -2947,7 +3063,6 @@ var Planner = class {
|
|
|
2947
3063
|
metric: "avgSatisfaction",
|
|
2948
3064
|
direction: "below",
|
|
2949
3065
|
threshold: Math.max(20, metrics.avgSatisfaction - 10),
|
|
2950
|
-
// rollback if sat drops >10 pts
|
|
2951
3066
|
checkAfterTick: metrics.tick + estimatedLag + 3
|
|
2952
3067
|
},
|
|
2953
3068
|
simulationResult,
|
|
@@ -2962,6 +3077,9 @@ var Planner = class {
|
|
|
2962
3077
|
recordRolledBack(_plan) {
|
|
2963
3078
|
this.activePlanCount = Math.max(0, this.activePlanCount - 1);
|
|
2964
3079
|
}
|
|
3080
|
+
recordSettled(_plan) {
|
|
3081
|
+
this.activePlanCount = Math.max(0, this.activePlanCount - 1);
|
|
3082
|
+
}
|
|
2965
3083
|
isOnCooldown(param, currentTick, cooldownTicks) {
|
|
2966
3084
|
const lastApplied = this.cooldowns.get(param);
|
|
2967
3085
|
if (lastApplied === void 0) return false;
|
|
@@ -2980,40 +3098,54 @@ var Executor = class {
|
|
|
2980
3098
|
}
|
|
2981
3099
|
async apply(plan, adapter, currentParams) {
|
|
2982
3100
|
const originalValue = currentParams[plan.parameter] ?? plan.currentValue;
|
|
2983
|
-
await adapter.setParam(plan.parameter, plan.targetValue, plan.
|
|
3101
|
+
await adapter.setParam(plan.parameter, plan.targetValue, plan.scope);
|
|
2984
3102
|
plan.appliedAt = plan.diagnosis.tick;
|
|
2985
3103
|
this.activePlans.push({ plan, originalValue });
|
|
2986
3104
|
}
|
|
2987
3105
|
/**
|
|
2988
3106
|
* Check all active plans for rollback conditions.
|
|
2989
|
-
*
|
|
2990
|
-
* Returns list of plans that were rolled back.
|
|
3107
|
+
* Returns { rolledBack, settled } — plans that were undone and plans that passed their window.
|
|
2991
3108
|
*/
|
|
2992
3109
|
async checkRollbacks(metrics, adapter) {
|
|
2993
3110
|
const rolledBack = [];
|
|
3111
|
+
const settled = [];
|
|
2994
3112
|
const remaining = [];
|
|
2995
3113
|
for (const active of this.activePlans) {
|
|
2996
3114
|
const { plan, originalValue } = active;
|
|
2997
3115
|
const rc = plan.rollbackCondition;
|
|
3116
|
+
const maxActiveTicks = 200;
|
|
3117
|
+
if (plan.appliedAt !== void 0 && metrics.tick - plan.appliedAt > maxActiveTicks) {
|
|
3118
|
+
settled.push(plan);
|
|
3119
|
+
continue;
|
|
3120
|
+
}
|
|
2998
3121
|
if (metrics.tick < rc.checkAfterTick) {
|
|
2999
3122
|
remaining.push(active);
|
|
3000
3123
|
continue;
|
|
3001
3124
|
}
|
|
3002
3125
|
const metricValue = this.getMetricValue(metrics, rc.metric);
|
|
3126
|
+
if (Number.isNaN(metricValue)) {
|
|
3127
|
+
console.warn(
|
|
3128
|
+
`[AgentE] Rollback check: metric path '${rc.metric}' resolved to NaN for plan '${plan.id}'. Triggering rollback as fail-safe.`
|
|
3129
|
+
);
|
|
3130
|
+
await adapter.setParam(plan.parameter, originalValue, plan.scope);
|
|
3131
|
+
rolledBack.push(plan);
|
|
3132
|
+
continue;
|
|
3133
|
+
}
|
|
3003
3134
|
const shouldRollback = rc.direction === "below" ? metricValue < rc.threshold : metricValue > rc.threshold;
|
|
3004
3135
|
if (shouldRollback) {
|
|
3005
|
-
await adapter.setParam(plan.parameter, originalValue, plan.
|
|
3136
|
+
await adapter.setParam(plan.parameter, originalValue, plan.scope);
|
|
3006
3137
|
rolledBack.push(plan);
|
|
3007
3138
|
} else {
|
|
3008
3139
|
const settledTick = rc.checkAfterTick + 10;
|
|
3009
3140
|
if (metrics.tick > settledTick) {
|
|
3141
|
+
settled.push(plan);
|
|
3010
3142
|
} else {
|
|
3011
3143
|
remaining.push(active);
|
|
3012
3144
|
}
|
|
3013
3145
|
}
|
|
3014
3146
|
}
|
|
3015
3147
|
this.activePlans = remaining;
|
|
3016
|
-
return rolledBack;
|
|
3148
|
+
return { rolledBack, settled };
|
|
3017
3149
|
}
|
|
3018
3150
|
getMetricValue(metrics, metricPath) {
|
|
3019
3151
|
const parts = metricPath.split(".");
|
|
@@ -3102,7 +3234,8 @@ var DecisionLog = class {
|
|
|
3102
3234
|
return {
|
|
3103
3235
|
id: `stub_${metrics.tick}`,
|
|
3104
3236
|
diagnosis,
|
|
3105
|
-
parameter: action.
|
|
3237
|
+
parameter: action.resolvedParameter ?? action.parameterType,
|
|
3238
|
+
...action.scope !== void 0 ? { scope: action.scope } : {},
|
|
3106
3239
|
currentValue: 1,
|
|
3107
3240
|
targetValue: 1,
|
|
3108
3241
|
maxChangePercent: 0,
|
|
@@ -3340,13 +3473,13 @@ var PersonaTracker = class {
|
|
|
3340
3473
|
Earner: 0,
|
|
3341
3474
|
Builder: 0,
|
|
3342
3475
|
Social: 0,
|
|
3343
|
-
|
|
3476
|
+
HighValue: 0,
|
|
3344
3477
|
Influencer: 0
|
|
3345
3478
|
};
|
|
3346
3479
|
let total = 0;
|
|
3347
3480
|
for (const [, history] of this.agentHistory) {
|
|
3348
3481
|
const persona = this.classify(history);
|
|
3349
|
-
counts[persona]
|
|
3482
|
+
counts[persona] = (counts[persona] ?? 0) + 1;
|
|
3350
3483
|
total++;
|
|
3351
3484
|
}
|
|
3352
3485
|
if (total === 0) return {};
|
|
@@ -3366,7 +3499,7 @@ var PersonaTracker = class {
|
|
|
3366
3499
|
const extraction = avg("netExtraction");
|
|
3367
3500
|
const uniqueItems = avg("uniqueItemsHeld");
|
|
3368
3501
|
const spend = avg("spendAmount");
|
|
3369
|
-
if (spend > 1e3) return "
|
|
3502
|
+
if (spend > 1e3) return "HighValue";
|
|
3370
3503
|
if (txRate > 10) return "Trader";
|
|
3371
3504
|
if (uniqueItems > 5 && extraction < 0) return "Collector";
|
|
3372
3505
|
if (extraction > 100) return "Earner";
|
|
@@ -3375,12 +3508,116 @@ var PersonaTracker = class {
|
|
|
3375
3508
|
}
|
|
3376
3509
|
};
|
|
3377
3510
|
|
|
3511
|
+
// src/ParameterRegistry.ts
|
|
3512
|
+
var ParameterRegistry = class {
|
|
3513
|
+
constructor() {
|
|
3514
|
+
this.parameters = /* @__PURE__ */ new Map();
|
|
3515
|
+
}
|
|
3516
|
+
/** Register a parameter. Overwrites if key already exists. */
|
|
3517
|
+
register(param) {
|
|
3518
|
+
this.parameters.set(param.key, { ...param });
|
|
3519
|
+
}
|
|
3520
|
+
/** Register multiple parameters at once. */
|
|
3521
|
+
registerAll(params) {
|
|
3522
|
+
for (const p of params) this.register(p);
|
|
3523
|
+
}
|
|
3524
|
+
/**
|
|
3525
|
+
* Resolve a parameterType + scope to a concrete RegisteredParameter.
|
|
3526
|
+
* Returns the best match, or undefined if no match.
|
|
3527
|
+
*
|
|
3528
|
+
* Matching rules (in priority order):
|
|
3529
|
+
* 1. Exact type match + all scope fields match
|
|
3530
|
+
* 2. Exact type match + partial scope match (tags overlap)
|
|
3531
|
+
* 3. Exact type match + no scope constraints
|
|
3532
|
+
* 4. undefined (no match)
|
|
3533
|
+
*/
|
|
3534
|
+
resolve(type, scope) {
|
|
3535
|
+
const candidates = this.findByType(type);
|
|
3536
|
+
if (candidates.length === 0) return void 0;
|
|
3537
|
+
if (candidates.length === 1) return candidates[0];
|
|
3538
|
+
let bestScore = -1;
|
|
3539
|
+
let best;
|
|
3540
|
+
for (const candidate of candidates) {
|
|
3541
|
+
const score = this.scopeMatchScore(candidate.scope, scope);
|
|
3542
|
+
if (score > bestScore) {
|
|
3543
|
+
bestScore = score;
|
|
3544
|
+
best = candidate;
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
return best;
|
|
3548
|
+
}
|
|
3549
|
+
/** Find all parameters of a given type. */
|
|
3550
|
+
findByType(type) {
|
|
3551
|
+
const results = [];
|
|
3552
|
+
for (const param of this.parameters.values()) {
|
|
3553
|
+
if (param.type === type) results.push(param);
|
|
3554
|
+
}
|
|
3555
|
+
return results;
|
|
3556
|
+
}
|
|
3557
|
+
/** Find all parameters belonging to a given system. */
|
|
3558
|
+
findBySystem(system) {
|
|
3559
|
+
const results = [];
|
|
3560
|
+
for (const param of this.parameters.values()) {
|
|
3561
|
+
if (param.scope?.system === system) results.push(param);
|
|
3562
|
+
}
|
|
3563
|
+
return results;
|
|
3564
|
+
}
|
|
3565
|
+
/** Get a parameter by its concrete key. */
|
|
3566
|
+
get(key) {
|
|
3567
|
+
return this.parameters.get(key);
|
|
3568
|
+
}
|
|
3569
|
+
/** Get the flow impact of a parameter by its concrete key. */
|
|
3570
|
+
getFlowImpact(key) {
|
|
3571
|
+
return this.parameters.get(key)?.flowImpact;
|
|
3572
|
+
}
|
|
3573
|
+
/** Update the current value of a registered parameter. */
|
|
3574
|
+
updateValue(key, value) {
|
|
3575
|
+
const param = this.parameters.get(key);
|
|
3576
|
+
if (param) {
|
|
3577
|
+
param.currentValue = value;
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
/** Get all registered parameters. */
|
|
3581
|
+
getAll() {
|
|
3582
|
+
return [...this.parameters.values()];
|
|
3583
|
+
}
|
|
3584
|
+
/** Number of registered parameters. */
|
|
3585
|
+
get size() {
|
|
3586
|
+
return this.parameters.size;
|
|
3587
|
+
}
|
|
3588
|
+
// ── Private ─────────────────────────────────────────────────────────────
|
|
3589
|
+
scopeMatchScore(paramScope, queryScope) {
|
|
3590
|
+
if (!queryScope) return 0;
|
|
3591
|
+
if (!paramScope) return 0;
|
|
3592
|
+
let score = 0;
|
|
3593
|
+
if (queryScope.system && paramScope.system) {
|
|
3594
|
+
if (queryScope.system === paramScope.system) score += 10;
|
|
3595
|
+
else return -1;
|
|
3596
|
+
}
|
|
3597
|
+
if (queryScope.currency && paramScope.currency) {
|
|
3598
|
+
if (queryScope.currency === paramScope.currency) score += 5;
|
|
3599
|
+
else return -1;
|
|
3600
|
+
}
|
|
3601
|
+
if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3602
|
+
const overlap = queryScope.tags.filter((t) => paramScope.tags.includes(t)).length;
|
|
3603
|
+
if (overlap > 0) {
|
|
3604
|
+
score += overlap * 3;
|
|
3605
|
+
} else {
|
|
3606
|
+
return -1;
|
|
3607
|
+
}
|
|
3608
|
+
} else if (queryScope.tags && queryScope.tags.length > 0 && paramScope.tags && paramScope.tags.length > 0) {
|
|
3609
|
+
return -1;
|
|
3610
|
+
}
|
|
3611
|
+
return score;
|
|
3612
|
+
}
|
|
3613
|
+
};
|
|
3614
|
+
|
|
3378
3615
|
// src/AgentE.ts
|
|
3379
3616
|
var AgentE = class {
|
|
3380
3617
|
constructor(config) {
|
|
3381
|
-
this.simulator = new Simulator();
|
|
3382
3618
|
this.planner = new Planner();
|
|
3383
3619
|
this.executor = new Executor();
|
|
3620
|
+
this.registry = new ParameterRegistry();
|
|
3384
3621
|
// ── State ──
|
|
3385
3622
|
this.log = new DecisionLog();
|
|
3386
3623
|
this.personaTracker = new PersonaTracker();
|
|
@@ -3405,7 +3642,8 @@ var AgentE = class {
|
|
|
3405
3642
|
gracePeriod: config.gracePeriod ?? 50,
|
|
3406
3643
|
checkInterval: config.checkInterval ?? 5,
|
|
3407
3644
|
maxAdjustmentPercent: config.maxAdjustmentPercent ?? 0.15,
|
|
3408
|
-
cooldownTicks: config.cooldownTicks ?? 15
|
|
3645
|
+
cooldownTicks: config.cooldownTicks ?? 15,
|
|
3646
|
+
parameters: config.parameters ?? []
|
|
3409
3647
|
};
|
|
3410
3648
|
this.thresholds = {
|
|
3411
3649
|
...DEFAULT_THRESHOLDS,
|
|
@@ -3417,6 +3655,10 @@ var AgentE = class {
|
|
|
3417
3655
|
this.observer = new Observer(tickConfig);
|
|
3418
3656
|
this.store = new MetricStore(tickConfig);
|
|
3419
3657
|
this.diagnoser = new Diagnoser(ALL_PRINCIPLES);
|
|
3658
|
+
if (config.parameters) {
|
|
3659
|
+
this.registry.registerAll(config.parameters);
|
|
3660
|
+
}
|
|
3661
|
+
this.simulator = new Simulator(this.registry);
|
|
3420
3662
|
if (config.onDecision) this.on("decision", config.onDecision);
|
|
3421
3663
|
if (config.onAlert) this.on("alert", config.onAlert);
|
|
3422
3664
|
if (config.onRollback) this.on("rollback", config.onRollback);
|
|
@@ -3454,15 +3696,24 @@ var AgentE = class {
|
|
|
3454
3696
|
this.currentTick = currentState.tick;
|
|
3455
3697
|
const events = [...this.eventBuffer];
|
|
3456
3698
|
this.eventBuffer = [];
|
|
3457
|
-
|
|
3699
|
+
let metrics;
|
|
3700
|
+
try {
|
|
3701
|
+
metrics = this.observer.compute(currentState, events);
|
|
3702
|
+
} catch (err) {
|
|
3703
|
+
console.error(`[AgentE] Observer.compute() failed at tick ${currentState.tick}:`, err);
|
|
3704
|
+
return;
|
|
3705
|
+
}
|
|
3458
3706
|
this.store.record(metrics);
|
|
3459
3707
|
this.personaTracker.update(currentState);
|
|
3460
3708
|
metrics.personaDistribution = this.personaTracker.getDistribution();
|
|
3461
|
-
const rolledBack = await this.executor.checkRollbacks(metrics, this.adapter);
|
|
3709
|
+
const { rolledBack, settled } = await this.executor.checkRollbacks(metrics, this.adapter);
|
|
3462
3710
|
for (const plan2 of rolledBack) {
|
|
3463
3711
|
this.planner.recordRolledBack(plan2);
|
|
3464
3712
|
this.emit("rollback", plan2, "rollback condition triggered");
|
|
3465
3713
|
}
|
|
3714
|
+
for (const plan2 of settled) {
|
|
3715
|
+
this.planner.recordSettled(plan2);
|
|
3716
|
+
}
|
|
3466
3717
|
if (metrics.tick < this.config.gracePeriod) return;
|
|
3467
3718
|
if (metrics.tick % this.config.checkInterval !== 0) return;
|
|
3468
3719
|
const diagnoses = this.diagnoser.diagnose(metrics, this.thresholds);
|
|
@@ -3484,7 +3735,8 @@ var AgentE = class {
|
|
|
3484
3735
|
metrics,
|
|
3485
3736
|
simulationResult,
|
|
3486
3737
|
this.params,
|
|
3487
|
-
this.thresholds
|
|
3738
|
+
this.thresholds,
|
|
3739
|
+
this.registry
|
|
3488
3740
|
);
|
|
3489
3741
|
if (!plan) {
|
|
3490
3742
|
let reason = "skipped_cooldown";
|
|
@@ -3504,6 +3756,7 @@ var AgentE = class {
|
|
|
3504
3756
|
}
|
|
3505
3757
|
await this.executor.apply(plan, this.adapter, this.params);
|
|
3506
3758
|
this.params[plan.parameter] = plan.targetValue;
|
|
3759
|
+
this.registry.updateValue(plan.parameter, plan.targetValue);
|
|
3507
3760
|
this.planner.recordApplied(plan, metrics.tick);
|
|
3508
3761
|
const entry = this.log.record(topDiagnosis, plan, "applied", metrics);
|
|
3509
3762
|
this.emit("decision", entry);
|
|
@@ -3513,6 +3766,7 @@ var AgentE = class {
|
|
|
3513
3766
|
async apply(plan) {
|
|
3514
3767
|
await this.executor.apply(plan, this.adapter, this.params);
|
|
3515
3768
|
this.params[plan.parameter] = plan.targetValue;
|
|
3769
|
+
this.registry.updateValue(plan.parameter, plan.targetValue);
|
|
3516
3770
|
this.planner.recordApplied(plan, this.currentTick);
|
|
3517
3771
|
}
|
|
3518
3772
|
// ── Developer API ───────────────────────────────────────────────────────────
|
|
@@ -3537,6 +3791,12 @@ var AgentE = class {
|
|
|
3537
3791
|
removePrinciple(id) {
|
|
3538
3792
|
this.diagnoser.removePrinciple(id);
|
|
3539
3793
|
}
|
|
3794
|
+
registerParameter(param) {
|
|
3795
|
+
this.registry.register(param);
|
|
3796
|
+
}
|
|
3797
|
+
getRegistry() {
|
|
3798
|
+
return this.registry;
|
|
3799
|
+
}
|
|
3540
3800
|
registerCustomMetric(name, fn) {
|
|
3541
3801
|
this.observer.registerCustomMetric(name, fn);
|
|
3542
3802
|
}
|
|
@@ -3938,11 +4198,11 @@ export {
|
|
|
3938
4198
|
Executor,
|
|
3939
4199
|
FEEDBACK_LOOP_PRINCIPLES,
|
|
3940
4200
|
INCENTIVE_PRINCIPLES,
|
|
3941
|
-
LIVEOPS_PRINCIPLES,
|
|
3942
4201
|
MARKET_DYNAMICS_PRINCIPLES,
|
|
3943
4202
|
MEASUREMENT_PRINCIPLES,
|
|
3944
4203
|
MetricStore,
|
|
3945
4204
|
OPEN_ECONOMY_PRINCIPLES,
|
|
4205
|
+
OPERATIONS_PRINCIPLES,
|
|
3946
4206
|
Observer,
|
|
3947
4207
|
P10_SpawnWeightingUsesInversePopulation,
|
|
3948
4208
|
P11_TwoTierPressure,
|
|
@@ -4004,9 +4264,10 @@ export {
|
|
|
4004
4264
|
P7_NonSpecialistsSubsidiseSpecialists,
|
|
4005
4265
|
P8_RegulatorCannotFightDesign,
|
|
4006
4266
|
P9_RoleSwitchingNeedsFriction,
|
|
4267
|
+
PARTICIPANT_EXPERIENCE_PRINCIPLES,
|
|
4007
4268
|
PERSONA_HEALTHY_RANGES,
|
|
4008
|
-
PLAYER_EXPERIENCE_PRINCIPLES,
|
|
4009
4269
|
POPULATION_PRINCIPLES,
|
|
4270
|
+
ParameterRegistry,
|
|
4010
4271
|
PersonaTracker,
|
|
4011
4272
|
Planner,
|
|
4012
4273
|
REGULATOR_PRINCIPLES,
|