Skip to main content
Glama
cambroussard9

trail-factors

Trail Factors

Trail and ultra running analysis from your own Garmin FIT files, served to Claude through a local MCP server.

CI License: MIT

Trail Factors demo

Why I built this

I'm training for my first 50-mile trail race. Garmin Connect reports averages, and on rolling trail terrain averaging destroys the signal: an average heart rate across eight climbs can't tell me whether I was tired or the trail was hard. Trails add a second problem. Under ridges and in creek drainages, GPS coverage drops out, and elevation read from a drifting position turns into noise.

So I built my own analytics layer and connected it to the AI chat I use for coaching. Trail Factors takes FIT files from my watch, loads them into a local DuckDB database, refines them through a medallion architecture (raw bronze, enriched silver, summarized gold), and exposes the gold layer to Claude through an MCP server. Elevation comes from a digital elevation model instead of the watch, so the same hill returns the same profile every time. I ask questions in plain English and get answers computed from my own data: running-only pace by grade, heart rate drift on matched terrain, the same hill compared across months.

Two design rules shaped it:

  • The tools carry the filters. The chat never queries the database directly. Every number comes through a tool that applies the gates and exclusions that make it trustworthy, and if a tool can't answer a question, it says so.

  • The athlete outranks the instrument. When the data and my account of a run disagree, the first question is what the measurement couldn't see, like a GPS dead spot in a creek drainage or a watch that died mid-run.

I built it in VS Code with the Claude Code extension. I designed the system and wrote the specs; Claude Code wrote most of the code. I use it after nearly every run.

Related MCP server: runcoach

How it works

flowchart LR
    FIT["FIT files"] --> B["Bronze: parsed as recorded"]
    B --> S["Silver: enriched records"]
    DEM["DEM elevation tiles"] --> S
    WX["Weather"] --> S
    S --> G["Gold: per-run and per-segment summaries"]
    G --> T["MCP tools"]
    T --> C["Claude"]

Raw FIT files are the immutable source of truth. The database is derived from them, with athlete-supplied state re-applied, and can be rebuilt. Elevation is looked up locally from downloaded USGS 3DEP tiles rather than taken from the watch, so no per-coordinate query leaves the machine and the same trail returns the identical profile on every traversal. The MCP server is a thin wrapper over the same functions the CLI calls: it runs over stdio only and opens every database connection read-only.

More detail: docs/ARCHITECTURE.md, docs/tools.md (all 29 MCP tools), docs/HISTORY.md, and SPEC.md (the full design).

What you can ask

These answers come from the bundled demo database (data/demo.duckdb, built by uv run trail-factors demo), not from a live account.

"On my most recent long run, show my running pace per mile and when my heart rate started to drift." → mile_splits() and drift_onset()

The most recent long run in the demo is 2026-10-11: 7.62 mi in 106 minutes. Pace counts running time only; walk breaks are left out of the pace and shown in their own column.

Mile

Running pace

HR (running)

Walking

1

11:12/mi

129

0:00

2

13:26/mi

162

1:48

3

13:53/mi

154

8:02

4

12:57/mi

162

7:14

5

11:49/mi

168

6:55

6

10:53/mi

164

2:14

7

12:12/mi

168

5:56

8 (0.62 mi)

11:46/mi

175

3:11

Garmin's own lap for mile 2 reads 14:05/mi because it includes the walking; it is returned beside these figures for cross-checking and never substituted for them.

On drift, the tool finds an onset at 85 minutes: the first 5-minute bin where heart rate on matched ground drifts upward and keeps drifting upward in every later bin (dew point 63–66 °F). It also refuses to call that a finding. Only 1 of 7 demo runs recorded every second produces an onset, and 8 at a comparable dew point are needed before anyone can tell whether the onset repeats. So the 85 minutes is reported as a diagnostic, with the reason attached.

"Is my heart rate drifting on the same ground?" → matched_terrain_drift()

"matched_terrain_drift: median 9.79 bpm/hour over 9 of 10 runs." It pairs records on the same ground (within 20 m, at least 600 s apart, both running, speed matched within 0.35 m/s). The tenth run had no qualifying pairs, and the result says so instead of reporting a number.

"What training load have I done recently?" → session_load(last_n=11)

"6 of 11 sessions priced, 2625 AU (a lower bound: 5 unpriced)." Load is Garmin's post-run RPE × timer minutes. The five runs with no Garmin self-evaluation are left out rather than counted as zero, so the total is labelled a lower bound.

Quick start

Requires Python 3.12, uv and Claude Code. The demo needs no Garmin account and no network.

git clone https://github.com/cambroussard9/trail-factors.git && cd trail-factors
uv sync
uv run trail-factors demo

Register the MCP server with Claude Code, from the clone root:

claude mcp add trail-factors -e TRAIL_FACTORS_DB=data/demo.duckdb -- uv run --directory "$PWD" trail-factors-mcp
claude mcp get trail-factors      # or: claude mcp list

Then ask Claude one of the questions above.

Using Codex instead? See SETUP.md, step 11 (from OpenAI's docs, untested).

Use your own Garmin data

Copy config/athlete.example.yaml to config/athlete.yaml, log in once with uv run trail-factors garmin-login, and run uv run trail-factors sync to download, ingest and validate your activities. Your data stays in the gitignored data/ directory on your machine. The full walkthrough is in SETUP.md.

Security and quality

Control

Where

Why it exists

gitleaks

pre-commit (.pre-commit-config.yaml)

Blocks a commit whose staged changes contain a secret.

ruff (lint + format)

pre-commit (.pre-commit-config.yaml)

Keeps style and common errors out of commits.

ruff and pytest

CI (.github/workflows/ci.yml), every push and pull request

Installs from the lockfile, checks lint and formatting, runs the tests. Corpus tests skip because no database is set.

TruffleHog

.github/workflows/secrets.yml, every push

Scans the full git history and fails on any verified or unknown finding.

Dependabot

.github/dependabot.yml

Proposes weekly updates for GitHub Actions and the uv-managed Python dependencies.

Secrets-blocking hooks

The author's own Claude Code user settings (not shipped in this repo)

SonarQube secrets hooks run on prompt submit and before file reads. They need the sonar CLI.

More in SECURITY.md.

Design principles

  • Tools carry the filters. MCP tools are parameterised primitives that never take SQL: the selection is free, the computation is fixed, and every result states its applied filters and what it excluded. Every report section carries one of four statuses (ok, gated, refused, unavailable), never a bare null.

  • The athlete outranks the instrument. A file the validator rejects names its own fix, and the athlete confirms the valid window with confirm-file; the window is applied before validation, so a car ride at the end of a recording no longer sinks the run.

  • The database rebuilds from raw FIT. Files in data/raw/ are immutable and never edited. The database is derived from them, with athlete-supplied state re-applied, so deleting it and re-running ingest is safe. Athlete-supplied state (window confirmations, segment names, notes) lives in data/athlete/, outside the rebuild path, because nothing can regenerate it. It is gitignored with the rest of data/, so back it up yourself.

Known limitations

Known issues and limitations are tracked in GitHub issues. The constraints built into the design:

  • One athlete by design. No multi-tenancy, no app, no web UI.

  • Terrain needs a DEM tile. Grade and elevation come from USGS 3DEP tiles, which cover the United States only; fetch-tile refuses a cell outside US territory before sending any request. A run with no tile on disk gets no terrain numbers, and the report says which tile is missing.

  • Garmin download uses an unofficial library (garminconnect). Garmin can throttle its login, and a failed login locks further attempts locally for 30 minutes.

  • The MCP server runs over stdio only.

Built with

VS Code and the Claude Code extension.

About me

LinkedIn

License

MIT. See LICENSE.

Available Tools

29 tools
basic_metricsB

§6.0 the run's own description: average HR, three paces, windowed bests, run/walk/stand time, and cadence.

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.

THESE ARE ANCHORS, NOT SIGNALS. For a run/walk athlete holding an HR cap,
average HR barely moves from run to run because HR is held nearly flat
across grade — quote it as the level that drift and efficiency are
deviations FROM, not as a finding.

Paces are never pooled: `overall` is Garmin's own basis (distance over
timer time), `running` and `walking` come from the rwd_* splits and are
separate quantities. A class below the minimum time is `gated` with its
time stated, not silently absent.

The bests are SLIDING WINDOWS, never an instantaneous maximum, and they are
NOT comparable across sampling regimes. Read each window's
`walk_time_fraction` and `flagged_record_fraction` before quoting it: a
maximum selects for positive measurement error in a way a mean does not.

Cadence is steps per minute. It is running-only and non-zero-only, so it
does NOT equal Garmin's own averageRunningCadence, which includes standing.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior3/5

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

With no annotations, the description carries the full burden, and it does disclose meaningful behavior: paces are never pooled, classes below a minimum time are `gated` with their time stated, bests are sliding windows not instantaneous maxima, and cadence excludes standing. However, it says nothing about read-only vs mutating nature, failure modes, or how the many date/filter parameters change the scope of results.

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

Conciseness3/5

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

It is front-loaded with what is returned, which is good, but the body drifts into essayistic reasoning ('a maximum selects for positive measurement error in a way a mean does not') and carries a stray '§6.0 the run's own description' artifact. Much of the caution text is valuable; some of it is prose that costs tokens without changing agent behavior.

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

Completeness3/5

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

An output schema exists, yet the description spends most of its length explaining return values it did not need to, while leaving 7 of 8 input parameters undefined. For a tool whose filtering behavior is driven by those parameters, the definition is asymmetric: rich on interpretation, thin on how to actually scope a call.

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

Parameters2/5

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

Schema description coverage is 0% across 8 parameters, so the description must compensate — but it only documents `run` (run_id, activity_id or Garmin file id; empty means latest). The other seven (`last_n`, `cluster`, `start_date`, `end_date`, `run_type`, `direction`, `segment_id`) are left entirely unexplained, so their semantics remain invisible.

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

Purpose4/5

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

The description names the concrete contents returned for a single run (average HR, three pace bases, windowed bests, run/walk/stand time, cadence), which is far more specific than a restatement of the name. It does not explicitly contrast itself with siblings like session_series or efficiency_factor, leaving the agent to infer that this is the per-run summary anchor.

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

Usage Guidelines3/5

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

There is one piece of real routing guidance — that average HR is a baseline to be quoted as the level drift and efficiency deviate from, not a finding. That implies this tool is a starting point before the analytic siblings, but no alternative is ever named and no when-not-to-use condition is given.

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

cadence_by_gradeB

§6.0 cadence per 5% grade bin over a selection, split by split_type.

Never pooled across run and walk — running and walking cadence sit tens of
spm apart, so a pooled bin reports a number neither mode took.

Needs a DEM tile for the grade, so it sees only DEM-covered runs;
`n_runs_without_grade` says how many of the selection had none.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it warns that run and walk are never pooled and explains why, and it discloses the DEM-coverage constraint plus the `n_runs_without_grade` counter for excluded runs. It omits any statement on read-only semantics, cost, or result shape, but the data-coverage caveats are exactly the kind of context an agent cannot get elsewhere.

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?

Three short sentences, front-loaded with the operation, with zero filler — the pooling rationale earns its space by justifying the split. The leading '§6.0' reference is cryptic overhead but negligible.

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

Completeness3/5

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

An output schema exists, so return values needn't be explained, and the coverage caveat is handled well. But for a 7-parameter tool with zero schema descriptions, the description should say what the selection, cluster, direction, and date arguments do; that gap is material.

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

Parameters2/5

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

Seven parameters at 0% schema description coverage (titles only) — last_n, cluster, end_date, run_type, direction, segment_id, start_date are all undocumented in both places. The description mentions `split_type` and `n_runs_without_grade`, neither of which appears in the input schema, so it adds confusion rather than meaning for the actual callable arguments.

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

Purpose4/5

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

States a specific metric (cadence), a specific bucketing (per 5% grade bin), a selection scope, and a grouping key (split_type). That is enough to distinguish it from siblings like grade_binned_pace, though it never names an alternative directly.

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

Usage Guidelines3/5

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

Usage is implied through 'over a selection' and the split_type grouping, and the 'never pooled' note tells the agent how results behave. However, there is no explicit when-to-use or when-not guidance relative to siblings such as grade_binned_pace, leaving the agent to infer the choice.

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

delta_hrC

§6.3 HR excursion across an effort, by direction, over a selection.

Ascent and descent are NOT comparable on this metric: the excursion
differs systematically by direction. Tau is never returned by this tool;
whether it is reportable at all is §6.3's corpus-level gate.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.6/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It does disclose that ascent and descent are not comparable and that tau is excluded, but it does not state whether the operation is read-only, what permissions are needed, whether there are side effects, or other operational constraints.

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 short and front-loads the metric definition before the caveats. However, the repeated '§6.3' references are opaque to an agent that lacks the referenced specification, which slightly reduces clarity.

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

Completeness2/5

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

The tool has 7 parameters, no schema descriptions, and no annotations, so the description needs to compensate substantially. It provides metric context and two important caveats, but it omits parameter semantics and when-to-use guidance, leaving the definition incomplete for invocation.

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

Parameters1/5

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

There are 7 parameters with 0% schema description coverage, and the description explains none of them beyond a vague reference to 'direction' and 'selection.' Key parameters such as last_n, cluster, start_date, end_date, run_type, and segment_id are left completely undocumented in both the schema and the description.

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

Purpose4/5

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

The description identifies a specific metric: HR excursion across an effort, broken out by direction and constrained to a selection. It is clear enough to distinguish this from generic metrics tools, but it does not explicitly name or distinguish itself from closely related siblings such as segment_effort_drift or matched_terrain_drift.

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

Usage Guidelines2/5

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

There is no explicit guidance on when to use this tool versus alternatives. The only usage-adjacent information is a caveat that ascent and descent are not comparable and that tau is never returned, which is interpretation guidance rather than selection guidance.

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

drift_onsetB

§6.9 WHEN in a run cardiac drift begins — a VIEW of §6.7, currently REFUSED.

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.

The result carries `gate`, which is computed from the live corpus. While
`gate.reportable` is false the curve is a DIAGNOSTIC and must not be quoted
as a finding — the same standing as tau (§6.3). Read `gate.reason`: it says
exactly what would make it start reporting.

Onset is confounded with run length and its earliest representable value is
§6.7's own 600 s minimum pair separation. Dew point travels with every
value because onset is uninterpretable without it.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose meaningful behavior: the gate is computed against a live corpus, unreportable results are diagnostic-only, onset is confounded with run length, the earliest representable value is bounded by a 600 s pair separation, and dew point travels with every value for interpretability. What it does not clarify is what 'REFUSED' operationally means for the caller (empty result, error, or a flagged row).

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

Conciseness3/5

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

The purpose is front-loaded, which is good, and every paragraph is about something real. But the section-number jargon and the 'currently REFUSED' framing consume space without adding actionable meaning, and the Args block documents only one of eight arguments despite the space it takes.

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

Completeness3/5

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

An output schema exists, so the description needn't enumerate return fields, yet the gate/reportable/reason interpretation it does provide is genuinely necessary context for a tool whose output can be non-reportable. Against that, seven undocumented parameters and an unresolved 'REFUSED' status leave an agent guessing about invocation.

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

Parameters2/5

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

Schema description coverage is 0% across 8 parameters, and the description documents only 'run' (run_id/activity_id/Garmin file id, empty = latest). The remaining seven — last_n, cluster, end_date, run_type, direction, segment_id, start_date — are left entirely to a bare schema, so an agent cannot infer filtering or scope semantics from the text.

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

Purpose3/5

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

The description names a specific quantity (the time in a run at which cardiac drift begins) but buries it under internal section references (§6.9, §6.7, §6.3) that mean nothing to an agent without the source documentation. It never differentiates itself from drift-flavored siblings like matched_terrain_drift or segment_effort_drift, and the phrase 'currently REFUSED' is ambiguous about whether the tool answers at all or just marks results non-reportable.

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

Usage Guidelines3/5

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

It gives real interpretive guidance — do not quote the curve as a finding while gate.reportable is false, and read gate.reason to learn what would change that. But it says nothing about when to reach for this tool versus the other drift siblings, and the 'Empty means the latest run' note only covers one parameter. Usage is implied rather than routed.

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

efficiency_factorC

§6.8 speed per heartbeat on segment-matched terrain, over a selection.

Matched by segment identity, NOT by GAP — GAP is unvalidated (§12.2).

NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.4/5.0
Behavior2/5

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

With no annotations, the description carries the full behavioral burden. It discloses one meaningful trait — that matching uses segment identity rather than GAP because GAP is unvalidated — but says nothing about read-only vs mutation nature, cost, what happens with an empty selection, how defaults on the seven optional filters behave, or failure modes.

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

Conciseness3/5

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

It is short and the metric definition is front-loaded, so there is little waste. But the spec-section citations (§6.8, §12.2) occupy space without conveying anything to an agent that cannot read the spec, making the text dense yet under-informative.

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

Completeness2/5

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

The existence of an output schema excuses it from explaining return values. Everything else is missing: seven undocumented parameters at 0% coverage, no annotations, no precondition or exclusion guidance, and a rationale-heavy framing that leaves an agent unable to construct a correct call confidently.

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

Parameters2/5

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

Schema description coverage is 0% across seven parameters, so the description must compensate and largely fails. 'Over a selection' vaguely gestures at the filtering parameters (last_n, cluster, date range, run_type, direction, segment_id) but explains none of their units, formats, default semantics (empty string vs 0), or interaction.

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

Purpose3/5

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

The phrase 'speed per heartbeat on segment-matched terrain' identifies the computed metric and its scope ('over a selection'), which is more than a restatement of the name. However, it never uses a verb like 'compute' or 'calculate', and the leading '§6.8' reference assumes the agent already knows the spec. The contrast with GAP-based matching hints at sibling differentiation but does not name an alternative tool.

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

Usage Guidelines2/5

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

'Matched by segment identity, NOT by GAP' is a methodological constraint on the computation, not guidance on when to invoke this tool. Nothing tells the agent when to pick this over matched_terrain_drift, segment_effort_drift, or basic_metrics, nor what preconditions (segment history, sufficient rides) are required.

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

grade_binned_paceB

§6.2 pace by grade bin, split by split_type, over a selection.

Run and walk are never pooled: pooling reads as "pace does not vary with
grade" purely because each bin mixes the two modes.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior3/5

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

With no annotations, the description carries the full burden, and it does disclose one important trait: run and walk are never pooled, with the rationale for why pooling misleads. It omits other key behavior — what empty-string/zero defaults mean (all data vs none), permission needs, and how a 'selection' is bounded.

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?

Front-loaded with the core operation and tightly sized — two short sentences with no filler. The section-number prefix and slightly verbose second sentence cost a point.

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

Completeness2/5

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

