Skip to content

Feature-complete roadmap: user-story coverage and gapsΒ #197

Description

@JarbasAl

πŸ€– Auto-generated by Claude Fable 5 (claude-fable-5) via Claude Code β€” NOT human-reviewed. Verify before acting. Claims marked βœ“ were re-verified against source by the model; the rest come from a model-written inventory of the feat/media-backend-v2-port branch (42e7e21).

Feature-complete roadmap

Tracking issue for taking ovos-media from "MediaBackend v2 train ready" to feature complete: every user story implemented, tested (unit + e2e), documented, live-validated, and audited. This body is the living state β€” it gets edited in place as items land.

Blocked on the release train

Everything in the "fix" sections below lands after OPM #442 merges and #194 follows (the train's commit sequence). Until then only harness, spec, docs, and audit work moves.

Coverage gaps (from the full user-story inventory)

Spec conformance (OCP-1):

  • βœ“ Skill can_seek declaration (Β§4.3.1) unimplemented: catalog/catalog.py never reads can_seek from ovos.common_play.announce, and SkillPlayerAdapter.seek() unconditionally warns-and-drops. Skill playback can never become seekable. Implement announce-side ingestion + conditional seek delegation + MPRIS CanSeek passthrough.
  • βœ“ Relative seek: RESOLVED as a spec amendment. An ecosystem sweep found no emitter uses the spec's position field β€” the deployed wire is seekValue (absolute ms, GUI seekbar) and seconds (signed relative, OCPInterface.seek_forward/seek_backward β€” the skill-facing API, a pre-spec surface with mandatory backcompat). Player-side resolution of seconds is atomic against live position, which is stronger against concurrent seekers than requester-side resolution from a stale state read; OCP-1 Β§4.2.2 is being rewritten to document both real shapes with the corrected rationale. ovos-pydantic-models' seek model (position) needs aligning to the wire.
  • Β§5 per-session isolation: RESOLVED β€” OCP-1 now states the registry MAY be satisfied by deployment topology (per-satellite embedded daemons; hub serves its local session). Originally: implementation is a binary default/non-default gate on a single player, relying on the one-daemon-per-satellite topology (documented in service.py). Spec text should state explicitly that the per-session registry MAY be satisfied by per-satellite daemon instances, or the gap is real.
  • ovos.common_play.register_keyword: RESOLVED β€” Β§4.1 carve-out for non-mutating advisory emissions (control requests in, registration hints) landed; state authorship stays the player's alone. Originally: Β§4.1's reservation wording doesn't carve out advisory non-mutating messages. Spec clarification.

Wrong-session behavior:

  • βœ“ Wire state reports (media.state/track.state from media_backends/base.py) are bare Message(topic, data) with no context.session β€” OCP-1 Β§4/Β§4.4 require the originating session so hub consumers can demultiplex (peer spec-audit finding, verified file:line). Fix together with the dialog-session item below: stash the requester's session at play time, derive all state reports and notifications from it.
  • βœ“ All spoken dialogs (track.failed, queue.finished, no.playback.backend, …) land on the default session even for satellite-triggered playback β€” acknowledged in skill.py's own docstring. Fix: stash the triggering message's session at play time and carry it through END_OF_MEDIA / INVALID_MEDIA / retry-timer paths.

Coverage holes:

  • PlaybackType.SKILL full-cycle e2e added on the v2 branch (5 cells: delegation verbs + wire states).
  • βœ“ Config live-reload: hot knobs (autoplay, validate_source with explicit-override precedence honored end-to-end incl. the voice skill, preferred_*_services) read live configuration; cold knobs pinned by an armed test (feat: hot-reload cheap media config knobsΒ #207, converged).
  • Shuffle/repeat/relative-seek/like-unlike e2e cells added on the v2 branch (+11 mutation-proofed, incl. a found-and-fixed unclamped negative-seek defect); MPRIS headless graceful-degrade verified live; MPRIS on by default with a Playlists stub and lifecycle logging, validated on a real bus (feat: MPRIS on by default with a Playlists stub and lifecycle loggingΒ #210, converged).
  • ovoscope v2 harness built and converged (ovoscope#168: MediaBackendHarness reporter-capture layer + OCPPlayerHarness v2 repair + v2 mock; three adversarial rounds + an executed two-venv gate). Held draft until the v2 train releases, then floors bump and it merges β€” un-skipping media-plugin e2e cells fleet-wide.
  • Remote backends (chromecast, mass, spotify, mpris) have review-verified v2 ports but no real-device live playback validation; remote verb confirmation (silently ignored pause on a dead device) needs a timeout/notify design.

Product polish:

  • Voice intents for like/unlike, queue and track repeat (spec'd repeat.set mode), relative seek, shuffle state, and a bounded what's-next preview (spec'd Β§4.4.1 next_track/next_track_hint) β€” feat: voice intents for like, repeat, seek, shuffle state and queue peekΒ #209, converged.
  • OCP-1 Β§4.4.3 named-collection read query serving the derived history playlists β€” feat: named collection read query per OCP-1 Β§4.4.3Β #208, converged.
  • Play counts only accumulate for already-liked tracks; ranking can never surface a heavily-played unliked track. Decide global play-count vs documented limitation.
  • Album/artist metadata intents mostly answer "no info" (MediaEntry has no album field). Decide enrich vs trim intents.
  • Docs: technical-manual one-story page + plugin migration guide (queued with the docs campaign, keyed to the v2 wire-changes table).

Validation plan

  • Several independent expert audits (concurrency on the dispatcher/lock model, UX on voice flows, adversarial on the merged train) and user-persona runs (fresh-install quickstart verbatim, satellite user, desktop MPRIS user), each producing findings triaged into this list.
  • Final gate: voice-driven live round trip on released packages only, incl. restart/network-kill/bad-stream recovery on all three namespaces.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions