Reported issues for Long Run Hybrid Coach
Pod holds 21 of 31 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.
Back to Long Run Hybrid Coach.
Most discussed
Agent entries: finish the Custom GPT mobile loop and add a hosted MCP server
The contract every entry inherits
A Custom GPT has no durable memory of prior conversations. That is acceptable only because the product memory lives outside the agent:
current PlanState + DecisionEvent history + latest actuals
Every new chat reconstructs continuity by calling the gateway and reading that same state. No entry owns a second plan, second memory, second validator, second coaching rules engine, or provider-specific state. Every entry is a thin adapter around th
Read the thread · 2026-08-15 · closed · 4 comments
Gateway security review follow-ups: public origin, OAuth conformance, volume guard, rotation
Record of the 2026-08-26 gateway security review. This body is the current follow-up list; #15 owns priority.
Current status — 2026-08-26
Completed
- Legacy
/v1/coach/*REST surface — DONE via #292. The 22 routes that could accept a raw Intervals provider credential as identity were deleted. Socket-level HTTP tests moved to/mcp, behavior tests use the internal route dispatch, and regressions assert all retired paths return 404 without authenticating or touching owner state
Read the thread · 2026-08-26 · closed · 3 comments
OpenClaw / ClawHub distribution: package canonical Skill + MCP endpoint for chat-based agent users
Goal
Provide a first-class distribution package and integration path for OpenClaw (小龍蝦) / ClawHub users, enabling athletes to use Long Run Hybrid Coach directly from their preferred chat interfaces (e.g. WeChat, Telegram, Discord, desktop GUI) via hosted MCP or local MCP.
This realizes Priority 3 (P3) of the distribution roadmap (#114) and builds upon the canonical Skill + MCP foundation (#117).
Context & Motivation
OpenClaw is an open-source conversational AI agent framework. Users ("
Read the thread · 2026-08-17 · open · 3 comments
[Direction settled] Hosted + local distribution architecture; current status lives in #15/docs/distribution
目的
把 Long Run Hybrid Coach 的對外分發收斂成一條清楚的產品路線,避免之後每遇到一個 agent 平台就重新討論架構或複製一套 coach。
已拍板:
- Hosted MCP 會長期存在,且是 canonical public service。 不再討論要不要移除 hosted backend。
- Local execution 也是 first-class alternative。 使用者可以選擇完全在自己電腦執行,不依賴我們的 hosted backend。
- 所有平台入口都只能是薄 adapter;不得複製 Coach 邏輯、PlanState schema、validator、delivery semantics 或 provider adapter。
- 模型推理留在使用者選擇的 ChatGPT / Claude / Gemini / OpenClaw 等 agent;本產品不增加自己的 LLM API runtime。
兩種 canonical deployment mode
A. Hosted
Read the thread · 2026-08-16 · closed · 3 comments
Feasibility spike: distribute Long Run Hybrid Coach through Claude Connectors (Directory + self-deploy)
Owner request
先驗證 Long Run Hybrid Coach 能不能透過 Claude 的連接器機制對外分發,讓更多人(不只 ting 自己)能自助用起來——包含官方 Connectors Directory 上架,以及讓技術使用者自架自己那份的路徑。本 issue 只做查證與方案比較,不寫 production 程式碼、不改 gateway。
Why this is a separate spike
現有產品已經有:
- 一個 stable HTTPS Coach Gateway,OAuth-authenticated,owner-scoped PlanState;
- Custom GPT Action 路徑(OpenAPI/REST,不是 MCP 協定);
- #35 Part B 定義了「把既有 command surface 包成 MCP tools」的範圍,但明確被 owner 在 2026-08-15 的 comment 標記為 deferred("Part B (hosted MCP) remains deferred; do no
Read the thread · 2026-08-16 · closed · 3 comments
startCoachSession returns 63 KB, and it grows with the athlete's history
Symptom
Every coaching turn opens with startCoachSession. Measured against the owner account on 2026-08-23, one call returns 63,560 characters of JSON:
| part | chars |
|---|---|
context |
41,690 |
plan_state |
10,285 |
coaching_guidance |
7,600 |
delivery |
2,791 |
reconciliation |
903 |
| rest | ~290 |
Inside context:
| field | chars |
|---|---|
segment_execution |
16,206 |
recent_actuals |
8,271 |
cycle_sessions |
3,048 |
baseline_evidence |
Read the thread · 2026-08-23 · closed · 2 comments
The product verifies Intervals against the live account and never verified itself against a live client
What was found
This repository has a rule it applies rigorously — "Verify against the live account, not against the plan" — and had never applied it to its own clients. Over 1,600 tests, every one of them checking the repo against the repo. Nothing asked whether an athlete's ChatGPT or claude.ai actually receives what the server sends.
Asking produced this:
| Client | Has the orchestration layer before the first turn? | Evidence |
|---|---|---|
| claude.ai (web connector) | **N |
Read the thread · 2026-08-19 · open · 2 comments
Restrict MCP client registration to trusted redirect origins and retain security audit events
Threat
/oauth/authorize now binds a presented client_id to the redirect URIs sealed into that registration, so one client's id cannot be paired with another callback. That is necessary but not sufficient.
/oauth/register is still open to any caller. Today an attacker can register https://evil.example/callback, receive a valid client id, start PKCE themselves, induce an athlete to approve the real Long Run Hybrid Coach application at Intervals, and receive this gateway's authorizatio
Read the thread · 2026-08-16 · closed · 2 comments
Most recent
[Current — eval coverage] Give pre_plan_observations a contract so a first-plan case can name its evidence
Finding
The first plan is the only layer that may author goal, cycle, week and outlook at once, and it is the only layer with no committed eval case. That is not because the read is missing — two scenarios already take it and pass:
09_no_plan__provider_healthy10_no_plan__recovery_read_fails
Both hand back pre_plan_observations carrying athlete_evidence,
recent_training and recovery_signals. No eval case uses either. The two
committed plan_cycle cases both bind to `12_pla
Read the thread · 2026-08-29 · closed · 0 comments
plan_state_exists tells the model what exists but not what the retry needs, so the turn ends there
What happened, with the counter as evidence
On 2026-08-27 an external athlete's client made four tool calls in one day — one each of
startCoachSession, inspectIntervalsPermissions, prepareCoachDecision and
confirmPrescribedStrength. Two were accepted, two refused: plan_state_exists and
invalid_request. The account already had a plan from the day before and ended the day
with zero deliveries. No applyCoachDecision, no delivery call of any kind.
plan_state_exists can only
Read the thread · 2026-08-28 · closed · 0 comments
An anonymous OAuth 400 says only "400": the access log the silent refusals defer to carries no error code
What happened
On 2026-08-27, a local MCP client repeatedly failed to connect and I could not tell from the logs why. The same sequence appears twice, ~20 minutes apart, from two different loopback ports:
02:37:52.470 POST /oauth/register -> 201 client_registration accepted (127.0.0.1:9999)
02:37:52.784 GET /oauth/authorize -> 400 no security event
02:37:53.061 GET /oauth/authorize -> 400 no security event
02:37:53.461 POST /oauth/register -> 400 client_registration refus
[Read the thread](https://github.com/atomchung/long-run-hybrid-coach/issues/301) · 2026-08-27 · closed · 1 comment
### [Edge case] The DNS-rebinding check still trusts a header outside release mode
Noticed while doing #288 item 2, and deliberately not fixed there. **Low priority, and the cheap fix is probably to change nothing** — filed so the next reader of `_require_allowed_origin` does not have to re-derive it.
## What
`_require_allowed_origin` (`garmin_coach_loop/gateway.py`) refuses a browser calling `/mcp` from an origin this server does not answer to. Three answers are trusted: `MCP_ALLOWED_ORIGINS`, the operator's `allowed_mcp_origins`, and **this request's own origin**, computed
[Read the thread](https://github.com/atomchung/long-run-hybrid-coach/issues/297) · 2026-08-27 · open · 0 comments
### [Scale gate — availability] Bound hosted gateway concurrency and request timeouts
## Problem
The production hosted MCP endpoint is internet-facing and is served directly by Python's `http.server.ThreadingHTTPServer` in `garmin_coach_loop/gateway.py`. The gateway already bounds request bodies (`MAX_REQUEST_BYTES`) and outbound provider calls have timeouts, but the public inbound server currently has no explicit application-level concurrency ceiling or per-connection/read timeout.
`ThreadingHTTPServer` creates a thread per request/connection. A sufficiently large number of sl
[Read the thread](https://github.com/atomchung/long-run-hybrid-coach/issues/285) · 2026-08-26 · open · 1 comment
### [Release gate — OAuth] Enforce single-use authorization codes
## Problem
The hosted MCP OAuth bridge issues its own authorization code as a signed/encrypted stateless envelope in `garmin_coach_loop/gateway.py`. The code is short-lived (`AUTHORIZATION_CODE_TTL_SECONDS = 60`) and is bound to the client, redirect URI and PKCE challenge, but it is not consumed after a successful token exchange.
**Correction from the 2026-08-26 security review (#288): `resource` is not currently bound consistently.** Authorization can seal no resource, and token exchange comp
[Read the thread](https://github.com/atomchung/long-run-hybrid-coach/issues/284) · 2026-08-26 · closed · 1 comment
### [Release gate — supply chain] Pin and verify MCP Registry publisher
## Problem
`.github/workflows/publish-mcp-registry.yml` downloads `mcp-publisher` from the mutable `releases/latest` URL and executes it directly in a job with `id-token: write`:
```yaml
curl -fsSL "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_...tar.gz" | tar xz mcp-publisher
./mcp-publisher login github-oidc
./mcp-publisher publish
There is no exact publisher version, checksum/signature verification, or immutable artifact pin. If the upstream r
Read the thread · 2026-08-26 · open · 0 comments
[Release gate — privacy] Sanitize filesystem failures before model-facing output
Finding
Hosted failure paths are not consistently sanitized before they become client/model-visible text.
Two confirmed paths on current main:
1. Common StateStoreError mapping can echo an absolute path
store._read_object(path) catches an OSError and builds:
raise StateStoreError(f"cannot read {path.name}: {exc}")
Using path.name in the prefix looks safe, but the original OSError string commonly carries the full path itself, e.g. a PermissionError is shaped l
Read the thread · 2026-08-26 · closed · 0 comments
[Scheduled — verify in onboarding] First-plan preview/apply plan_id handoff
Finding
The unified prepareCoachDecision / applyCoachDecision first-plan path has a self-contradictory handoff.
When no PlanState exists, prepare_decision() translates to prepare_initialization(), whose response contains the derived but not yet persisted identifiers:
"plan_id": plan["plan_id"],
"plan_version": plan["version"],
The public MCP output schema allows those values, so the model receives them.
But the matching apply path translates through `_first_plan
Read the thread · 2026-08-26 · open · 1 comment
This gateway speaks 2025-06-18, and two newer MCP revisions now exist
What is true today
PROTOCOL_VERSION in garmin_coach_loop/mcp_transport.py
is 2025-06-18, and HTTP_PROTOCOL_VERSIONS is that plus 2025-03-26. A
MCP-Protocol-Version header outside those two is a 400 before the body is read.
The specification repository now carries five released revisions: 2024-11-05,
2025-03-26, 2025-06-18, 2025-11-25 and 2026-07-28. We are two behind.
Why this is not obviously broken, and
Read the thread · 2026-08-20 · open · 0 comments
Walk a real Hermes Agent connection once, and record what it does
Why this is blocking something
Two separate rules point at the same missing fact:
- Hermes Atlas — the community map — requires an entry to be "specifically built for or integrated with Hermes Agent". This is a general MCP server that has never been connected to one, so it does not qualify today.
- Our own checklist — step 2 of
docs/distribution/hermes-agent.mdsays to connect once from a real client *before submitting anyt
Read the thread · 2026-08-20 · open · 0 comments
recovery_signals makes a client send nine explicit nulls to report one reading
What
startCoachSession.recovery_signals requires all ten per-day fields on every day it carries — date, readiness_score, readiness_level, hrv_status, hrv_7d_avg_ms, acute_load, recovery_time_sec, body_battery_high, body_battery_low, avg_stress. Both the MCP input schema in garmin_coach_loop/mcp_transport.py and _keys inside validation.py demand the full set.
A local agent that can read only Body Battery therefore has to send nine explicit nulls per day to r
Read the thread · 2026-08-19 · closed · 1 comment
The plugin token endpoint redeems a code for anyone: add gateway client authentication to /oauth/intervals/token
Found during a full security review of the gateway on 2026-08-19. Nothing else in that review met the reporting bar; this one is a residual risk worth closing rather than a proven vulnerability, and the prerequisite is stated below.
What
CoachGateway.exchange_token (garmin_coach_loop/gateway.py, the handler behind POST /oauth/intervals/token) reads exactly two fields from the form: grant_type and code. It then calls _redeem_intervals_code, which posts the server-held `GARMIN_COA
Read the thread · 2026-08-19 · closed · 0 comments
The remaining reports are on the project's issue tracker.