An output schema exists so return values needn't be explained, but for a 7-parameter, annotation-free analytical tool the description leaves the entire parameter surface and the default/empty-value behavior unexplained. Only the non-pooling caveat is covered.

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

Parameters2/5

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

Seven parameters at 0% schema description coverage, and the description explains none of them. It mentions a 'split_type' that is not even a parameter, and never clarifies run_type, direction, last_n, or the date/cluster filters, so it fails to compensate for the coverage gap.

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

Purpose4/5

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

States a specific computation (pace binned by grade, split by split_type) scoped to a selection, which is distinguishable from siblings like cadence_by_grade and hill_pace. The '§6.2' reference and the absence of a real verb keep it from being a crisp 5.

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

Usage Guidelines3/5

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

Usage is only implied: 'over a selection' hints at when it applies, and the run/walk warning explains interpretation rather than tool selection. No sibling is named as an alternative (e.g., when to choose this vs. hill_pace or cadence_by_grade).

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

hill_paceB

§6.0g pace on every slope effort of one run, split by direction.

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.

Each effort carries mean pace (whole effort, summit to col, moving time)
AND best 30 s (the part actually run fast). They are different quantities —
a slow mean beside a much faster best 30 s is a description of how the
effort was run (walked in part, run in part), not a contradiction.

READ `comparable_ground.length_ratio` BEFORE COMPARING THE DIRECTIONS.
Ascents and descents need not cover the same ground — plateau absorption
can glue flat ground onto one direction (§14k) — so part of
any ascent-vs-descent difference is terrain rather than the athlete.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior4/5

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

With no annotations, the description carries the burden and does add substantive behavioral context: it explains that mean pace and best 30 s are different quantities, that a slow mean beside a fast best is not a contradiction, and that ascent-vs-descent comparisons are terrain-confounded. It does not explicitly state read-only behavior or side-effect profile, but for an analytics tool the non-obvious output semantics are well disclosed.

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 structured with an Args section, and the interpretive caveats are relevant rather than filler. It is somewhat prose-heavy, but each paragraph serves a real comprehension purpose.

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

Completeness2/5

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

The core output interpretation is covered, and an output schema exists, but the description is not complete for an 8-parameter tool with 0% schema description coverage: most filters are never explained. An agent can understand the headline metric but not how to correctly scope the query.

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

Parameters2/5

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

Schema description coverage is 0% across 8 parameters, and the description explains only `run` (run_id/activity_id/Garmin file id, empty means latest). It leaves `last_n`, `cluster`, `start_date`, `end_date`, `run_type`, `direction`, and `segment_id` entirely undocumented, so an agent must guess their semantics.

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

Purpose4/5

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

The description states a precise resource and scope: pace on every slope effort of one run, split by direction. It is clear what the tool computes, but it does not differentiate itself from siblings such as grade_binned_pace or segment-based tools.

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

Usage Guidelines2/5

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

The only guidance is interpretive: read comparable_ground.length_ratio before comparing directions. There is no explicit statement of when to choose this tool over siblings, nor any when-not-to-use or alternative-tool guidance.

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

hr_aboveA

Every contiguous excursion at or above a heart-rate threshold (§14e-ter).

THE UNIT IS THE EXCURSION, NOT THE RECORD. A sustained bout would otherwise
arrive as hundreds of rows and a single spike as one, with nothing in the
shape to tell them apart — which is the whole question when deciding
whether a ceiling is demonstrated or merely recorded.

Each excursion carries the run and date, start offset, span, peak with its
timestamp, mean, the 30 s window CENTRED on the peak, record count,
§15.4 flag count, sampling regime, and pace / grade / cadence. **The same
peak reached while climbing at a walking pace and while running fast on
the flat are different facts about the same heart.**

RAW heart rate, never lag-shifted. FLAGS ARE REPORTED, NOT APPLIED: at the
top of the range a flag may mark a real artifact or a real spike and cannot
settle which. **A run whose peak has unresolved provenance (§14e-bis;
`unresolved_peak_run` in config/athlete.yaml, when set) is MARKED and never
dropped, and every total is reported a second time without it** under
`without_unresolved_peak`.

Args:
    threshold: bpm. 0 (the default) means the configured threshold,
        `hr_above_default_bpm` in config/athlete.yaml -- set it near the
        top of your own HR distribution. `threshold_bpm` in the result
        says which value was used.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
thresholdNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so unusually well: it discloses that HR is raw and never lag-shifted, that flags are reported but not applied, that runs with unresolved peak provenance are marked and never dropped, and that totals are re-reported under without_unresolved_peak. These are exactly the behavioral facts an agent could not infer from the schema.

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

Conciseness3/5

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

The core statement is front-loaded and the key caveats are legible, but the prose is padded with emphatic asides and a rhetorical line about climbing versus flat running that consume space without adding callable information. The heavy capitalization and bold formatting also fight the reader rather than helping.

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

Completeness3/5

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

An output schema exists, so the long enumeration of returned fields (run, date, offset, span, peak, 30 s window, flags, pace/grade/cadence) is largely redundant, while the 7 undocumented filter parameters are the real gap. For an 8-parameter query tool the description is complete on semantics of the data but incomplete on how to scope the query.

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

Parameters2/5

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

Schema description coverage is 0% across 8 parameters, so the description must compensate. It documents only threshold (0 means the configured hr_above_default_bpm, and threshold_bpm in the result echoes the value used); last_n, cluster, start_date, end_date, run_type, direction, and segment_id are left entirely undefined.

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

Purpose4/5

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

States a specific resource and scope: 'Every contiguous excursion at or above a heart-rate threshold,' and explicitly frames the unit of return as an excursion rather than a record. That distinguishes it conceptually from row-per-reading tools, though it never names a sibling like time_above_hr or max_hr_over.

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

Usage Guidelines3/5

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

It motivates the tool ('deciding whether a ceiling is demonstrated or merely recorded') and explains the threshold parameter's default, which implies when to reach for it. But it gives no explicit when-not guidance and does not say how it differs from the closely named time_above_hr or max_hr_over siblings.

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

list_runsA

Corpus listing, newest first. All filters optional and AND-ed.

Args:
    start_date: inclusive YYYY-MM-DD.
    end_date: inclusive YYYY-MM-DD.
    run_type: REJECTED when non-empty -- this build has no run_type
        source. Each row reports run_type null, labelled "not collected";
        a later version re-enables it through user-defined run types.
    cluster: a cluster name from config/athlete.yaml, or NO_GPS / OTHER.
    limit: maximum rows.
    sport: empty means running. "any" lists every sport; otherwise one
        sport by name (cycling, hiking, ...).

Each row carries `local_date`, the day the athlete would call it.
NameRequiredDescriptionDefault
limitNo
sportNo
clusterNo
end_dateNo
run_typeNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description does real work: it discloses that run_type filters are REJECTED, that rows report run_type as null labelled 'not collected', and that rows carry local_date. These are non-obvious behaviors an agent could not derive from schema or annotations. Gaps remain around permissions and limit edge behavior, preventing a 5.

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 lead sentence front-loads purpose and ordering before the parameter block. The docstring-style 'Args:' formatting and the multi-line run_type explanation are somewhat verbose, but every clause conveys actionable semantics rather than filler.

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

Completeness4/5

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

An output schema exists, so return values need not be described, and the description covers filter interaction, ordering, and the notable run_type degradation. Minor gaps (pagination ceiling, whether results are truncated silently) remain for a 6-parameter query tool.

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

Parameters5/5

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

Schema coverage is 0%, so the description must carry all parameter meaning, and it does: date formats and inclusivity, the rejected run_type path, cluster special values (NO_GPS / OTHER) sourced from config, and the critical sport semantics ('empty' = running, 'any' = all sports). Only 'limit: maximum rows' is thin, but it is sufficient.

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

Purpose4/5

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

States a specific verb and resource ('Corpus listing') plus ordering ('newest first') and scoping semantics ('All filters optional and AND-ed'). It never names the nearest sibling (list_segments) or explicitly says 'runs', so differentiation is left to inference, which keeps it below a 5.

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

Usage Guidelines3/5

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

Usage is implied by the sport/cluster semantics ('empty means running', 'a cluster name from config/athlete.yaml'), so an agent can infer when this tool applies. However, there is no explicit when-to-use/when-not guidance and no reference to alternatives such as list_segments.

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

list_segmentsC

The slope library: every segment, with where the reference run meets it.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. It implies an unfiltered enumeration via 'every segment', but never states read-only behavior, side effects, ordering, or what 'reference run' means; the output schema covers return fields but not call behavior.

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?

A single sentence with no filler is appropriately concise, but the metaphor 'slope library' and unexplained 'reference run' make it cryptic rather than clearly front-loaded with an action.

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

Completeness3/5

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

For a zero-parameter list tool with an output schema, the description is almost sufficient: it signals complete enumeration and inclusion of reference-run intersection data. However, it does not clarify what 'reference run' means or how this differs from siblings like segment_history.

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?

The tool has zero parameters, so there are no parameter semantics to document. Baseline 4 is appropriate because the description need not compensate for any schema gaps.

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

Purpose3/5

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

Identifies the resource (segments) and scope ('every segment'), but lacks an explicit verb and the phrase 'where the reference run meets it' is ambiguous. An agent can infer this is a list operation, but not precisely what a segment record represents.

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

Usage Guidelines2/5

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

No when-to-use or when-not guidance is provided, and no alternatives are named among the many sibling tools such as segment_history. 'The slope library' weakly implies discovery, but the description does not say when to choose this over segment-focused siblings.

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

