add_fact
Record ONE thing you now know about the athlete, with how long it is true. This is the assistant's memory: it is NOT a copy of the snapshot and NOT a training log. Three tests, all must pass — (1) it is not already handed to you every turn (age, weight, hours, available days, thresholds, zones, race dates, the plan, load, readiness, response_profile), (2) no tool computes it (get_metric_history, get_records, get_activity), (3) it outlives this session — the verdict on one workout goes on that workout with set_activity_notes.
AREA decides what survives when context is tight: "health" and "constraint" are never cut, "pattern" is the only capped area. Nuance goes in tags, which are free.
CONSTRAINTS include a fixed commitment on a day the profile calls free, another coach's remit, an injury to plan around, and EQUIPMENT — tagged equipment, recorded as what they actually own in their words, with a horizon like anything else (a gym membership is an until, a turbo in the hallway is often a season).
HORIZON is required and there is no "unknown": if you cannot say how long it holds, ASK before writing. "stands" = until they say otherwise. "until" + dueDate = it ends (a race, an arrangement); when the date passes the fact stops applying and its opposite does NOT start applying. "recheck" + dueDate = it does not become false, it becomes untrustworthy (a threshold, a blood value, weekly hours). "season" + seasonFrom/seasonTo = true only part of the year (months, may wrap: 11-03 is November to March). "pattern" = an observation; set confirmations as you see it again.
dueAction is the line between a date that becomes a CALENDAR item and a date that is merely a question. Set it only when the due date carries something the athlete DOES ("сдать ферритин", "перемерить порог 30-мин тестом") — that is proposed as a calendar entry on the date itself. Leave it empty for "ask whether this still holds": no calendar clutter for a conversation.
Silent when the athlete just told you the fact. A CARD when it carries a dueAction (it will put something in their calendar), when it is a pattern (that is your inference about them, not their words), or when it replaces a fact already on their page.
ONE IDEA, ONE LINE. If a live fact of the same area already says something like this, the call is HELD and you get those facts back with their ids: answer with new:true (genuinely different — both stay, and a different day, date, trip or measurement IS different however alike the wording), replaces:<id> (this supersedes it — the old one is retired as this is written), or confirms:<id> (literally the same thing — that fact is bumped and your line is discarded). Every fact in your snapshot already ends with its #id, so a pattern you see again is confirm_fact on that id, not a second add_fact.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| new | No | true = write it beside the similar facts add_fact showed you, because it is a different thing | |
| area | Yes | ||
| tags | No | ||
| text | Yes | the fact itself, in the athlete's language, one thing only | |
| source | Yes | athlete = they said it; assistant = you inferred it | |
| dueDate | No | required for until / recheck | |
| horizon | Yes | ||
| confirms | No | id of a live fact that already says this — it is bumped instead, nothing new is written (only after add_fact held your call and showed it) | |
| dueLabel | No | what it is tied to, e.g. '10 км' | |
| replaces | No | id of a live fact this one supersedes — retired as this is written; a card | |
| seasonTo | No | ||
| dueAction | No | what the athlete DOES on that date; set it and it becomes a calendar item | |
| seasonFrom | No | ||
| confirmations | No | patterns only — how many times you have seen it |