@dataworks-technology/cli 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,15 @@
1
1
  ---
2
2
  name: query-dataworks-metrics
3
- description: Query historical Dataworks athlete metrics such as GPS, heart rate, speed, altitude, cadence, power, timing, or custom metrics. Use when a user asks for latest, last, recent, or time-bounded metric values for an athlete by ID or name.
3
+ description: Query historical Dataworks metrics such as GPS, heart rate, speed, altitude, cadence, power, timing, or custom metrics, for one athlete or across a whole event. Use when a user asks for latest, last, recent, or time-bounded metric values, or needs to find an athlete or event ID.
4
4
  ---
5
5
 
6
6
  # Query Dataworks metrics
7
7
 
8
- Use the `query_metrics` tool. It is read-only and uses the current authenticated
9
- `dw` session and selected tenant.
8
+ Three read-only tools use the current authenticated `dw` session and tenant:
9
+
10
+ - `query_metrics` — metric values, scoped to an athlete, an event, or a datasource.
11
+ - `list_athletes` — find an athlete ID, or confirm someone is not in this tenant.
12
+ - `list_events` — find an event ID for a race, by name.
10
13
 
11
14
  If `query_metrics` is unavailable, tell the user to run `dw agents install`
12
15
  once in their terminal, then start a new Codex thread or run `/reload-plugins`
@@ -14,18 +17,42 @@ in Claude Code. Do not substitute raw GraphQL or guess that setup succeeded.
14
17
 
15
18
  ## Construct the request
16
19
 
17
- - Pass `athlete_id` when the user provides a Dataworks athlete public ID.
18
- - Otherwise pass `athlete_name`; let the tool resolve it and surface ambiguity.
20
+ - Scope every query. Pass at least one of `athlete_id`, `athlete_name`,
21
+ `event_id`, or `dataset_datasource_id`; the tool refuses an unscoped query
22
+ rather than sweeping the tenant.
23
+ - For a question about a person, pass `athlete_id` when the user gives an ID,
24
+ otherwise `athlete_name` and let the tool resolve it.
25
+ - For a question about a race or feed — "the latest heart rate at T100 San
26
+ Francisco" — omit the athlete entirely and pass `event_id`. Do not invent an
27
+ athlete to satisfy the call. Rows still carry `athlete_id` per value.
28
+ - To compare people, pass `athlete_ids` rather than one query each; combined
29
+ with `aggregate` it returns one value per athlete. Use `event_ids` likewise to
30
+ span a series of races. Resolve names to IDs with `list_athletes` first, and
31
+ note an athlete with no data simply has no rows rather than an error.
19
32
  - Map the user's wording onto a canonical metric name from the catalogue below.
20
33
  Case, spaces, hyphens and underscores are ignored, so "Heart Rate" resolves to
21
34
  `heartrate`. Do not invent a metric name.
22
35
  - Default to `limit: 30` and `order: newest` only when the user did not specify
23
36
  a count or order.
24
37
  - Preserve explicit `from` and `to` times as ISO 8601 date-times.
25
- - Pass `event_id`, `dataset_datasource_id`, or `tenant_id` only when explicitly
26
- supplied or already resolved. Never guess an ID.
38
+ - Never guess or infer an ID. Resolve one with `list_athletes` or `list_events`,
39
+ or use an ID the user supplied. An ID inferred from a shared prefix, a naming
40
+ pattern, or a row count is a guess: say you could not resolve it instead.
27
41
  - For a genuinely custom metric absent from the catalogue, pass its exact name
28
42
  and an explicit `metric_category`.