matched_terrain_driftA

§6.7 HR drift on the SAME ground, bpm/hour, over a selection of runs.

Pairs RECORDS within 20 m of each other, at least 10 min apart, BOTH
rwd_run, with speed matched to 0.35 m/s. Walking is not paired. Read
`applied_filters` — those tolerances are what the number means.

Effort-matched by construction, so it is the substitute when §6.4's
steady-effort gate fails. Read `excluded` too — a drift figure over "five
long runs" means something different if two were dropped for coverage.

`segment_effort_drift` is a DIFFERENT quantity, usually several times
larger. Neither is "the" drift.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden well: it discloses pairing rules, distance and time tolerances, speed matching, exclusion of walking, and that users should inspect `applied_filters` and `excluded`. It does not state read-only or permission assumptions, but the operational filtering behavior is unusually well documented.

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 the metric definition and remains relatively tight. It includes some internal section references and backtick field names that may be unnecessary noise, but every substantive sentence adds behavioral or selection context.

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

Completeness2/5

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

The output schema means return values need not be explained, and the description explains the metric's construction and exclusions well. However, for a tool with seven undocumented input parameters and no annotations, the description is materially incomplete for correct invocation because it provides no parameter guidance.

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

Parameters1/5

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

The schema has seven parameters with 0% description coverage, and the description does not explain any of them. Terms like `last_n`, `cluster`, `run_type`, `direction`, and `segment_id` are left entirely for the agent to infer, so the description fails to compensate for the schema gap.

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?

The description states a specific metric and scope: HR drift on the same ground, expressed in bpm/hour, over selected runs. It explicitly distinguishes this quantity from `segment_effort_drift`, so an agent can tell which drift metric is being requested.

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

Usage Guidelines4/5

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

It gives a clear usage condition: this is the substitute when the steady-effort gate in §6.4 fails. It also warns that `segment_effort_drift` is a different quantity and that neither is 'the' drift, which directly helps tool selection. The only weakness is reliance on an external section reference.

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

max_hr_overA

The highest heart rate in a selection, and the run that produced it (§6.0).

TWO CEILINGS, and the difference between them is the point.
`max_hr_recorded` is the single highest sample -- what the watch displayed,
and a SPIKE CANDIDATE, because a maximum selects for positive measurement
error. `max_hr_30s` is the highest 30 s rolling mean with §15.4-flagged
records excluded, and it is the defensible figure. When the two come from
DIFFERENT runs, the corpus's highest spike and its highest sustained effort
are not the same session, and `same_run` says so.

EACH WINNER CARRIES ITS CIRCUMSTANCES: date, run_id and dew point. **A
maximum found on a hot run is a different fact from one found on a hard
effort** -- neither disqualifies a peak, and both change what anchoring a
zone scale to that peak would mean. run_type is null and labelled "not
collected": this build has no source for it.

`declared_ceiling` compares the corpus peak against the max HR the athlete's
zones are actually anchored to (§14e). It is REPORTED, never corrected:
re-anchoring zones is an athlete decision with a coach behind it.

THE COMPARISON IS GATED ON THE SELECTION ITSELF. It is reported only when
a run IN THIS SELECTION reached within the ceiling band of the
demonstrated 30 s ceiling; otherwise it is REFUSED, naming the
selection's best 30 s value and the band. Over easy runs the gap measures
the selection, not the heart.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so well: it flags max_hr_recorded as a spike candidate selected for positive measurement error, discloses that §15.4-flagged records are excluded from the 30 s ceiling, states that run_type is null by design, and explains that declared_ceiling is reported but never corrected. It also documents the gated/refusal behavior of the comparison and names what it returns when refused, which is exactly the behavioral context structured fields don't supply.

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

Conciseness3/5

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

The first sentence is well front-loaded, but the body is long for a small result object and spends much of its length on emphasized editorial framing (ALL CAPS, bold, §-references) rather than new information. The core facts are present but padded.

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

Completeness3/5

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

An output schema exists, so return-value explanation is legitimately omitted, and the behavioral/semantic side of the result is thoroughly covered. What is missing is the input side: with seven undocumented optional parameters and no required ones, an agent lacks enough guidance to construct a meaningful selection, which is the one thing this tool cannot work without.

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

Parameters2/5

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

Seven parameters with 0% schema description coverage, and the description never mentions any of them by name. It repeatedly refers to 'a selection' and 'IN THIS SELECTION' but never says which of last_n, cluster, start_date, end_date, run_type, direction, or segment_id define that selection or how they combine. For a tool whose entire output depends on the selection boundary, this is a significant compensation failure.

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

Purpose4/5

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

The opening sentence names a specific resource ('the highest heart rate in a selection') and states that it returns the producing run, then splits the result into two named measures (max_hr_recorded vs max_hr_30s). It is a clear verb+resource statement, but it never positions itself against siblings like delta_hr, hr_above, or basic_metrics, so an agent must infer that this is the peak-value tool rather than a distribution or threshold tool.

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

Usage Guidelines3/5

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

Usage context is implied rather than stated: 'Over easy runs the gap measures the selection, not the heart' is a caution about interpreting the result, not an instruction on when to call this versus delta_hr or hr_above. No explicit when/when-not/alternatives appear anywhere in the text.

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

mile_splitsA

Per mile (or unit="quarter"): running-only pace, HR, DEM gain/loss and time by gait, with Garmin's own laps beside it for cross-check.

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.
    unit: "mile" (default) or "quarter".

BOUNDARIES from the device odometer, interpolated exactly at each mile
(the windowed-best rule), never from 30 s bins; across a standing stretch
the LAST instant at that distance. The final unit is a PARTIAL with its
real length. A unit crossing a recording gap over 20 s is FLAGGED
(`contains_gap` / `boundary_in_gap`), not refused.

RUNNING-ONLY PACE: rwd_run splits intersected with the unit, stopped time
removed. A walk break inside a mile is excluded from pace and counted in
`time_walking_s`. `hr_running` (PRIMARY) is time-weighted over the same
running overlap; `hr_all_gaits` covers the whole unit. Both RAW, no lag.

Gain/loss from the smoothed DEM profile, in m and ft; with no DEM they are
null and `elevation_reason` says why. `garmin_laps` are Garmin's laps AS
RECORDED -- only distance-triggered ones are miles, and their pace
includes walking -- and are never substituted for ours.
NameRequiredDescriptionDefault
runNo
unitNomile

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior5/5

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

With no annotations, the description carries the full behavioral burden and does so thoroughly: boundary interpolation rules, partial final units, gap flagging, running-only pace excluding stopped/walking time, HR averaging semantics, elevation null reasons, and that Garmin laps are never substituted. These are meaningful behavioral disclosures beyond the schema.

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 the main output and then gives argument and behavioral details. It is longer and denser than ideal, with some repetition around Garmin laps, but most sentences add necessary semantic value for a complex splits tool.

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?

Given the complex per-mile computation, two undocumented schema parameters, no annotations, and a present output schema, the description is complete enough for correct invocation. It covers parameter meanings, edge cases, and field semantics without needing to repeat the output schema.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate. It fully explains both parameters: `run` accepts run_id, activity_id, or Garmin file id and empty means latest run; `unit` accepts "mile" or "quarter" with mile as default.

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

Purpose4/5

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

The description clearly defines a per-mile (or quarter-mile) running-splits output with pace, HR, elevation gain/loss, and gait time, plus Garmin laps for cross-check. It is specific about the resource and computed fields, but does not explicitly name sibling tools or state how it differs from adjacent metrics tools.

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

Usage Guidelines3/5

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

Usage is implied by the description: per-mile running splits with cross-check against Garmin laps, and `run` empty means latest run. However, it gives no explicit when-to-use/when-not guidance and does not route the agent away from alternatives such as segment_history, session_series, or basic_metrics.

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

pingA

Is the server alive, which code is it running, is the database locked.

NEVER TOUCHES THE DATABASE, so it answers during a sync. A `broken` from
any other tool while `write_locked` is true is the lock, not the corpus.
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses the critical behavioral trait (NEVER TOUCHES THE DATABASE, therefore responsive during a sync) and supplies an interpretation rule — a 'broken' result from another tool while write_locked is true indicates the lock, not corrupt data. Missing is any statement of side effects (none) or of what the tool itself returns on failure, but for a read-only probe the key traits are covered.

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

Conciseness5/5

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

Three short sentences, each earning its place: what it reports, the key behavioral guarantee, and how to read failures from other tools. The framing as questions is slightly informal but front-loads the payload immediately.

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

Completeness4/5

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

An output schema exists, so return values need not be explained, and the description still names write_locked, one of the likely returned fields, tying it to diagnostic use. For a zero-parameter probe this is essentially complete; only an explicit statement of what the tool returns when the server is down would improve it.

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?

The tool takes zero parameters, so the baseline is 4; there is nothing for the description to disambiguate.

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

Purpose4/5

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

The description frames the tool as three concrete questions it answers: liveness, running code version, and database lock state. That is a clear, specific health-probe purpose distinguishable from data-returning siblings like sync_status or basic_metrics, though it never explicitly states 'this is the health check, use it before/after X' or names a sibling it could be confused with.

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

Usage Guidelines4/5

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

It gives real usage context: call it to verify the server is alive and to check whether a lock explains failures, and it explains that it 'answers during a sync' when other tools may not. It stops short of explicit routing (e.g. 'use this instead of sync_status when you only need liveness'), so it is strong but not a full when/when-not/alternative statement.

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

reportC

The §16.2 post-run report for one run, against its recent history.

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.

Presents only — it does not judge. Eliminating causes is your work.
Read `notable` first, then `unenforced`.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden. It usefully discloses that the tool 'presents only — it does not judge' and implies comparison against recent history, but it does not explicitly state read-only behavior, side effects, or other operational constraints.

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 short and front-loads the core purpose before its parameter note and reading guidance. The only inefficiency is the opaque '§16.2' reference and an Args section that covers just one of eight parameters.

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

Completeness2/5

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

An output schema exists, so return values need less description, but the tool has 8 parameters with 0% schema coverage and none are explained except `run`. For an agent to invoke it correctly, the description should clarify the roles of the other filtering and comparison parameters.

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

Parameters2/5

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

Schema description coverage is 0% and there are 8 parameters, so the description must compensate. It only explains the `run` parameter (accepting run_id, activity_id, or Garmin file id, with empty meaning latest), leaving last_n, cluster, end_date, run_type, direction, segment_id, and start_date undocumented in both schema and description.

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

Purpose4/5

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

The description clearly identifies a report for one run against its recent history, which is a specific resource and scope. However, it does not differentiate this tool from sibling metric-oriented tools like basic_metrics or session_series, and the internal label '§16.2' adds little external meaning.

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

Usage Guidelines2/5

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

It gives output-reading guidance ('Read `notable` first, then `unenforced`') and states that eliminating causes is the caller's work, but it does not explain when to choose this tool over siblings such as basic_metrics or efficiency_factor. The post-run context is implied, not explicitly framed as when-to-use guidance.

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

resistance_historyB

§18.1 HR at matched resistance over CALENDAR TIME — the longitudinal cut.

EFFECTIVE n IS THE NUMBER OF BLOCKS, NEVER THE NUMBER OF HR RECORDS. A
block is one exposure to one resistance; its several hundred HR samples are
one observation of it. This project has made the opposite mistake twice
(§6.9, §2.6) and both are recorded as the same disease.

A group with fewer than three blocks reports `trend_status: insufficient`
and says how many it has, rather than drawing a line through two points.
Blocks with no stated RPM are grouped SEPARATELY from blocks that have one:
no stated cadence is not a cadence that happens to match.
NameRequiredDescriptionDefault
match_rpmNo
resistanceNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose key behavior: effective n is the number of blocks, fewer than three blocks returns trend_status insufficient, and missing RPM is grouped separately. It does not cover auth/rate-limit behavior, but for an analysis tool the important statistical semantics are present.

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

Conciseness3/5

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

The core purpose is front-loaded, but the project-history aside with section references (§6.9, §2.6) and 'same disease' does not help an agent select or call the tool. The all-caps emphasis and internal references add noise.

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

Completeness2/5

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

An output schema exists, so return shape need not be explained. However, with no annotations and 0% schema description coverage, the description leaves both parameters and usage relative to siblings unexplained, which is a substantial gap for a two-parameter analysis tool.

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

Parameters2/5

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

Schema coverage is 0% for both parameters, and the description never defines what match_rpm controls or how the resistance value is interpreted. It mentions matched resistance and RPM grouping, but does not explain the boolean toggle or default resistance=0.

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

Purpose4/5

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

The opening states a specific analysis: HR at matched resistance over calendar time, described as the longitudinal cut. This is clear enough to distinguish it from aggregate/resistance tools, but it never names a sibling or explicitly says it returns a time series.

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

Usage Guidelines2/5

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

The description explains internal grouping behavior, but gives no guidance on when to use this tool versus time_in_resistance, ride_blocks, or other siblings. There are no stated exclusions or selection conditions.

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

ride_blocksB

§18 the stationary ride's blocks, each with its HR summary.

The watch records HEART RATE ONLY for these -- measured on the indoor
cycling activities in the corpus: no cadence, no speed, no position, no power,
and distance_m is a constant 0.0 rather than null. So resistance, RPM and
the block boundaries are ATHLETE-RECALLED, and `provenance` says so on
every payload. `machine_totals` is the console readout -- machine-reported,
a different reliability, and the machine is the only source for it.

A block containing an off-bike event (water bottle, restroom) is FLAGGED:
the clock keeps running, so the break lands inside a block and its HR is
recovery rather than work at that resistance.

An unannotated ride returns `unavailable` WITH A REASON, never an empty
list -- nothing logged is a different fact from a ride with no structure.
NameRequiredDescriptionDefault
runNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so: it discloses HR-only recording, constant distance, athlete-recalled resistance/RPM/boundaries, provenance, machine_totals reliability, off-bike flagging, and unavailable-with-reason behavior.

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?

Front-loads the resource and then uses short paragraphs for caveats; the length is justified by the data-quality disclosures. Minor verbosity but no wasted sentences.

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

Completeness4/5

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

Output schema exists, so return shape needn't be explained, and the description covers the unusual data limitations and unavailable case well. The missing parameter semantics is the main gap.

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

Parameters1/5

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

The sole parameter `run` has 0% schema description coverage and is never mentioned in the description. The description does not explain what run identifies or how to supply it.

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

Purpose4/5

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

States it returns the stationary ride's blocks with HR summary, a specific resource and payload. It does not explicitly contrast with save_ride_blocks or resistance_history, so sibling differentiation is left implicit.

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

Usage Guidelines2/5

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

No explicit when-to-use or when-not-to-use guidance, and no named alternative. The unannotated-ride behavior is a return contract, not usage guidance.

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

run_walk_cyclesB

M3 run/walk cycle economics — does the walk buy anything? (§17.2)

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.

CHOICE, NOT CAPACITY (§6.6). This is how the athlete elected to structure
the run; it says nothing about what they could have done.

`purchase` pairs each walk with the NEXT run block's pace; `decay` is run
pace by cycle index. Both are PAIRED SERIES, never a fitted slope — time
into the run confounds both, and a coefficient over four points is wider
than itself. Read `elapsed_at_*` before concluding the walk caused anything.

Run blocks under the 120 s pace gate report duration but no pace.

WHAT GOVERNED THE WALKS DECIDES WHAT THIS MEASURES, and this build does
not know. If a rule (an HR cap, a clock) decided them, purchase and decay
measure what the STRUCTURE delivered; if the athlete walked when they felt
like it, identical arithmetic measures WILLINGNESS. `walk_protocol` is
"not collected" here, so `poolable_with_other_runs` is false on every run:
structure that has not been established cannot be assumed. Read each run
on its own.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior5/5

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

With no annotations provided, the description carries the behavioral burden and does so richly: it states that walk protocol is not collected, `poolable_with_other_runs` is false, sub-120s blocks lack pace, and the measures are paired series rather than fitted slopes. It also warns that identical arithmetic can mean structure or willingness depending on what governed the walks.

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

Conciseness3/5

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

The description is front-loaded with the purpose and important caveats, and much of the length is justified by the complexity. However, it includes dense internal references and rhetorical framing, while its Args section covers only one of eight parameters, making the structure uneven.

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

Completeness3/5

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

An output schema exists, so return values do not need full explanation in the description. But with no annotations, eight mostly undocumented parameters, and only partial usage guidance, an agent still lacks enough context to confidently use all filtering options.

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

Parameters2/5

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

Schema description coverage is 0% and there are eight parameters, but the description explains only `run`, including accepted ID types and that an empty value means the latest run. The other seven parameters (`last_n`, `cluster`, date bounds, `run_type`, `direction`, `segment_id`) are left undocumented.

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

Purpose4/5

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

The description clearly states the tool computes run/walk cycle economics and explains the `purchase` and `decay` measures. It is specific but relies on internal labels like M3 and §17.2, and does not explicitly differentiate itself from sibling analytics tools.

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

Usage Guidelines2/5

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

The description gives interpretation caveats, such as reading `elapsed_at_*` before concluding causation and reading each run on its own. However, it does not explicitly say when to use this tool versus alternatives like `mile_splits`, `drift_onset`, or other pacing analytics.

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

save_ride_blocksA

Store one stationary ride's block structure. THE ONE tool that writes athlete input.

A writer is a deliberate act: the watch cannot record resistance or RPM,
and nothing else in this system does either, so there is no existing
channel this competes with. Perceived effort is NOT a field here --
Garmin's own self-evaluation, where the device asked for one, is the
effort channel (see session_load), and a second would be two places for
one answer.

Args:
    payload: a JSON object. Required: run_id (or activity_id), raw_text,
        blocks. Optional: events, machine_totals.
    supersede: replace an existing log for this ride, AS AN ARGUMENT
        BESIDE the payload and never a field inside it. The previous
        revision is KEPT.

BLOCKS ARE END-ANCHORED: each entry is {resistance, end_min, rpm?}, and
start_min is the previous entry's end (0 for the first). Supplying
start_min is REJECTED -- one way to state a boundary means no way for two
statements to disagree. Storage is explicit [start_min, end_min).

resistance is DECIMAL knob-turns from closed (quarter turns such as 4.25,
4.5, 4.75 are ordinary values), validated against [0, MAX]. That ceiling is
DECLARED, not
measured, until the athlete tests where the knob stops.

rpm is a number or [low, high] and is stored as [low, high], NEVER
collapsed to a midpoint -- a midpoint invents precision the recollection
does not have. Absent is absent; a log with no RPM at all is complete.

raw_text is REQUIRED and stored VERBATIM through every revision. The
parsed blocks are an interpretation of it; the text is the record, for the
same reason bronze keeps the raw file.

AMBIGUITY IS REFUSED, NOT RESOLVED. This tool takes already-structured
blocks; overlapping or contradictory entries are rejected naming both.
Parsing prose is the chat's job, at save time, with the athlete present.

Athlete-recalled average HR is NOT a field here -- the watch's HR is
authoritative and already in the corpus. It survives in raw_text only.
NameRequiredDescriptionDefault
payloadYes
supersedeNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so thoroughly: supersede keeps the previous revision, ambiguity is refused rather than resolved, start_min is rejected, raw_text is stored verbatim through revisions, and RPM is never collapsed to a midpoint. It also discloses validation against a declared ceiling and what is intentionally not stored.

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

Conciseness3/5

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

The purpose is front-loaded, but the description runs long with philosophical asides such as the bronze-file analogy and repeated framing of what is not a field. Much of the content is valuable, but several sentences could be compressed without losing operational meaning.

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 write tool with no annotations and a rich behavioral surface, the description is complete: it covers required and optional payload contents, supersede semantics, block anchoring, resistance and RPM rules, raw text preservation, ambiguity rejection, and exclusions. An output schema exists, so return-value detail is appropriately omitted.

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

Parameters5/5

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

Schema coverage is 0%, so the description must compensate, and it does: payload is broken into required fields (run_id/activity_id, raw_text, blocks) and optional fields (events, machine_totals), supersede is explained as an argument beside the payload rather than a field inside it. Block entry structure and end-anchoring rules add meaning far beyond the bare schema.

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?

The first sentence gives a precise verb and resource: 'Store one stationary ride's block structure.' It immediately distinguishes this tool from all siblings by declaring it 'THE ONE tool that writes athlete input,' making its unique write role unambiguous.

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?

It explicitly states when to use this tool and when not to use related fields: perceived effort is excluded in favor of session_load, athlete-recalled HR is excluded because the watch is authoritative, and parsing prose belongs to the chat at save time. These exclusions and alternatives leave little inference.

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

segment_effort_driftA

Effort-level HR drift on a matched slope. NOT §6.7 — a DIFFERENT quantity.

Pairs whole effort averages with no speed match and no split_type filter,
and normalises by the gap between effort starts, so a short gap amplifies:
+10 bpm over 10 min reads as +60 bpm/hour. On the same run it can read
several times larger than matched_terrain_drift.

Use `matched_terrain_drift` unless you specifically want the slope-matched
measure. NEVER present either as "the" drift. Read `applied_filters`.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

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

No annotations, so the description carries the full burden. It does disclose real behavioural traits — the gap normalisation amplifies short gaps (+10 bpm over 10 min reads as +60 bpm/hour), the value can be several times larger than matched_terrain_drift on the same run, and the agent should read applied_filters. That is meaningful, but it doesn't state freshness, data source, or what happens when no matched segment exists.

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?

Front-loaded with the metric definition, then the formula caveat, then the routing advice. Prose is compact. The 'NOT §6.7 — a DIFFERENT quantity' line assumes internal spec knowledge and costs a sentence without adding interpretable meaning.

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

Completeness4/5

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

An output schema exists, so return values needn't be described. The description covers what the measure is, how it is scaled, and the caveat against presenting it as canonical drift. It falls short only on the seven undocumented parameters.

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

Parameters2/5

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

Seven parameters with 0% schema description coverage, and the description explains none of them. last_n, cluster, run_type, direction, segment_id, start_date and end_date are all undocumented in both schema and prose. The mention of 'no split_type filter' hints at a filter dimension but doesn't clarify which parameter governs it.

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

Purpose4/5

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

Names a specific metric (effort-level HR drift on a matched segment) and states exactly how it is computed: whole effort averages paired with no speed match, normalised by the gap between effort starts. It is differentiated from its sibling matched_terrain_drift by naming it and describing the divergence. The 'NOT §6.7' framing adds ambiguity for an agent that doesn't know what §6.7 refers to.

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

Usage Guidelines4/5

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

Explicit routing: 'Use matched_terrain_drift unless you specifically want the slope-matched measure.' That tells the agent when to prefer the sibling. There is no guidance on the date/cluster/run_type filters or what conditions make this measure the right call beyond the slope note.

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

segment_historyC

§6.6 one slope, every traversal, over time — the trending primitive.

Use `report` to find segment ids; they are unrecognisable on their own, so
the report lists them in the order the reference run meets them.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idYes
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.6/5.0
Behavior2/5

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

No annotations are provided, so the description carries the full behavioral burden. It discloses that segment ids come from `report` and are ordered by the reference run, but says nothing about read-only status, permissions, filtering behavior, date-range handling, or other operational traits beyond that single sourcing detail.

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

Conciseness3/5

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

The description is short and front-loads the concept, but '§6.6' and 'one slope' are cryptic, and the two sentences are under-specified for a seven-parameter tool. It avoids verbosity but does not use its brief space to convey the most necessary semantics.

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

Completeness2/5

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

The tool has seven parameters, 0% schema description coverage, and no annotations, so the description must do substantial work. It only covers the conceptual purpose and how to obtain a segment id; it leaves most parameter behavior and usage context unexplained, despite an output schema being present.

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

Parameters2/5

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

Schema description coverage is 0% with seven parameters. The description only indirectly clarifies `segment_id` by saying ids come from `report`; it adds no meaning for `last_n`, `cluster`, `start_date`, `end_date`, `run_type`, or `direction`.

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

Purpose3/5

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

The phrase 'one slope, every traversal, over time — the trending primitive' suggests historical trend data for a segment, but it is metaphorical rather than a clear verb+resource statement. It does not explicitly say what is returned or distinguish this tool from sibling segment-related tools such as segment_effort_drift or list_segments.

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

Usage Guidelines3/5

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

It gives one useful prerequisite: use `report` to find segment ids, and explains that ids are unrecognisable on their own. However, it gives no guidance on when to choose this tool versus other segment or history tools, and no exclusions or conditions.

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

session_loadA

Foster session load: Garmin's own post-run RPE x timer minutes, in AU.

Args:
    run: run_id, activity_id or Garmin file id -- ONE activity. Empty,
        with no selection filter, means the latest run.
    start_date, end_date, cluster, last_n: a SELECTION instead of one
        activity -- of EVERY SPORT, since load is a dose and a rated
        ride is load the legs carried (`summary.n_by_sport`). Name a run
        OR a selection, never both.
    run_type: REJECTED when non-empty -- this build has no run_type source.

THE RPE IS GARMIN'S. Some watches ask "how hard was that?" when an
activity is saved; an activity where the device did not ask, or the
rating was declined, is `unavailable` with that reason -- NEVER priced at
0 and never filled from another activity. `garmin_feel` is SHOWN and
never used: it is a different question, and its 1-5 direction is
unverified.

TIMER TIME, NOT MOVING TIME: load is a session DOSE, not a rate, so
standing time counts. Read `filters` for the formula and its basis.

OVER A SELECTION, `summary.sum_foster_load_au_priced` sums the priced
sessions. When any session is unpriced -- unrated (`n_unrated`), or rated
with no timer time (`n_rated_unpriced`, each with its reason) -- it is a
LOWER BOUND and `is_lower_bound` says so; unpriced sessions are left out,
never counted as zero. No GPS coverage gate applies -- load is volume,
not a terrain comparison.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does it well: it discloses that unrated sessions are 'unavailable' with a reason and never priced at 0, that garmin_feel is shown but unused, that timer time (not moving time) is the basis system, and that selection sums may be lower bounds flagged by is_lower_bound. These are exactly the non-obvious behaviors an agent would otherwise get wrong.

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?

Front-loaded with the definition and an Args block, and every paragraph addresses a distinct behavioral risk. It is longer than most definitions but the density is justified by the number of pitfalls; the heavy all-caps emphasis is slightly noisy but not wasteful.

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

Completeness4/5

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

For a complex eight-parameter tool with no annotations, the description covers semantics, selection logic and aggregation caveats, and an output schema exists so return shape need not be spelled out (though it usefully names key summary fields). The only real hole is the undocumented direction and segment_id parameters.

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 coverage is 0%, so the description must compensate; it documents the meaning, exclusivity and defaults of run, start_date, end_date, cluster, last_n and the run_type rejection in useful detail. However, two of the eight parameters, direction and segment_id, are never mentioned at all, leaving an agent to guess whether they apply to this tool.

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

Purpose4/5

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

The opening sentence names the specific metric, its source, its formula (Garmin RPE x timer minutes) and its unit (AU), so an agent knows exactly what this tool returns. It does not, however, distinguish itself from siblings such as session_series or basic_metrics, which also operate on sessions.

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

Usage Guidelines4/5

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

Clear operating rules for choosing one activity versus a selection, the explicit exclusivity ('Name a run OR a selection, never both'), the empty-means-latest default, and the run_type rejection. What is missing is when to reach for this tool instead of a sibling for related load/dose questions.

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

session_seriesA

§17.1b the session as a 30 s binned series — for "over the run" reasoning.

Args:
    run: run_id, activity_id or Garmin file id. Empty means the latest run.
    include_dynamics: add the per-bin running-dynamics block (below).
        Default false: it is the bulk of the payload, and when false it is
        absent from EVERY bin, with `dynamics_included: false` saying so.
        `dynamics_available` is reported either way.

NULL-DISTANCE BINS (D4). A bin with fewer than two records that carry a
distance -- a GPS gap, an indoor stretch -- reports only the DISTANCE-
DERIVED fields null (distance_start_m/end_m, mps, pace_per_mile), with
`distance_reason` saying how many distance records it had. avg_hr,
steps_per_min, elevation_m, n_records and coverage are still reported
from the records the bin does hold. A bin with NO records at all (past
the last record, inside a long gap) is null throughout with n_records 0.
(A stationary ride is the opposite case: its odometer is a constant 0.0,
not null, so its bins report mps 0.0 -- a known defect, CLAUDE.md §18.)

Pace, HR, elevation, cadence and run/walk/stand state per bin, indexed by
BOTH elapsed seconds and path distance, so "at minute 40" and "at mile 4"
are both answerable from one payload.

STATE IS SECONDS, NOT A LABEL. Each bin carries `run_s`, `walk_s` and
`stand_s`. Many run/walk walks are shorter than a 30 s bin, so a majority
label would erase much of the walking — and on a run/walk session a large
share of bins contain both running and walking.

Elevation is DEM-gated and absent on more than half the corpus; read
`elevation_available`. No position is ever emitted.

RUNNING DYNAMICS PER BIN (§17.1b-bis): stance_time_ms, step_length_mm,
vertical_oscillation_mm and vertical_ratio_pct, each {value, n, unit}.
Garmin's units, unchanged -- millimetres, milliseconds, percent -- and
vertical_ratio is the DEVICE'S OWN field, never recomputed from the other
two.

rwd_run RECORDS ONLY, which is a DIFFERENT RECORD SET from the one behind
`steps_per_min` in the same bin (all records with cadence > 0, running and
walking pooled). `filters.gait_conventions` states each field's, because
reading them as one gait is the mistake the two conventions invite.

n IS PER FIELD. The device drops the four independently -- one field can
sit on a handful of records where another sits on thousands -- so a
per-bin n would misstate the evidence behind a field by orders of
magnitude.

THREE ABSENCES, NEVER 0.0, all distinguishable: `dynamics_reason`
"no_device_channel" (this activity carries none -- FR245, phone file, or a
non-running sport), "no_running_in_bin" (the device records them, this bin
has no running), or null with n 0 (running present, device wrote nothing
for that field here).

`flags_available` says whether §15.4 flags could be applied. Where
records_enriched covers the run, flagged records are excluded; where it
does not, every record is included -- the same figure with and without
flags is NOT the same quantity, so the payload says which it is rather
than refusing the run.
NameRequiredDescriptionDefault
runNo
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo
include_dynamicsNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so thoroughly: it explains null-distance bins, state-as-seconds semantics, elevation availability, dynamics absence reasons, per-field n, and flags coverage. These are exactly the behavioral traits an agent needs to interpret the payload correctly.

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

Conciseness3/5

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

The purpose is front-loaded and the content is information-dense, but the description is very long, with section references, all-caps asides, and repeated caveats. It is useful but could be structured more tightly.

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

Completeness3/5

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

An output schema exists, so return values need not be explained, and the behavioral edge cases are well covered. However, with 0% schema description coverage and seven undocumented parameters, the definition is not complete enough for an agent to use all inputs confidently.

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

Parameters2/5

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

Schema description coverage is 0% across 9 parameters, and the description documents only run and include_dynamics. The other seven parameters (last_n, cluster, end_date, run_type, direction, segment_id, start_date) are left unexplained, so the description cannot compensate for the schema gap.

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

Purpose4/5

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

States a specific resource and granularity: the session as a 30 s binned series, intended for 'over the run' reasoning. It is clear what the tool returns, but it does not explicitly distinguish itself from siblings such as mile_splits or basic_metrics.

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

Usage Guidelines3/5

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

The phrase 'for over the run reasoning' implies when to use it, but there is no explicit when-to-use guidance, no exclusions, and no named alternatives among the many sibling tools.

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

spec_contextA

The standing brief: how to read results, and the measured findings that make a number interpretable. Load this ONCE at the start of a conversation.

Stable across runs — refetch only if told the spec changed.
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the burden, and it usefully discloses that the content is stable across runs and should be cached unless the spec changes. It does not explicitly discuss read-only behavior or side effects, but the load-once guidance provides strong operational context.

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

Conciseness5/5

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

Three short sentences front-load the purpose, usage timing, and caching rule with no filler. Every sentence adds useful guidance.

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

Completeness4/5

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

The output schema presumably explains the returned brief, so the description need not enumerate return values. It covers purpose, usage timing, and stability, though it could be slightly more explicit about what kinds of measured findings are included.

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?

The tool has zero parameters, so there are no parameter semantics to explain beyond the baseline. The description appropriately avoids inventing parameter details.

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

Purpose4/5

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

The description clearly positions this as a contextual primer rather than a metric-computation sibling: it provides a standing brief for interpreting results. It does not specify exactly what form the brief takes, but the distinction from the many metric tools is clear.

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?

It explicitly says to load it ONCE at the start of a conversation and to refetch only if told the spec changed. That gives both the when and the when-not, leaving little inference for the agent.

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

syncA

Fetch new Garmin activities and process them. Returns a JOB ID at once.

This takes minutes and holds the database's exclusive write lock while it
runs, so it cannot be awaited: a synchronous version would make every other
tool call fail for the duration. Poll `sync_status` instead.

NEW FILES ONLY. Downloads APPEND to data/raw/; nothing in this path
modifies, moves, renames or deletes an existing raw file (§3).

A FILE THAT DID NOT INGEST IS REPORTED BY NAME. A finished job with
`clean: false` lists each rejected file under `rejected` with the reason
and a `next_step` carrying the exact command: a recording with a drive or
a forgotten stop at one end is cleared by confirming the window that is
the run (`confirm-file <garmin-id> --end '...'`) and syncing again.
Confirming a window is CLI-ONLY -- no tool here does it -- so relay the
command to the athlete rather than looking for one.

A STEP THAT FAILS COSTS ONLY ITSELF. Each step's outcome is in `steps`
(done / skipped / failed); a failure is in `step_errors` and `problems`
by step name and makes the job `clean: false`, and the rejections are
still reported. With no DEM tiles on disk the terrain steps (dem, silver,
match, recovery) are SKIPPED with the reason in `skipped_steps` -- the
normal state of a fresh install, not a failure.
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so: it discloses runtime of minutes, an exclusive database write lock, why it cannot be awaited, append-only writes that never modify/move/rename/delete raw files, and per-step partial-failure semantics. It even pre-empts a false alarm — DEM-dependent steps being skipped is described as normal on a fresh install.

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?

Front-loaded: the first two lines give purpose, return value and the polling alternative. Each subsequent block covers a distinct failure mode, though the detailed field-by-field recounting of `steps`, `step_errors`, `problems`, `rejected` and `skipped_steps` partially duplicates what the existing output schema already conveys, and the all-caps emphasis is loud.

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 long-running, lock-holding job with no annotations, the description supplies everything an agent needs: async contract, polling target, write-scope guarantees, partial-failure interpretation, and the CLI-only escape hatch for stuck recordings. No material gaps remain.

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?

The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline of 4 applies. No stray parameter claims are made.

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?

Opens with a specific verb+resource ('Fetch new Garmin activities and process them') and immediately states the return contract ('Returns a JOB ID at once'). The asynchronous nature cleanly separates it from the sibling `sync_status`, which is explicitly named as the polling counterpart.

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

Usage Guidelines4/5

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

Explicitly routes the agent away from awaiting the call and toward `sync_status`, and warns that `confirm-file` is CLI-only so the agent should relay a command rather than hunt for a tool. Missing only a positive trigger ('call this when new recordings are on disk').

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

sync_statusA

Progress of a sync job. Empty job_id returns the most recent.

States: queued, running (with the current step), done, failed (with which
step failed -- a Garmin outage and a corrupt file are different problems).
A job fails outright only when the DOWNLOAD fails; a later step that
raises is reported inside a `done` job's result, by name, under
`step_errors` with `clean: false`, so the rejections still arrive.
NameRequiredDescriptionDefault
job_idNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does so well: it enumerates the state machine (queued, running with current step, done, failed with failing step), and explains that only DOWNLOAD failures fail the job outright while later-step exceptions surface inside a `done` job under `step_errors` with `clean: false`. That is exactly the kind of non-obvious behavior an agent could not infer from the schema. It stops short of noting polling cost, result persistence, or whether old jobs expire.

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 core behavior and the empty-arg default are front-loaded in the first two sentences, with failure semantics following. Every clause is substantive, though the parenthetical "a Garmin outage and a corrupt file are different problems" is motivational color rather than operational instruction.

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

Completeness4/5

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

An output schema exists, so return structure needn't be restated, yet the description usefully names `step_errors` and `clean`. Combined with the documented states and default-job behavior, this is enough for an agent to call the tool correctly; only edge cases (invalid/expired job_id, polling guidance) are absent.

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 coverage is 0% and the only parameter's schema is a bare `string` with `default: ""`, so the description's "Empty job_id returns the most recent" is the sole explanation of what the empty value means and what the parameter selects. That compensates for the near-total schema gap, though it doesn't say what an unrecognized job_id yields.

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

Purpose4/5

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

The first sentence states a specific resource and read intent: the progress/status of a sync job, which cleanly separates it from the sibling `sync` (the trigger) and from analytical siblings like `report` or `session_load`. It does not explicitly name `sync` as the companion tool, so the differentiation is inferable rather than spelled out.

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

Usage Guidelines3/5

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

"Empty job_id returns the most recent" gives concrete guidance on the parameter's default case, implying the intended poll-after-sync workflow. However, there is no explicit statement of when to call this versus `sync`, whether it should be polled repeatedly, or what happens with an unknown job_id — the usage is implied, not directed.

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

