@vitness/fds-skill 0.1.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.
- package/CLAUDE.md +55 -0
- package/SKILL.md +441 -0
- package/examples/expected-outputs/simple-exercise-transformed.json +225 -0
- package/examples/mapping-configs/simple-exercise-mapping.json +167 -0
- package/examples/source-schemas/simple-exercise-db.json +65 -0
- package/knowledge/enrichment.md +409 -0
- package/knowledge/mappings.md +354 -0
- package/knowledge/schemas.md +309 -0
- package/package.json +32 -0
- package/prompts/exercise-classification.md +173 -0
- package/prompts/exercise-description.md +178 -0
- package/prompts/exercise-metrics.md +278 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# FDS Mapping Strategies
|
|
2
|
+
|
|
3
|
+
## Common Source Formats
|
|
4
|
+
|
|
5
|
+
### Format 1: Simple Exercise Database
|
|
6
|
+
```json
|
|
7
|
+
{
|
|
8
|
+
"id": "0001",
|
|
9
|
+
"name": "3/4 sit-up",
|
|
10
|
+
"bodyPart": "waist",
|
|
11
|
+
"equipment": "body weight",
|
|
12
|
+
"target": "abs",
|
|
13
|
+
"gifUrl": "http://example.com/0001.gif"
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Mapping Strategy:**
|
|
18
|
+
| Source Field | FDS Field | Transform |
|
|
19
|
+
|--------------|-----------|-----------|
|
|
20
|
+
| `id` | `metadata.externalRefs[0].id` | Keep as external ref |
|
|
21
|
+
| - | `exerciseId` | Generate UUIDv4 |
|
|
22
|
+
| `name` | `canonical.name` | `titleCase` |
|
|
23
|
+
| `name` | `canonical.slug` | `slugify` |
|
|
24
|
+
| - | `canonical.description` | AI enrichment |
|
|
25
|
+
| `bodyPart` | Context for AI | Used in classification |
|
|
26
|
+
| `equipment` | `equipment.required[0]` | Registry lookup |
|
|
27
|
+
| `target` | `targets.primary[0]` | Registry lookup + AI |
|
|
28
|
+
| `gifUrl` | `media[0]` | `toMediaArray` |
|
|
29
|
+
| - | `classification.*` | AI enrichment |
|
|
30
|
+
| - | `metrics.primary` | AI enrichment |
|
|
31
|
+
|
|
32
|
+
### Format 2: Detailed Exercise with Categories
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"exercise_id": "ex-123",
|
|
36
|
+
"title": "Barbell Back Squat",
|
|
37
|
+
"description": "A compound lower body exercise...",
|
|
38
|
+
"category": "legs",
|
|
39
|
+
"subcategory": "quadriceps",
|
|
40
|
+
"difficulty": "intermediate",
|
|
41
|
+
"equipment_needed": ["barbell", "squat rack"],
|
|
42
|
+
"muscles_primary": ["quadriceps", "glutes"],
|
|
43
|
+
"muscles_secondary": ["hamstrings", "core"],
|
|
44
|
+
"video_url": "https://...",
|
|
45
|
+
"instructions": ["Step 1...", "Step 2..."]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Mapping Strategy:**
|
|
50
|
+
| Source Field | FDS Field | Transform |
|
|
51
|
+
|--------------|-----------|-----------|
|
|
52
|
+
| `exercise_id` | `metadata.externalRefs[0].id` | External ref |
|
|
53
|
+
| - | `exerciseId` | Generate UUIDv4 |
|
|
54
|
+
| `title` | `canonical.name` | Direct |
|
|
55
|
+
| `title` | `canonical.slug` | `slugify` |
|
|
56
|
+
| `description` | `canonical.description` | Direct |
|
|
57
|
+
| `difficulty` | `classification.level` | Map: intermediate→intermediate |
|
|
58
|
+
| `equipment_needed` | `equipment.required[]` | Registry lookup (array) |
|
|
59
|
+
| `muscles_primary` | `targets.primary[]` | Registry lookup (array) |
|
|
60
|
+
| `muscles_secondary` | `targets.secondary[]` | Registry lookup (array) |
|
|
61
|
+
| `video_url` | `media[0]` | `toMediaArray` type=video |
|
|
62
|
+
| `category` + `subcategory` | `classification.*` | AI enrichment with context |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Transform Functions
|
|
67
|
+
|
|
68
|
+
### slugify
|
|
69
|
+
Converts a string to a URL-safe slug.
|
|
70
|
+
|
|
71
|
+
**Input:** `"Barbell Bench Press"`
|
|
72
|
+
**Output:** `"barbell-bench-press"`
|
|
73
|
+
|
|
74
|
+
**Rules:**
|
|
75
|
+
1. Lowercase
|
|
76
|
+
2. Replace spaces with hyphens
|
|
77
|
+
3. Remove special characters (keep alphanumeric and hyphens)
|
|
78
|
+
4. Collapse multiple hyphens
|
|
79
|
+
5. Trim hyphens from start/end
|
|
80
|
+
|
|
81
|
+
**Edge Cases:**
|
|
82
|
+
- Numbers: `"21s Bicep Curl"` → `"21s-bicep-curl"`
|
|
83
|
+
- Special chars: `"Push-Up (Incline)"` → `"push-up-incline"`
|
|
84
|
+
- Fractions: `"3/4 Sit-Up"` → `"three-quarter-sit-up"` (needs special handling)
|
|
85
|
+
|
|
86
|
+
### titleCase
|
|
87
|
+
Converts to title case for display names.
|
|
88
|
+
|
|
89
|
+
**Input:** `"barbell bench press"`
|
|
90
|
+
**Output:** `"Barbell Bench Press"`
|
|
91
|
+
|
|
92
|
+
**Rules:**
|
|
93
|
+
1. Capitalize first letter of each word
|
|
94
|
+
2. Keep acronyms: `"EZ Bar Curl"` stays `"EZ Bar Curl"`
|
|
95
|
+
3. Handle hyphenated: `"Push-Up"` stays `"Push-Up"`
|
|
96
|
+
|
|
97
|
+
### registryLookup
|
|
98
|
+
Finds matching registry entry with fuzzy matching.
|
|
99
|
+
|
|
100
|
+
**Options:**
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"registry": "muscles",
|
|
104
|
+
"matchField": "name",
|
|
105
|
+
"fuzzyMatch": true,
|
|
106
|
+
"threshold": 0.8,
|
|
107
|
+
"caseSensitive": false
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Matching Priority:**
|
|
112
|
+
1. Exact match on `name` or `slug`
|
|
113
|
+
2. Exact match in `aliases`
|
|
114
|
+
3. Fuzzy match on `name` (Levenshtein distance)
|
|
115
|
+
4. AI fallback if not found
|
|
116
|
+
|
|
117
|
+
**Examples:**
|
|
118
|
+
- `"abs"` → Matches `"Abs"` (exact) or `"Rectus Abdominis"` (alias)
|
|
119
|
+
- `"body weight"` → Matches `"Body Weight"` (fuzzy, space handling)
|
|
120
|
+
- `"quads"` → Matches `"Quadriceps"` (alias)
|
|
121
|
+
|
|
122
|
+
### toMediaArray
|
|
123
|
+
Converts URL(s) to FDS media array format.
|
|
124
|
+
|
|
125
|
+
**Options:**
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"type": "image",
|
|
129
|
+
"baseUrl": "file:///path/to/local/",
|
|
130
|
+
"urlTransform": {
|
|
131
|
+
"pattern": "http://old.cdn.com/(\\d+)\\.gif",
|
|
132
|
+
"replace": "https://new.cdn.com/$1.gif"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Input:** `"http://old.cdn.com/0001.gif"`
|
|
138
|
+
**Output:**
|
|
139
|
+
```json
|
|
140
|
+
[{
|
|
141
|
+
"type": "image",
|
|
142
|
+
"uri": "https://new.cdn.com/0001.gif"
|
|
143
|
+
}]
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### prefixUUID
|
|
147
|
+
Generates or formats UUIDs with optional prefix.
|
|
148
|
+
|
|
149
|
+
**Options:**
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"prefix": "ex-",
|
|
153
|
+
"generate": true
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**If source has ID:**
|
|
158
|
+
- Input: `"0001"` → Output: `"ex-0001-{uuid}"` or preserve + add external ref
|
|
159
|
+
|
|
160
|
+
**If generate:**
|
|
161
|
+
- Output: `"ex-{generated-uuid-v4}"`
|
|
162
|
+
|
|
163
|
+
### autoGenerate
|
|
164
|
+
Auto-generates metadata fields.
|
|
165
|
+
|
|
166
|
+
**Options:**
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"createdAt": "now",
|
|
170
|
+
"updatedAt": "now",
|
|
171
|
+
"status": "draft",
|
|
172
|
+
"source": "import-job-123"
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Mapping Configuration Examples
|
|
179
|
+
|
|
180
|
+
### Basic Exercise Import
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"$schema": "https://spec.vitness.me/schemas/transformer/v1.0.0/mapping.schema.json",
|
|
184
|
+
"version": "1.0.0",
|
|
185
|
+
"targetSchema": {
|
|
186
|
+
"version": "1.0.0",
|
|
187
|
+
"entity": "exercise"
|
|
188
|
+
},
|
|
189
|
+
"registries": {
|
|
190
|
+
"muscles": { "source": "local", "local": "./registries/muscles.registry.json" },
|
|
191
|
+
"equipment": { "source": "local", "local": "./registries/equipment.registry.json" },
|
|
192
|
+
"muscleCategories": { "source": "local", "local": "./registries/muscle-categories.registry.json" }
|
|
193
|
+
},
|
|
194
|
+
"mappings": {
|
|
195
|
+
"schemaVersion": { "default": "1.0.0" },
|
|
196
|
+
"exerciseId": { "from": null, "transform": "uuid" },
|
|
197
|
+
"canonical.name": { "from": "name", "transform": "titleCase" },
|
|
198
|
+
"canonical.slug": { "from": "name", "transform": "slugify" },
|
|
199
|
+
"canonical.description": {
|
|
200
|
+
"from": null,
|
|
201
|
+
"enrichment": {
|
|
202
|
+
"enabled": true,
|
|
203
|
+
"prompt": "exercise_description",
|
|
204
|
+
"context": ["name", "bodyPart", "target", "equipment"]
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"classification": {
|
|
208
|
+
"from": null,
|
|
209
|
+
"enrichment": {
|
|
210
|
+
"enabled": true,
|
|
211
|
+
"prompt": "exercise_classification",
|
|
212
|
+
"context": ["name", "bodyPart", "target", "equipment"]
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
"targets.primary": {
|
|
216
|
+
"from": "target",
|
|
217
|
+
"transform": "registryLookup",
|
|
218
|
+
"options": { "registry": "muscles", "fuzzyMatch": true }
|
|
219
|
+
},
|
|
220
|
+
"equipment.required": {
|
|
221
|
+
"from": "equipment",
|
|
222
|
+
"transform": "registryLookup",
|
|
223
|
+
"options": { "registry": "equipment", "fuzzyMatch": true }
|
|
224
|
+
},
|
|
225
|
+
"metrics.primary": {
|
|
226
|
+
"from": null,
|
|
227
|
+
"enrichment": {
|
|
228
|
+
"enabled": true,
|
|
229
|
+
"prompt": "exercise_metrics",
|
|
230
|
+
"context": ["name", "classification.exerciseType"]
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"media": {
|
|
234
|
+
"from": "gifUrl",
|
|
235
|
+
"transform": "toMediaArray",
|
|
236
|
+
"options": { "type": "image" }
|
|
237
|
+
},
|
|
238
|
+
"metadata": {
|
|
239
|
+
"transform": "autoGenerate",
|
|
240
|
+
"options": {
|
|
241
|
+
"createdAt": "now",
|
|
242
|
+
"updatedAt": "now",
|
|
243
|
+
"status": "draft",
|
|
244
|
+
"source": "exercises-import"
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
"metadata.externalRefs": {
|
|
248
|
+
"from": "id",
|
|
249
|
+
"transform": "template",
|
|
250
|
+
"options": {
|
|
251
|
+
"template": [{ "system": "source-db", "id": "{{value}}" }]
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"output": {
|
|
256
|
+
"format": "json",
|
|
257
|
+
"pretty": true,
|
|
258
|
+
"directory": "./output/exercises/",
|
|
259
|
+
"naming": "{{slug}}.json"
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Nested Path Mapping
|
|
267
|
+
|
|
268
|
+
FDS uses nested structures. Use dot notation:
|
|
269
|
+
|
|
270
|
+
- `canonical.name` → `{ canonical: { name: value } }`
|
|
271
|
+
- `targets.primary` → `{ targets: { primary: value } }`
|
|
272
|
+
- `metadata.externalRefs[0].id` → First item in array
|
|
273
|
+
|
|
274
|
+
### Array Handling
|
|
275
|
+
|
|
276
|
+
**Single value to array:**
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"targets.primary": {
|
|
280
|
+
"from": "target",
|
|
281
|
+
"transform": ["registryLookup", "toArray"]
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Multiple source to array:**
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"targets.primary": {
|
|
290
|
+
"from": ["primary_muscle", "secondary_muscle"],
|
|
291
|
+
"transform": "registryLookup",
|
|
292
|
+
"options": { "registry": "muscles" }
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Conditional Mapping
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"classification.unilateral": {
|
|
304
|
+
"from": "name",
|
|
305
|
+
"transform": "template",
|
|
306
|
+
"options": {
|
|
307
|
+
"template": "{{value.toLowerCase().includes('single') || value.toLowerCase().includes('one arm') || value.toLowerCase().includes('one leg')}}"
|
|
308
|
+
},
|
|
309
|
+
"condition": "source.name != null"
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Default Values
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{
|
|
320
|
+
"classification.kineticChain": {
|
|
321
|
+
"from": null,
|
|
322
|
+
"default": "mixed"
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Error Handling
|
|
330
|
+
|
|
331
|
+
### Required Fields
|
|
332
|
+
Mark critical fields as required to fail early:
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"canonical.name": {
|
|
336
|
+
"from": "name",
|
|
337
|
+
"required": true
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Fallback Chain
|
|
343
|
+
```json
|
|
344
|
+
{
|
|
345
|
+
"canonical.description": {
|
|
346
|
+
"from": ["description", "summary", "notes"],
|
|
347
|
+
"transform": "coalesce",
|
|
348
|
+
"enrichment": {
|
|
349
|
+
"enabled": true,
|
|
350
|
+
"when": "empty"
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# FDS Schema Reference
|
|
2
|
+
|
|
3
|
+
## Exercise Schema (v1.0.0)
|
|
4
|
+
|
|
5
|
+
### Top-Level Structure
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
interface FDSExercise {
|
|
9
|
+
schemaVersion: string; // Required: "1.0.0"
|
|
10
|
+
exerciseId: string; // Required: UUIDv4
|
|
11
|
+
canonical: Canonical; // Required
|
|
12
|
+
classification: Classification; // Required
|
|
13
|
+
targets: Targets; // Required
|
|
14
|
+
equipment?: Equipment; // Optional
|
|
15
|
+
constraints?: Constraints; // Optional
|
|
16
|
+
relations?: Relation[]; // Optional
|
|
17
|
+
metrics: Metrics; // Required
|
|
18
|
+
media?: Media[]; // Optional
|
|
19
|
+
attributes?: Record<string, any>;// Optional: x: namespaced
|
|
20
|
+
extensions?: Record<string, any>;// Optional: x: namespaced
|
|
21
|
+
metadata: Metadata; // Required
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Canonical
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
interface Canonical {
|
|
29
|
+
name: string; // Required: Display name
|
|
30
|
+
slug: string; // Required: URL-safe identifier, pattern: ^[a-z0-9-]{2,}$
|
|
31
|
+
description?: string; // Optional: Detailed description
|
|
32
|
+
aliases?: string[]; // Optional: Alternative names
|
|
33
|
+
localized?: Localized[]; // Optional: Translations
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface Localized {
|
|
37
|
+
lang: string; // Required: ISO 639-1 code
|
|
38
|
+
name: string; // Required
|
|
39
|
+
description?: string;
|
|
40
|
+
aliases?: string[];
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Classification
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
interface Classification {
|
|
48
|
+
exerciseType: string; // Required: strength, cardio, mobility, plyometric, balance
|
|
49
|
+
movement: Movement; // Required: See enum
|
|
50
|
+
mechanics: Mechanics; // Required: compound, isolation
|
|
51
|
+
force: Force; // Required: push, pull, static, mixed
|
|
52
|
+
level: Level; // Required: beginner, intermediate, advanced
|
|
53
|
+
unilateral?: boolean; // Optional: default false
|
|
54
|
+
kineticChain?: KineticChain; // Optional: open, closed, mixed
|
|
55
|
+
tags?: string[]; // Optional: free-form tags
|
|
56
|
+
taxonomyRefs?: TaxonomyRef[]; // Optional: external taxonomy references
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Targets
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface Targets {
|
|
64
|
+
primary: MuscleRef[]; // Required: at least 1
|
|
65
|
+
secondary?: MuscleRef[]; // Optional
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface MuscleRef {
|
|
69
|
+
id: string; // Required: UUIDv4
|
|
70
|
+
slug?: string; // Optional
|
|
71
|
+
name: string; // Required
|
|
72
|
+
categoryId: string; // Required: muscle category UUID
|
|
73
|
+
aliases?: string[]; // Optional
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Equipment
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
interface Equipment {
|
|
81
|
+
required?: EquipmentRef[];
|
|
82
|
+
optional?: EquipmentRef[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface EquipmentRef {
|
|
86
|
+
id: string; // Required: UUIDv4
|
|
87
|
+
slug?: string; // Optional
|
|
88
|
+
name: string; // Required
|
|
89
|
+
abbreviation?: string; // Optional
|
|
90
|
+
categories?: string[]; // Optional
|
|
91
|
+
aliases?: string[]; // Optional
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Metrics
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
interface Metrics {
|
|
99
|
+
primary: MetricRef; // Required
|
|
100
|
+
secondary?: MetricRef[]; // Optional
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface MetricRef {
|
|
104
|
+
type: MetricType; // Required: See enum
|
|
105
|
+
unit: MetricUnit; // Required: See enum
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Metadata
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface Metadata {
|
|
113
|
+
createdAt: string; // Required: ISO 8601 datetime
|
|
114
|
+
updatedAt: string; // Required: ISO 8601 datetime
|
|
115
|
+
source?: string; // Optional: data source identifier
|
|
116
|
+
version?: string; // Optional: record version
|
|
117
|
+
status: Status; // Required: See enum
|
|
118
|
+
deprecated?: {
|
|
119
|
+
since?: string; // Schema version when deprecated
|
|
120
|
+
replacedBy?: string; // ID of replacement exercise
|
|
121
|
+
};
|
|
122
|
+
externalRefs?: ExternalRef[];
|
|
123
|
+
history?: HistoryEntry[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface ExternalRef {
|
|
127
|
+
system: string; // Required: external system name
|
|
128
|
+
id: string; // Required: ID in that system
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Media
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface MediaItem {
|
|
136
|
+
type: "image" | "video" | "doc" | "3d"; // Required
|
|
137
|
+
uri: string; // Required: URI format
|
|
138
|
+
caption?: string;
|
|
139
|
+
license?: string;
|
|
140
|
+
attribution?: string;
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Equipment Schema (v1.0.0)
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
interface FDSEquipment {
|
|
150
|
+
schemaVersion: string; // Required
|
|
151
|
+
id: string; // Required: UUIDv4
|
|
152
|
+
canonical: {
|
|
153
|
+
name: string; // Required
|
|
154
|
+
slug: string; // Required
|
|
155
|
+
abbreviation?: string;
|
|
156
|
+
description?: string;
|
|
157
|
+
aliases?: string[];
|
|
158
|
+
localized?: Localized[];
|
|
159
|
+
};
|
|
160
|
+
classification?: {
|
|
161
|
+
tags?: string[];
|
|
162
|
+
};
|
|
163
|
+
media?: Media[];
|
|
164
|
+
attributes?: Record<string, any>;
|
|
165
|
+
extensions?: Record<string, any>;
|
|
166
|
+
metadata: Metadata; // Required
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Muscle Schema (v1.0.0)
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
interface FDSMuscle {
|
|
176
|
+
schemaVersion: string; // Required
|
|
177
|
+
id: string; // Required: UUIDv4
|
|
178
|
+
canonical: {
|
|
179
|
+
name: string; // Required
|
|
180
|
+
slug: string; // Required
|
|
181
|
+
description?: string;
|
|
182
|
+
aliases?: string[];
|
|
183
|
+
localized?: Localized[];
|
|
184
|
+
};
|
|
185
|
+
classification: {
|
|
186
|
+
categoryId: string; // Required: muscle category UUID
|
|
187
|
+
region: RegionGroup; // Required: See enum
|
|
188
|
+
laterality?: Laterality;
|
|
189
|
+
};
|
|
190
|
+
heatmap?: {
|
|
191
|
+
atlasId: string;
|
|
192
|
+
areaIds: string[];
|
|
193
|
+
};
|
|
194
|
+
media?: Media[];
|
|
195
|
+
attributes?: Record<string, any>;
|
|
196
|
+
extensions?: Record<string, any>;
|
|
197
|
+
metadata: Metadata; // Required
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Muscle Category Schema (v1.0.0)
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
interface FDSMuscleCategory {
|
|
207
|
+
schemaVersion: string; // Required
|
|
208
|
+
id: string; // Required: UUIDv4
|
|
209
|
+
canonical: {
|
|
210
|
+
name: string; // Required
|
|
211
|
+
slug: string; // Required
|
|
212
|
+
description?: string;
|
|
213
|
+
aliases?: string[];
|
|
214
|
+
localized?: Localized[];
|
|
215
|
+
};
|
|
216
|
+
classification?: {
|
|
217
|
+
tags?: string[];
|
|
218
|
+
};
|
|
219
|
+
media?: Media[];
|
|
220
|
+
attributes?: Record<string, any>;
|
|
221
|
+
extensions?: Record<string, any>;
|
|
222
|
+
metadata: Metadata; // Required
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Enumerations
|
|
229
|
+
|
|
230
|
+
### Movement
|
|
231
|
+
```typescript
|
|
232
|
+
type Movement =
|
|
233
|
+
| "squat"
|
|
234
|
+
| "hinge"
|
|
235
|
+
| "lunge"
|
|
236
|
+
| "push-horizontal"
|
|
237
|
+
| "push-vertical"
|
|
238
|
+
| "pull-horizontal"
|
|
239
|
+
| "pull-vertical"
|
|
240
|
+
| "carry"
|
|
241
|
+
| "core-anti-extension"
|
|
242
|
+
| "core-anti-rotation"
|
|
243
|
+
| "rotation"
|
|
244
|
+
| "locomotion"
|
|
245
|
+
| "isolation"
|
|
246
|
+
| "other";
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### MetricType
|
|
250
|
+
```typescript
|
|
251
|
+
type MetricType =
|
|
252
|
+
| "reps"
|
|
253
|
+
| "weight"
|
|
254
|
+
| "duration"
|
|
255
|
+
| "distance"
|
|
256
|
+
| "speed"
|
|
257
|
+
| "pace"
|
|
258
|
+
| "power"
|
|
259
|
+
| "heartRate"
|
|
260
|
+
| "steps"
|
|
261
|
+
| "calories"
|
|
262
|
+
| "height"
|
|
263
|
+
| "tempo"
|
|
264
|
+
| "rpe";
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### MetricUnit
|
|
268
|
+
```typescript
|
|
269
|
+
type MetricUnit =
|
|
270
|
+
| "count"
|
|
271
|
+
| "kg"
|
|
272
|
+
| "lb"
|
|
273
|
+
| "s"
|
|
274
|
+
| "min"
|
|
275
|
+
| "m"
|
|
276
|
+
| "km"
|
|
277
|
+
| "mi"
|
|
278
|
+
| "m_s"
|
|
279
|
+
| "km_h"
|
|
280
|
+
| "min_per_km"
|
|
281
|
+
| "min_per_mi"
|
|
282
|
+
| "W"
|
|
283
|
+
| "bpm"
|
|
284
|
+
| "kcal"
|
|
285
|
+
| "cm"
|
|
286
|
+
| "in";
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### RegionGroup
|
|
290
|
+
```typescript
|
|
291
|
+
type RegionGroup =
|
|
292
|
+
| "upper-front"
|
|
293
|
+
| "upper-back"
|
|
294
|
+
| "lower-front"
|
|
295
|
+
| "lower-back"
|
|
296
|
+
| "core"
|
|
297
|
+
| "full-body"
|
|
298
|
+
| "n/a";
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Status
|
|
302
|
+
```typescript
|
|
303
|
+
type Status =
|
|
304
|
+
| "draft"
|
|
305
|
+
| "review"
|
|
306
|
+
| "active"
|
|
307
|
+
| "inactive"
|
|
308
|
+
| "deprecated";
|
|
309
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vitness/fds-skill",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "FDS (Fitness Data Standard) AI skill and knowledge base for schema transformation and enrichment",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./SKILL.md",
|
|
7
|
+
"files": [
|
|
8
|
+
"SKILL.md",
|
|
9
|
+
"CLAUDE.md",
|
|
10
|
+
"knowledge",
|
|
11
|
+
"prompts",
|
|
12
|
+
"examples"
|
|
13
|
+
],
|
|
14
|
+
"keywords": [
|
|
15
|
+
"fds",
|
|
16
|
+
"fitness",
|
|
17
|
+
"data",
|
|
18
|
+
"standard",
|
|
19
|
+
"ai",
|
|
20
|
+
"skill",
|
|
21
|
+
"knowledge-base",
|
|
22
|
+
"llm",
|
|
23
|
+
"prompt"
|
|
24
|
+
],
|
|
25
|
+
"author": "VITNESS",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/vitness-me/fds-spec-website.git",
|
|
30
|
+
"directory": "packages/fds-skill"
|
|
31
|
+
}
|
|
32
|
+
}
|