Proposal: Multi-athlete workspace architecture
A proposal to convert Coach Luca from a Sidney-centered workspace into a true multi-athlete system
Summary
Coach Luca is partially ready for a roster model, but the current implementation still collapses back to one athlete in several critical places.
The most visible issue is the official output path: athlete/ should become athlete/, with one subdirectory per athlete. However, the folder rename alone will not solve the actual multi-athlete problem. The deeper blockers are:
- single shared coordinator planning files in
intake/planning/ - top-level intake, data, and media locations that break athlete self-containment
- global daily output folders that are not athlete-scoped
- hard-coded Sidney delivery and TrainingPeaks assumptions
- specialist doctrine and memory that place Sidney-specific rules in shared or semi-global locations
- routing, staging, and media workflows that do not carry a structured athlete identifier
This proposal recommends a stricter multi-tenant workspace structure centered on athlete/, where all athlete-specific material lives inside that athlete directory: intake, data access, schedules, plans, logs, notes, media references, and other durable records.
Core architectural principle
Everything related to one athlete should be self-contained inside athlete/.
That means the athlete directory is not only the official output area. It is also the canonical home for:
- profile and identity data
- constraints and current status
- goals, race calendar, and travel schedule
- season plan and rolling plans
- athlete-facing notes and team reports
- routing and intake records for that athlete
- nutrition staging and nutrition-related media references for that athlete
- data access notes and external-platform identifiers
- archived or processed athlete performance data pointers
Shared doctrine, shared tooling, and shared team operating rules can remain outside athlete/. Athlete-specific durable material should not.
Why this change is needed
The current system was built while actively coaching Sidney, so many design decisions are correct for one athlete but fragile for a roster. That is now creating three classes of conflict:
- Path conflicts: official files, reports, and rolling plans still assume one active athlete.
- State conflicts: routing, nutrition staging, and delivery state are global rather than athlete-scoped.
- Identity conflicts: athlete name, contact target, and TrainingPeaks identity are scattered across files rather than resolved from one canonical registry.
If these are not fixed before onboarding additional athletes, the system will risk writing files to the wrong location, reading the wrong planning context, or sending a message to the wrong target.
What is already multi-athlete ready
Several parts of the project already point in the right direction.
intake/athlete/already uses an athlete-scoped intake pattern. During migration, its identity and constraint files merge intoathlete/at the root level, while any intake-specific workflow records (routing, staging) go intoathlete/intake/.team/coach-luca/athlete/already uses an athlete-scoped working area for coordinator research and long-form planning. During migration, this content moves toathlete/team/coach-luca/andathlete/planning/.skills/morning-plan/SKILL.mdandskills/evening-summary/SKILL.mdalready describe the current athlete as a variable and use<username>in several path references.planning/multi-athlete-local-time-delivery-proposal.mdalready argues for athlete-scoped delivery settings and due-time evaluation.data/sidney/already uses athlete-scoped storage. However, it exists at the top level of the workspace rather than inside the athlete root. The target moves this toathlete/data/, closing that remaining level of ambiguity.
The main issue is not the absence of a multi-athlete concept. The issue is that the system uses athlete-scoped design in some places and single-athlete shortcuts in other places, while still distributing one athlete's durable record across multiple top-level roots.
Current blockers and conflicts
1. Official outputs are still global, not athlete-scoped
Severity: High
The current official output area is athlete/, with global daily and weekly folders under athlete/athlete-notes/ and athlete/team-reports/.
Conflicts:
- a second athlete would collide with the same daily file namespace
- morning and evening workflows search a shared note directory rather than an athlete-specific one
- team reports are not separated by athlete
Evidence:
README.mddefinesathlete/as the official output locationathlete/README.mddocuments one shared output areaskills/morning-plan/SKILL.mdwrites toathlete/athlete-notes/daily/YYYY-MM-DD-morning.mdskills/evening-summary/SKILL.mdwrites toathlete/athlete-notes/daily/YYYY-MM-DD-evening.mdandathlete/team-reports/daily/YYYY-MM-DD.mdHEARTBEAT.mdchecks one shared morning-note and team-report path
This is the clearest reason to rename athlete/ to athlete/ and move the official outputs under each username.
2. Coordinator planning source of truth is single-tenant
Severity: High
The workspace currently treats intake/planning/goals-and-priority-events.md, intake/planning/race-schedule.md, and intake/planning/travel-schedule.md as the live coordinator planning source of truth.
That works for one athlete, but it does not scale because those files contain one athlete's priorities, calendar, and travel reality at a time.
Conflicts:
- specialists load one shared planning context at startup
- the current planning files are already populated with Sidney's information
- adding a second athlete would either overwrite the shared files or force ambiguous mixed-athlete content into one document
Evidence:
AGENTS.mdinstructs the coordinator to always read the three sharedintake/planning/files on startupshared/doctrine/team-doctrine.mddefines those three files as the coordinator-owned planning records- all specialist
AGENTS.mdfiles also load the same three shared planning files planning/phase-two-daily-ops-plan.mdandplanning/phase-two-daily-ops.mdpromote Sidney intake files into those shared coordinator planning files
This is one of the highest-priority architectural changes. The current singletons must become athlete-scoped records stored inside each athlete directory.
3. The workspace contains split source-of-truth patterns
Severity: High
The project currently spreads athlete state across three separate layers:
intake/athlete/for raw intake and identityathlete/sidney/for official rolling plans and season planteam/coach-luca/athlete/for coordinator research and long-form planning
This is workable for one athlete because the human operator can remember the map. It becomes error-prone with a roster.
Conflicts:
- some files are clearly intake records, some are official outputs, and some are working notes, but the boundary is not always obvious
- several planning documents tell the system to check multiple locations for related material
- a second athlete would multiply the ambiguity rather than merely duplicate structure
Evidence:
team/coach-luca/PHILOSOPHY.mddirects Coach Luca to checkteam/coach-luca/athlete/training-plans/before generating rolling plan filesshared/doctrine/ownership-map.mdroutes macro-load changes toathlete/sidney/season-plan.mdorathlete/sidney/rolling-3-week.mdplanning/phase-two-daily-ops.mdandplanning/phase-three-knowledgebase-and-philosophy.mdpoint at theathlete/sidney/planning files as live outputs
This directly conflicts with the self-contained-athlete requirement. The system needs one canonical athlete root, athlete/, with any internal working material either moved there or explicitly treated as a derived internal workspace that mirrors the same athlete boundary.
4. Delivery identity is not centralized and is currently inconsistent
Severity: High
The workspace does not have a single canonical athlete-delivery registry. Instead, athlete delivery targets appear in several different places, and they are not fully consistent.
Conflicts:
- athlete messaging can be routed from example commands rather than a canonical athlete record
- test and production targets are mixed across memory and doctrine
- adding multiple athletes would make this ambiguity unsafe
Evidence:
USER.mdstores a Telegram user ID of6018768717MEMORY.mdstores Sidney's Telegram user ID as8761249729intake/athlete/profile.mdstores Sidney's Telegram user ID in her intake profileAGENTS.md,team/coach-luca/AGENTS.md, andteam/coach-luca/synthesis/routing-playbook.mdinclude direct-send examples targeting6018768717planning/multi-athlete-local-time-delivery-proposal.mdalready recommends a per-athlete delivery registry, but that registry does not yet exist
Before multiple athletes are supported, delivery identity has to move to one canonical athlete record stored inside each athlete directory, with any roster index outside that directory treated as a convenience index rather than the source of truth.
5. TrainingPeaks access is hard-coded to Sidney
Severity: High
TrainingPeaks support is currently athlete-specific all the way down to the athlete ID and archive path, but the durable record is not self-contained within the athlete's own directory.
Conflicts:
- browser automation scripts open Sidney's specific TrainingPeaks calendar
- raw archive guidance points only to
data/sidney/ - TrainingPeaks access details are stored in Sidney's athlete intake, while the actual data path is stored outside the athlete directory
Evidence:
scripts/tp_check.jsopensapp.trainingpeaks.com/#calendar/athlete/1575220scripts/tp_last_activity.jssearches for the same athlete-specific URL and usesSidneyas the text hintintake/athlete/data-access.mdrecords athlete ID1575220USER.mdandMEMORY.mddefine the canonical raw archive path asdata/sidney/trainingpeaks/raw/
This is not just historical data. It is executable logic that must be parameterized before a roster is viable, and the resulting durable access record should live under athlete/.
6. Routing, staging, and nutrition records are global and only loosely identify the athlete
Severity: High
Several operational files already support repeated entries, but they do not carry a strong athlete key as part of the durable data model, and they live outside the athlete boundary.
Conflicts:
intake/routing-log.mdis one shared logintake/nutrition/staged-items.mdis one shared filemedia/nutrition/is organized by date only, not by athlete- nutrition records rely on athlete name appearing in prose rather than a consistently structured username or athlete ID field
Evidence:
intake/routing-log.mdentries describe the athlete in note text rather than in a structured athlete columnintake/nutrition/staged-items.mduses lines such asSender: athlete via Telegram direct chatand narrative notes tied to Sidney contentteam/nutrition agent/records/nutrition-records.mdandteam/nutrition agent/logs/daily/*.mdembed Sidney-specific media filenames and athlete names in free textmedia/nutrition/currently stores content by date only
This will create ambiguity immediately when two athletes send photos on the same day. It also breaks the self-contained-athlete rule because the durable intake trail for one athlete is spread across shared top-level files.
7. Shared doctrine and specialist memory still contain Sidney-specific operating rules
Severity: Medium
Some Sidney-specific coaching rules belong in Sidney's athlete profile, not in shared doctrine or specialist memory.
Conflicts:
- specialist behavior can be biased toward Sidney even when reasoning about another athlete
- the boundary between system-wide doctrine and athlete-specific coaching constraints is currently too loose
Evidence:
team/nutrition agent/domain/dietary-safety-triggers.mdexplicitly defines Sidney-specific gluten-free and dairy-free compatibility handlingteam/endurance/MEMORY.md,team/strength/MEMORY.md,team/nutrition agent/MEMORY.md, andteam/recovery/MEMORY.mdall contain Sidney-specific planning rulesteam/endurance/PHILOSOPHY.md,team/recovery/PHILOSOPHY.md,team/strength/PHILOSOPHY.md,team/nutrition agent/PHILOSOPHY.md, andteam/coach-luca/PHILOSOPHY.mdall containCurrent application to Sidneysections
These are not wrong. They are simply in the wrong layer for a multi-athlete system.
8. Startup behavior assumes one live athlete context
Severity: Medium
The system has strong startup and routing doctrine, but it does not yet define how the active athlete is selected before reading athlete-scoped records.
Conflicts:
- startup instructions load shared planning files with no athlete selector
- skills say to resolve the current athlete from context, but there is no durable cross-workflow athlete registry or session contract in place yet
Evidence:
AGENTS.mddefines a fixed startup read list and does not specify an athlete selection stepskills/morning-plan/SKILL.mdexplicitly says to resolve the current athlete's first name, username, and messaging target from task context and routing inputsskills/evening-summary/SKILL.mdassumes the same, but the surrounding workspace still defaults to shared outputs and shared planning files
This means the skill layer is ahead of the workspace architecture.
9. Historical Sidney content is extensive, but not itself a blocker
Severity: Low
The workspace contains a large amount of Sidney-specific material, including planning, notes, team reports, nutrition logs, and data archives.
This is expected and acceptable. It should not be treated as a design mistake. The migration problem is not that the workspace contains Sidney's data. The problem is that some system rules still assume that only Sidney can exist.
Recommended target structure
The recommended top-level change is:
- rename
athlete/toathlete/ - make each athlete directory the canonical home for all athlete-specific records
Recommended structure:
athletes/
README.md
sidney/
profile.md
constraints.md
current-status.md
data-access.md
delivery-config.md
goals.md
race-calendar.md
race-history.md
current-focus.md
goals-and-priority-events.md
race-schedule.md
travel-schedule.md
season-plan.md
rolling-3-week.md
rolling-7-day.md
intake/
routing-log.md
nutrition-staged-items.md
data/
trainingpeaks/
raw/
json/
media/
nutrition/
YYYY-MM-DD/
athlete-notes/
daily/
weekly/
team-reports/
daily/
weekly/
coach-notes/
(migrated from team/coach-luca/athlete/)
planning/
long-range/
drafts/
<username>/
(same structure as sidney/ above)
This gives each athlete a self-contained directory with no filename collisions and no ambiguity about where athlete facts, logs, plans, and operational history belong.
Recommended source-of-truth layout
The workspace should use one primary athlete boundary consistently.
1. Canonical athlete root
The canonical source of truth for any athlete-specific durable material is athlete/. See the full recommended directory layout in the preceding section.
The athlete root must include, at minimum:
- identity and constraints (
profile.md,constraints.md,current-status.md) - goals, schedules, and planning (
current-focus.md,goals-and-priority-events.md,race-schedule.md,travel-schedule.md,season-plan.md,rolling-3-week.md,rolling-7-day.md) - delivery configuration and platform identifiers (
delivery-config.md,data-access.md) - intake and routing (
intake/routing-log.md,intake/nutrition-staged-items.md) - performance data (
data/trainingpeaks/) - media references (
media/nutrition/) - official outputs (
athlete-notes/,team-reports/) - coordinator working notes (
coach-notes/)
Why:
- it keeps athlete identity, constraints, schedules, data access, plans, logs, and media references together
- it makes the athlete directory the obvious source of truth for humans and workflows
- it removes cross-root ambiguity when onboarding a second athlete
2. Shared workspace layer
Anything outside athlete/ should be either shared doctrine or shared tooling, not athlete-specific durable state.
Examples that can remain outside:
shared/(doctrine, templates, automation notes)- generic scripts that accept athlete inputs dynamically
- shared team philosophy that is truly cross-athlete
- specialist domain knowledge that applies to any athlete (philosophy, knowledgebase)
- specialist working logs and daily operational notes, provided they are organized by username internally (see open question below)
3. Specialist athlete-specific records
Specialist working areas (team/<specialist>/) currently contain athlete-specific durable records. The most developed example is the nutrition agent, whose team/nutrition agent/records/nutrition-records.md and team/nutrition agent/logs/daily/*.md files embed Sidney-specific content.
This creates a tension with the athlete-boundary principle. Two approaches are viable:
Option A: Move specialist athlete-specific records under the athlete root. Nutrition durable records, daily logs, and equivalent specialist records for each athlete would live under athlete/. Specialists would write into the athlete directory instead of their own. This fully enforces the self-contained-athlete rule but changes the current ownership model where each specialist writes only in team/<specialist>/.
Option B: Keep specialist records in team/<specialist>/ but organize by username. Specialist directories would add an athlete/ layer internally, for example team/nutrition agent/athlete/records/ and team/nutrition agent/athlete/logs/daily/. This preserves the existing ownership boundary but distributes one athlete's durable state across multiple directory trees.
Recommendation: Option A is architecturally cleaner and consistent with the core principle. The ownership-map adjustment is small: specialists still own the records, they just write them inside the athlete root instead of inside team/<specialist>/. The ownership map should be updated to reflect that specialist athlete-specific records are co-located with the athlete, not with the specialist workspace.
This decision should be confirmed before migration begins.
4. Roster index (discovery only, not canonical)
If a roster index is needed, it should live at a shared location such as athletes/registry.yaml or athletes/index.md. It is a discovery and enumeration layer only. It must not become the canonical storage location for athlete facts.
Recommended minimum fields per entry:
athlete_slugstatus(active or inactive)athlete_root
The canonical per-athlete record, stored inside athlete/delivery-config.md or equivalent, should hold:
- delivery target
- username
- athlete name
- timezone fallback
- data access path
- platform-specific identifiers
Each athlete's canonical delivery config, identifiers, and operational state must live inside that athlete's own folder, not in the roster index.
Required operational data-model changes
Before multiple athletes are active, the following durable records need to move under each athlete root.
Routing log
Replace the global routing log with:
athlete/intake/routing-log.md
Each entry should include at least:
- username
- athlete name
- source channel
- source sender ID
Nutrition staging
Replace the shared staging file with:
athlete/intake/nutrition-staged-items.md
Each entry should include at least:
- username
- athlete name
- received channel
- sender ID
- workspace media path
Media storage
Athlete nutrition media should move from:
media/nutrition/YYYY-MM-DD/...
to:
/athlete/logs/media/YYYY-MM-DD/...
Data storage
Athlete performance data should move from shared top-level data roots to:
athlete/data/trainingpeaks/raw/athlete/data/trainingpeaks/json/- other athlete-scoped performance data paths as needed
Specialist athlete-specific records
If Option A is confirmed (see source-of-truth layout above), move the following under each athlete root:
- nutrition agent durable records (currently
team/nutrition agent/records/nutrition-records.md) toathlete/team/nutrition/records.mdor equivalent - nutrition agent daily logs (currently
team/nutrition agent/logs/daily/*.md) toathlete/team/nutrition/logs/daily/*.mdor equivalent - any equivalent athlete-specific records from other specialists
The specialist workspace (team/<specialist>/) would retain domain knowledge, philosophy, shared knowledgebase, and cross-athlete operational notes, but not athlete-specific durable records.
Coordinator working notes
Coordinator athlete-specific working notes should move from:
team/coach-luca/athlete/
to:
athlete/team/coach-luca/athlete/planning/
This consolidates all coordinator working material for an athlete into the athlete root.
Doctrine cleanup required for roster support
The project should separate three kinds of rules.
Shared doctrine
Belongs in shared doctrine only if it applies to every athlete and every workflow.
Examples:
- Coach Luca is the only athlete-facing gateway
- specialists own their domain files
- official outputs stay inside the workspace
Athlete-specific constraints
Belong in athlete-specific records under athlete/.
Examples:
- Hashimoto's context
- gluten-free or dairy-free rules
- Monday rest preference
- race-duration assumptions
- channel preference and timezone
Specialist interpretation rules
Belong in specialist philosophy or knowledgebase only when they are general principles that can be applied to any athlete.
Current Sidney-specific sections should be retained, but moved into Sidney's athlete directory or rewritten so they pull from athlete context rather than embedding Sidney directly in the specialist baseline.
Recommended migration sequence
Phase 1: Define the registry and target structure
- create the roster index and per-athlete canonical record layout
- define one canonical username per athlete
- define
athlete/as the canonical home for all athlete-specific records
Phase 2: Consolidate Sidney into one athlete root
- rename
athlete/toathlete/ - move Sidney files to
athlete/ - migrate athlete-specific intake records from
intake/athlete/intoathlete/ - migrate coordinator working notes from
team/coach-luca/athlete/intoathlete/team/coach-luca/andathlete/planning/ - migrate athlete-specific planning, data, and media references under
athlete/
Note: skills, doctrine, templates, and heartbeat path references are updated in Phase 5 as part of the broader workflow loading cleanup.
Phase 3: Eliminate top-level athlete state
- replace the shared
intake/planning/singletons with athlete-local planning files - replace top-level
data/andmedia/athlete stores with athlete-local equivalents - replace shared routing and staging files with athlete-local equivalents
Phase 4: Parameterize delivery and TrainingPeaks access
- move Telegram target and channel preference to the athlete's canonical record
- move TrainingPeaks athlete ID and archive paths to athlete-local access records
- update scripts to accept athlete identity as input rather than assuming Sidney
Phase 5: Update workflow loading and path references
- update startup instructions so the active athlete is resolved before athlete files are read
- update skills, doctrine, templates, and heartbeat checks to use the new athlete-scoped paths
- remove references that still assume shared top-level athlete planning files
- update ownership map to reflect specialist write locations under athlete roots (if Option A is confirmed)
- update nutrition workflow doctrine so the nutrition agent writes durable records and daily logs into the athlete directory rather than
team/nutrition agent/
Phase 6: Migrate specialist athlete-specific content
- move Sidney-specific operational rules out of shared specialist memory and philosophy files
- move athlete-specific specialist records (nutrition agent durable records, daily logs, and equivalents from other specialists) into the relevant athlete directory
- keep athlete-specific coaching constraints in athlete records
- keep shared doctrine and specialist domain knowledge genuinely shared
Recommendation
Do not treat this as a simple rename of athlete/ to athlete/.
The rename is correct and should happen, but it should be executed as part of a broader multi-athlete refactor with four immediate priorities:
- make
athlete/the canonical home for all athlete-specific records - move Sidney's current intake, planning, output, data, and media references under that root
- retire the single shared coordinator planning files in
intake/planning/ - parameterize delivery targets and TrainingPeaks identity from athlete-local records
If those four changes are completed, the rest of the system becomes much easier to scale. If they are not completed, a second athlete will expose inconsistent reads, incorrect writes, and delivery-risk immediately.
Related proposal
This proposal should be read alongside:
planning/multi-athlete-local-time-delivery-proposal.md
That document solves the timing and channel-dispatch side of multi-athlete delivery. This document solves the workspace structure, source-of-truth, and athlete-identity side.