time_above_hrB

Time at or above each rung of the configured HR ladder (time_above_ladder_bpm in config/athlete.yaml), per run and corpus-wide. thresholds_bpm in the result lists the rungs used.

THE QUESTION THE EXCURSION LIST CANNOT ANSWER: is the top of the range a
place this athlete has been REPEATEDLY, or twice? One run contributing six
excursions and six runs contributing one each look identical at the top of
a list sorted by peak.

Timer-time weighting, capped per record: time at a heart rate is a DOSE,
not a rate, so stopped time is not subtracted — the heart does not stop at
a road crossing. Totals are also reported without the run whose provenance
is open (§14e-bis).
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does substantial work: it discloses timer-time weighting, that stopped time is deliberately not subtracted (with a rationale), that time is capped per record, and that corpus totals omit a run with open provenance. What it omits is the practical profile: read-only nature, pagination/size limits, and failure modes.

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

Conciseness3/5

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

The core computation is front-loaded, but the block on timer-time weighting is discursive and the '§14e-bis' provenance reference is internal jargon an agent cannot resolve. Roughly a third of the text is rationale rather than operational instruction.

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

Completeness2/5

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

An output schema exists, so return values needn't be explained, and the metric's methodology is well covered. But for a 7-parameter tool with zero schema descriptions, leaving every filter and scope parameter undefined is a significant gap that the description should have closed.

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

Parameters2/5

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

Seven optional parameters at 0% schema description coverage, and the description explains none of them — `cluster`, `direction`, `segment_id`, and `run_type` are completely opaque as to accepted values and effect. The only identifier mentioned, `thresholds_bpm`, is a result field, not an input. Names like `last_n` and `start_date` are inferable, which keeps this above a 1.

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

Purpose4/5

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

States a specific computation: time at or above each rung of the configured HR ladder, reported per run and corpus-wide, with the rungs exposed via `thresholds_bpm`. It even frames the analytical question it answers (repeated exposure at the top of the range vs. a one-off). It stops short of naming the sibling it differs from (`hr_above`, `max_hr_over`), so an agent must infer the boundary.

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

Usage Guidelines3/5

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

The 'THE QUESTION THE EXCURSION LIST CANNOT ANSWER' framing implies when this tool is the right choice, but it never names the alternative tool or states a selection rule. There is no explicit 'use this instead of X when...' and no prerequisites for calling it.

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

time_in_resistanceB

§18.2 minutes per resistance value and per 0.5-turn band, per LOCAL week.

The same shape as time-in-zones, and the only ride read that rests on NO assumption beyond the blocks having been logged correctly. Pure aggregation of stored blocks.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations the description carries the full burden, and it does add real behavioral context: results are a pure aggregation of stored blocks and are only as valid as the logged blocks. It stops short of saying what happens when no blocks are logged (empty result vs error) and gives no indication of scope across rides or any cost/size characteristics.

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

Conciseness3/5

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

The measure statement is short and front-loaded, but the leading '§18.2' is an opaque cross-reference that means nothing without the external document, and 'The same shape as time-in-zones' points at a tool that is not in the sibling set. Both sentences spend space on references the agent cannot resolve.

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

Completeness3/5

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

An output schema exists, so return values need not be explained, and the unit/granularity (0.5-turn bands, LOCAL week) is covered. The remaining gap is scope: with zero parameters the agent cannot tell whether this aggregates every stored ride block or only a default window, and the prerequisite relationship to save_ride_blocks/ride_blocks is only hinted at.

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?

The tool takes zero parameters, so per the baseline this is a 4; there is nothing for the description to disambiguate. The schema is fully self-describing (empty object).

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

Purpose4/5

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

The description names the measure precisely: minutes bucketed per resistance value and per 0.5-turn band, per LOCAL week, produced by "pure aggregation of stored blocks." That is a specific verb+resource+granularity. It does not, however, distinguish itself from actual siblings in the list (resistance_history, ride_blocks) — it instead compares to 'time-in-zones', which is not among the sibling tools, so the differentiation target is unverifiable.

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

Usage Guidelines3/5

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

The clause 'the only ride read that rests on NO assumption beyond the blocks having been logged correctly' implies when to prefer it (when an assumption-free ride read is wanted, versus derived metrics like efficiency_factor or drift_onset), but that comparison is never made explicit. There is no stated when-not condition and no named alternative tool.

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

zone_by_gaitC

M7 time in HR zone split by GAIT — running vs walking vs standing.

Zone-2 minutes are the headline, per run and rolled up per LOCAL ISO week.

WHY THE SPLIT MATTERS: a pooled zone-2 total mixes a walk up a climb
with running on the flat, and those are different training. On a hilly
run/walk session the walking share of zone 2 can exceed the running share
— invisible in the pooled figure, and the whole point of the run/walk
structure.

Boundaries come from EACH ACTIVITY'S OWN FILE where present (§14e); a
corpus spanning zone changes holds several distinct sets, and
`boundary_set` says which ruler a
run was measured with, and a week spanning two is reported as SPLIT rather
than summed into a number that is on no scale.

Do not compare this against Garmin's hrTimeInZone: ours excludes stops and
flagged records and applies the 40 s HR lag, so it reads lower by design.
NameRequiredDescriptionDefault
last_nNo
clusterNo
end_dateNo
run_typeNo
directionNo
segment_idNo
start_dateNo

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does well: it discloses that boundaries come from each activity's own file, that weeks spanning multiple boundary sets are reported as SPLIT rather than summed, that stops and flagged records are excluded, and that a 40s HR lag is applied. These are non-obvious traits that materially affect interpretation.

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

Conciseness3/5

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

The main purpose is front-loaded, but the description is long and includes motivational context ('why the split matters') that could be trimmed. It is structured but not tight; several sentences explain interpretation rather than invocation.

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

Completeness2/5

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

For a tool with seven undocumented parameters and no annotations, the description is incomplete on the input side. It provides excellent behavioral and interpretive context, and the output schema covers return values, but the missing parameter semantics leave a critical gap for correct invocation.

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

Parameters1/5

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

Schema description coverage is 0% and the description does not explain any of the seven parameters (last_n, cluster, end_date, run_type, direction, segment_id, start_date). An agent has no way to know what values to supply or how they affect the result.

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

Purpose4/5

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

States a specific verb and resource: time in HR zone split by gait (running vs walking vs standing). This is clear enough for an agent to distinguish it from a simple zone-total tool, though it doesn't explicitly name sibling alternatives.

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

Usage Guidelines2/5

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

The description explains why the gait split matters but gives no explicit guidance on when to use this tool versus alternatives like basic_metrics or time_above_hr. The only comparison is to Garmin's external metric, not to sibling tools in this server.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 29 tool updatesv0.1.0
    • First observedbasic_metrics
    • First observedcadence_by_grade
    • First observeddelta_hr
    • First observeddrift_onset
    • First observedefficiency_factor
    • First observedgrade_binned_pace
    • First observedhill_pace
    • First observedhr_above
    • First observedlist_runs
    • First observedlist_segments
    • First observedmatched_terrain_drift
    • First observedmax_hr_over
    • First observedmile_splits
    • First observedping
    • First observedreport
    • First observedresistance_history
    • First observedride_blocks
    • First observedrun_walk_cycles
    • First observedsave_ride_blocks
    • First observedsegment_effort_drift
    • First observedsegment_history
    • First observedsession_load
    • First observedsession_series
    • First observedspec_context
    • First observedsync
    • First observedsync_status
    • First observedtime_above_hr
    • First observedtime_in_resistance
    • First observedzone_by_gait

TDQS

B3.3/5.0

Scored across 29 tools

Disambiguation4/5

Most tools target distinct analytical questions, and descriptions explicitly contrast near-duplicates such as matched_terrain_drift vs segment_effort_drift and max_hr_over vs hr_above. However, the density of HR, pace, and drift metrics means an agent must read carefully; a few pairs could be confused without the explicit warnings.

Naming Consistency4/5

All names are snake_case and follow a predictable domain vocabulary, with action tools using verbs (list_, save_, sync) and analysis tools using metric nouns. The mix of verb-led and noun-phrase names is readable but not a single verb_noun convention throughout.

Tool Count3/5

29 tools is heavy, but the scope spans run analysis, HR metrics, segments, sync, and stationary rides, so many tools represent distinct analyses. It is borderline: each earns its place, yet the surface is large for an agent to navigate.

Completeness4/5

The set covers core lifecycle: sync, list, per-run metrics, segment analysis, drift, zones, and ride logging with supersede. Minor gaps exist (e.g., no explicit delete for ride logs, config editing is external), but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Connects Claude Desktop to your Garmin Connect running data stored locally in SQLite, enabling querying, syncing, and AI analysis of fitness activities.
    1
    -
  • A
    license
    A
    quality
    A
    maintenance
    Provides Claude Code and Claude Desktop with safe, read-only access to your local Garmin training data, readiness decisions, run details, and trends so you can get coaching advice in natural language.
    15
    9
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Lets Claude read a runner's recent activities and wellness signals — sleep, HRV, resting heart rate — and then design, schedule, edit, or delete structured workouts. Planned sessions are written to an intervals.icu calendar that syncs through Garmin Connect onto the user's watch, without exposing Garmin credentials.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Connects Garmin training data to Claude so it can read recent activities, wellness and recovery signals, and upcoming calendar events. It also lets Claude create, update, and delete structured workouts that sync through intervals.icu to Garmin Connect and onto the user's watch.
    MIT