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 3 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 this week and the next in one call — sessions are written two weeks out, and every week beyond holds its training block's TARGET (set_training_blocks), not sessions: 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 lay the season out in blocks (set_training_blocks) with week targets, and put only the next two weeks in sessions. Returns per-item result with the new iid, duration and TSS.

Input 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
noteEditsNoYOUR OWN day notes (by:"ai") this change makes wrong, changed in the same card: replaces = the start of that note; note "" removes it, new text rewrites it, to moves it

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / context / items / enum
      Previous value: -[
      -  "workout",
      -  "heat",
      -  "altitude",
      -  "indoor",
      -  "race",
      -  "test",
      -  "group",
      -  "commute"
      -]New value: +[
      +  "workout",
      +  "heat",
      +  "altitude",
      +  "indoor",
      +  "race",
      +  "test",
      +  "group",
      +  "commute",
      +  "offroad"
      +]
  2. 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"
      -            },
      -            "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; a sprint is 250–400) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -              "maximum": 600,
      -              "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"
      -            },
      -            "task": {
      -              "additionalProperties": {},
      -              "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      -              "properties": {
      -                "kind": {
      -                  "enum": [
      -                    "ramp",
      -                    "core"
      -                  ],
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "kind"
      -              ],
      -              "type": "object"
      -            },
      -            "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": 50,
      -        "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; a sprint is 250–400) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      -        "maximum": 600,
      -        "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"
      -      },
      -      "task": {
      -        "additionalProperties": {},
      -        "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      -        "properties": {
      -          "kind": {
      -            "enum": [
      -              "ramp",
      -              "core"
      -            ],
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "kind"
      -        ],
      -        "type": "object"
      -      },
      -      "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; a sprint is 250–400) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +              "maximum": 600,
      +              "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"
      +            },
      +            "task": {
      +              "additionalProperties": {},
      +              "description": "autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C, top 39.5: a guide, sensor reads low, no heat-dose proof",
      +              "properties": {
      +                "kind": {
      +                  "enum": [
      +                    "ramp",
      +                    "core"
      +                  ],
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "kind"
      +              ],
      +              "type": "object"
      +            },
      +            "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": 50,
      +        "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; a sprint is 250–400) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +        "maximum": 600,
      +        "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"
      +      },
      +      "task": {
      +        "additionalProperties": {},
      +        "description": "autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C, top 39.5: a guide, sensor reads low, no heat-dose proof",
      +        "properties": {
      +          "kind": {
      +            "enum": [
      +              "ramp",
      +              "core"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "kind"
      +        ],
      +        "type": "object"
      +      },
      +      "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"
      +  }
      +]
  3. 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"
      -      },
      -      "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"
      -  }
      -]New value: +[
      +  {
      +    "properties": {
      +      "load": {
      +        "description": "sec and m modes only: the kg carried or pushed — a farmer's carry is mode m, val 50, load 32. Omit when there is none or you do not know it; not in the name",
      +        "maximum": 1000,
      +        "minimum": 0,
      +        "type": "number"
      +      },
      +      "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', they named a number in this conversation, or the log holds a load for this exercise: start from that). 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": {
      +            "load": {
      +              "description": "sec and m modes only: the kg carried or pushed — a farmer's carry is mode m, val 50, load 32. Omit when there is none or you do not know it; not in the name",
      +              "maximum": 1000,
      +              "minimum": 0,
      +              "type": "number"
      +            },
      +            "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', they named a number in this conversation, or the log holds a load for this exercise: start from that). 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"
      +  }
      +]
  4. Changed2 schema fields 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"
      -            },
      -            "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"
      -            },
      -            "task": {
      -              "additionalProperties": {},
      -              "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      -              "properties": {
      -                "kind": {
      -                  "enum": [
      -                    "ramp",
      -                    "core"
      -                  ],
      -                  "type": "string"
      -                }
      -              },
      -              "required": [
      -                "kind"
      -              ],
      -              "type": "object"
      -            },
      -            "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": 50,
      -        "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"
      -      },
      -      "task": {
      -        "additionalProperties": {},
      -        "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      -        "properties": {
      -          "kind": {
      -            "enum": [
      -              "ramp",
      -              "core"
      -            ],
      -            "type": "string"
      -          }
      -        },
      -        "required": [
      -          "kind"
      -        ],
      -        "type": "object"
      -      },
      -      "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; a sprint is 250–400) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +              "maximum": 600,
      +              "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"
      +            },
      +            "task": {
      +              "additionalProperties": {},
      +              "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      +              "properties": {
      +                "kind": {
      +                  "enum": [
      +                    "ramp",
      +                    "core"
      +                  ],
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "kind"
      +              ],
      +              "type": "object"
      +            },
      +            "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": 50,
      +        "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; a sprint is 250–400) or %threshold pace (running) or %CSS (swimming — 100 = their CSS pace, below 100 = slower/easier, e.g. 92 for an aerobic set)",
      +        "maximum": 600,
      +        "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"
      +      },
      +      "task": {
      +        "additionalProperties": {},
      +        "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      +        "properties": {
      +          "kind": {
      +            "enum": [
      +              "ramp",
      +              "core"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "kind"
      +        ],
      +        "type": "object"
      +      },
      +      "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"
      +  }
      +]
    • addedInput schema / properties / noteEdits
      Added value: +{
      +  "description": "YOUR OWN day notes (by:\"ai\") this change makes wrong, changed in the same card: replaces = the start of that note; note \"\" removes it, new text rewrites it, to moves it",
      +  "items": {
      +    "properties": {
      +      "date": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      },
      +      "note": {
      +        "maxLength": 1000,
      +        "type": "string"
      +      },
      +      "replaces": {
      +        "maxLength": 200,
      +        "minLength": 4,
      +        "type": "string"
      +      },
      +      "to": {
      +        "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "date",
      +      "replaces"
      +    ],
      +    "type": "object"
      +  },
      +  "maxItems": 10,
      +  "type": "array"
      +}
  5. Changed1 schema field changed
    • changedInput schema / properties / items / items / properties / key / description
      Previous value: -"mark as the week's KEY session — the one the week is built around, declared before the fact. A PRIORITY, not a difficulty: a long base endurance ride can be the key session and a midweek opener need not be. You may set at most 2 per week YOURSELF; past that the session still lands, WITHOUT the star, and the result says so — tell the athlete and let them star it. That cap is on you, not on them — they can star as many sessions as they like in the app."New value: +"mark as the week's KEY session — the one the week is built around, declared before the fact. A PRIORITY, not a difficulty: a long base endurance ride can be the key session and a midweek opener need not be. You may set at most 3 per week YOURSELF; past that the session still lands, WITHOUT the star, and the result says so — tell the athlete and let them star it. That cap is on you, not on them — they can star as many sessions as they like in the app."
  6. 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"
      -            },
      -            "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": 50,
      -        "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"
      -  }
      -]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"
      +            },
      +            "task": {
      +              "additionalProperties": {},
      +              "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      +              "properties": {
      +                "kind": {
      +                  "enum": [
      +                    "ramp",
      +                    "core"
      +                  ],
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "kind"
      +              ],
      +              "type": "object"
      +            },
      +            "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": 50,
      +        "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"
      +      },
      +      "task": {
      +        "additionalProperties": {},
      +        "description": "trainer autopilot task, cycling, only when asked: {kind:ramp,hr?,rpe?,stepPct?,everySec?} climbs until hr/rpe then ends the step; {kind:core,lo,hi} holds core °C",
      +        "properties": {
      +          "kind": {
      +            "enum": [
      +              "ramp",
      +              "core"
      +            ],
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "kind"
      +        ],
      +        "type": "object"
      +      },
      +      "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"
      +  }
      +]
  7. 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"
      -            },
      -            "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"
      -  }
      -]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": 50,
      +        "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"
      +  }
      +]
  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"
      -            },
      -            "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"
      +  }
      +]
  9. 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"
      +  }
      +]
  10. 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"
      +}
  11. 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
  12. 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."
  13. 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"
      +}
  14. 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)."
  15. 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"
      +  }
      +]
  16. 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"
      +}
  17. 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"
      +  }
      +]
  18. 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"
      +}
  19. 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"
      +  }
      +]
  20. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing return shape ('per-item result with the new iid, duration and TSS'), persistence behavior ('sessions are written two weeks out'), server-side validation, and that custom workouts are saved to the athlete's library. It also explains operational limits: the 40-item cap is a ceiling, a call too long to finish saves nothing, and the agent's key-session cap differs from the athlete's. No contradiction with readOnlyHint=false or destructiveHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and a per-day workflow, and most sentences carry operational guidance that earns its place. It is dense but appropriate for a high-complexity scheduling tool; a few parenthetical clauses could be trimmed, but nothing is seriously bloated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with a large nested schema and no output schema, the description covers the essential workflow, batching limits, long-horizon alternative, and return values. The remaining parameter details, such as why and noteEdits, are fully documented in the schema, so an agent has enough context to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already carries most parameter meaning. The description still adds useful selection semantics by clarifying when to use workoutId versus a custom workout, and by specifying that key sessions should be declared first and filled around, which is not obvious from the field definitions alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Add one or more workouts to the athlete's training calendar (the days appear in Blocks).' It distinguishes the tool from catalog search and custom creation by prescribing workoutId from the catalog or search_catalog first, so an agent can tell what this tool does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit workflow: prefer an existing workout by id, use search_catalog when no catalog map is present, and only create a custom workout when nothing suitable exists. It also names the alternative for longer horizons (set_training_blocks) and gives batching guidance ('Batch this week and the next in one call'), covering both when to use this tool and when to use a sibling instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources