@isparling/engram-coach 0.1.0 → 0.2.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.
Files changed (51) hide show
  1. package/README.md +85 -18
  2. package/SETUP.md +559 -0
  3. package/SKILL_PACK.md +75 -0
  4. package/analyses/catalog.md +257 -0
  5. package/analysis-tools/hrv-trend.ts +592 -0
  6. package/analysis-tools/migrate-structured-capture.ts +234 -0
  7. package/analysis-tools/race-context.ts +96 -0
  8. package/analysis-tools/stream-analyze.ts +1008 -0
  9. package/analysis-tools/tsb-predict.ts +117 -0
  10. package/capture-handler.ts +301 -0
  11. package/config.json.example +21 -0
  12. package/engram-coach-ambient-capture.ts +336 -0
  13. package/engram-coach-capture-types.ts +185 -0
  14. package/engram-coach-config.ts +268 -0
  15. package/engram-coach-domain.ts +7 -2
  16. package/engram-coach-keys.ts +189 -0
  17. package/engram-coach-materialization.ts +638 -0
  18. package/engram-coach-migration.ts +1078 -0
  19. package/engram-coach-pack.ts +17 -12
  20. package/engram-coach-presentation.ts +10 -1
  21. package/engram-coach-reconciliation.ts +305 -2
  22. package/engram-coach-structured-capture.ts +622 -0
  23. package/package.json +39 -6
  24. package/personas/aggressive-monitoring.md +121 -0
  25. package/personas/aggressive.json +85 -0
  26. package/personas/conservative-monitoring.md +133 -0
  27. package/personas/conservative.json +93 -0
  28. package/personas/polarized-monitoring.md +112 -0
  29. package/personas/polarized.json +72 -0
  30. package/personas/volume-monitoring.md +85 -0
  31. package/personas/volume.json +108 -0
  32. package/shared/retrieval.md +71 -0
  33. package/shared/setup.md +207 -0
  34. package/skills/.gitkeep +0 -0
  35. package/skills/adapt-plan/SKILL.md +263 -0
  36. package/skills/block-review/SKILL.md +275 -0
  37. package/skills/consult/SKILL.md +176 -0
  38. package/skills/intake/SKILL.md +315 -0
  39. package/skills/lactate-analyze/SKILL.md +230 -0
  40. package/skills/lessons-rollup/SKILL.md +196 -0
  41. package/skills/monitoring-rollup/SKILL.md +208 -0
  42. package/skills/race-analysis/SKILL.md +219 -0
  43. package/skills/season-retrospective/SKILL.md +200 -0
  44. package/skills/set-goal/SKILL.md +297 -0
  45. package/templates/base.md +55 -0
  46. package/templates/build-1.md +57 -0
  47. package/templates/build-2.md +62 -0
  48. package/templates/race-report.md +51 -0
  49. package/templates/race-specificity.md +62 -0
  50. package/templates/season-review.md +40 -0
  51. package/engram-coach-extractor.ts +0 -295
