Repository navigation
Description
Decision / why this has teeth
Add a bounded, opt-in live-playback troubleshooting contract, extending existing probes and semantic Accessibility—not a general-purpose REST server or an agent-only replacement for the UI.
Recent native Mac playback investigation repeatedly required full Accessibility snapshots, transient menu discovery, and manual chrome revelation just to inspect quality, copy-versus-encode decisions, consent, seek progress, and cleanup. Auto-hiding chrome and stale AX references increase retries. Computer Use remains appropriate for visual inspection, but should not be the sole way to establish these machine-readable facts.
This is a focused follow-up under #182, complementary to #262 (isolated Mac browse fixture), #264 (visionOS probe-first workflow), and #226 (human-facing accessibility). It does not reopen or duplicate their baseline runner work. Related real-playback motivator: #288.
Existing foundation (reuse, do not replace)
scripts/agent-macos-run.sh/agent-macos-ax-driver.swift: bounded semantic Home-to-detail fixture flow, isolated identity, exact-PID cleanup, JSON artifacts.scripts/perf-macos-ax-driver.swift: additional semantic browse/search/artwork automation; performance evidence has its own contract and must remain isolated.Labstream/Shared/Debug/Debug{Plex,Jellyfin,Emby}PlaybackProbe.swift: DEBUG-only, explicitly launched, authenticated in-process probes using production playback paths, seek/progress checks, and cleanup.DebugPlaybackFrameCapture: decoded frame evidence; transport success alone does not establish correct picture.scripts/diagnostics-summarize.py: bounded, privacy-conscious triage/delta artifacts; retain this rather than dumping raw logs into agent context.CustomPlayerChrome.swift: native accessible controls exist; current playback changes also add consent identifiers. A complete stable player selector/state contract is not established merely by those two identifiers.
Remaining gap
The Mac fixture runner exposes only passive Home and Home-to-detail scenarios. Existing live playback probes exercise predetermined launch-time sequences, not a unified, versioned contract for observing an already-running playback session and exercising quality/track/consent transitions. They do not replace confirmation that the visible UI is attached to the controller under test.
We need to distinguish requested quality, negotiated video copy/encode/unknown, audio conversion, active rendered format, consent-pending state, actual time progression, and terminal cleanup—without inferring them from a generic “transcoding” label or reconstructing them from repeated screenshots.
Bounded proposal
- Define the evidence contract first. Versioned allowlisted JSON snapshot/events: build identity, backend enum, opaque session/generation, controller-to-visible-window attachment, playback phase, position/buffer buckets, requested quality, video/audio decisions with provenance, HDR/rendered format where available, consent state, bounded error category, cleanup status. Unknown facts remain explicitly unknown. No raw server responses.
- Expand named DEBUG probe scenarios, using the same production launcher/controller operations: Original start, seek, track change, capped/Maximum selection, pending consent → decline, and separately authorized consent → approve. Require explicit live-session admission; fixture mode is default. Emit finite pass/fail/blocked artifacts with deadlines and cleanup in cancellation/error paths.
- Complete semantic player Accessibility for controls and selected/disabled/pending states. Keep labels useful to VoiceOver and identifiers independent of localization/private media names. Add a semantic way to reveal/reach player controls without coordinate clicking; verify behavior when chrome hides, playback buffers, and a menu/consent overlay is active. This portion may ship as ordinary accessibility improvements coordinated with Accessibility follow-ups from Apple UI idiom sweep #226.
- Evaluate an interactive DEBUG adapter only if named scenarios + AX leave a measured gap. Prefer a local CLI adapter around the same typed contract; choose transport in a small ADR. Do not pre-commit to HTTP, MCP, App Intents, or a shipping control endpoint. Read-only snapshot/export is the first operation; mutation is separately admitted and scoped to the exact playback generation.
Security / release boundaries
- No default listener, LAN exposure, arbitrary URL fetching, shell execution, credential export, or auth bypass. A custom URL scheme is not caller authentication; loopback alone is not authorization.
- DEBUG control code and launch hooks must be absent/inert in Release and PerformanceAudit, verified by existing artifact-contract checks. A future production diagnostics feature requires its own explicit design/review, not accidental promotion of debug hooks.
- Default to isolated app identity and synthetic fixtures. Reusing a signed-in production-identity development build requires explicit user opt-in; never reset its container or Keychain as part of this workflow.
- If IPC is justified: authenticated local peer/capability, short lifetime, restrictive filesystem permissions where applicable, bounded payload/rate limits, exact process/build/session binding, and immediate revocation on stop, logout, backend change, or app exit. Reject stale generations and replayed mutation requests.
- Never auto-approve a video encode because “automation mode” is active. Preserve the real UI approval boundary; an approval scenario must be separately authorized and cannot grant durable future approval.
- No credentials, real hosts/IPs, media titles/paths, raw item/client IDs, or token-bearing URLs in default JSON or public artifacts. Frame capture is separately opt-in and private by default. Diagnostic enablement must be explicit, bounded, and restored.
- Report server-job cleanup as confirmed only with appropriate evidence; a client stop request alone is not proof. Never bypass OS Accessibility trust or locked-session restrictions.
Alternatives / platform guidance
- AX/XCUITest only: lowest additional attack surface and essential for visible UI proof; still constrained by ephemeral chrome and platform automation limits.
- Extend existing launch probes only: preferred initial implementation for deterministic playback facts; does not prove visible menu interaction or hardware presentation.
- App Intents: potentially appropriate for future user-facing actions, not automatically a privileged diagnostics channel. Apple supports explicit authentication policies; any adoption needs a separate supported-platform and authorization review.
- Always-on app API/MCP server: not justified by current evidence; creates unnecessary security, lifecycle, sandbox, and release obligations. A future external MCP wrapper could call the bounded local tooling rather than embedding a server in the app.
Apple references: SwiftUI accessibility identifiers, UI automation with Xcode, App Intent authentication policy.
Acceptance criteria
- Document the contract and transport/no-transport decision, with precise distinction between fixture, live-controller, visible-UI, and hardware evidence.
- One command runs a bounded fixture playback transition scenario and emits schema-validated pass/fail/blocked JSON without screenshots as the state oracle.
- Opt-in live scenarios cover Plex/Jellyfin/Emby Original/copy, seek, quality change, consent decline, separately authorized approval, and cleanup where supported; unsupported cases report blocked, not pass.
- Semantic Mac regression covers hidden chrome, buffering, quality/track selection, and pending consent without coordinates or localized text as the sole selector. Preserve VoiceOver labels, focus, and actions.
- Negative tests reject stale session/generation commands, unauthorized mutation, missing auth, cancellation/timeouts, backend changes, and secret-bearing artifact fields.
- Release/PerformanceAudit checks demonstrate no debug command surface; isolated runner cleanup cannot affect another app identity or process.
- Compare the same troubleshooting scenario before/after: AX/screenshot calls, elapsed time, retries, artifact bytes, and unproven assertions. Claim savings only from measured runs.
- Keep a small actual visual/frame check and physical-device gates for black frames, tint, HDR/audio output, and platform interactions; API success cannot close these.
Investigation-only issue: no implementation, app launch, simulator interaction, or live playback mutation performed for this assessment.
Activity
jlipworth commentedon Sep 6, 2026
Work is now prioritized ahead of release readiness; deeper Emby investigation is deferred to #291. First foundation is implemented locally: scripts/playback-evidence.py provides a strict versioned, size/sample-bounded offline progress contract and synthetic self-check. It rejects stale generations, gaps, seek-like jumps, private/unknown fields, and three-seconds-then-frozen false positives, including paused starvation. Negotiation, visible attachment, hardware decode and server cleanup remain explicitly unknown. Seven focused tests and the full 311-test Python tooling suite pass under the repository Python runtime; hygiene, strict docs, links and Mermaid checks pass. No app/network control surface was added. This is NOT yet the app fixture/live acceptance: existing DEBUG probes still need to emit/use the contract, followed by semantic player controls and measured before/after troubleshooting. The implementation plan is docs/plans/2026-09-06-agent-playback-evidence.md. Commits remain local, not pushed; issue remains open.
jlipworth commentedon Sep 6, 2026
Implementation and acceptance are underway locally: typed bounded progress/report contracts, named opt-in live scenarios, semantic Mac player controls, isolated controller/visible fixtures, and offline validation are implemented. Final semantic hidden-chrome, buffering, and consent-decline checks passed without coordinates or screenshots. Core suite: 1,695 tests; focused hosted Mac suite: 14 tests; one-command controller fixture: 3 tests. Native build/smoke and Release/PerformanceAudit exclusion checks passed before two DEBUG exporter corrections. Live testing caught and fixed a backend-label mismatch and unified-log string truncation; ordered bounded fragments now reconstruct and validate successfully from an exact-process log pull. A live Plex seek report correctly records video copy/audio conversion, failed progress, detached presentation, and client cleanup requested—not a playback or server-cleanup pass. Jellyfin Maximum reached the transition but encode provenance remained unknown, so it reported blocked. More live acceptance and final closeout remain; #290 stays open and commits have not been published. Deeper playback failures remain separate from the troubleshooting contract and are not being declared resolved.
jlipworth commentedon Sep 6, 2026
Local implementation is now committed as 51a91a5 (not pushed). Scoped verification is complete: final clean Debug builds and passive install/launch/log/visual smoke passed on mobile, TV and visionOS; signed Mac live probes and the final four-test hosted controller command passed their contract checks. Final Release and PerformanceAudit builds passed, with no DEBUG playback markers and a passing audit binary contract. The 315-test Python tooling suite, strict docs, links, Mermaid, and hygiene passed. All simulators and live probe processes are stopped. Live reports correctly preserve failed/blocked outcomes: Plex seek failed progress despite server-proven video copy; Jellyfin capped-to-Maximum progressed but encoding provenance was unknown; Emby approval retry had no pending consent, audio failed playback, and subtitles had no supported alternate. These are validated diagnostic outcomes, not claims that the underlying playback issues or hardware release gates are resolved. Backend identity, truncated unified-log export, and probe ordering behind unrelated download hydration were corrected during acceptance. No new sign-in is currently required. Publication/issue closure remains pending; the requested Astra codebase sweep has not started yet.
jlipworth commentedon Sep 6, 2026
Published the validated troubleshooting implementation on codex/client-first-playback, including commit 51a91a5. Scoped acceptance and limitations are recorded in the preceding verification comment and implementation plan. Closing the agent-troubleshooting contract, not the separate playback investigations or hardware/release gates. This branch is published, not merged into main.
jlipworth commentedon Sep 6, 2026
Fast-forward integrated the published branch into local main: 595d063..518e286 (four commits, including the client-first playback foundation used by #290). No rebase changes or conflicts; the exact previously validated source tree is retained. Eleven focused Python evidence/runner tests passed again from main and git diff --check is clean. Prior final native builds/smokes and Release/PerformanceAudit exclusion evidence remain applicable to this unchanged tip; full hosted baseline remains 686 passed / 1 known failure tracked in #299. The guide is promoted and the completed plan archived. Newly identified runner cleanup defect is tracked separately in #297, not claimed fixed. Publication truth: merged locally, not yet pushed to origin/main; the implementation remains available on the published feature branch. No other issue's acceptance gates are promoted.
Client-first playback and bounded agent troubleshooting (#290) (#300)
jlipworth commentedon Sep 6, 2026
Now reachable on origin/main via protected-branch PR #300, squash commit 6189816. All five CI checks passed before auto-merge. The resulting tree exactly matches the validated source, including the user-requested 1.6.2 build-1 bump for all four apps and PMSKit. All four generated bundles were verified; native smoke, PMSKit and hygiene checks passed. No 1.6.2 archive/upload or hardware acceptance is claimed. The merged feature branch is being retired; documentation-alignment cleanup is a separate stale-worktree decision.