Skip to content

fix: resolve device names and preserve opaque IDs - #85

Merged
steipete merged 3 commits into
openclaw:mainfrom
VACInc:fix/web-device-name-resolution
Sep 22, 2026
Merged

steipete merged 3 commits into
openclaw:mainfrom
VACInc:fix/web-device-name-resolution

Conversation

@VACInc

@VACInc VACInc commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Web API playback previously sent a documented device name such as Desk Speaker as a raw ID, causing Spotify's 404 Device not found. The generic request layer also added that playback-only selector to library and playlist mutations.

Keep device selection in one playback helper. Pass the supplied selector through unchanged first; after a 404, resolve a case-insensitive exact device name and retry with its usable ID. This preserves arbitrary Spotify device IDs without guessing their format or requiring device-list permission for successful raw-ID commands. Never retry a named device with a missing ID, and preserve authentication, cooldown, cancellation, and other non-404 failures. Unrelated mutations no longer receive device_id. Share exact-ID-first, case-insensitive-name matching with Connect and device set; reject named transfers with no usable ID. This also fixes existing case-folded ID matching that could select a different device.

Validation: the original main fails both name-resolution and unrelated-mutation regressions. The initial PR also fails an opaque-ID regression; the finished implementation passes. Tests cover all nine playback controls, retained command parameters, unusable IDs, unknown devices, lookup failures, cancellation, and raw IDs without discovery. Full Linux race/coverage, lint, dead-code scan, docs build, and built CLI version/completion smoke checks run on Crabbox; platform and Go-floor coverage run in CI.

Thanks @VACInc for the original fix, tests, documentation, and reported live play/pause verification. Maintainer verification uses synthetic Spotify endpoints.

@clawsweeper

clawsweeper Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 16, 2026
@clawsweeper

clawsweeper Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed September 22, 2026, 8:03 AM ET / 12:03 UTC (Revision 6).

ClawSweeper review

What this changes

Resolve device names for Web API playback after a rejected selector, preserve opaque device IDs across engines, and remove playback-only parameters from unrelated mutations.

Merge readiness

✅ Ready for maintainer review

The fix remains necessary on current main and v0.13.0. The earlier missing-ID finding is resolved, and the reviewed patch has no blocking correctness findings.

Priority: P2
Reviewed head: fec7da4fb419945b0c762041cf06d3de40df6f80

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A focused repair with broad regression coverage and no identified blocking defect.
Proof confidence 🌊 off-meta tidepool Not applicable: The MEMBER-authored PR is exempt from ordinary contributor proof. Its body reports play/pause verification and synthetic-endpoint checks of the playback client; these were not independently executed here. No stored-data contract or material authorization boundary changes.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: The MEMBER-authored PR is exempt from ordinary contributor proof. Its body reports play/pause verification and synthetic-endpoint checks of the playback client; these were not independently executed here. No stored-data contract or material authorization boundary changes.
Evidence reviewed 8 items Pinned patch and merge result: Read the complete introduced diff. The verified test merge has the pinned main and PR head as its parents, and its tree matches the PR head.
Current-main behavior: Main’s playback methods still use generic request helpers without name resolution; the generic request layer attaches the configured selector directly to mutations.
Latest release still has the affected behavior: The v0.13.0 request implementation directly attaches c.device to PUT, POST, and DELETE requests without resolving names.
Findings None None.
Security None None.

How this fits together

spogo routes CLI playback commands through Spotify Connect or Spotify’s Web API. Device selectors come from command flags or profile settings and determine which Spotify device receives playback controls.

flowchart TD
 A[CLI playback command] --> B[Configured device selector]
 B --> C[Web API playback request]
 C --> D{Selector rejected with 404?}
 D -->|No| E[Return result]
 D -->|Yes| F[Discover and match device]
 F --> G[Retry with usable device ID]
 G --> E
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test delta Production +70/-52 (net +18); tests +319/-0 The modest production growth centralizes device resolution and has focused coverage for playback and selector compatibility.

Technical review

Best possible solution:

Keep device resolution confined to playback, with unchanged raw-ID requests and one shared exact-ID-first matcher.

Do we have a high-confidence way to reproduce the issue?

Yes, from source: main sends a documented device name unchanged as device_id and also adds it to unrelated mutations. No live Spotify reproduction was executed during this review.

Is this the best way to solve the issue?

Yes. Playback-local resolution preserves successful opaque-ID requests, shares matching across engines, and avoids adding configuration or persisted state.

AGENTS.md: not found in the target repository.

Codex review notes: model internal, reasoning medium; reviewed against 3d4edc230f5e.

Labels

Label changes:

No label changes.

Label justifications:

  • P2: Repairs the existing device-name contract for a bounded playback workflow.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The MEMBER-authored PR is exempt from ordinary contributor proof. Its body reports play/pause verification and synthetic-endpoint checks of the playback client; these were not independently executed here. No stored-data contract or material authorization boundary changes.

Evidence

What I checked:

  • Pinned patch and merge result: Read the complete introduced diff. The verified test merge has the pinned main and PR head as its parents, and its tree matches the PR head. (fec7da4fb419)
  • Current-main behavior: Main’s playback methods still use generic request helpers without name resolution; the generic request layer attaches the configured selector directly to mutations. (internal/spotify/client_playback.go:46, 3d4edc230f5e)
  • Latest release still has the affected behavior: The v0.13.0 request implementation directly attaches c.device to PUT, POST, and DELETE requests without resolving names. (internal/spotify/client_request.go:58, 34935e20659b)
  • Playback retry and prior finding: The helper first preserves the supplied selector, performs discovery only after HTTP 404, rejects missing IDs, avoids retrying an unchanged ID, and retains command parameters and payload. The nullable-ID regression now asserts only the initial rejected request occurs. (internal/spotify/client_playback.go:99, fec7da4fb419)
  • Existing selector contract and regression coverage: The CLI already advertises device names or IDs. Added tests cover all nine playback controls, raw IDs without discovery, missing IDs, lookup failures, non-404 failures, exact-ID precedence, and unrelated library mutations. Tests were inspected, not executed during this read-only review. (internal/spotify/client_device_test.go:13, fec7da4fb419)
  • Related merged work is distinct: fix: fall back to Web API when no active device for play command #21 added inactive-Connect playback fallback to the Web API; it did not resolve Web API device names. The bounded GitHub PR listing found no replacement implementing this fix. (internal/spotify/connect_commands.go:69, fe493222ddb4)

Likely related people:

  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • unknown: The claimed source-line change could not be verified from bounded local history. (role: source history unknown; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (5 earlier review cycles)
  • reviewed 2026-09-16T01:25:39.797Z sha b44cb77 :: needs changes before merge. :: [P2] Reject name matches without a usable device ID
  • reviewed 2026-09-16T01:34:39.695Z sha c7fa011 :: needs maintainer review before merge. :: none
  • reviewed 2026-09-17T11:35:18.881Z sha c7fa011 :: needs maintainer review before merge. :: none
  • reviewed 2026-09-20T06:59:53.373Z sha c7fa011 :: needs maintainer review before merge. :: none
  • reviewed 2026-09-21T11:53:57.863Z sha c7fa011 :: needs maintainer review before merge. :: none

@VACInc

VACInc commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

Addressed the nullable device ID finding in c7fa011:

  • reject a matching named device when Spotify returns no usable ID
  • do not send the playback request
  • cover the documented id: null response with a regression test

Validated with the targeted regressions repeated 20 times, go test ./..., go vet ./..., golangci-lint, and git diff --check.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 16, 2026
Try raw selectors before Web API name lookup, and share exact-ID-first device matching with Connect and device set. Cover all playback controls, raw-ID scope independence, absent IDs, case and whitespace preservation, and API error behavior.

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
@steipete
steipete merged commit 2365605 into openclaw:main Sep 22, 2026
7 of 8 checks passed
@steipete steipete changed the title fix: resolve Web API device names fix: resolve device names and preserve opaque IDs Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants