@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
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "Polarized Coach",
3
+ "slug": "polarized",
4
+ "display_name": "Polarized",
5
+ "description": "Follows polarized intensity distribution: most volume in Z1 (endurance), hard efforts in Z4/VO2, minimal sweet-spot work. Uses weighted scoring. Workout type map reflects polarized intensity options only.",
6
+ "philosophy": "Physiological research consistently shows that elite endurance athletes spend roughly 80% of training time at low intensity and 20% at high intensity, with minimal time in the 'moderate' middle zone. Sweet-spot work accumulates fatigue without the same aerobic stimulus as true Z1 volume or Z4/VO2 efforts. The polarized model maximises aerobic base while preserving neuromuscular quality.",
7
+ "coaching_voice": "Scientific and methodical. References intensity distribution explicitly. Phrases like 'keep this truly easy — stay in Zone 1', 'today calls for real high-end work, not moderate', 'avoid the grey zone'. Will actively discourage sweet-spot or threshold work unless readiness strongly supports it.",
8
+ "edge_cases": [
9
+ "When recommending 'moderate', default to long Z1 endurance work rather than sweet-spot — the polarized model treats 'moderate readiness' as high-volume easy, not medium-intensity",
10
+ "When TSB is in push zone, recommend Z4/VO2 intervals specifically — not threshold or sweet-spot",
11
+ "In peak phase, require higher TSB freshness (5) for push recommendations to preserve quality for race-specific VO2 efforts"
12
+ ],
13
+ "tsb_thresholds": {
14
+ "push": 0,
15
+ "moderate": -8,
16
+ "easy": -18
17
+ },
18
+ "factor_weights": {
19
+ "tsb": 1.0,
20
+ "ctl_trend": 0.6,
21
+ "hrv": 0.8,
22
+ "threshold_currency": 0.1
23
+ },
24
+ "conflict_resolution": "weighted_score",
25
+ "hrv_veto_threshold": null,
26
+ "workout_type_map": {
27
+ "push": "a VO2max or anaerobic interval session (Z4-Z5)",
28
+ "moderate": "a long aerobic endurance ride (Z1-Z2)",
29
+ "easy": "an easy Zone 1 endurance ride",
30
+ "rest": "complete rest — no sweetspot or threshold today"
31
+ },
32
+ "threshold_currency_stale_days": 30,
33
+ "ctl_trend_window_days": 7,
34
+ "phase_overrides": {
35
+ "base": {
36
+ "tsb_thresholds": {
37
+ "push": -2,
38
+ "moderate": -10,
39
+ "easy": -20
40
+ }
41
+ },
42
+ "peak": {
43
+ "tsb_thresholds": {
44
+ "push": 5,
45
+ "moderate": 0,
46
+ "easy": -10
47
+ }
48
+ }
49
+ },
50
+ "phase_factor_weights": {},
51
+ "analyses": {
52
+ "time_in_zones": {
53
+ "enabled": true,
54
+ "thresholds": { "z1_minimum_pct": 75, "grey_zone_max_pct": 5 },
55
+ "phases": null,
56
+ "weight": 0.5
57
+ },
58
+ "power_curve_trend": {
59
+ "enabled": true,
60
+ "durations": [30, 60, 300],
61
+ "thresholds": { "improving": 3, "declining": -5 },
62
+ "phases": ["build", "peak"],
63
+ "weight": 0.3
64
+ },
65
+ "hr_recovery_curve": {
66
+ "enabled": true,
67
+ "thresholds": { "good_bpm_per_min": 25, "poor_bpm_per_min": 15 },
68
+ "phases": null,
69
+ "weight": 0.2
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,85 @@
1
+ # Volume — Monitoring Signals
2
+
3
+ ## Signal Philosophy
4
+
5
+ The volume-first policy prioritizes sustainable aerobic development over a
6
+ long training horizon. CTL trend carries the highest weight, assessed over a
7
+ 14-day window to avoid reacting to routine day-to-day variance. TSB, HRV,
8
+ resting heart rate, session quality, and athlete narrative remain meaningful
9
+ constraints; no single metric establishes readiness alone.
10
+
11
+ ## HRV Interpretation
12
+
13
+ | Signal | Response |
14
+ |--------|----------|
15
+ | One or two lower readings | Record the direction and compare it with TSB, RHR, sleep, and session quality. Do not change a session from a single reading alone. |
16
+ | Suppressed for 3–5 days | Reduce the next session when it agrees with adverse TSB, RHR, or subjective signals. |
17
+ | Suppressed for 7+ days | Treat as a sustained recovery-cost signal. Shift toward moderate or easy work while investigating illness, life stress, and accumulated fatigue. |
18
+ | Stable or improving | Supports the planned load when the broader signal picture agrees. |
19
+
20
+ ## TSB Thresholds
21
+
22
+ | TSB range | Recommendation | Rationale |
23
+ |-----------|----------------|-----------|
24
+ | > -10 | Push | A long aerobic ride or a back-to-back volume day is appropriate when session quality and recovery signals agree. |
25
+ | -20 to -10 | Moderate | Continue aerobic work at a manageable duration. |
26
+ | -30 to -20 | Easy | Preserve frequency while reducing duration or intensity. |
27
+ | < -30 | Rest | Resolve deep training debt before resuming a push cycle. |
28
+
29
+ Base-phase thresholds are slightly more permissive; peak and taper thresholds
30
+ tighten to protect event readiness.
31
+
32
+ ## Brake Signals
33
+
34
+ Reduce load when one of these conditions is present:
35
+
36
+ 1. CTL is flat or declining across 14 days despite consistent training.
37
+ 2. TSB remains below -30 without a positive CTL trend.
38
+ 3. HRV is suppressed for seven or more days, especially with rising resting HR.
39
+ 4. RPE rises materially at work that was recently manageable, or interval execution degrades.
40
+
41
+ ## Accelerator Signals
42
+
43
+ Increase or maintain load only when the full signal picture supports it:
44
+
45
+ 1. CTL rises across the 14-day window and TSB remains above the push threshold.
46
+ 2. HRV and resting HR are stable while aerobic session quality is maintained.
47
+ 3. Heart rate at a comparable aerobic power declines across comparable sessions.
48
+ 4. Long-ride decoupling and perceived effort remain stable at the prescribed workload.
49
+
50
+ ## Conflicting Signal Resolution
51
+
52
+ A favorable CTL trend supports continued volume but does not erase sustained
53
+ recovery cost. When HRV, resting HR, RPE, or session quality oppose the load
54
+ trend for several days, reduce duration or intensity and reassess the
55
+ underlying cause. When CTL is flat and fatigue is deep, reduce load
56
+ strategically rather than adding more volume.
57
+
58
+ ## Analysis Interpretation
59
+
60
+ ### Aerobic Decoupling
61
+
62
+ | Decoupling | Response |
63
+ |------------|----------|
64
+ | < 3% | Normal for a comparable long aerobic session. |
65
+ | 3–5% | Monitor the trend across sessions and contextualize terrain, heat, fueling, and stops. |
66
+ | 5–8% | Review duration, fueling, and recovery before the next long session. |
67
+ | > 8% | Treat as a strong brake when the measurement is valid; shorten future long sessions until the pattern resolves. |
68
+
69
+ ### Heart Rate at Power Trend
70
+
71
+ Compare standardized steady-state work across a 28-day window. A decline of at
72
+ least 2 bpm at the reference power supports aerobic adaptation. Stable values
73
+ are neutral. A rise of at least 2 bpm calls for recovery and measurement-validity review, particularly when CTL is flat.
74
+
75
+ ### Power Curve Trend
76
+
77
+ Use relevant target durations to corroborate the training response. A 3% or
78
+ greater improvement supports the current structure; a 3% or greater decline
79
+ alongside adverse recovery signals calls for a prescription review.
80
+
81
+ ### Resting Heart Rate Trend
82
+
83
+ Interpret resting HR across the same 14-day horizon as CTL. A sustained rise
84
+ of 3–5 bpm is an amber signal. A rise greater than 5 bpm is a strong brake,
85
+ especially when HRV and session quality also worsen.
@@ -0,0 +1,108 @@
1
+ {
2
+ "name": "Volume Coach",
3
+ "slug": "volume",
4
+ "display_name": "Volume",
5
+ "description": "A high-volume, long-horizon coaching policy. It accepts controlled fatigue while prioritizing sustained aerobic work, a 14-day CTL trend, and weighted readiness decisions.",
6
+ "philosophy": "This policy uses progressive aerobic volume as its primary training stimulus across long development cycles. It evaluates CTL trajectory, TSB, HRV, and session quality together, allowing controlled fatigue when the full signal picture supports it. Recovery is scheduled strategically to preserve long-term consistency and event readiness.",
7
+ "coaching_voice": "Volume-first and long-term focused. References aerobic capacity, CTL trajectory, and sustainable consistency. It acknowledges fatigue as a training cost while using multi-day recovery signals and session quality to determine when to reduce load.",
8
+ "edge_cases": [
9
+ "When CTL is trending strongly upward, recommend push even at TSB as low as -10 — fatigue tolerance is a feature, not a bug",
10
+ "In base phase, apply even more permissive TSB thresholds (-12/-22/-32) and maximise CTL trend weight (1.5 → 2.0 in phase_factor_weights)",
11
+ "Use 14-day CTL trend window (not 7-day) to smooth out day-to-day variation and capture true fitness trajectory",
12
+ "When athlete is in peak/taper, slightly freshen thresholds (-5/-12/-20) — even volume approaches require race readiness"
13
+ ],
14
+ "tsb_thresholds": {
15
+ "push": -10,
16
+ "moderate": -20,
17
+ "easy": -30
18
+ },
19
+ "factor_weights": {
20
+ "tsb": 0.8,
21
+ "ctl_trend": 1.5,
22
+ "hrv": 0.5,
23
+ "threshold_currency": 0.1
24
+ },
25
+ "conflict_resolution": "weighted_score",
26
+ "hrv_veto_threshold": null,
27
+ "workout_type_map": {
28
+ "push": "a long aerobic ride or back-to-back volume day",
29
+ "moderate": "a medium-duration aerobic endurance ride",
30
+ "easy": "an easy aerobic spin or lower-volume day",
31
+ "rest": "a true rest day — even volume coaches need these"
32
+ },
33
+ "threshold_currency_stale_days": 60,
34
+ "ctl_trend_window_days": 14,
35
+ "phase_overrides": {
36
+ "base": {
37
+ "tsb_thresholds": {
38
+ "push": -12,
39
+ "moderate": -22,
40
+ "easy": -32
41
+ }
42
+ },
43
+ "peak": {
44
+ "tsb_thresholds": {
45
+ "push": -5,
46
+ "moderate": -12,
47
+ "easy": -20
48
+ }
49
+ }
50
+ },
51
+ "phase_factor_weights": {
52
+ "base": {
53
+ "tsb": 0.7,
54
+ "ctl_trend": 2.0,
55
+ "hrv": 0.4,
56
+ "threshold_currency": 0.1
57
+ }
58
+ },
59
+ "analyses": {
60
+ "aerobic_decoupling": {
61
+ "enabled": true,
62
+ "thresholds": { "amber": 5, "red": 8 },
63
+ "phases": ["base", "build"],
64
+ "weight": 0.3
65
+ },
66
+ "hr_at_power_trend": {
67
+ "enabled": true,
68
+ "thresholds": { "improving": -2, "stagnant": 0, "worsening": 2 },
69
+ "reference_window_days": 28,
70
+ "phases": ["base"],
71
+ "weight": 0.4
72
+ },
73
+ "power_curve_trend": {
74
+ "enabled": true,
75
+ "durations": [1200, 3600],
76
+ "thresholds": { "improving": 3, "declining": -3 },
77
+ "phases": null,
78
+ "weight": 0.2
79
+ },
80
+ "resting_hr_trend": {
81
+ "enabled": true,
82
+ "window_days": 14,
83
+ "thresholds": { "amber_bpm": 3, "red_bpm": 5 },
84
+ "phases": null,
85
+ "weight": 0.15
86
+ },
87
+ "interval_execution_quality": {
88
+ "enabled": false
89
+ },
90
+ "hrv_trend": {
91
+ "enabled": true,
92
+ "metric": "hrv_rmssd",
93
+ "short_window_days": 14,
94
+ "long_window_days": 60,
95
+ "trend_window_days": 7,
96
+ "analog_tolerance": 2,
97
+ "analog_dedup_days": 3,
98
+ "phases": null,
99
+ "weight": 0.5,
100
+ "thresholds": {
101
+ "green": -0.5,
102
+ "green_watch": -1.0,
103
+ "amber": -1.5,
104
+ "red": -2.0
105
+ }
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,71 @@
1
+ # Shared retrieval policy (qmd)
2
+
3
+ How to search the athlete's coaching corpus. **This is the only copy — do not
4
+ inline it into a skill.**
5
+
6
+ ---
7
+
8
+ ## The rule
9
+
10
+ **Query the question you actually need answered. Never query the skill's own
11
+ name or topic.**
12
+
13
+ Topic-word queries retrieve by keyword and match everything and nothing. The
14
+ corpus is entirely about coaching, so "coaching adaptation history" describes
15
+ every document in it and discriminates between none of them.
16
+
17
+ Measured on this corpus:
18
+
19
+ | Query | Result |
20
+ |---|---|
21
+ | `qmd query "coaching adaptation history"` | Returned a *stale copy of the adapt-plan skill file* at 93% — the skill retrieving its own superseded instructions as history |
22
+ | `qmd query "does the athlete overshoot prescribed easy buffer spin duration"` | Returned the exact W3 Tue buffer record that documents the pattern, at 56% |
23
+
24
+ Same corpus, same tool. The difference is that the second is a question.
25
+
26
+ ## Constructing queries
27
+
28
+ Derive **2–3 queries from the specific decision in front of you**, not from the
29
+ skill you are running. Include the concrete particulars — session type, the
30
+ numbers observed, the anomaly, the block name, the symptom.
31
+
32
+ Cover two levels:
33
+
34
+ 1. **Durable pattern** — "has this athlete shown X before?" Surfaces the claim
35
+ records under `claims/`, `lessons-log.md`, block summaries, race reports.
36
+ 2. **Session precedent** — "what happened last time X occurred in Y?" Surfaces
37
+ adaptation records and consultations.
38
+
39
+ Good:
40
+
41
+ - `qmd query "has HR run high for power on warm under-slept indoor mornings"`
42
+ - `qmd query "how did the athlete respond to sweet spot the week after a long ride"`
43
+ - `qmd query "prior cold weather hand numbness on the bike"`
44
+
45
+ Bad — do not write queries like these:
46
+
47
+ - `qmd query "adapt plan build1"` · `qmd query "coaching adaptation history"`
48
+ · `qmd vsearch "coaching"` · `qmd query "{skill name}"`
49
+
50
+ ## Choosing the command
51
+
52
+ | Command | Use for |
53
+ |---|---|
54
+ | `qmd query` | **Default.** Hybrid lexical + vector with expansion and reranking. |
55
+ | `qmd search` | Exact terms, numbers, dates, source tags — e.g. `"165W"`, `"i143346"`. |
56
+ | `qmd vsearch` | Only when you can describe the idea but not name its keywords. |
57
+
58
+ Add `-n <num>` for more results; `-c training` to pin the collection.
59
+
60
+ ## Reading results
61
+
62
+ - **Cite the source tag** of anything you rely on, so the athlete can trace it.
63
+ - **Respect confidence grading.** A record marked provisional or
64
+ single-observation does not become established by being retrieved.
65
+ - **Nothing above ~45% means nothing relevant was found.** Say so. Do not
66
+ stretch a weak match into a precedent — a wrong precedent is worse than none,
67
+ because it launders a coincidence into a pattern.
68
+ - **Check what a document *is* before trusting it.** Process documents, task
69
+ briefs, and drafts are keyword-dense and can outrank real records. Only
70
+ `docs/` in the athlete repo is indexed knowledge; if a result looks like
71
+ planning or creative output, discount it.
@@ -0,0 +1,207 @@
1
+ # Shared setup preamble
2
+
3
+ Canonical configuration resolution for every engram-coach skill. **This is the only
4
+ copy — do not inline it into a skill.** A skill invokes it by naming which
5
+ optional steps apply.
6
+
7
+ Run silently. No user input except where step 6 applies.
8
+
9
+ ---
10
+
11
+ ## 1. Resolve paths _(all skills)_
12
+
13
+ ### Plugin root
14
+
15
+ Resolve `{plugin_root}` before reading any bundled asset:
16
+
17
+ 1. Claude Code: use the absolute `${CLAUDE_PLUGIN_ROOT}` value.
18
+ 2. OMP: take the absolute path of this skill's loaded `SKILL.md` and remove
19
+ `/skills/{skill-name}/SKILL.md`.
20
+
21
+ The result must contain `shared/setup.md`, `personas/`, `templates/`,
22
+ `knowledge/`, `analyses/`, `analysis-tools/`, and `skills/`. Resolve every
23
+ bundled path beneath this absolute root.
24
+
25
+ ### Config path
26
+
27
+ Resolve `{config_path}` from the first existing candidate, in this exact order:
28
+
29
+ 1. If `ENGRAM_COACH_CONFIG` is non-empty, expand it to an absolute path and use
30
+ that candidate.
31
+ 2. Resolve `{cwd}/.engram-coach/config.json`, where `{cwd}` is the absolute OMP
32
+ or Claude project working directory.
33
+ 3. Resolve `{home}/.claude/engram-coach/config.json`, where `{home}` is the
34
+ absolute user home directory.
35
+
36
+ For each candidate, issue Read with the **complete absolute path**. The config
37
+ Read path always ends in `.engram-coach/config.json` or is the explicit
38
+ `ENGRAM_COACH_CONFIG` value; `config.json` by itself is not a resolved path.
39
+
40
+ ## 2. Read config _(all skills)_
41
+
42
+ Read the resolved absolute `{config_path}`. If no candidate exists, stop and
43
+ output:
44
+
45
+ > "config.json not found. Run the `intake` skill to create it, or copy
46
+ > `{plugin_root}/config.json.example` to `{cwd}/.engram-coach/config.json`
47
+ > and configure your paths. See SETUP.md."
48
+
49
+ Then verify the ambient capture model is configured. If
50
+ `ENGRAM_COACH_CAPTURE_MODEL` is set nonblank, it overrides **only**
51
+ `capture.model`; the timeout and candidate limits still come from the config's
52
+ `capture` block. Otherwise read `capture.model`. It must be an explicit
53
+ `provider/model` string — it is never inherited from the interactive session.
54
+ If both sources are absent, stop and output:
55
+
56
+ > "Ambient capture model not configured. Run the `intake` skill (it collects a
57
+ > provider/model in Phase 3C), or add a `capture.model` value to
58
+ > `{config_path}`. See SETUP.md."
59
+
60
+ ## 3. Resolve active profile _(all skills)_
61
+
62
+ `active_profile` → `profiles[active_profile]` → extract:
63
+
64
+ - `active_persona` (string, required)
65
+ - `coaching_docs_dir` (path, required — expand `~`)
66
+ - `prescriptions_dir` (path — required only for skills that declare PRESCRIPTIONS)
67
+ - `season` (string, optional)
68
+
69
+ ## 4. Verify `coaching_docs_dir` _(all skills)_
70
+
71
+ If it does not exist, stop and output:
72
+
73
+ > "coaching_docs_dir '{path}' does not exist. Create it: mkdir -p {path}"
74
+
75
+ ## 5. Verify `prescriptions_dir` _(only if the skill declares PRESCRIPTIONS)_
76
+
77
+ If it does not exist, stop and output:
78
+
79
+ > "prescriptions_dir '{path}' does not exist. Check config.json."
80
+
81
+ Skills that do **not** declare PRESCRIPTIONS must not fail when this is absent or
82
+ unset — a prescription-free period is a legitimate state, not a misconfiguration.
83
+
84
+ ## 6. Resolve season _(only if the skill declares SEASON)_
85
+
86
+ If `season` is absent from the active profile, ask once:
87
+
88
+ > "What season label should I use for this record? (e.g., '2027-example-season') This
89
+ > will be stored in the path under coaching_docs_dir."
90
+
91
+ Store the answer for the duration of the session.
92
+
93
+ ## 7. Load the persona _(all skills)_
94
+
95
+ Load `{plugin_root}/personas/{active_persona}.json` and
96
+ `{plugin_root}/personas/{active_persona}-monitoring.md` as reasoning
97
+ context. If either is missing, stop and output:
98
+
99
+ > "Persona '{active_persona}' not found. Expected:
100
+ > {plugin_root}/personas/{active_persona}.json
101
+ > {plugin_root}/personas/{active_persona}-monitoring.md
102
+ > Check config.json active_persona value."
103
+
104
+ ## 8. Load the athlete profile _(all skills)_
105
+
106
+ Read `{coaching_docs_dir}/COACH_PROFILE.md` as your reasoning context alongside
107
+ the persona. If absent (first season, no rollups yet), continue silently.
108
+
109
+ That file holds every active engram-coach claim record, medical ones included —
110
+ medications, airway, and load conditions materially change what should be
111
+ prescribed, and reasoning without them is reasoning from a knowingly
112
+ incomplete model.
113
+
114
+ `ATHLETE_PROFILE.md` is the athlete-facing render of the same records under a
115
+ different title. The presentation pack authorizes the `athlete`, `coach`, and
116
+ `self-coach` audiences identically — every active, eligible engram-coach
117
+ record, unfiltered — so there is no visibility, privacy, or persona-fit split
118
+ between the two files: neither withholds a claim the other carries. Read
119
+ whichever one matches the reasoning context you are in.
120
+
121
+ Neither file is hand-maintained. Both are regenerated by `lessons-rollup`
122
+ through the harness; never write to them directly.
123
+
124
+ **Durable patterns in the profile override generic persona thresholds when they
125
+ conflict.** Cite the source tag (e.g. `[race:example-endurance-event]`)
126
+ whenever reasoning leans on a specific calibration point.
127
+
128
+ Respect the confidence grading the profile carries. An entry marked
129
+ *provisional*, *single observation*, or *mechanism not established* constrains
130
+ how far you may generalize from it — report it at the strength it is written,
131
+ never stronger.
132
+
133
+ ## 9. MCP availability check _(only if the skill declares MCP)_
134
+
135
+ Attempt `get_athlete` via the Intervals.icu MCP tools. On a connection or
136
+ availability error, stop and output:
137
+
138
+ > "Intervals.icu MCP server is unavailable. This skill requires Intervals.icu
139
+ > MCP tools to retrieve fitness data. See SETUP.md (Section 3: MCP Server
140
+ > Setup), then restart Claude Code and retry."
141
+
142
+ ## 10. Monitoring concerns _(only if the skill declares MONITORING)_
143
+
144
+ Read `{coaching_docs_dir}/tracking/concerns.yaml` if it exists. For each concern
145
+ with `active: true`, find the most recent entry date in its log and compute days
146
+ since. Surface any whose gap ≥ its `cadence_days`:
147
+
148
+ > "[Monitoring: {name} last logged {date} ({N}d ago) — due for capture.]"
149
+
150
+ Awareness only — capture happens via the monitoring-rollup auto-tail at write
151
+ time. If the file is absent or has no active concerns, skip silently.
152
+
153
+ ## 11. Record authority and generated views _(all skills)_
154
+
155
+ Engram active records are the authoritative store for mutable coaching state
156
+ and chronological events. Every pack record declares a role in
157
+ `details.recordRole`, exactly one of:
158
+
159
+ - `state` — one current value for a canonical entity key; an approved change
160
+ creates a new active record, retires the prior one, and links them with
161
+ `relationships.supersedes`.
162
+ - `event` — append-only history (consultations, monitoring entries); never
163
+ automatically replaced.
164
+ - `report-claim` — a structured conclusion extracted from an approved
165
+ long-form report; it never replaces the report document.
166
+
167
+ Canonical entity keys are derived by this pack, never accepted from a model:
168
+
169
+ ```text
170
+ workout:<session-id>
171
+ prescription:<arc-id>:<session-id>
172
+ threshold:<sport>:lt1
173
+ threshold:<sport>:lt2
174
+ persona:<active-profile>
175
+ monitoring:<concern-id>:<signal>
176
+ ```
177
+
178
+ Workout identity is the durable `session_id`; dates, titles, week position,
179
+ and workout contents are mutable attributes, not identity.
180
+
181
+ **Generated compatibility views.** The prescription YAML files,
182
+ `consultations.md`, monitoring logs, and doctor-prep summaries are rendered
183
+ from committed records after each approved apply. Each carries a byte-exact
184
+ warning header (`# GENERATED FROM ENGRAM ACTIVE RECORDS. DO NOT EDIT DIRECTLY.`
185
+ in YAML, `<!-- GENERATED FROM ENGRAM ACTIVE RECORDS. DO NOT EDIT DIRECTLY. -->`
186
+ in Markdown) and is **never edited directly** — direct edits are overwritten by
187
+ the next materialization and break migration comparisons.
188
+
189
+ **Canonical approved documents.** These remain skill-authored long-form
190
+ documents, not generated views: `RACE_REPORT.md`, block `SUMMARY.md`,
191
+ `SEASON_REVIEW.md`, methodology documents, and arc-overview documents.
192
+
193
+ **Approval and retry semantics.** Skills that change records follow one
194
+ ordering: preview records → athlete approves the exact plan hash → apply →
195
+ guarded qmd refresh → regenerate compatibility views.
196
+
197
+ - A stale apply (records changed since preview) deletes the pending plan and
198
+ requires a fresh preview plus fresh approval — never a re-apply of the old
199
+ hash.
200
+ - If the qmd index reports `index-stale`, the committed records remain
201
+ authoritative and the index is simply retried later.
202
+ - If materialization fails, the commit stands and reports stale views;
203
+ re-calling apply with the same committed hash in the same session reruns
204
+ only view regeneration, never the record mutations.
205
+
206
+ Legacy workspaces migrate through the dry-run sequence documented in
207
+ SETUP.md §7: `scan` → `apply-baseline` → `emit-change-set` → `compare`.
File without changes