43
+ - Rows carry every column the metric's category provides. Heart rate and power
44
+ add rolling `max`, `min`, `avg` and a seven-zone breakdown, all under `extra`
45
+ on each row — read zones from there rather than computing them.
46
+ - To find high or low readings, pass `min_value` or `max_value` rather than
47
+ fetching everything and filtering; the server applies the bound.
48
+ - To rank by value rather than recency, pass `order_by: "current"`. It defaults
49
+ to `timestamp`, and `order` controls the direction either way.
50
+ - For a maximum, minimum, average, sum, or count, pass `aggregate` instead of
51
+ fetching rows and computing it yourself. The server aggregates over every
52
+ matching sample; taking a maximum over returned rows only covers the rows
53
+ `limit` allowed through. Results arrive in `aggregate.groups` and `rows` is
54
+ empty. `group_by` defaults to `athletepublicid`, so an event-scoped aggregate
55
+ returns one value per athlete; pass `eventpublicid` for one value per event.
29
56
 
30
57
  ## Metric catalogue
31
58
 
@@ -55,6 +82,20 @@ Haigh"`, `metric: "GPS"`, `limit: 30`, `order: "newest"`.
55
82
  `metric: "heartrate"`, then take the maximum over the returned rows.
56
83
  - “Cadence for Sam since noon” → `athlete_name: "Sam"`, `metric: "cadence"`,
57
84
  `from: <the unambiguous ISO 8601 time requested>`.
85
+ - “Latest 10 heart rate values for T100 San Francisco” → `list_events` with
86
+ `search: "T100 San Francisco"` to get the ID, then `query_metrics` with
87
+ `event_id: <that ID>`, `metric: "heartrate"`, `limit: 10`, and no athlete.
88
+ - “Hayden Wilde's maximum heart rate” → `query_metrics` with
89
+ `athlete_name: "Hayden Wilde"`, `metric: "heartrate"`, `aggregate: "max"`.
90
+ Read the answer from `aggregate.groups`; do not fetch rows and compare them.
91
+ - “When was Sam above 180bpm?” → `metric: "heartrate"`, `min_value: 180`.
92
+ - “Sam's highest heart rate readings” → `metric: "heartrate"`,
93
+ `order_by: "current"`, which ranks by value instead of recency.
94
+ - “Sam's heart rate zones” → an ordinary query; read `extra.z1_percentage`
95
+ through `extra.z7_percentage` from any returned row.
96
+ - “Compare Hayden and Sam's peak heart rate” → `list_athletes` for both IDs,
97
+ then one call with `athlete_ids: [<both>]`, `metric: "heartrate"`,
98
+ `aggregate: "max"`; each athlete appears once in `aggregate.groups`.
58
99
 
59
100
  ## Handle results
60
101
 
@@ -63,8 +104,20 @@ environment, tenant, canonical metric, order, and returned count. GPS rows inclu
63
104
  decoded `position.latitude` and `position.longitude`; heart-rate values are
64
105
  numeric with unit `bpm` when the source value is valid.
65
106
 
66
- If the tool reports `ATHLETE_AMBIGUOUS`, present its candidates and ask the user
67
- to choose. For `AUTH_REQUIRED` or `TENANT_REQUIRED`, follow the recovery command
107
+ Every error carries a `recovery` field. Follow it rather than improvising, and
108
+ never fall back to raw GraphQL or `dw data ...` to work around a failure.
109
+
110
+ - `ATHLETE_AMBIGUOUS` — present the candidates and ask the user to choose.
111
+ - `ATHLETE_NOT_FOUND` — the athlete is not in this tenant. Do not retry with
112
+ name variations. Call `list_athletes` once to check, then tell the user.
113
+ - `QUERY_SCOPE_REQUIRED` — add an athlete, `event_id`, or
114
+ `dataset_datasource_id`.
115
+ - `METRIC_CATEGORY_REQUIRED` — retry with one of the returned `suggestions`.
116
+
117
+ `list_events` reports where its results came from in `source`: the events API,
118
+ or each dataset's event relation. Either is authoritative. Only when
119
+ `unavailable: true` did both routes yield nothing — report that and stop rather
120
+ than identifying an event some other way. For `AUTH_REQUIRED` or `TENANT_REQUIRED`, follow the recovery command
68
121
  in the error and retry. For `METRIC_CATEGORY_REQUIRED`, the error's `suggestions`
69
122
  list the closest canonical names — retry with one rather than asking the user to
70
123
  spell the metric. Never expose credentials or session material.