Skip to main content
Glama

plan_workouts

Add one or more workouts to the athlete's training calendar (the days appear in Blocks). WORKFLOW per day: prefer an existing workout and pass its id as workoutId — from the catalog map already in your context if you have one, otherwise via search_catalog. Only when nothing suitable exists, pass a custom workout (validated server-side; also saved to the athlete's library). Optionally attach a short note per item, and set key:true on the one or two sessions the week is built around (you may set at most 2 per week yourself — the athlete has no such limit — declare them FIRST and fill the rest of the week around them, which is also the order a week is planned in). Batch the whole block (e.g. 3 weeks) in one call — at most about four weeks per call: the 40-item cap is a ceiling, not a target, and a call too long to finish is cut by the length limit and saves nothing. For a longer horizon place the first block, say the rest goes in block by block, and repeat weeks with copy_week. Returns per-item result with the new iid, duration and TSS.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
whyNoONE line, in the athlete's language: WHY this change — the reason from the conversation ("travel Thu-Fri, long ride moved to Sat", "deload after 3 build weeks"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.
itemsYesone entry per scheduled workout

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / workout / properties / blocks / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "children": {
      -        "items": {
      -          "properties": {
      -            "cad": {
      -              "description": "target cadence rpm",
      -              "maximum": 9007199254740991,
      -              "minimum": -9007199254740991,
      -              "type": "integer"
      -            },
      -            "dist": {
      -              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -              "maximum": 50000,
      -              "minimum": 25,
      -              "type": "integer"
      -            },
      -            "dur": {
      -              "description": "seconds (omit when using dist)",
      -              "exclusiveMinimum": 0,
      -              "maximum": 9007199254740991,
      -              "type": "integer"
      -            },
      -            "gear": {
      -              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -              "items": {
      -                "enum": [
      -                  "paddles",
      -                  "buoy",
      -                  "fins",
      -                  "board",
      -                  "snorkel"
      -                ],
      -                "type": "string"
      -              },
      -              "maxItems": 3,
      -              "type": "array"
      -            },
      -            "label": {
      -              "maxLength": 80,
      -              "type": "string"
      -            },
      -            "maxHr": {
      -              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      -              "maximum": 220,
      -              "minimum": 80,
      -              "type": "integer"
      -            },
      -            "maxRpe": {
      -              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      -              "maximum": 10,
      -              "minimum": 1,
      -              "type": "integer"
      -            },
      -            "maxW": {
      -              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      -              "maximum": 2000,
      -              "minimum": 50,
      -              "type": "integer"
      -            },
      -            "mode": {
      -              "description": "SWIMMING: swim (default) | kick | pull | drill",
      -              "enum": [
      -                "swim",
      -                "kick",
      -                "pull",
      -                "drill"
      -              ],
      -              "type": "string"
      -            },
      -            "open": {
      -              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -              "type": "boolean"
      -            },
      -            "power": {
      -              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -              "maximum": 200,
      -              "minimum": 30,
      -              "type": "number"
      -            },
      -            "sft": {
      -              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      -              "type": "boolean"
      -            },
      -            "stroke": {
      -              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -              "enum": [
      -                "free",
      -                "back",
      -                "breast",
      -                "fly",
      -                "im",
      -                "choice"
      -              ],
      -              "type": "string"
      -            },
      -            "target": {
      -              "description": "this step's own device target, over the session's",
      -              "enum": [
      -                "power",
      -                "pace",
      -                "hr",
      -                "rpe"
      -              ],
      -              "type": "string"
      -            },
      -            "untilLap": {
      -              "description": "the step ends when the athlete presses Lap",
      -              "type": "boolean"
      -            },
      -            "zone": {
      -              "enum": [
      -                "recovery",
      -                "endurance",
      -                "tempo",
      -                "threshold",
      -                "vo2",
      -                "sprint"
      -              ],
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "zone",
      -            "power"
      -          ],
      -          "type": "object"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "reps": {
      -        "maximum": 30,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "sendoff": {
      -        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      -        "maximum": 1800,
      -        "minimum": 10,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "repeat",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "reps",
      -      "children"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "cad": {
      -        "description": "target cadence rpm",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "dist": {
      -        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -        "maximum": 50000,
      -        "minimum": 25,
      -        "type": "integer"
      -      },
      -      "dur": {
      -        "description": "seconds (omit when using dist)",
      -        "exclusiveMinimum": 0,
      -        "maximum": 9007199254740991,
      -        "type": "integer"
      -      },
      -      "gear": {
      -        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -        "items": {
      -          "enum": [
      -            "paddles",
      -            "buoy",
      -            "fins",
      -            "board",
      -            "snorkel"
      -          ],
      -          "type": "string"
      -        },
      -        "maxItems": 3,
      -        "type": "array"
      -      },
      -      "label": {
      -        "maxLength": 80,
      -        "type": "string"
      -      },
      -      "maxHr": {
      -        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      -        "maximum": 220,
      -        "minimum": 80,
      -        "type": "integer"
      -      },
      -      "maxRpe": {
      -        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      -        "maximum": 10,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "maxW": {
      -        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      -        "maximum": 2000,
      -        "minimum": 50,
      -        "type": "integer"
      -      },
      -      "mode": {
      -        "description": "SWIMMING: swim (default) | kick | pull | drill",
      -        "enum": [
      -          "swim",
      -          "kick",
      -          "pull",
      -          "drill"
      -        ],
      -        "type": "string"
      -      },
      -      "open": {
      -        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -        "type": "boolean"
      -      },
      -      "power": {
      -        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -        "maximum": 200,
      -        "minimum": 30,
      -        "type": "number"
      -      },
      -      "sft": {
      -        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      -        "type": "boolean"
      -      },
      -      "stroke": {
      -        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -        "enum": [
      -          "free",
      -          "back",
      -          "breast",
      -          "fly",
      -          "im",
      -          "choice"
      -        ],
      -        "type": "string"
      -      },
      -      "target": {
      -        "description": "this step's own device target, over the session's",
      -        "enum": [
      -          "power",
      -          "pace",
      -          "hr",
      -          "rpe"
      -        ],
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "steady",
      -        "type": "string"
      -      },
      -      "untilLap": {
      -        "description": "the step ends when the athlete presses Lap",
      -        "type": "boolean"
      -      },
      -      "zone": {
      -        "enum": [
      -          "recovery",
      -          "endurance",
      -          "tempo",
      -          "threshold",
      -          "vo2",
      -          "sprint"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "zone",
      -      "power"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "children": {
      +        "items": {
      +          "properties": {
      +            "cad": {
      +              "description": "target cadence rpm",
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            },
      +            "dist": {
      +              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +              "maximum": 50000,
      +              "minimum": 25,
      +              "type": "integer"
      +            },
      +            "dur": {
      +              "description": "seconds (omit when using dist)",
      +              "exclusiveMinimum": 0,
      +              "maximum": 9007199254740991,
      +              "type": "integer"
      +            },
      +            "gear": {
      +              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +              "items": {
      +                "enum": [
      +                  "paddles",
      +                  "buoy",
      +                  "fins",
      +                  "board",
      +                  "snorkel"
      +                ],
      +                "type": "string"
      +              },
      +              "maxItems": 3,
      +              "type": "array"
      +            },
      +            "hr": {
      +              "description": "the athlete's own HR corridor for this step, bpm (\"135-145\") — over the zone's band on the card, the watch and the autopilot; only when they named one",
      +              "properties": {
      +                "hi": {
      +                  "maximum": 220,
      +                  "minimum": 61,
      +                  "type": "integer"
      +                },
      +                "lo": {
      +                  "maximum": 219,
      +                  "minimum": 60,
      +                  "type": "integer"
      +                }
      +              },
      +              "required": [
      +                "lo",
      +                "hi"
      +              ],
      +              "type": "object"
      +            },
      +            "label": {
      +              "maxLength": 80,
      +              "type": "string"
      +            },
      +            "maxHr": {
      +              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      +              "maximum": 220,
      +              "minimum": 80,
      +              "type": "integer"
      +            },
      +            "maxRpe": {
      +              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      +              "maximum": 10,
      +              "minimum": 1,
      +              "type": "integer"
      +            },
      +            "maxW": {
      +              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      +              "maximum": 2000,
      +              "minimum": 50,
      +              "type": "integer"
      +            },
      +            "mode": {
      +              "description": "SWIMMING: swim (default) | kick | pull | drill",
      +              "enum": [
      +                "swim",
      +                "kick",
      +                "pull",
      +                "drill"
      +              ],
      +              "type": "string"
      +            },
      +            "open": {
      +              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +              "type": "boolean"
      +            },
      +            "power": {
      +              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +              "maximum": 200,
      +              "minimum": 30,
      +              "type": "number"
      +            },
      +            "sft": {
      +              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +              "type": "boolean"
      +            },
      +            "stroke": {
      +              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +              "enum": [
      +                "free",
      +                "back",
      +                "breast",
      +                "fly",
      +                "im",
      +                "choice"
      +              ],
      +              "type": "string"
      +            },
      +            "target": {
      +              "description": "this step's own device target, over the session's",
      +              "enum": [
      +                "power",
      +                "pace",
      +                "hr",
      +                "rpe"
      +              ],
      +              "type": "string"
      +            },
      +            "untilLap": {
      +              "description": "the step ends when the athlete presses Lap",
      +              "type": "boolean"
      +            },
      +            "zone": {
      +              "enum": [
      +                "recovery",
      +                "endurance",
      +                "tempo",
      +                "threshold",
      +                "vo2",
      +                "sprint"
      +              ],
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "zone",
      +            "power"
      +          ],
      +          "type": "object"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "reps": {
      +        "maximum": 30,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "sendoff": {
      +        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      +        "maximum": 1800,
      +        "minimum": 10,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "repeat",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "reps",
      +      "children"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "cad": {
      +        "description": "target cadence rpm",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "dist": {
      +        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +        "maximum": 50000,
      +        "minimum": 25,
      +        "type": "integer"
      +      },
      +      "dur": {
      +        "description": "seconds (omit when using dist)",
      +        "exclusiveMinimum": 0,
      +        "maximum": 9007199254740991,
      +        "type": "integer"
      +      },
      +      "gear": {
      +        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +        "items": {
      +          "enum": [
      +            "paddles",
      +            "buoy",
      +            "fins",
      +            "board",
      +            "snorkel"
      +          ],
      +          "type": "string"
      +        },
      +        "maxItems": 3,
      +        "type": "array"
      +      },
      +      "hr": {
      +        "description": "the athlete's own HR corridor for this step, bpm (\"135-145\") — over the zone's band on the card, the watch and the autopilot; only when they named one",
      +        "properties": {
      +          "hi": {
      +            "maximum": 220,
      +            "minimum": 61,
      +            "type": "integer"
      +          },
      +          "lo": {
      +            "maximum": 219,
      +            "minimum": 60,
      +            "type": "integer"
      +          }
      +        },
      +        "required": [
      +          "lo",
      +          "hi"
      +        ],
      +        "type": "object"
      +      },
      +      "label": {
      +        "maxLength": 80,
      +        "type": "string"
      +      },
      +      "maxHr": {
      +        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      +        "maximum": 220,
      +        "minimum": 80,
      +        "type": "integer"
      +      },
      +      "maxRpe": {
      +        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      +        "maximum": 10,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "maxW": {
      +        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      +        "maximum": 2000,
      +        "minimum": 50,
      +        "type": "integer"
      +      },
      +      "mode": {
      +        "description": "SWIMMING: swim (default) | kick | pull | drill",
      +        "enum": [
      +          "swim",
      +          "kick",
      +          "pull",
      +          "drill"
      +        ],
      +        "type": "string"
      +      },
      +      "open": {
      +        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +        "type": "boolean"
      +      },
      +      "power": {
      +        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +        "maximum": 200,
      +        "minimum": 30,
      +        "type": "number"
      +      },
      +      "sft": {
      +        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +        "type": "boolean"
      +      },
      +      "stroke": {
      +        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +        "enum": [
      +          "free",
      +          "back",
      +          "breast",
      +          "fly",
      +          "im",
      +          "choice"
      +        ],
      +        "type": "string"
      +      },
      +      "target": {
      +        "description": "this step's own device target, over the session's",
      +        "enum": [
      +          "power",
      +          "pace",
      +          "hr",
      +          "rpe"
      +        ],
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "steady",
      +        "type": "string"
      +      },
      +      "untilLap": {
      +        "description": "the step ends when the athlete presses Lap",
      +        "type": "boolean"
      +      },
      +      "zone": {
      +        "enum": [
      +          "recovery",
      +          "endurance",
      +          "tempo",
      +          "threshold",
      +          "vo2",
      +          "sprint"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "zone",
      +      "power"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / workout / properties / strength / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "mode": {
      -        "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
      -        "enum": [
      -          "kg",
      -          "sec",
      -          "m"
      -        ],
      -        "type": "string"
      -      },
      -      "name": {
      -        "description": "exercise name, e.g. 'Back squat', 'Sled push'",
      -        "maxLength": 80,
      -        "type": "string"
      -      },
      -      "note": {
      -        "description": "optional cue: target HR, technique focus",
      -        "maxLength": 300,
      -        "type": "string"
      -      },
      -      "reps": {
      -        "description": "kg mode only",
      -        "maximum": 1000,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "rpe": {
      -        "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
      -        "maximum": 10,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "sets": {
      -        "maximum": 50,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "ex",
      -        "type": "string"
      -      },
      -      "val": {
      -        "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
      -        "maximum": 100000,
      -        "minimum": 0,
      -        "type": "number"
      -      }
      -    },
      -    "required": [
      -      "name",
      -      "mode",
      -      "val",
      -      "sets"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "ex": {
      -        "items": {
      -          "properties": {
      -            "mode": {
      -              "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
      -              "enum": [
      -                "kg",
      -                "sec",
      -                "m"
      -              ],
      -              "type": "string"
      -            },
      -            "name": {
      -              "description": "exercise name, e.g. 'Back squat', 'Sled push'",
      -              "maxLength": 80,
      -              "type": "string"
      -            },
      -            "note": {
      -              "description": "optional cue: target HR, technique focus",
      -              "maxLength": 300,
      -              "type": "string"
      -            },
      -            "reps": {
      -              "description": "kg mode only",
      -              "maximum": 1000,
      -              "minimum": 1,
      -              "type": "integer"
      -            },
      -            "rpe": {
      -              "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
      -              "maximum": 10,
      -              "minimum": 1,
      -              "type": "integer"
      -            },
      -            "val": {
      -              "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
      -              "maximum": 100000,
      -              "minimum": 0,
      -              "type": "number"
      -            }
      -          },
      -          "required": [
      -            "name",
      -            "mode",
      -            "val"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 8,
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "sets": {
      -        "description": "shared rounds for the whole superset",
      -        "maximum": 50,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "ss",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "sets",
      -      "ex"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "mode": {
      +        "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
      +        "enum": [
      +          "kg",
      +          "sec",
      +          "m"
      +        ],
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "exercise name, e.g. 'Back squat', 'Sled push'",
      +        "maxLength": 80,
      +        "type": "string"
      +      },
      +      "note": {
      +        "description": "optional cue: target HR, technique focus",
      +        "maxLength": 300,
      +        "type": "string"
      +      },
      +      "reps": {
      +        "description": "kg mode only",
      +        "maximum": 1000,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "rpe": {
      +        "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
      +        "maximum": 10,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "sets": {
      +        "maximum": 50,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "ex",
      +        "type": "string"
      +      },
      +      "unit": {
      +        "description": "lb = this exercise's weight is in pounds (their dumbbells or a machine in lb); omit for kg. Keep the unit the athlete logs it in",
      +        "enum": [
      +          "lb"
      +        ],
      +        "type": "string"
      +      },
      +      "val": {
      +        "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
      +        "maximum": 100000,
      +        "minimum": 0,
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "mode",
      +      "val",
      +      "sets"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "ex": {
      +        "items": {
      +          "properties": {
      +            "mode": {
      +              "description": "kg = weight×reps, sec = timed hold/effort, m = distance-based",
      +              "enum": [
      +                "kg",
      +                "sec",
      +                "m"
      +              ],
      +              "type": "string"
      +            },
      +            "name": {
      +              "description": "exercise name, e.g. 'Back squat', 'Sled push'",
      +              "maxLength": 80,
      +              "type": "string"
      +            },
      +            "note": {
      +              "description": "optional cue: target HR, technique focus",
      +              "maxLength": 300,
      +              "type": "string"
      +            },
      +            "reps": {
      +              "description": "kg mode only",
      +              "maximum": 1000,
      +              "minimum": 1,
      +              "type": "integer"
      +            },
      +            "rpe": {
      +              "description": "target RPE 1-10 — REQUIRED on kg work, because RPE is the actual prescription and the weight is at most a starting suggestion they autoregulate from",
      +              "maximum": 10,
      +              "minimum": 1,
      +              "type": "integer"
      +            },
      +            "unit": {
      +              "description": "lb = this exercise's weight is in pounds (their dumbbells or a machine in lb); omit for kg. Keep the unit the athlete logs it in",
      +              "enum": [
      +                "lb"
      +              ],
      +              "type": "string"
      +            },
      +            "val": {
      +              "description": "kg → weight; sec → seconds; m → metres. FOR kg: 0 MEANS NO WEIGHT PRESCRIBED, and 0 is the right answer unless you actually know what they own (a fact tagged 'equipment', or they named a number in this conversation). Do not guess a round figure — an athlete with 9 kg dumbbells reads your invented 10 kg as an instruction they cannot follow. Write 0, prescribe the RPE, and say in your reply that they pick the weight.",
      +              "maximum": 100000,
      +              "minimum": 0,
      +              "type": "number"
      +            }
      +          },
      +          "required": [
      +            "name",
      +            "mode",
      +            "val"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 8,
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "sets": {
      +        "description": "shared rounds for the whole superset",
      +        "maximum": 50,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "ss",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "sets",
      +      "ex"
      +    ],
      +    "type": "object"
      +  }
      +]
  3. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / time
      Added value: +{
      +  "description": "HH:MM start — set it when the day holds more than one session; the calendar orders the day by it",
      +  "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
      +  "type": "string"
      +}
  4. Changed2 schema fields changed
    • changedInput schema / properties / items / items / properties / note / description
      Previous value: -"optional short note (a few words)"New value: +"optional session brief — how to ride it, fuelling (tight)"
    • changedInput schema / properties / items / items / properties / note / maxLength
      Previous value: -140New value: +500
  5. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / goal / description
      Previous value: -"WHY this session exists — one plain line the athlete reads right under its name (\"Raise the ceiling: repeatable efforts near VO2max.\"), not how to ride it. Give one for EVERY custom workout. A catalog workout already shows its own line, so pass this only when this placement has a reason of its own (\"Opener for Sunday's race.\")."New value: +"THE QUALITY this session trains — why it is in the plan — as a short phrase that LEADS with the quality, in the athlete's language: «Аэробная база», «МПК: поднять потолок», «Порог: гоночная мощность», «Силовая выносливость ног», «Экономичность бега», «Восстановление»; a test or race says what it is («Тест: лактатная шкала», «Гонка A»). Not the day's context (no «свежесть к Long», no pulse caps, no logistics) and not how to ride it — that is the note. Give one for EVERY custom workout; a catalog workout already shows its own, so pass this only to change it."
  6. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / goal
      Added value: +{
      +  "description": "WHY this session exists — one plain line the athlete reads right under its name (\"Raise the ceiling: repeatable efforts near VO2max.\"), not how to ride it. Give one for EVERY custom workout. A catalog workout already shows its own line, so pass this only when this placement has a reason of its own (\"Opener for Sunday's race.\").",
      +  "maxLength": 140,
      +  "type": "string"
      +}
  7. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / workout / properties / strength / description
      Previous value: -"strength/gym only: exercises + supersets instead of blocks. No duration/TSS is computed for strength sessions."New value: +"strength/gym only: exercises + supersets instead of blocks. No duration/TSS is computed for strength sessions. Every exercise serves the athlete's goal — no plank/crunch \"core finishers\" for an endurance athlete unless they asked (the base shows no reliable endurance transfer)."
  8. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / workout / properties / blocks / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "children": {
      -        "items": {
      -          "properties": {
      -            "cad": {
      -              "description": "target cadence rpm",
      -              "maximum": 9007199254740991,
      -              "minimum": -9007199254740991,
      -              "type": "integer"
      -            },
      -            "dist": {
      -              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -              "maximum": 50000,
      -              "minimum": 25,
      -              "type": "integer"
      -            },
      -            "dur": {
      -              "description": "seconds (omit when using dist)",
      -              "exclusiveMinimum": 0,
      -              "maximum": 9007199254740991,
      -              "type": "integer"
      -            },
      -            "gear": {
      -              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -              "items": {
      -                "enum": [
      -                  "paddles",
      -                  "buoy",
      -                  "fins",
      -                  "board",
      -                  "snorkel"
      -                ],
      -                "type": "string"
      -              },
      -              "maxItems": 3,
      -              "type": "array"
      -            },
      -            "label": {
      -              "maxLength": 80,
      -              "type": "string"
      -            },
      -            "maxHr": {
      -              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      -              "maximum": 220,
      -              "minimum": 80,
      -              "type": "integer"
      -            },
      -            "maxRpe": {
      -              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      -              "maximum": 10,
      -              "minimum": 1,
      -              "type": "integer"
      -            },
      -            "maxW": {
      -              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      -              "maximum": 2000,
      -              "minimum": 50,
      -              "type": "integer"
      -            },
      -            "mode": {
      -              "description": "SWIMMING: swim (default) | kick | pull | drill",
      -              "enum": [
      -                "swim",
      -                "kick",
      -                "pull",
      -                "drill"
      -              ],
      -              "type": "string"
      -            },
      -            "open": {
      -              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -              "type": "boolean"
      -            },
      -            "power": {
      -              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -              "maximum": 200,
      -              "minimum": 30,
      -              "type": "number"
      -            },
      -            "sft": {
      -              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      -              "type": "boolean"
      -            },
      -            "stroke": {
      -              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -              "enum": [
      -                "free",
      -                "back",
      -                "breast",
      -                "fly",
      -                "im",
      -                "choice"
      -              ],
      -              "type": "string"
      -            },
      -            "zone": {
      -              "enum": [
      -                "recovery",
      -                "endurance",
      -                "tempo",
      -                "threshold",
      -                "vo2",
      -                "sprint"
      -              ],
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "zone",
      -            "power"
      -          ],
      -          "type": "object"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "reps": {
      -        "maximum": 30,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "sendoff": {
      -        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      -        "maximum": 1800,
      -        "minimum": 10,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "repeat",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "reps",
      -      "children"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "cad": {
      -        "description": "target cadence rpm",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "dist": {
      -        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -        "maximum": 50000,
      -        "minimum": 25,
      -        "type": "integer"
      -      },
      -      "dur": {
      -        "description": "seconds (omit when using dist)",
      -        "exclusiveMinimum": 0,
      -        "maximum": 9007199254740991,
      -        "type": "integer"
      -      },
      -      "gear": {
      -        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -        "items": {
      -          "enum": [
      -            "paddles",
      -            "buoy",
      -            "fins",
      -            "board",
      -            "snorkel"
      -          ],
      -          "type": "string"
      -        },
      -        "maxItems": 3,
      -        "type": "array"
      -      },
      -      "label": {
      -        "maxLength": 80,
      -        "type": "string"
      -      },
      -      "maxHr": {
      -        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      -        "maximum": 220,
      -        "minimum": 80,
      -        "type": "integer"
      -      },
      -      "maxRpe": {
      -        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      -        "maximum": 10,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "maxW": {
      -        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      -        "maximum": 2000,
      -        "minimum": 50,
      -        "type": "integer"
      -      },
      -      "mode": {
      -        "description": "SWIMMING: swim (default) | kick | pull | drill",
      -        "enum": [
      -          "swim",
      -          "kick",
      -          "pull",
      -          "drill"
      -        ],
      -        "type": "string"
      -      },
      -      "open": {
      -        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -        "type": "boolean"
      -      },
      -      "power": {
      -        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -        "maximum": 200,
      -        "minimum": 30,
      -        "type": "number"
      -      },
      -      "sft": {
      -        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      -        "type": "boolean"
      -      },
      -      "stroke": {
      -        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -        "enum": [
      -          "free",
      -          "back",
      -          "breast",
      -          "fly",
      -          "im",
      -          "choice"
      -        ],
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "steady",
      -        "type": "string"
      -      },
      -      "zone": {
      -        "enum": [
      -          "recovery",
      -          "endurance",
      -          "tempo",
      -          "threshold",
      -          "vo2",
      -          "sprint"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "zone",
      -      "power"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "children": {
      +        "items": {
      +          "properties": {
      +            "cad": {
      +              "description": "target cadence rpm",
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            },
      +            "dist": {
      +              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +              "maximum": 50000,
      +              "minimum": 25,
      +              "type": "integer"
      +            },
      +            "dur": {
      +              "description": "seconds (omit when using dist)",
      +              "exclusiveMinimum": 0,
      +              "maximum": 9007199254740991,
      +              "type": "integer"
      +            },
      +            "gear": {
      +              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +              "items": {
      +                "enum": [
      +                  "paddles",
      +                  "buoy",
      +                  "fins",
      +                  "board",
      +                  "snorkel"
      +                ],
      +                "type": "string"
      +              },
      +              "maxItems": 3,
      +              "type": "array"
      +            },
      +            "label": {
      +              "maxLength": 80,
      +              "type": "string"
      +            },
      +            "maxHr": {
      +              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      +              "maximum": 220,
      +              "minimum": 80,
      +              "type": "integer"
      +            },
      +            "maxRpe": {
      +              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      +              "maximum": 10,
      +              "minimum": 1,
      +              "type": "integer"
      +            },
      +            "maxW": {
      +              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      +              "maximum": 2000,
      +              "minimum": 50,
      +              "type": "integer"
      +            },
      +            "mode": {
      +              "description": "SWIMMING: swim (default) | kick | pull | drill",
      +              "enum": [
      +                "swim",
      +                "kick",
      +                "pull",
      +                "drill"
      +              ],
      +              "type": "string"
      +            },
      +            "open": {
      +              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +              "type": "boolean"
      +            },
      +            "power": {
      +              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +              "maximum": 200,
      +              "minimum": 30,
      +              "type": "number"
      +            },
      +            "sft": {
      +              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +              "type": "boolean"
      +            },
      +            "stroke": {
      +              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +              "enum": [
      +                "free",
      +                "back",
      +                "breast",
      +                "fly",
      +                "im",
      +                "choice"
      +              ],
      +              "type": "string"
      +            },
      +            "target": {
      +              "description": "this step's own device target, over the session's",
      +              "enum": [
      +                "power",
      +                "pace",
      +                "hr",
      +                "rpe"
      +              ],
      +              "type": "string"
      +            },
      +            "untilLap": {
      +              "description": "the step ends when the athlete presses Lap",
      +              "type": "boolean"
      +            },
      +            "zone": {
      +              "enum": [
      +                "recovery",
      +                "endurance",
      +                "tempo",
      +                "threshold",
      +                "vo2",
      +                "sprint"
      +              ],
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "zone",
      +            "power"
      +          ],
      +          "type": "object"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "reps": {
      +        "maximum": 30,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "sendoff": {
      +        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      +        "maximum": 1800,
      +        "minimum": 10,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "repeat",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "reps",
      +      "children"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "cad": {
      +        "description": "target cadence rpm",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "dist": {
      +        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +        "maximum": 50000,
      +        "minimum": 25,
      +        "type": "integer"
      +      },
      +      "dur": {
      +        "description": "seconds (omit when using dist)",
      +        "exclusiveMinimum": 0,
      +        "maximum": 9007199254740991,
      +        "type": "integer"
      +      },
      +      "gear": {
      +        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +        "items": {
      +          "enum": [
      +            "paddles",
      +            "buoy",
      +            "fins",
      +            "board",
      +            "snorkel"
      +          ],
      +          "type": "string"
      +        },
      +        "maxItems": 3,
      +        "type": "array"
      +      },
      +      "label": {
      +        "maxLength": 80,
      +        "type": "string"
      +      },
      +      "maxHr": {
      +        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      +        "maximum": 220,
      +        "minimum": 80,
      +        "type": "integer"
      +      },
      +      "maxRpe": {
      +        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      +        "maximum": 10,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "maxW": {
      +        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      +        "maximum": 2000,
      +        "minimum": 50,
      +        "type": "integer"
      +      },
      +      "mode": {
      +        "description": "SWIMMING: swim (default) | kick | pull | drill",
      +        "enum": [
      +          "swim",
      +          "kick",
      +          "pull",
      +          "drill"
      +        ],
      +        "type": "string"
      +      },
      +      "open": {
      +        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +        "type": "boolean"
      +      },
      +      "power": {
      +        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +        "maximum": 200,
      +        "minimum": 30,
      +        "type": "number"
      +      },
      +      "sft": {
      +        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +        "type": "boolean"
      +      },
      +      "stroke": {
      +        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +        "enum": [
      +          "free",
      +          "back",
      +          "breast",
      +          "fly",
      +          "im",
      +          "choice"
      +        ],
      +        "type": "string"
      +      },
      +      "target": {
      +        "description": "this step's own device target, over the session's",
      +        "enum": [
      +          "power",
      +          "pace",
      +          "hr",
      +          "rpe"
      +        ],
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "steady",
      +        "type": "string"
      +      },
      +      "untilLap": {
      +        "description": "the step ends when the athlete presses Lap",
      +        "type": "boolean"
      +      },
      +      "zone": {
      +        "enum": [
      +          "recovery",
      +          "endurance",
      +          "tempo",
      +          "threshold",
      +          "vo2",
      +          "sprint"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "zone",
      +      "power"
      +    ],
      +    "type": "object"
      +  }
      +]
  9. Changed1 schema field changed
    • addedInput schema / properties / items / items / properties / target
      Added value: +{
      +  "description": "ride power|hr|rpe, run pace|hr|rpe",
      +  "enum": [
      +    "power",
      +    "pace",
      +    "hr",
      +    "rpe"
      +  ],
      +  "type": "string"
      +}
  10. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / workout / properties / blocks / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "children": {
      -        "items": {
      -          "properties": {
      -            "cad": {
      -              "description": "target cadence rpm",
      -              "maximum": 9007199254740991,
      -              "minimum": -9007199254740991,
      -              "type": "integer"
      -            },
      -            "dist": {
      -              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -              "maximum": 50000,
      -              "minimum": 25,
      -              "type": "integer"
      -            },
      -            "dur": {
      -              "description": "seconds (omit when using dist)",
      -              "exclusiveMinimum": 0,
      -              "maximum": 9007199254740991,
      -              "type": "integer"
      -            },
      -            "gear": {
      -              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -              "items": {
      -                "enum": [
      -                  "paddles",
      -                  "buoy",
      -                  "fins",
      -                  "board",
      -                  "snorkel"
      -                ],
      -                "type": "string"
      -              },
      -              "maxItems": 3,
      -              "type": "array"
      -            },
      -            "label": {
      -              "maxLength": 80,
      -              "type": "string"
      -            },
      -            "mode": {
      -              "description": "SWIMMING: swim (default) | kick | pull | drill",
      -              "enum": [
      -                "swim",
      -                "kick",
      -                "pull",
      -                "drill"
      -              ],
      -              "type": "string"
      -            },
      -            "open": {
      -              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -              "type": "boolean"
      -            },
      -            "power": {
      -              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -              "maximum": 200,
      -              "minimum": 30,
      -              "type": "number"
      -            },
      -            "sft": {
      -              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      -              "type": "boolean"
      -            },
      -            "stroke": {
      -              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -              "enum": [
      -                "free",
      -                "back",
      -                "breast",
      -                "fly",
      -                "im",
      -                "choice"
      -              ],
      -              "type": "string"
      -            },
      -            "zone": {
      -              "enum": [
      -                "recovery",
      -                "endurance",
      -                "tempo",
      -                "threshold",
      -                "vo2",
      -                "sprint"
      -              ],
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "zone",
      -            "power"
      -          ],
      -          "type": "object"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "reps": {
      -        "maximum": 30,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "sendoff": {
      -        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      -        "maximum": 1800,
      -        "minimum": 10,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "repeat",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "reps",
      -      "children"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "cad": {
      -        "description": "target cadence rpm",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "dist": {
      -        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -        "maximum": 50000,
      -        "minimum": 25,
      -        "type": "integer"
      -      },
      -      "dur": {
      -        "description": "seconds (omit when using dist)",
      -        "exclusiveMinimum": 0,
      -        "maximum": 9007199254740991,
      -        "type": "integer"
      -      },
      -      "gear": {
      -        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -        "items": {
      -          "enum": [
      -            "paddles",
      -            "buoy",
      -            "fins",
      -            "board",
      -            "snorkel"
      -          ],
      -          "type": "string"
      -        },
      -        "maxItems": 3,
      -        "type": "array"
      -      },
      -      "label": {
      -        "maxLength": 80,
      -        "type": "string"
      -      },
      -      "mode": {
      -        "description": "SWIMMING: swim (default) | kick | pull | drill",
      -        "enum": [
      -          "swim",
      -          "kick",
      -          "pull",
      -          "drill"
      -        ],
      -        "type": "string"
      -      },
      -      "open": {
      -        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -        "type": "boolean"
      -      },
      -      "power": {
      -        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -        "maximum": 200,
      -        "minimum": 30,
      -        "type": "number"
      -      },
      -      "sft": {
      -        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      -        "type": "boolean"
      -      },
      -      "stroke": {
      -        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -        "enum": [
      -          "free",
      -          "back",
      -          "breast",
      -          "fly",
      -          "im",
      -          "choice"
      -        ],
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "steady",
      -        "type": "string"
      -      },
      -      "zone": {
      -        "enum": [
      -          "recovery",
      -          "endurance",
      -          "tempo",
      -          "threshold",
      -          "vo2",
      -          "sprint"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "zone",
      -      "power"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "children": {
      +        "items": {
      +          "properties": {
      +            "cad": {
      +              "description": "target cadence rpm",
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            },
      +            "dist": {
      +              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +              "maximum": 50000,
      +              "minimum": 25,
      +              "type": "integer"
      +            },
      +            "dur": {
      +              "description": "seconds (omit when using dist)",
      +              "exclusiveMinimum": 0,
      +              "maximum": 9007199254740991,
      +              "type": "integer"
      +            },
      +            "gear": {
      +              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +              "items": {
      +                "enum": [
      +                  "paddles",
      +                  "buoy",
      +                  "fins",
      +                  "board",
      +                  "snorkel"
      +                ],
      +                "type": "string"
      +              },
      +              "maxItems": 3,
      +              "type": "array"
      +            },
      +            "label": {
      +              "maxLength": 80,
      +              "type": "string"
      +            },
      +            "maxHr": {
      +              "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      +              "maximum": 220,
      +              "minimum": 80,
      +              "type": "integer"
      +            },
      +            "maxRpe": {
      +              "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      +              "maximum": 10,
      +              "minimum": 1,
      +              "type": "integer"
      +            },
      +            "maxW": {
      +              "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      +              "maximum": 2000,
      +              "minimum": 50,
      +              "type": "integer"
      +            },
      +            "mode": {
      +              "description": "SWIMMING: swim (default) | kick | pull | drill",
      +              "enum": [
      +                "swim",
      +                "kick",
      +                "pull",
      +                "drill"
      +              ],
      +              "type": "string"
      +            },
      +            "open": {
      +              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +              "type": "boolean"
      +            },
      +            "power": {
      +              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +              "maximum": 200,
      +              "minimum": 30,
      +              "type": "number"
      +            },
      +            "sft": {
      +              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +              "type": "boolean"
      +            },
      +            "stroke": {
      +              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +              "enum": [
      +                "free",
      +                "back",
      +                "breast",
      +                "fly",
      +                "im",
      +                "choice"
      +              ],
      +              "type": "string"
      +            },
      +            "zone": {
      +              "enum": [
      +                "recovery",
      +                "endurance",
      +                "tempo",
      +                "threshold",
      +                "vo2",
      +                "sprint"
      +              ],
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "zone",
      +            "power"
      +          ],
      +          "type": "object"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "reps": {
      +        "maximum": 30,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "sendoff": {
      +        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      +        "maximum": 1800,
      +        "minimum": 10,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "repeat",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "reps",
      +      "children"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "cad": {
      +        "description": "target cadence rpm",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "dist": {
      +        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +        "maximum": 50000,
      +        "minimum": 25,
      +        "type": "integer"
      +      },
      +      "dur": {
      +        "description": "seconds (omit when using dist)",
      +        "exclusiveMinimum": 0,
      +        "maximum": 9007199254740991,
      +        "type": "integer"
      +      },
      +      "gear": {
      +        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +        "items": {
      +          "enum": [
      +            "paddles",
      +            "buoy",
      +            "fins",
      +            "board",
      +            "snorkel"
      +          ],
      +          "type": "string"
      +        },
      +        "maxItems": 3,
      +        "type": "array"
      +      },
      +      "label": {
      +        "maxLength": 80,
      +        "type": "string"
      +      },
      +      "maxHr": {
      +        "description": "heart-rate ceiling, bpm: over it the trainer autopilot takes watts off",
      +        "maximum": 220,
      +        "minimum": 80,
      +        "type": "integer"
      +      },
      +      "maxRpe": {
      +        "description": "RPE ceiling (1-10): a rating over it, asked or tapped mid-step, takes watts off this step",
      +        "maximum": 10,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "maxW": {
      +        "description": "CYCLING: the most watts ERG may hold on this step (a ceiling, e.g. 190 on an easy ride). Put limits HERE, not in the label or note — the trainer autopilot reads this field",
      +        "maximum": 2000,
      +        "minimum": 50,
      +        "type": "integer"
      +      },
      +      "mode": {
      +        "description": "SWIMMING: swim (default) | kick | pull | drill",
      +        "enum": [
      +          "swim",
      +          "kick",
      +          "pull",
      +          "drill"
      +        ],
      +        "type": "string"
      +      },
      +      "open": {
      +        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +        "type": "boolean"
      +      },
      +      "power": {
      +        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +        "maximum": 200,
      +        "minimum": 30,
      +        "type": "number"
      +      },
      +      "sft": {
      +        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +        "type": "boolean"
      +      },
      +      "stroke": {
      +        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +        "enum": [
      +          "free",
      +          "back",
      +          "breast",
      +          "fly",
      +          "im",
      +          "choice"
      +        ],
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "steady",
      +        "type": "string"
      +      },
      +      "zone": {
      +        "enum": [
      +          "recovery",
      +          "endurance",
      +          "tempo",
      +          "threshold",
      +          "vo2",
      +          "sprint"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "zone",
      +      "power"
      +    ],
      +    "type": "object"
      +  }
      +]
  11. Changed1 schema field changed
    • addedInput schema / properties / why
      Added value: +{
      +  "description": "ONE line, in the athlete's language: WHY this change — the reason from the conversation (\"travel Thu-Fri, long ride moved to Sat\", \"deload after 3 build weeks\"). The athlete's other assistant surface reads it later; without it, it sees only that the plan changed. No health details beyond what the plan needs.",
      +  "maxLength": 200,
      +  "type": "string"
      +}
  12. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / workout / properties / blocks / items / anyOf
      Previous value: -[
      -  {
      -    "properties": {
      -      "children": {
      -        "items": {
      -          "properties": {
      -            "cad": {
      -              "description": "target cadence rpm",
      -              "maximum": 9007199254740991,
      -              "minimum": -9007199254740991,
      -              "type": "integer"
      -            },
      -            "dist": {
      -              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -              "maximum": 50000,
      -              "minimum": 25,
      -              "type": "integer"
      -            },
      -            "dur": {
      -              "description": "seconds (omit when using dist)",
      -              "exclusiveMinimum": 0,
      -              "maximum": 9007199254740991,
      -              "type": "integer"
      -            },
      -            "gear": {
      -              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -              "items": {
      -                "enum": [
      -                  "paddles",
      -                  "buoy",
      -                  "fins",
      -                  "board",
      -                  "snorkel"
      -                ],
      -                "type": "string"
      -              },
      -              "maxItems": 3,
      -              "type": "array"
      -            },
      -            "label": {
      -              "maxLength": 80,
      -              "type": "string"
      -            },
      -            "mode": {
      -              "description": "SWIMMING: swim (default) | kick | pull | drill",
      -              "enum": [
      -                "swim",
      -                "kick",
      -                "pull",
      -                "drill"
      -              ],
      -              "type": "string"
      -            },
      -            "open": {
      -              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -              "type": "boolean"
      -            },
      -            "power": {
      -              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -              "maximum": 200,
      -              "minimum": 30,
      -              "type": "number"
      -            },
      -            "stroke": {
      -              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -              "enum": [
      -                "free",
      -                "back",
      -                "breast",
      -                "fly",
      -                "im",
      -                "choice"
      -              ],
      -              "type": "string"
      -            },
      -            "zone": {
      -              "enum": [
      -                "recovery",
      -                "endurance",
      -                "tempo",
      -                "threshold",
      -                "vo2",
      -                "sprint"
      -              ],
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "zone",
      -            "power"
      -          ],
      -          "type": "object"
      -        },
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "reps": {
      -        "maximum": 30,
      -        "minimum": 1,
      -        "type": "integer"
      -      },
      -      "sendoff": {
      -        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      -        "maximum": 1800,
      -        "minimum": 10,
      -        "type": "integer"
      -      },
      -      "type": {
      -        "const": "repeat",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "reps",
      -      "children"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "properties": {
      -      "cad": {
      -        "description": "target cadence rpm",
      -        "maximum": 9007199254740991,
      -        "minimum": -9007199254740991,
      -        "type": "integer"
      -      },
      -      "dist": {
      -        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      -        "maximum": 50000,
      -        "minimum": 25,
      -        "type": "integer"
      -      },
      -      "dur": {
      -        "description": "seconds (omit when using dist)",
      -        "exclusiveMinimum": 0,
      -        "maximum": 9007199254740991,
      -        "type": "integer"
      -      },
      -      "gear": {
      -        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      -        "items": {
      -          "enum": [
      -            "paddles",
      -            "buoy",
      -            "fins",
      -            "board",
      -            "snorkel"
      -          ],
      -          "type": "string"
      -        },
      -        "maxItems": 3,
      -        "type": "array"
      -      },
      -      "label": {
      -        "maxLength": 80,
      -        "type": "string"
      -      },
      -      "mode": {
      -        "description": "SWIMMING: swim (default) | kick | pull | drill",
      -        "enum": [
      -          "swim",
      -          "kick",
      -          "pull",
      -          "drill"
      -        ],
      -        "type": "string"
      -      },
      -      "open": {
      -        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      -        "type": "boolean"
      -      },
      -      "power": {
      -        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -        "maximum": 200,
      -        "minimum": 30,
      -        "type": "number"
      -      },
      -      "stroke": {
      -        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      -        "enum": [
      -          "free",
      -          "back",
      -          "breast",
      -          "fly",
      -          "im",
      -          "choice"
      -        ],
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "steady",
      -        "type": "string"
      -      },
      -      "zone": {
      -        "enum": [
      -          "recovery",
      -          "endurance",
      -          "tempo",
      -          "threshold",
      -          "vo2",
      -          "sprint"
      -        ],
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "zone",
      -      "power"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "children": {
      +        "items": {
      +          "properties": {
      +            "cad": {
      +              "description": "target cadence rpm",
      +              "maximum": 9007199254740991,
      +              "minimum": -9007199254740991,
      +              "type": "integer"
      +            },
      +            "dist": {
      +              "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +              "maximum": 50000,
      +              "minimum": 25,
      +              "type": "integer"
      +            },
      +            "dur": {
      +              "description": "seconds (omit when using dist)",
      +              "exclusiveMinimum": 0,
      +              "maximum": 9007199254740991,
      +              "type": "integer"
      +            },
      +            "gear": {
      +              "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +              "items": {
      +                "enum": [
      +                  "paddles",
      +                  "buoy",
      +                  "fins",
      +                  "board",
      +                  "snorkel"
      +                ],
      +                "type": "string"
      +              },
      +              "maxItems": 3,
      +              "type": "array"
      +            },
      +            "label": {
      +              "maxLength": 80,
      +              "type": "string"
      +            },
      +            "mode": {
      +              "description": "SWIMMING: swim (default) | kick | pull | drill",
      +              "enum": [
      +                "swim",
      +                "kick",
      +                "pull",
      +                "drill"
      +              ],
      +              "type": "string"
      +            },
      +            "open": {
      +              "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +              "type": "boolean"
      +            },
      +            "power": {
      +              "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +              "maximum": 200,
      +              "minimum": 30,
      +              "type": "number"
      +            },
      +            "sft": {
      +              "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +              "type": "boolean"
      +            },
      +            "stroke": {
      +              "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +              "enum": [
      +                "free",
      +                "back",
      +                "breast",
      +                "fly",
      +                "im",
      +                "choice"
      +              ],
      +              "type": "string"
      +            },
      +            "zone": {
      +              "enum": [
      +                "recovery",
      +                "endurance",
      +                "tempo",
      +                "threshold",
      +                "vo2",
      +                "sprint"
      +              ],
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "zone",
      +            "power"
      +          ],
      +          "type": "object"
      +        },
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "reps": {
      +        "maximum": 30,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      "sendoff": {
      +        "description": "SWIMMING: the send-off in seconds — the whole cycle, swim PLUS rest (\"10×100 on 1:40\" = 100). Rest is what is left of it. Use this OR a rest step inside the set, never both: they are two different sessions, and on a send-off swimming faster buys rest instead of ending the interval sooner.",
      +        "maximum": 1800,
      +        "minimum": 10,
      +        "type": "integer"
      +      },
      +      "type": {
      +        "const": "repeat",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "type",
      +      "reps",
      +      "children"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "cad": {
      +        "description": "target cadence rpm",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "dist": {
      +        "description": "RUNNING and SWIMMING: measure this rep by distance in metres (2000 for 2 km on the road, 100 for a pool rep) instead of time; time is derived from the target pace. For SWIMMING this is the normal case — a set is written in metres, never in minutes. Give either dur or dist, not both.",
      +        "maximum": 50000,
      +        "minimum": 25,
      +        "type": "integer"
      +      },
      +      "dur": {
      +        "description": "seconds (omit when using dist)",
      +        "exclusiveMinimum": 0,
      +        "maximum": 9007199254740991,
      +        "type": "integer"
      +      },
      +      "gear": {
      +        "description": "SWIMMING: paddles | buoy | fins | board | snorkel",
      +        "items": {
      +          "enum": [
      +            "paddles",
      +            "buoy",
      +            "fins",
      +            "board",
      +            "snorkel"
      +          ],
      +          "type": "string"
      +        },
      +        "maxItems": 3,
      +        "type": "array"
      +      },
      +      "label": {
      +        "maxLength": 80,
      +        "type": "string"
      +      },
      +      "mode": {
      +        "description": "SWIMMING: swim (default) | kick | pull | drill",
      +        "enum": [
      +          "swim",
      +          "kick",
      +          "pull",
      +          "drill"
      +        ],
      +        "type": "string"
      +      },
      +      "open": {
      +        "description": "a maximal effort (test, all-out) — no target on the device; power stays as the expected level",
      +        "type": "boolean"
      +      },
      +      "power": {
      +        "description": "%FTP (cycling) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +        "maximum": 200,
      +        "minimum": 30,
      +        "type": "number"
      +      },
      +      "sft": {
      +        "description": "true = the athlete's SFT: load and length come from their profile at export; follow it with 60 s easy",
      +        "type": "boolean"
      +      },
      +      "stroke": {
      +        "description": "SWIMMING: free (default) | back | breast | fly | im | choice",
      +        "enum": [
      +          "free",
      +          "back",
      +          "breast",
      +          "fly",
      +          "im",
      +          "choice"
      +        ],
      +        "type": "string"
      +      },
      +      "type": {
      +        "const": "steady",
      +        "type": "string"
      +      },
      +      "zone": {
      +        "enum": [
      +          "recovery",
      +          "endurance",
      +          "tempo",
      +          "threshold",
      +          "vo2",
      +          "sprint"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "zone",
      +      "power"
      +    ],
      +    "type": "object"
      +  }
      +]
  13. First observed

TDQS

Score is being calculated.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources