# muse mist read: owner/ID form sends request to wrong API path ## Background `muse mist read` accepts two input forms: - Bare ID: `muse mist read H7XFVEzeDfqk` - Owner-qualified: `muse mist read gabriel/H7XFVEzeDfqk` The help text and docstring both document the `owner/ID` form as valid. But when `run_read` detects a `/` in the input, it constructs the wrong API path: ```python # muse/cli/commands/mist.py:616 — BUG api_path = f"/api/{owner_part}/mists/{id_part}" ``` The server has no route at `/api/{owner}/mists/{id}`. The real route is `GET /api/mists/{mist_id}` — owner is not part of the API path. The result is an HTTP 404 that surfaces to the user as: ``` ❌ Hub returned HTTP 0: Server returned invalid JSON: Expecting value: line 1 column 1 (char 0) ``` The error message is also misleading: the underlying 404 body is `{"detail": "Not Found"}` — valid JSON — but the CLI swallows the HTTP status and reports a JSON parse failure instead. ## Root cause `run_read` is the only mist command that got the path wrong. Every other command that handles `owner/ID` input correctly discards the owner and routes to `/api/mists/{id}`: | Command | Line | Path built | Correct? | |---------|------|-----------|----------| | `run_read` | 616 | `/api/{owner}/mists/{id}` | ❌ **bug** | | `run_delete` | 903 | `/api/mists/{id}` | ✅ | | `run_update` | 994 | `/api/mists/{id}` | ✅ | | `run_forks` | 1053 | `/api/mists/{id}/forks` | ✅ | | `run_raw` | 1113 | `/api/mists/{id}/raw` | ✅ | | `run_embed` | 811 | `/api/{owner}/mists/{id}/embed` | ✅ (embed route intentionally needs owner) | The `run_fork` command (line 690–696) was also checked — it correctly extracts just the `id_part` for `/api/mists/{id}/fork`. ## Goal `muse mist read gabriel/H7XFVEzeDfqk --hub https://staging.musehub.ai --json` returns the mist JSON. Both the bare-ID and the `owner/ID` form work identically. ## Phases ### Phase 1 — Fix `run_read` One-line change in `muse/cli/commands/mist.py`. #### Deliverable - [ ] `MR_01` — Change line 616: ```python # Before api_path = f"/api/{owner_part}/mists/{id_part}" # After api_path = f"/api/mists/{id_part}" ``` The `owner_part` variable becomes unused; remove the assignment too (lines 613–614 can simplify to extracting only `id_part`). --- ### Phase 2 — Fix the misleading 404 error message When `_hub_api` receives a non-2xx response, the caller sees a JSON-parse error instead of the actual HTTP status. The error should surface the HTTP status code and the response body so the user can diagnose it. #### Deliverable - [ ] `MR_02` — `_hub_api` (or its caller in `run_read`) raises a clear error on non-2xx HTTP: `❌ Hub returned HTTP 404: {"detail": "Not Found"}`. The current `"Server returned invalid JSON"` message must not appear for a response that actually contains valid JSON. --- ### Phase 3 — Tests No test currently exercises `run_read` with the `owner/ID` form. Add tests to prevent regression. #### Deliverables - [ ] `MR_03` — Unit test: `run_read` with `"gabriel/H7XFVEzeDfqk"` calls `_hub_api` with path `/api/mists/H7XFVEzeDfqk` (not `/api/gabriel/mists/…`). Mock `_hub_api` and assert the `api_path` argument. - [ ] `MR_04` — Unit test: `run_read` with bare `"H7XFVEzeDfqk"` calls `_hub_api` with path `/api/mists/H7XFVEzeDfqk`. Existing happy-path smoke, now with explicit path assertion. - [ ] `MR_05` — Unit test: `run_read` with `"owner/ID"` does NOT include the owner in the path — the `owner` portion is silently discarded (it is advisory information only; the ID alone uniquely identifies a mist). - [ ] `MR_06` — Unit test: when `_hub_api` receives a 404, `run_read` exits with a message containing the HTTP status code (validates MR_02 fix). --- ### Phase 4 — Staging smoke - [ ] `MR_07` — `muse mist read gabriel/H7XFVEzeDfqk --hub https://staging.musehub.ai --json` returns the mist JSON with `mist_id == "H7XFVEzeDfqk"`. - [ ] `MR_08` — `muse mist read H7XFVEzeDfqk --hub https://staging.musehub.ai --json` returns identical output (both forms are equivalent). ## Acceptance criteria 1. `muse mist read owner/ID` and `muse mist read ID` return identical JSON output. 2. HTTP 404 from the server surfaces as `❌ Hub returned HTTP 404: …` — not a JSON parse error. 3. MR_03–MR_06 tests green. 4. Staging smoke passes (MR_07–MR_08). ## Out of scope - Validating that the owner in `owner/ID` matches the mist's actual owner (the server owns that check; the CLI's job is just to extract the ID) - Changing the server-side routes - Other mist subcommands — all others already handle `owner/ID` correctly