@sunsteel/contracts 0.86.0 → 0.88.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.cjs CHANGED
@@ -96,6 +96,19 @@ __export(index_exports, {
96
96
  INCHES_PER_FOOT: () => INCHES_PER_FOOT,
97
97
  LENGTH_UNITS: () => LENGTH_UNITS,
98
98
  LIMITED_SHORTFALL_KG: () => LIMITED_SHORTFALL_KG,
99
+ LP_BLOCK_STEPS: () => LP_BLOCK_STEPS,
100
+ LP_ESTIMATE_MAX_REPS_TO_FAILURE: () => LP_ESTIMATE_MAX_REPS_TO_FAILURE,
101
+ LP_ESTIMATE_MIN_SETS: () => LP_ESTIMATE_MIN_SETS,
102
+ LP_ESTIMATE_STEPS: () => LP_ESTIMATE_STEPS,
103
+ LP_NEXT_BLOCK_KINDS: () => LP_NEXT_BLOCK_KINDS,
104
+ LP_PHASES: () => LP_PHASES,
105
+ LP_PROGRESS_CAP: () => LP_PROGRESS_CAP,
106
+ LP_PROGRESS_THRESHOLD: () => LP_PROGRESS_THRESHOLD,
107
+ LP_RECOVERY: () => LP_RECOVERY,
108
+ LP_REFERENCE_MAX_KG: () => LP_REFERENCE_MAX_KG,
109
+ LP_REST_SECONDS: () => LP_REST_SECONDS,
110
+ LP_STEPS: () => LP_STEPS,
111
+ LP_WORKING_SETS: () => LP_WORKING_SETS,
99
112
  MAX_SETS_PER_EXERCISE: () => MAX_SETS_PER_EXERCISE,
100
113
  MEASURABLE_GOALS_MAX: () => MEASURABLE_GOALS_MAX,
101
114
  MEASURABLE_GOAL_DIRECTIONS: () => MEASURABLE_GOAL_DIRECTIONS,
@@ -104,6 +117,7 @@ __export(index_exports, {
104
117
  MESSAGES_PER_MINUTE_MAX: () => MESSAGES_PER_MINUTE_MAX,
105
118
  MESSAGE_BODY_MAX: () => MESSAGE_BODY_MAX,
106
119
  MESSAGE_PERMISSIONS: () => MESSAGE_PERMISSIONS,
120
+ MESSAGE_REPORT_CONTEXT_BEFORE: () => MESSAGE_REPORT_CONTEXT_BEFORE,
107
121
  MINUTES_IN_DAY: () => MINUTES_IN_DAY,
108
122
  MODERATION_ACTION_KINDS: () => MODERATION_ACTION_KINDS,
109
123
  MODERATION_HISTORY_PAGE_SIZE: () => MODERATION_HISTORY_PAGE_SIZE,
@@ -237,6 +251,7 @@ __export(index_exports, {
237
251
  WEIGHT_UNITS: () => WEIGHT_UNITS,
238
252
  WORKOUT_SESSION_STATUSES: () => WORKOUT_SESSION_STATUSES,
239
253
  accountExportFileName: () => accountExportFileName,
254
+ advanceLinearPeriodization: () => advanceLinearPeriodization,
240
255
  apiError: () => apiError,
241
256
  apiErrorMessage: () => apiErrorMessage,
242
257
  applyDeload: () => applyDeload,
@@ -247,6 +262,7 @@ __export(index_exports, {
247
262
  canLinkToNext: () => canLinkToNext,
248
263
  cmToFeetInches: () => cmToFeetInches,
249
264
  cmToInches: () => cmToInches,
265
+ continueLinearPeriodization: () => continueLinearPeriodization,
250
266
  countsAsWork: () => countsAsWork,
251
267
  countsForProgression: () => countsForProgression,
252
268
  customExerciseProblem: () => customExerciseProblem,
@@ -276,6 +292,17 @@ __export(index_exports, {
276
292
  isWithinQuietHours: () => isWithinQuietHours,
277
293
  latestBodyWeight: () => latestBodyWeight,
278
294
  leadWorkingWeight: () => leadWorkingWeight,
295
+ linearPeriodizationProblem: () => linearPeriodizationProblem,
296
+ lpEstimate: () => lpEstimate,
297
+ lpLoadKg: () => lpLoadKg,
298
+ lpPrescription: () => lpPrescription,
299
+ lpRecommendation: () => lpRecommendation,
300
+ lpRirMidpoint: () => lpRirMidpoint,
301
+ lpSampleRir: () => lpSampleRir,
302
+ lpSetEstimateKg: () => lpSetEstimateKg,
303
+ lpStep: () => lpStep,
304
+ lpStoredSets: () => lpStoredSets,
305
+ lpWorkingSets: () => lpWorkingSets,
279
306
  matchesDeletionConfirmation: () => matchesDeletionConfirmation,
280
307
  messageBodyLength: () => messageBodyLength,
281
308
  normalizeDashboardLayout: () => normalizeDashboardLayout,
@@ -288,10 +315,14 @@ __export(index_exports, {
288
315
  requiredToFinish: () => requiredToFinish,
289
316
  resolveActiveTrainingBlock: () => resolveActiveTrainingBlock,
290
317
  resolveRoutinePlan: () => resolveRoutinePlan,
318
+ roundDownToIncrement: () => roundDownToIncrement,
319
+ roundToIncrement: () => roundToIncrement,
291
320
  routineDayLabel: () => routineDayLabel,
321
+ sameLpPosition: () => sameLpPosition,
292
322
  sessionCorrectionWindow: () => sessionCorrectionWindow,
293
323
  setKindOf: () => setKindOf,
294
324
  setLogValuesDiffer: () => setLogValuesDiffer,
325
+ startLinearPeriodization: () => startLinearPeriodization,
295
326
  summarizeBodyProgress: () => summarizeBodyProgress,
296
327
  trainingBlockCovers: () => trainingBlockCovers,
297
328
  warmUpLoad: () => warmUpLoad,
@@ -311,7 +342,9 @@ var REP_TYPES = ["FIXED", "RANGE"];
311
342
  var PROGRESSION_SCHEMES = [
312
343
  "NONE",
313
344
  "DOUBLE_PROGRESSION",
314
- "DYNAMIC_DOUBLE_PROGRESSION"
345
+ "DYNAMIC_DOUBLE_PROGRESSION",
346
+ // ROUT-17: an 8-step block by percentage of a reference max and target RIR.
347
+ "LINEAR_PERIODIZATION"
315
348
  ];
316
349
  var MUSCLE_GROUPS = [
317
350
  "PECTORAL",
@@ -533,7 +566,11 @@ var REPORT_SUBJECT_KINDS = [
533
566
  // first one the TRUST-04 queue is likely to see in volume: everything above
534
567
  // is content its owner created for themselves and shared, where a comment is
535
568
  // aimed at somebody else.
536
- "COMMENT"
569
+ "COMMENT",
570
+ // MSG-09. A message has no page of its own and is not shared with anyone but
571
+ // the other participant, so its report captures what that participant could
572
+ // see -- the message and up to five before it -- for the moderator to read.
573
+ "MESSAGE"
537
574
  ];
538
575
  var REPORT_REASONS = [
539
576
  "SPAM",
@@ -550,7 +587,12 @@ var MODERATION_ACTION_KINDS = [
550
587
  "VIEW_SUBJECT",
551
588
  "DISMISS_REPORT",
552
589
  "HIDE_SUBJECT",
553
- "RESTORE_SUBJECT"
590
+ "RESTORE_SUBJECT",
591
+ // MSG-09. A power over an account rather than over one thing it made: it
592
+ // stops the account sending and starting conversations until it is lifted.
593
+ // Recorded against the member, from the report it was taken on.
594
+ "RESTRICT_MESSAGING",
595
+ "LIFT_MESSAGING_RESTRICTION"
554
596
  ];
555
597
  var MODERATION_NOTE_MAX_LENGTH = 500;
556
598
  var MODERATION_QUEUE_PAGE_SIZE = 20;
@@ -894,6 +936,224 @@ function requiredToFinish(kind) {
894
936
  return k === "WORKING" || k === "DROP";
895
937
  }
896
938
 
939
+ // src/linear-periodization.ts
940
+ var LP_BLOCK_STEPS = 8;
941
+ var LP_WORKING_SETS = 3;
942
+ var LP_REST_SECONDS = 180;
943
+ var LP_REFERENCE_MAX_KG = 1e3;
944
+ var EASY = { rirMin: 2, rirMax: 3, amrap: false };
945
+ var AMRAP = { rirMin: 0, rirMax: 0, amrap: true };
946
+ var HARD = { rirMin: 1, rirMax: 2, amrap: false };
947
+ var LP_STEPS = [
948
+ { step: 1, percentage: 0.63, sets: [EASY, EASY, AMRAP] },
949
+ { step: 2, percentage: 0.66, sets: [EASY, EASY, AMRAP] },
950
+ { step: 3, percentage: 0.69, sets: [EASY, EASY, AMRAP] },
951
+ { step: 4, percentage: 0.72, sets: [EASY, EASY, AMRAP] },
952
+ { step: 5, percentage: 0.75, sets: [HARD, HARD, HARD] },
953
+ { step: 6, percentage: 0.78, sets: [HARD, HARD, HARD] },
954
+ { step: 7, percentage: 0.81, sets: [HARD, HARD, HARD] },
955
+ { step: 8, percentage: 0.85, sets: [HARD, HARD, HARD] }
956
+ ];
957
+ function lpStep(step) {
958
+ const index = Math.min(Math.max(Math.trunc(step) || 1, 1), LP_BLOCK_STEPS);
959
+ return LP_STEPS[index - 1];
960
+ }
961
+ var LP_RECOVERY = { percentage: 0.7, sets: 2, reps: 5 };
962
+ var tidy = (value) => Math.round(value * 1e6) / 1e6;
963
+ function roundToIncrement(value, increment) {
964
+ if (!(increment > 0)) return tidy(value);
965
+ const steps = value / increment;
966
+ const floor = Math.floor(steps + 1e-9);
967
+ const fraction = steps - floor;
968
+ return tidy((fraction > 0.5 + 1e-9 ? floor + 1 : floor) * increment);
969
+ }
970
+ function roundDownToIncrement(value, increment) {
971
+ if (!(increment > 0)) return tidy(value);
972
+ return tidy(Math.floor(value / increment + 1e-9) * increment);
973
+ }
974
+ function lpLoadKg(referenceMaxKg, percentage, incrementKg) {
975
+ return roundToIncrement(referenceMaxKg * percentage, incrementKg);
976
+ }
977
+ var LP_PHASES = ["BLOCK", "RECOVERY", "FINISHED"];
978
+ function startLinearPeriodization(referenceMaxKg, cycle = 1) {
979
+ return {
980
+ referenceMaxKg,
981
+ phase: "BLOCK",
982
+ step: 1,
983
+ cycle,
984
+ samples: [],
985
+ finishedAt: null,
986
+ estimatedMaxKg: null,
987
+ nextReferenceMaxKg: null
988
+ };
989
+ }
990
+ function linearPeriodizationProblem(state) {
991
+ if (!Number.isFinite(state.referenceMaxKg) || state.referenceMaxKg <= 0 || state.referenceMaxKg > LP_REFERENCE_MAX_KG) {
992
+ return "The reference max must be above 0";
993
+ }
994
+ if (!LP_PHASES.includes(state.phase)) {
995
+ return "Unknown block phase";
996
+ }
997
+ if (!Number.isInteger(state.step) || state.step < 1 || state.step > LP_BLOCK_STEPS) {
998
+ return "The block step must be between 1 and 8";
999
+ }
1000
+ if (!Number.isInteger(state.cycle) || state.cycle < 1) {
1001
+ return "The block number must be 1 or more";
1002
+ }
1003
+ if (state.phase === "RECOVERY" && !((state.nextReferenceMaxKg ?? 0) > 0)) {
1004
+ return "A recovery step needs the next block's reference max";
1005
+ }
1006
+ return null;
1007
+ }
1008
+ function lpPrescription(state, incrementKg) {
1009
+ if (state.phase === "FINISHED") return [];
1010
+ if (state.phase === "RECOVERY") {
1011
+ const loadKg2 = lpLoadKg(
1012
+ state.referenceMaxKg,
1013
+ LP_RECOVERY.percentage,
1014
+ incrementKg
1015
+ );
1016
+ return Array.from({ length: LP_RECOVERY.sets }, () => ({
1017
+ loadKg: loadKg2,
1018
+ target: null,
1019
+ reps: LP_RECOVERY.reps
1020
+ }));
1021
+ }
1022
+ const step = lpStep(state.step);
1023
+ const loadKg = lpLoadKg(state.referenceMaxKg, step.percentage, incrementKg);
1024
+ return step.sets.map((target) => ({ loadKg, target, reps: null }));
1025
+ }
1026
+ function lpWorkingSets(sets) {
1027
+ return sets.filter((set) => setKindOf(set) !== "WARMUP");
1028
+ }
1029
+ var LP_ESTIMATE_STEPS = [7, 8];
1030
+ var LP_ESTIMATE_MAX_REPS_TO_FAILURE = 10;
1031
+ var LP_ESTIMATE_MIN_SETS = 3;
1032
+ function lpRirMidpoint(target) {
1033
+ return (target.rirMin + target.rirMax) / 2;
1034
+ }
1035
+ function lpSampleRir(sample) {
1036
+ const target = lpStep(sample.step).sets[sample.set - 1] ?? HARD;
1037
+ return lpRirMidpoint(target);
1038
+ }
1039
+ function lpSetEstimateKg(loadKg, reps, rir) {
1040
+ return loadKg * (1 + (reps + rir) / 30);
1041
+ }
1042
+ function lpEstimate(samples, incrementKg) {
1043
+ const sets = samples.filter((sample) => LP_ESTIMATE_STEPS.includes(sample.step)).map((sample) => ({ ...sample, rir: lpSampleRir(sample) })).filter(
1044
+ (sample) => sample.reps >= 1 && sample.loadKg > 0 && sample.reps + sample.rir <= LP_ESTIMATE_MAX_REPS_TO_FAILURE
1045
+ ).map((sample) => ({
1046
+ ...sample,
1047
+ estimateKg: tidy(lpSetEstimateKg(sample.loadKg, sample.reps, sample.rir))
1048
+ })).sort((a, b) => a.step - b.step || a.set - b.set);
1049
+ if (sets.length < LP_ESTIMATE_MIN_SETS) {
1050
+ return { estimatedMaxKg: null, sets };
1051
+ }
1052
+ const values = sets.map((set) => set.estimateKg).sort((a, b) => a - b);
1053
+ const middle = Math.floor(values.length / 2);
1054
+ const median = values.length % 2 ? values[middle] : (values[middle - 1] + values[middle]) / 2;
1055
+ return { estimatedMaxKg: roundDownToIncrement(median, incrementKg), sets };
1056
+ }
1057
+ var LP_PROGRESS_THRESHOLD = 0.025;
1058
+ var LP_PROGRESS_CAP = 0.05;
1059
+ var LP_NEXT_BLOCK_KINDS = ["PROGRESS", "REPEAT", "RESET"];
1060
+ function lpRecommendation(referenceMaxKg, estimatedMaxKg, incrementKg) {
1061
+ if (!(estimatedMaxKg && estimatedMaxKg > 0) || !(referenceMaxKg > 0)) {
1062
+ return { kind: "REPEAT", nextReferenceMaxKg: referenceMaxKg, change: null };
1063
+ }
1064
+ const change = estimatedMaxKg / referenceMaxKg - 1;
1065
+ if (change >= LP_PROGRESS_THRESHOLD - 1e-9) {
1066
+ const capped = Math.min(
1067
+ estimatedMaxKg,
1068
+ referenceMaxKg * (1 + LP_PROGRESS_CAP)
1069
+ );
1070
+ const next = roundDownToIncrement(capped, incrementKg);
1071
+ return {
1072
+ kind: "PROGRESS",
1073
+ nextReferenceMaxKg: next > referenceMaxKg ? next : referenceMaxKg,
1074
+ change
1075
+ };
1076
+ }
1077
+ if (change < -LP_PROGRESS_THRESHOLD - 1e-9) {
1078
+ return {
1079
+ kind: "RESET",
1080
+ nextReferenceMaxKg: roundDownToIncrement(estimatedMaxKg, incrementKg),
1081
+ change
1082
+ };
1083
+ }
1084
+ return { kind: "REPEAT", nextReferenceMaxKg: referenceMaxKg, change };
1085
+ }
1086
+ function sameLpPosition(a, b) {
1087
+ if (!a || !b) return !a && !b;
1088
+ return a.phase === b.phase && a.step === b.step && a.cycle === b.cycle && Math.abs(a.referenceMaxKg - b.referenceMaxKg) < 1e-6;
1089
+ }
1090
+ function advanceLinearPeriodization(state, logged, context) {
1091
+ if (state.phase === "FINISHED") return null;
1092
+ const prescribed = lpPrescription(state, context.incrementKg).length;
1093
+ for (let set = 1; set <= prescribed; set += 1) {
1094
+ if (!logged.some((entry) => entry.set === set && entry.completed)) {
1095
+ return null;
1096
+ }
1097
+ }
1098
+ if (state.phase === "RECOVERY") {
1099
+ return startLinearPeriodization(
1100
+ state.nextReferenceMaxKg ?? state.referenceMaxKg,
1101
+ state.cycle + 1
1102
+ );
1103
+ }
1104
+ const samples = LP_ESTIMATE_STEPS.includes(state.step) ? [
1105
+ ...state.samples.filter((sample) => sample.step !== state.step),
1106
+ ...logged.filter((entry) => entry.completed && entry.set <= prescribed).map((entry) => ({
1107
+ sessionId: context.sessionId,
1108
+ step: state.step,
1109
+ set: entry.set,
1110
+ loadKg: entry.loadKg,
1111
+ reps: entry.reps
1112
+ }))
1113
+ ] : state.samples;
1114
+ if (state.step < LP_BLOCK_STEPS) {
1115
+ return { ...state, step: state.step + 1, samples };
1116
+ }
1117
+ return {
1118
+ ...state,
1119
+ phase: "FINISHED",
1120
+ samples,
1121
+ finishedAt: context.finishedAt,
1122
+ estimatedMaxKg: lpEstimate(samples, context.incrementKg).estimatedMaxKg,
1123
+ nextReferenceMaxKg: null
1124
+ };
1125
+ }
1126
+ function continueLinearPeriodization(state, choice) {
1127
+ if (state.phase !== "FINISHED") return null;
1128
+ if (choice.recovery) {
1129
+ return {
1130
+ ...state,
1131
+ phase: "RECOVERY",
1132
+ nextReferenceMaxKg: choice.referenceMaxKg
1133
+ };
1134
+ }
1135
+ return startLinearPeriodization(choice.referenceMaxKg, state.cycle + 1);
1136
+ }
1137
+ function lpStoredSets(state, incrementKg) {
1138
+ if (!state) {
1139
+ return Array.from({ length: LP_WORKING_SETS }, () => ({
1140
+ repType: "FIXED",
1141
+ reps: null,
1142
+ weight: null,
1143
+ rir: null,
1144
+ kind: "WORKING"
1145
+ }));
1146
+ }
1147
+ const prescription = state.phase === "FINISHED" ? lpPrescription({ ...state, phase: "BLOCK", step: LP_BLOCK_STEPS }, incrementKg) : lpPrescription(state, incrementKg);
1148
+ return prescription.map((set) => ({
1149
+ repType: "FIXED",
1150
+ reps: set.reps,
1151
+ weight: set.loadKg,
1152
+ rir: set.target ? set.target.rirMin : null,
1153
+ kind: "WORKING"
1154
+ }));
1155
+ }
1156
+
897
1157
  // src/plate-loading.ts
898
1158
  var CANONICAL_SCALE = 1e4;
899
1159
  var DENSE_CAPACITY_LIMIT = 2e5;
@@ -1526,7 +1786,9 @@ var NOTIFICATION_KINDS = [
1526
1786
  "TRAINING_PARTNER_ENCOURAGEMENT",
1527
1787
  // NOTIF-07: selected activity from a partner who currently shares it.
1528
1788
  "TRAINING_PARTNER_SESSION",
1529
- "TRAINING_PARTNER_ACHIEVEMENT"
1789
+ "TRAINING_PARTNER_ACHIEVEMENT",
1790
+ // ROUT-18: an LP exercise finished its 8-step block.
1791
+ "LINEAR_BLOCK_FINISHED"
1530
1792
  ];
1531
1793
  var NOTIFICATIONS_LOOKBACK_DAYS = 30;
1532
1794
  var NOTIFICATIONS_RETENTION_DAYS = 90;
@@ -1713,6 +1975,14 @@ var API_ERROR_MESSAGES = {
1713
1975
  SWAP_SESSION_NOT_ACTIVE: "Exercises can only be swapped in an active session",
1714
1976
  SWAP_SETS_COMPLETED: "This exercise already has completed sets. Swap it before completing any.",
1715
1977
  NOTES_DISCARDED_SESSION: "A discarded workout cannot take notes",
1978
+ // ── Linear periodization (ROUT-17 to ROUT-19) ──────────────────────────
1979
+ LINEAR_BLOCK_INVALID: "This exercise's block is not valid: {reason}",
1980
+ LINEAR_BLOCK_EXTRA_SET: "An exercise on an 8-week block takes no extra sets",
1981
+ LINEAR_BLOCK_KIND_FIXED: "The working sets of an 8-week block cannot change kind",
1982
+ LINEAR_BLOCK_LOAD_FIXED: "The load of an 8-week block is prescribed and cannot be changed",
1983
+ LINEAR_BLOCK_SWAP_ROUTINE: "An exercise on an 8-week block can be swapped for this workout only",
1984
+ LINEAR_BLOCK_NOT_LINEAR: "This exercise is not on an 8-week block",
1985
+ LINEAR_BLOCK_NOT_FINISHED: "This exercise's block has not finished, so there is nothing to choose yet",
1716
1986
  // ── Corrections (LIVE-17) ──────────────────────────────────────────────
1717
1987
  CORRECTION_NOT_COMPLETED: "Only a completed workout can be corrected",
1718
1988
  CORRECTION_NOT_LATEST: "Only your most recent workout can be corrected",
@@ -1766,6 +2036,11 @@ var API_ERROR_MESSAGES = {
1766
2036
  MESSAGE_NOT_ADMITTED: "This member is not taking messages from you.",
1767
2037
  CONVERSATION_CLOSED: "This conversation can no longer receive messages.",
1768
2038
  MESSAGING_UNAVAILABLE: "Messaging is not available for this account.",
2039
+ // ── Message moderation (MSG-09) ────────────────────────────────────────
2040
+ MESSAGING_RESTRICTED: "Moderation has restricted your messaging. You can still read and delete messages.",
2041
+ REPORT_OWN_MESSAGE: "You cannot report your own message",
2042
+ MESSAGING_ALREADY_RESTRICTED: "This member's messaging is already restricted",
2043
+ MESSAGING_NOT_RESTRICTED: "This member's messaging is not restricted",
1769
2044
  // ── Account and settings ───────────────────────────────────────────────
1770
2045
  ACCOUNT_CONFLICT: "Account conflict for this email",
1771
2046
  ACCOUNT_DELETE_CONFIRMATION: "Type your username exactly as it appears to confirm.",
@@ -1862,6 +2137,7 @@ function normalizeMessageBody(body) {
1862
2137
  }
1863
2138
  return text;
1864
2139
  }
2140
+ var MESSAGE_REPORT_CONTEXT_BEFORE = 5;
1865
2141
  function isMessagePermission(value) {
1866
2142
  return MESSAGE_PERMISSIONS.includes(value);
1867
2143
  }
@@ -1943,6 +2219,19 @@ function isMessagePermission(value) {
1943
2219
  INCHES_PER_FOOT,
1944
2220
  LENGTH_UNITS,
1945
2221
  LIMITED_SHORTFALL_KG,
2222
+ LP_BLOCK_STEPS,
2223
+ LP_ESTIMATE_MAX_REPS_TO_FAILURE,
2224
+ LP_ESTIMATE_MIN_SETS,
2225
+ LP_ESTIMATE_STEPS,
2226
+ LP_NEXT_BLOCK_KINDS,
2227
+ LP_PHASES,
2228
+ LP_PROGRESS_CAP,
2229
+ LP_PROGRESS_THRESHOLD,
2230
+ LP_RECOVERY,
2231
+ LP_REFERENCE_MAX_KG,
2232
+ LP_REST_SECONDS,
2233
+ LP_STEPS,
2234
+ LP_WORKING_SETS,
1946
2235
  MAX_SETS_PER_EXERCISE,
1947
2236
  MEASURABLE_GOALS_MAX,
1948
2237
  MEASURABLE_GOAL_DIRECTIONS,
@@ -1951,6 +2240,7 @@ function isMessagePermission(value) {
1951
2240
  MESSAGES_PER_MINUTE_MAX,
1952
2241
  MESSAGE_BODY_MAX,
1953
2242
  MESSAGE_PERMISSIONS,
2243
+ MESSAGE_REPORT_CONTEXT_BEFORE,
1954
2244
  MINUTES_IN_DAY,
1955
2245
  MODERATION_ACTION_KINDS,
1956
2246
  MODERATION_HISTORY_PAGE_SIZE,
@@ -2084,6 +2374,7 @@ function isMessagePermission(value) {
2084
2374
  WEIGHT_UNITS,
2085
2375
  WORKOUT_SESSION_STATUSES,
2086
2376
  accountExportFileName,
2377
+ advanceLinearPeriodization,
2087
2378
  apiError,
2088
2379
  apiErrorMessage,
2089
2380
  applyDeload,
@@ -2094,6 +2385,7 @@ function isMessagePermission(value) {
2094
2385
  canLinkToNext,
2095
2386
  cmToFeetInches,
2096
2387
  cmToInches,
2388
+ continueLinearPeriodization,
2097
2389
  countsAsWork,
2098
2390
  countsForProgression,
2099
2391
  customExerciseProblem,
@@ -2123,6 +2415,17 @@ function isMessagePermission(value) {
2123
2415
  isWithinQuietHours,
2124
2416
  latestBodyWeight,
2125
2417
  leadWorkingWeight,
2418
+ linearPeriodizationProblem,
2419
+ lpEstimate,
2420
+ lpLoadKg,
2421
+ lpPrescription,
2422
+ lpRecommendation,
2423
+ lpRirMidpoint,
2424
+ lpSampleRir,
2425
+ lpSetEstimateKg,
2426
+ lpStep,
2427
+ lpStoredSets,
2428
+ lpWorkingSets,
2126
2429
  matchesDeletionConfirmation,
2127
2430
  messageBodyLength,
2128
2431
  normalizeDashboardLayout,
@@ -2135,10 +2438,14 @@ function isMessagePermission(value) {
2135
2438
  requiredToFinish,
2136
2439
  resolveActiveTrainingBlock,
2137
2440
  resolveRoutinePlan,
2441
+ roundDownToIncrement,
2442
+ roundToIncrement,
2138
2443
  routineDayLabel,
2444
+ sameLpPosition,
2139
2445
  sessionCorrectionWindow,
2140
2446
  setKindOf,
2141
2447
  setLogValuesDiffer,
2448
+ startLinearPeriodization,
2142
2449
  summarizeBodyProgress,
2143
2450
  trainingBlockCovers,
2144
2451
  warmUpLoad,