package/SETUP.md ADDED
@@ -0,0 +1,559 @@
1
+ # Setup
2
+
3
+ Full prerequisite reference for NanoClaw Training Skill Pack. Follow these steps in order before invoking any skill.
4
+
5
+ ---
6
+
7
+ ## 1. Prerequisites Overview
8
+
9
+ Confirm each item before continuing. Steps 2-5 below cover each in detail.
10
+
11
+ - [ ] NanoClaw installed and running
12
+ - [ ] Intervals.icu account with API key
13
+ - [ ] Athlete ID from Intervals.icu
14
+ - [ ] QMD installed and initialized
15
+ - [ ] engram-coach installed as a Claude Code plugin (see Step 6)
16
+ - [ ] `.engram-coach/config.json` created in your athlete repo (see Step 5)
17
+
18
+ ---
19
+
20
+ ## 2. Intervals.icu Setup
21
+
22
+ Skills call Intervals.icu via MCP tools. You need two values from your Intervals.icu account.
23
+
24
+ **API Key**
25
+
26
+ 1. Log into Intervals.icu
27
+ 2. Go to **Settings → Developer Settings**
28
+ 3. Copy your API Key
29
+
30
+ **Athlete ID**
31
+
32
+ 1. Go to **Settings → Account**
33
+ 2. Your Athlete ID appears in the URL as `i{ID}` (e.g., `i12345`)
34
+
35
+ **These values are used in two places.** The MCP server needs them as environment
36
+ variables (step 3) for the tools skills call during reasoning. The TypeScript
37
+ analysis tools read them from the `intervals_icu` block of your
38
+ `.engram-coach/config.json` (step 5) when invoked over the CLI. Set both.
39
+
40
+ ---
41
+
42
+ ## 3. Intervals.icu MCP Server Setup
43
+
44
+ The Intervals.icu MCP server exposes Intervals.icu API endpoints as MCP tools that skills call during execution. It must be configured in NanoClaw before skills can run.
45
+
46
+ **What it does**
47
+
48
+ Skills call MCP tools such as `get_wellness`, `get_athlete`, and `get_events` to retrieve training data. The MCP server handles authentication with Intervals.icu on each call.
49
+
50
+ **How to configure it in NanoClaw**
51
+
52
+ Refer to the [NanoClaw MCP configuration documentation](https://github.com/nanowell/nanoclaw) for the exact steps to add an MCP server. The general process:
53
+
54
+ 1. Add a new MCP server entry pointing to the Intervals.icu MCP server image or binary
55
+ 2. Set the required environment variables in the MCP server configuration:
56
+ - `INTERVALS_API_KEY` — your API key from step 2
57
+ - `INTERVALS_ATHLETE_ID` — your Athlete ID from step 2 (format: `i12345`)
58
+ 3. Configure bind-mounts if the MCP server needs access to files in this repo
59
+
60
+ > **Note on bind-mount syntax:** Bind-mount configuration syntax can vary between NanoClaw versions. Verify the correct syntax against the current NanoClaw documentation before running — do not rely on examples from older tutorials.
61
+
62
+ **Verify**
63
+
64
+ After configuring the MCP server, check NanoClaw's tool discovery to confirm the Intervals.icu tools appear in the available tool list.
65
+
66
+ ---
67
+
68
+ ## 4. QMD Setup
69
+
70
+ QMD is a local knowledge management tool that skills use to retrieve coaching history and reference documents. This section walks through full setup — QMD is not assumed to be pre-installed.
71
+
72
+ **Install**
73
+
74
+ ```
75
+ pip install qmd
76
+ ```
77
+
78
+ Or consult the [QMD installation documentation](https://github.com/tobi/qmd) for alternative installation methods.
79
+
80
+ **Initialize a collection scoped to this repo**
81
+
82
+ ```
83
+ cd ./engram-coach
84
+ qmd init
85
+ ```
86
+
87
+ This creates a QMD collection in the current directory.
88
+
89
+ **Verify initialization**
90
+
91
+ ```
92
+ qmd ls
93
+ ```
94
+
95
+ Should show the engram-coach collection without error.
96
+
97
+ **Run first index**
98
+
99
+ ```
100
+ qmd update
101
+ ```
102
+
103
+ This indexes existing documents in `knowledge/`. If `knowledge/` is empty (Phase 10), the command completes without error — this is expected.
104
+
105
+ **Verify indexing**
106
+
107
+ ```
108
+ qmd query "test"
109
+ ```
110
+
111
+ Should return results (possibly empty) without error.
112
+
113
+ **Ongoing use**
114
+
115
+ When you add new coaching records to your `coaching_docs_dir`, run `qmd update` to make them retrievable by future skill invocations. Skills query QMD to load coaching history as reasoning context.
116
+
117
+ ---
118
+
119
+ ## 5. Athlete Configuration
120
+
121
+ engram-coach is installed as a Claude Code **plugin** (§6). The plugin ships the
122
+ engine — skills, personas, templates, tools. Your athlete-specific configuration
123
+ lives **outside** the plugin, in the repo where your coaching records live.
124
+
125
+ > **Why not inside the plugin?** Plugins install by cloning into
126
+ > `~/.claude/plugins/cache/…` at a git SHA, and that directory is replaced on
127
+ > every update. Anything you put there is lost. Config also holds an API key,
128
+ > which should never sit in the engine repo.
129
+
130
+ **Config resolution order.** Skills use the first of these that exists:
131
+
132
+ | Order | Path | Use |
133
+ |---|---|---|
134
+ | 1 | `$ENGRAM_COACH_CONFIG` | Explicit override |
135
+ | 2 | `./.engram-coach/config.json` | **Default** — project-level, in your athlete repo |
136
+ | 3 | `~/.claude/engram-coach/config.json` | User-level fallback |
137
+
138
+ **Create it** (from your athlete repo — the one holding `docs/coaching/`):
139
+
140
+ ```bash
141
+ mkdir -p .engram-coach
142
+ cp "$(ls -d ~/.claude/plugins/cache/*/engram-coach/*/ | tail -1)config.json.example" .engram-coach/config.json
143
+ printf '\n# engram-coach machine-local config (holds Intervals.icu API key)\n.engram-coach/\n' >> .gitignore
144
+ ```
145
+
146
+ **`.engram-coach/` MUST be gitignored** — it holds your Intervals.icu API key.
147
+ Verify with `git check-ignore -v .engram-coach/config.json` before committing anything.
148
+
149
+ Or skip all of the above and run `engram-coach:intake`, which writes the file for you.
150
+
151
+ **Migrating from an existing pre-rename local config directory?** Rename it in
152
+ place — the config contents and schema are unchanged, only the directory name moved:
153
+
154
+ ```sh
155
+ mv .claw-coach .engram-coach
156
+ ```
157
+
158
+ There is no runtime fallback to the old directory name or the old explicit
159
+ configuration-override environment variable — rename before invoking any skill.
160
+
161
+ **Edit the config**
162
+
163
+ Open `.engram-coach/config.json` and replace the placeholder values:
164
+
165
+ ```json
166
+ {
167
+ "active_profile": "default",
168
+ "profiles": {
169
+ "default": {
170
+ "active_persona": "conservative",
171
+ "coaching_docs_dir": "~/REPLACE_WITH_YOUR_COACHING_DOCS_PATH",
172
+ "prescriptions_dir": "~/REPLACE_WITH_YOUR_PRESCRIPTIONS_PATH",
173
+ "season": "REPLACE_WITH_SEASON_LABEL"
174
+ }
175
+ },
176
+ "capture": {
177
+ "model": "REPLACE_WITH_PROVIDER/MODEL",
178
+ "timeout_seconds": 60,
179
+ "max_candidates_per_turn": 3
180
+ }
181
+ }
182
+ ```
183
+
184
+ **Fields:**
185
+
186
+ | Field | Value |
187
+ |-------|-------|
188
+ | `active_profile` | Leave as `"default"` unless running multiple configurations |
189
+ | `active_persona` | One of: `conservative`, `aggressive`, `polarized`, `volume` |
190
+ | `coaching_docs_dir` | Absolute path (~ supported) to where coaching records will be written and read. Create the directory if needed: `mkdir -p ~/coaching` |
191
+ | `prescriptions_dir` | Absolute path to your workout prescriptions directory |
192
+ | `capture.model` | **Required.** Explicit `provider/model` string used for ambient conversation capture (e.g. `anthropic/claude-sonnet-4-5`). Never inherited from the interactive session model. |
193
+ | `capture.timeout_seconds` | Headless extraction deadline in seconds. Default and maximum: `60`. |
194
+ | `capture.max_candidates_per_turn` | Candidate records per settled turn. Default and maximum: `3`. |
195
+
196
+ **Capture model precedence:** a nonblank `ENGRAM_COACH_CAPTURE_MODEL`
197
+ environment variable overrides **only** `capture.model`; the timeout and
198
+ candidate limits always come from the `capture` block. If neither source is
199
+ set, ambient capture fails as a configuration error — run `intake` (Phase 3C)
200
+ or edit the config rather than leaving it unset. There is no implicit fallback
201
+ to any session or default model.
202
+
203
+ **Verify config**
204
+
205
+ Run this check from your athlete repo to confirm no placeholder paths remain and
206
+ a capture model is configured (a nonblank `ENGRAM_COACH_CAPTURE_MODEL` also
207
+ satisfies the model check):
208
+
209
+ ```
210
+ python3 -c "import json,os; d=json.load(open('.engram-coach/config.json')); assert '~/REPLACE' not in str(d), 'Placeholder paths still present — edit .engram-coach/config.json'; assert str(d.get('capture',{}).get('model','')).strip() or os.environ.get('ENGRAM_COACH_CAPTURE_MODEL','').strip(), 'capture.model missing — run intake Phase 3C or see SETUP.md'; print('config OK')"
211
+ ```
212
+
213
+ Should print `config OK`.
214
+
215
+ ---
216
+
217
+ ## 6. Install the Plugin
218
+
219
+ engram-coach is a Claude Code plugin. Skills are discovered from their own
220
+ frontmatter in `skills/*/SKILL.md` — there is no wrapper layer to maintain, and
221
+ new skills register themselves.
222
+
223
+ **Add the marketplace and install**
224
+
225
+ ```
226
+ /plugin marketplace add isparling/engram-coach
227
+ /plugin install engram-coach@engram-coach
228
+ ```
229
+
230
+ For local development against a working checkout, point the marketplace at the
231
+ directory instead:
232
+
233
+ ```
234
+ /plugin marketplace add ~/code/engram-coach
235
+ ```
236
+
237
+ **Install tool dependencies.** The TypeScript analysis tools (`stream-analyze`,
238
+ `hrv-trend`, `race-context`, `tsb-predict`) depend on npm packages that are not
239
+ committed. Whether you need this step depends on how you installed:
240
+
241
+ | Install source | `npm install` needed? |
242
+ |---|---|
243
+ | GitHub / remote marketplace | **Yes, after every install and update.** Only tracked files are cloned, so `analysis-tools/node_modules` is absent. |
244
+ | Local path marketplace | **Usually no.** A local install copies the working directory as-is, including `analysis-tools/node_modules`. Run it only if the directory is missing or the lockfile changed. |
245
+
246
+ ```bash
247
+ cd "$(ls -d ~/.claude/plugins/cache/*/engram-coach/*/ | tail -1)analysis-tools" && npm install
248
+ ```
249
+
250
+ Skills degrade gracefully if this is skipped — each affected analysis annotates
251
+ `[<analysis> unavailable — … Proceeding without.]` rather than failing — but you
252
+ lose decoupling, HR-recovery, interval-CV, and HRV-trend analysis until it runs.
253
+
254
+ > **Local installs copy everything, including gitignored files.** A local-path
255
+ > install is a directory copy, not a git clone, so anything sitting in the working
256
+ > tree — untracked scratch files, `node_modules`, and **gitignored secrets** —
257
+ > is copied into the plugin cache. Keep credentials out of this repo entirely;
258
+ > athlete config belongs in the athlete repo (§5), never here.
259
+ >
260
+ > **Local installs are also unversioned.** Remote installs record a
261
+ > `gitCommitSha` in `~/.claude/plugins/installed_plugins.json`, so the running
262
+ > version is identifiable. A local install records no equivalent — the cache is
263
+ > an unlabeled snapshot of your working tree at install time and drifts silently
264
+ > as you edit. Reinstall after changing a skill, and when behavior looks stale,
265
+ > diff the cache against your checkout:
266
+ >
267
+ > ```bash
268
+ > diff -rq "$(ls -d ~/.claude/plugins/cache/*/engram-coach/*/ | tail -1)skills" ./skills
269
+ > ```
270
+
271
+ **Verify**
272
+
273
+ Restart Claude Code. Type `/engram-coach` — all ten skills should appear:
274
+ `adapt-plan`, `block-review`, `consult`, `intake`, `lactate-analyze`,
275
+ `lessons-rollup`, `monitoring-rollup`, `race-analysis`,
276
+ `season-retrospective`, `set-goal`.
277
+
278
+ ### Alternative: Direct OMP integration
279
+
280
+ Instead of (or in addition to) the Claude Code plugin, `engram-coach` can be
281
+ loaded directly into OMP as an Engram external pack, without the plugin layer:
282
+
283
+ ```sh
284
+ npm install @isparling/engram-coach @isparling/engram-harness @isparling/engram-cli @isparling/engram-omp
285
+ ```
286
+
287
+ Bind the OMP extension:
288
+
289
+ ```yaml
290
+ extensions:
291
+ - ./node_modules/@isparling/engram-omp/omp-extension.ts
292
+ ```
293
+
294
+ The adapter does not read coaching plugin state and does not choose a pack:
295
+ the active binding's `installed_packs` declaration does that. A complete Engram
296
+ binding registry with the space already registered is an external
297
+ prerequisite; this package neither creates nor registers one. For each fresh
298
+ OMP session, the extension selects the space declared by the nearest
299
+ `engram.space.json`. Set `ENGRAM_SPACE_ID` only when that durable project
300
+ default needs an explicit runtime override.
301
+ The `installed_packs` declaration syntax itself (the fields below, and how a
302
+ binding declares a pack) is documented in the
303
+ [external pack interface](https://github.com/isparling/engram/blob/main/harness/docs/pack-interface.md).
304
+ This package documents only the pack declaration to add:
305
+
306
+ ```json
307
+ {
308
+ "installed_packs": [
309
+ {
310
+ "id": "engram-coach",
311
+ "version": "0.1.0",
312
+ "from": "@isparling/engram-coach",
313
+ "extract": true
314
+ }
315
+ ]
316
+ }
317
+ ```
318
+
319
+ `version` here is the **pack identity** version exported by the package as
320
+ `engramCoachPackVersion`, not the npm release version of
321
+ `@isparling/engram-coach`. The two are deliberately independent: the core
322
+ matches pack identity by exact equality and refuses any mutation that would
323
+ change the pack provenance of an existing record, so the identity version
324
+ only ever changes together with a record migration. Keep `0.1.0` here even
325
+ when you install a newer npm release, and make your space manifest's
326
+ `required_packs` entry carry that same identity version.
327
+
328
+ **Set `ENGRAM_BINDING_REGISTRY`** to the absolute path of that binding
329
+ registry file before starting OMP. It is required, not optional: without it
330
+ the adapter logs a warning at session start and disables knowledge capture
331
+ entirely for the whole session.
332
+
333
+ ```sh
334
+ export ENGRAM_BINDING_REGISTRY=<absolute-path-to-registry.json>
335
+ # Optional runtime override; omit to use the nearest engram.space.json.
336
+ export ENGRAM_SPACE_ID=<space-id>
337
+ ```
338
+
339
+ **The space binding's `write_roots` must authorize both
340
+ `coaching_docs_dir` and `prescriptions_dir`**, not only the records
341
+ directory. Generated compatibility views are ordinary artifact writes, and
342
+ the core confines every artifact write to an active write root. If those two
343
+ directories are unauthorized, an approved capture still commits its records
344
+ and refreshes the index, but every view lands in the apply result's
345
+ `artifacts.stale` with `root_not_writable`, and the YAML and Markdown on disk
346
+ stay at their previous contents. Re-running `engram_capture_apply` with the
347
+ same committed hash after widening `write_roots` retries only materialization.
348
+
349
+ At each awaited OMP `session_stop`, the extension imports the binding-selected
350
+ pack and calls its optional `captureFromTurn` handler. `engram-coach` turns new
351
+ coaching observations into create-only `status: "candidate"` draft records and
352
+ refreshes the active space's scoped qmd index. Drafts remain excluded from
353
+ recall and all profile renders until explicitly reviewed and promoted to
354
+ `status: "active"`. Extraction is LLM-only through the configured capture
355
+ model — a failed or missing extraction emits a visible warning and creates no
356
+ draft.
357
+
358
+ During a turn, the agent can commit structured changes through two typed
359
+ tools: `engram_capture_preview({ change_set })` returns the exact mutation
360
+ plan bound to an immutable plan hash, and `engram_capture_apply({ plan_hash })`
361
+ commits that exact plan after the athlete approves the hash. `engram_status`
362
+ reports pending plan hashes and index freshness at any time. See §7 for the
363
+ authority model these tools enforce.
364
+
365
+ ---
366
+
367
+ ## 7. Knowledge Records, Generated Views, and Migration
368
+
369
+ ### Authority model
370
+
371
+ Engram active records are the authoritative store for mutable coaching state
372
+ and chronological events. Every pack record declares a role in
373
+ `details.recordRole`, exactly one of:
374
+
375
+ - `state` — one current value for a canonical entity key; an approved change
376
+ creates a new active record, retires the prior one, and links them via
377
+ `relationships.supersedes`.
378
+ - `event` — append-only history (consultations, monitoring entries); never
379
+ automatically replaced.
380
+ - `report-claim` — a structured conclusion extracted from an approved
381
+ long-form report; it never replaces the report document.
382
+
383
+ Canonical entity keys are derived by the pack, never accepted from a model:
384
+
385
+ ```text
386
+ workout:<session-id>
387
+ prescription:<arc-id>:<session-id>
388
+ threshold:<sport>:lt1
389
+ threshold:<sport>:lt2
390
+ persona:<active-profile>
391
+ monitoring:<concern-id>:<signal>
392
+ ```
393
+
394
+ Workout identity is the durable `session_id`; `session_date`, titles, week
395
+ position, and workout contents are mutable attributes, not identity. Existing
396
+ prescriptions without stable IDs receive them during migration, and rescheduling
397
+ preserves the ID.
398
+
399
+ **Generated compatibility views** — the prescription YAML files,
400
+ `consultations.md`, monitoring logs, and doctor-prep summaries — are rendered
401
+ deterministically from committed records after every approved apply. Each
402
+ carries a byte-exact warning header (`# GENERATED FROM ENGRAM ACTIVE RECORDS.
403
+ DO NOT EDIT DIRECTLY.` in YAML; `<!-- GENERATED FROM ENGRAM ACTIVE RECORDS.
404
+ DO NOT EDIT DIRECTLY. -->` in Markdown) and is **never edited directly**:
405
+ direct edits are overwritten by the next materialization and break migration
406
+ comparisons. **Canonical approved documents** remain skill-authored long-form
407
+ files: `RACE_REPORT.md`, block `SUMMARY.md`, `SEASON_REVIEW.md`, methodology
408
+ documents, and arc-overview documents.
409
+
410
+ ### Approval ordering and retry semantics
411
+
412
+ Skills that change records follow one ordering: preview records → athlete
413
+ approves the exact plan hash → apply → guarded qmd refresh → regenerate
414
+ compatibility views.
415
+
416
+ - A **stale apply** (the underlying records changed since preview) deletes the
417
+ pending plan and requires a fresh preview plus fresh approval. The old hash
418
+ can never be re-applied.
419
+ - An **`index-stale` status** means the qmd refresh failed or is outdated;
420
+ the committed records remain authoritative either way, and only the index
421
+ needs a later refresh.
422
+ - A **stale view** (materialization failed after commit) leaves the commit in
423
+ place. Re-calling `engram_capture_apply` with the same committed hash in the
424
+ same session reruns only view regeneration — never the record mutations.
425
+
426
+ ### Dry-run migration sequence
427
+
428
+ Legacy workspaces migrate through four modes of
429
+ `analysis-tools/migrate-structured-capture.ts` (run from the installed plugin's
430
+ `analysis-tools/` directory). Everything is dry-run except `apply-baseline`,
431
+ which writes only planned stable-ID insertions and warning headers:
432
+
433
+ ```sh
434
+ # 1. Plan stable session IDs + generated headers for every legacy
435
+ # prescription and compatibility log. Prints plan JSON; mutates nothing.
436
+ npx tsx migrate-structured-capture.ts scan --config .engram-coach/config.json > scan.json
437
+
438
+ # 2. Apply ONLY the planned ID insertions and warning headers. Refuses when
439
+ # the aggregate hash mismatches or any file drifted since the scan.
440
+ npx tsx migrate-structured-capture.ts apply-baseline --plan scan.json --expect <after-hash>
441
+
442
+ # 3. Plan the legacy import (prescription states + consultation events) into
443
+ # a StructuredChangeSet for preview/approval. Mutates nothing.
444
+ npx tsx migrate-structured-capture.ts emit-change-set --config .engram-coach/config.json --output change-set.json
445
+
446
+ # 4. Render the record-derived views into a temporary root and byte-compare
447
+ # them against the current source files. Exit 0 requires byte equality.
448
+ npx tsx migrate-structured-capture.ts compare --config .engram-coach/config.json --render-root /tmp/migration-render
449
+ ```
450
+
451
+ Migration is idempotent: stable source IDs prevent duplicate imports, and the
452
+ cutover to record authority happens only once step 4 reports byte-equivalent
453
+ generated views.
454
+
455
+ ---
456
+
457
+ ## 8. Verification
458
+
459
+ Run these checks to confirm the complete setup is working before invoking a skill.
460
+
461
+ - [ ] **Skills discovered from the plugin cache**
462
+ ```
463
+ ls ~/.claude/plugins/cache/*/engram-coach/*/skills/*/SKILL.md
464
+ ```
465
+ Should list all ten `SKILL.md` files — exactly one for `adapt-plan`, `block-review`,
466
+ `consult`, `intake`, `lactate-analyze`, `lessons-rollup`, `monitoring-rollup`,
467
+ `race-analysis`, `season-retrospective`, and `set-goal`. Skills are discovered directly
468
+ from each file's frontmatter (§6); there is no separate slash-command registration step
469
+ to verify.
470
+
471
+ - [ ] **QMD collection present**
472
+ ```
473
+ qmd ls
474
+ ```
475
+ Should show the engram-coach collection.
476
+
477
+ - [ ] **Active persona readable**
478
+ ```
479
+ cat .engram-coach/config.json | python3 -c "import json,sys; d=json.load(sys.stdin); print('active_persona:', d['profiles']['default']['active_persona'])"
480
+ ```
481
+ Should print your active persona slug.
482
+
483
+ - [ ] **Persona file resolves**
484
+ ```
485
+ ls personas/$(python3 -c "import json; print(json.load(open('.engram-coach/config.json'))['profiles']['default']['active_persona'])").json
486
+ ```
487
+ Should print the persona filename without error (e.g., `personas/volume.json`).
488
+
489
+ - [ ] **Intervals.icu MCP tools appear in NanoClaw** — Check NanoClaw's tool discovery interface to confirm the Intervals.icu tools are listed.
490
+
491
+ - [ ] **coaching_docs_dir exists**
492
+ ```
493
+ ls $(python3 -c "import json,os; print(os.path.expanduser(json.load(open('.engram-coach/config.json'))['profiles']['default']['coaching_docs_dir']))")
494
+ ```
495
+ Should list directory contents without error. If the directory does not exist, create it:
496
+ ```
497
+ mkdir -p <your-coaching-docs-path>
498
+ ```
499
+
500
+ All six checks passing means you are ready to invoke a skill.
501
+
502
+ ---
503
+
504
+ ## 9. Persistent Coaching Docs
505
+
506
+ Once you've run a few skills, your `coaching_docs_dir` will accumulate these documents:
507
+
508
+ | Document | Path | Maintained by | Purpose |
509
+ |---|---|---|---|
510
+ | `ATHLETE_PROFILE.md` | `{coaching_docs_dir}/ATHLETE_PROFILE.md` | `lessons-rollup` (curated) | Working summary of durable, athlete-specific patterns. Read by adapt-plan, consult, block-review, race-analysis, season-retrospective as reasoning context. |
511
+ | `lessons-log.md` | `{coaching_docs_dir}/lessons-log.md` | `lessons-rollup` (append-only) | Durable timestamped + source-tagged record of every calibration point captured. The skill never deletes from this file. |
512
+ | `SUMMARY.md` | `{coaching_docs_dir}/{season}/{block}/SUMMARY.md` | `block-review` | Per-block synthesis. Source for cross-block pattern detection. |
513
+ | `RACE_REPORT.md` | `{coaching_docs_dir}/{season}/races/{date-slug}/RACE_REPORT.md` | `race-analysis` | Per-race synthesis with computed metrics + athlete narrative. |
514
+ | `SEASON_REVIEW.md` | `{coaching_docs_dir}/{season}/SEASON_REVIEW.md` | `season-retrospective` | Season-level arc, persona-fit assessment, cross-block patterns. |
515
+
516
+ ### Curation discipline
517
+
518
+ `ATHLETE_PROFILE.md` directly influences coaching reasoning. The `lessons-rollup` skill self-curates, but you should review the profile periodically — especially after a season-retrospective. To retire an entry that turned out wrong, edit `lessons-log.md` directly (add a note explaining the retirement) and run `lessons-rollup` standalone to re-curate the profile from the updated log.
519
+
520
+ ---
521
+
522
+ ## 10. Troubleshooting
523
+
524
+ **`/engram-coach:intake` not appearing in Claude Code autocomplete**
525
+ Confirm the skill files exist in the installed plugin cache:
526
+ ```
527
+ ls ~/.claude/plugins/cache/*/engram-coach/*/skills/
528
+ ```
529
+ If the skills are missing, re-run the install in Step 6 and restart Claude Code —
530
+ plugins are loaded at session start. Check `/plugin` to confirm engram-coach is
531
+ listed and enabled.
532
+
533
+ **"config.json not found"**
534
+ You have not created the athlete config. Either run `engram-coach:intake`, or from
535
+ your athlete repo:
536
+ ```
537
+ mkdir -p .engram-coach
538
+ cp "$(ls -d ~/.claude/plugins/cache/*/engram-coach/*/ | tail -1)config.json.example" .engram-coach/config.json
539
+ ```
540
+ Remember to gitignore `.engram-coach/` — it holds your API key.
541
+
542
+ **"persona file not found" / `ls: personas/undefined.json: No such file or directory`**
543
+ Your `active_persona` value in `.engram-coach/config.json` does not match any file in `personas/`. Valid slugs are: `conservative`, `aggressive`, `polarized`, `volume`. Check for typos.
544
+
545
+ **"coaching_docs_dir does not exist" or similar path error**
546
+ Create the directory:
547
+ ```
548
+ mkdir -p <your-coaching-docs-path>
549
+ ```
550
+ Then re-run the verification check.
551
+
552
+ **"Placeholder paths still present"**
553
+ Open `.engram-coach/config.json` and replace all `~/REPLACE_WITH_...` values with real paths.
554
+
555
+ **MCP tools not appearing in NanoClaw**
556
+ Verify the Intervals.icu MCP server is correctly configured in NanoClaw. Consult the NanoClaw documentation for MCP server setup and confirm the server is listed as active. Check that `INTERVALS_API_KEY` and `INTERVALS_ATHLETE_ID` are set correctly in the MCP server environment.
557
+
558
+ **"qmd: command not found"**
559
+ QMD is not installed. Run `pip install qmd` or consult the QMD installation docs.
package/SKILL_PACK.md ADDED
@@ -0,0 +1,75 @@
1
+ # engram-coach Skill Pack
2
+
3
+ ## Overview
4
+
5
+ engram-coach is a document-driven endurance-coaching plugin. Skills use athlete-approved local records, Intervals.icu data, and explicit coaching policies to reason about training decisions. The repository ships the engine; athlete records and credentials remain in a separate local workspace.
6
+
7
+ ## Package contents
8
+
9
+ - `skills/` — Claude Code skill instructions.
10
+ - `personas/` — generic coaching-policy definitions.
11
+ - `templates/` — Markdown templates for planning and review artifacts.
12
+ - `analyses/` — stream-analysis catalog and data requirements.
13
+ - `analysis-tools/` — deterministic TypeScript analysis utilities.
14
+ - `shared/` — common setup and retrieval instructions.
15
+
16
+ ## Personas
17
+
18
+ | Persona | Slug | Policy |
19
+ |---|---|---|
20
+ | Conservative | `conservative` | Recovery-first; an adverse HRV signal vetoes hard training. |
21
+ | Aggressive | `aggressive` | Progressive overload with weighted readiness. |
22
+ | Polarized | `polarized` | High low-intensity volume with clearly separated high-intensity work. |
23
+ | Volume | `volume` | Long-horizon aerobic volume with a 14-day CTL trend. |
24
+
25
+ Built-in policies are generic. Create a custom policy with [`PERSONA_SCHEMA.md`](PERSONA_SCHEMA.md) when an athlete needs different thresholds or decision logic.
26
+
27
+ ## Setup
28
+
29
+ 1. Install this repository as a Claude Code plugin using your marketplace or local plugin source.
30
+ 2. Configure an Intervals.icu MCP server.
31
+ 3. Create a local `.engram-coach/config.json` from [`config.json.example`](config.json.example) in the athlete workspace.
32
+ 4. Keep `.engram-coach/` gitignored: it contains credentials and local paths.
33
+ 5. Run `/engram-coach:intake` to establish goals, policies, and coaching-record locations.
34
+
35
+ See [`SETUP.md`](SETUP.md) for the detailed configuration contract.
36
+
37
+ ## Structured capture contract
38
+
39
+ Skills that change coaching records do not write state files directly. They
40
+ call `engram_capture_preview({ change_set })`, present the returned mutation
41
+ plan for approval against its exact plan hash, and commit with
42
+ `engram_capture_apply({ plan_hash })`. Records declare a `details.recordRole`
43
+ of `state` (superseded by approved changes), `event` (append-only), or
44
+ `report-claim` (a conclusion tied to an approved report). Prescription YAML,
45
+ consultation/monitoring logs, and doctor-prep summaries are generated
46
+ compatibility views carrying a `GENERATED FROM ENGRAM ACTIVE RECORDS.
47
+ DO NOT EDIT DIRECTLY.` warning header — never edited directly. Long-form
48
+ reports (`RACE_REPORT.md`, block `SUMMARY.md`, `SEASON_REVIEW.md`, methodology
49
+ and arc-overview documents) remain canonical approved documents authored by
50
+ their skills.
51
+
52
+ Ambient conversation capture uses an explicit provider/model from
53
+ `.engram-coach/config.json` (`capture.model`; `ENGRAM_COACH_CAPTURE_MODEL`
54
+ overrides the model only). See [`SETUP.md`](SETUP.md) §7 for the authority
55
+ model, retry semantics, and the dry-run migration sequence
56
+ (`scan` → `apply-baseline` → `emit-change-set` → `compare`).
57
+
58
+ ## Skills
59
+
60
+ | Skill | Invocation | Purpose |
61
+ |---|---|---|
62
+ | intake | `/engram-coach:intake` | Set up a new athlete workspace and coaching policy. |
63
+ | set-goal | `/engram-coach:set-goal` | Create a goal arc, methodology documents, and prescriptions. |
64
+ | adapt-plan | `/engram-coach:adapt-plan` | Assess readiness after a key workout and adapt the next session. |
65
+ | lactate-analyze | `/engram-coach:lactate-analyze` | Query lactate tests and threshold estimates. |
66
+ | consult | `/engram-coach:consult` | Provide evidence-based advice within an active plan. |
67
+ | block-review | `/engram-coach:block-review` | Produce an end-of-block summary. |
68
+ | race-analysis | `/engram-coach:race-analysis` | Produce a post-race report from activity data and narrative. |
69
+ | season-retrospective | `/engram-coach:season-retrospective` | Synthesize cross-block and race patterns. |
70
+ | lessons-rollup | `/engram-coach:lessons-rollup` | Curate durable athlete lessons from coaching records. |
71
+ | monitoring-rollup | `/engram-coach:monitoring-rollup` | Maintain declared longitudinal monitoring records. |
72
+
73
+ ## Data boundary
74
+
75
+ Do not commit athlete records, local configuration, tokens, generated data, or private narratives. Public examples in this repository are fictional and synthetic.