Skip to content

feat(android): transactional subtitles and PGS support (PR 108 slice E) - #116

Merged
RXWatcher merged 14 commits into
mainfrom
split/108-e-subtitles
Jul 27, 2026
Merged

feat(android): transactional subtitles and PGS support (PR 108 slice E)#116
RXWatcher merged 14 commits into
mainfrom
split/108-e-subtitles

Conversation

@RXWatcher

Copy link
Copy Markdown
Collaborator

Stack

Scope

  • Typed transactional subtitle identity and staged publication on phone and TV.
  • Stable Media3 mount contracts, client-side PGS extraction, and libass lifecycle/timeline fixes.
  • Per-item subtitle sync, web-parity appearance, diagnostics gating, and letterbox/title-safe cue placement.
  • Auth-scoped durable selection writes with process-level replacement ordering.

The Dolby Vision/color-range paths preserve slice-D playback metadata and fallback behavior across the new adapter boundary; they do not add slice-G catalog behavior.

Review corrections

Independent review drove three test-first correction rounds:

  • Bind final selection writes to the playback-captured server/profile/auth generation and reject identity switches.
  • Propagate Room acceptance through retry/flush handling and reserve TV retirement ordering before asynchronous settlement.
  • Bound malformed PGS display sets and retain ordering state until abandoned in-flight writes fully exit.

Final independent verdict: Ready Yes; no remaining Critical, Important, or Minor findings.

Verification

  • ./scripts/check-build-supply-chain.sh
  • ./gradlew --no-daemon testDebugUnitTest --max-workers=2 --rerun-tasks — 127/127 tasks executed, pass
  • ./gradlew --no-daemon :androidApp:assembleRelease :androidTvApp:assembleRelease --max-workers=2 — 207 tasks, pass
  • Focused subtitle/PGS/Room/concurrency suites, including deterministic retired-adapter and in-flight-abandon races
  • git diff --check

One earlier full run exposed a known staged-replan scheduling flake; the exact test passed five forced isolated reruns and the subsequent fresh full suite passed.

Traceability

The commit-to-PR-108 mapping, review corrections, and verification record are in docs/superpowers/plans/2026-07-27-pr108-slice-e-transactional-subtitles.md.

RXWatcher added 11 commits July 27, 2026 11:46
Forward-port shared subtitle identity and latest-intent transition contracts from PR 108 archival squash 65c4b31 while retaining the newer PlaybackSourceDescriptorV3 contract from slice D.
Forward-port PR 108 staged publication and settlement from 65c4b31 with fixes d724114, 8403b8b, c8481f1, and ac14e51. Preserve slice-D external-start epoch/cancellation cleanup and stale-failure suppression.
Forward-port the PR 108 mount resolver from 65c4b31 with catalog materialization and SDH identity corrections from 4add279 and 274ffc6. Keep a temporary legacy backend overload until platform adapters migrate in the next checkpoint.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@RXWatcher, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b08103ed-8454-4ba2-9544-0bd464305b48

📥 Commits

Reviewing files that changed from the base of the PR and between f41bda9 and 9ceb317.

⛔ Files ignored due to path filters (1)
  • android-shared/src/androidUnitTest/resources/pgs/display-set-0.bin is excluded by !**/*.bin
📒 Files selected for processing (100)
  • .superpowers/sdd/2026-07-27-pr108-slice-e-transactional-subtitles/final-review-fix-report.md
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/data/repository/RoomUserItemStateRepository.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/DolbyVisionColorInfoExtractorsFactory.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/DolbyVisionProfile7Transformer.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/LetterboxDetection.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackCapabilityDetector.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackColorRangeFallback.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackSessionLifecycle.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackSessionManager.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackTrackSelectionWriteCoordinator.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackV3Session.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/SiloPlaybackService.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/SiloPlayerFactory.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/SubtitleDiagnostics.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/SubtitleManager.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/SubtitleMountResolver.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/VideoPlayerMediaMounter.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/VideoPlayerMediaSpec.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/backend/Media3VideoPlaybackBackend.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/backend/VideoPlaybackBackend.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/subtitle/PgsSupExtractor.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/video/VideoTrackSelectionCoordinator.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/settings/AndroidPlayerSettingsStore.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/settings/PlayerSettingsStore.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/data/repository/RoomUserItemStateRepositoryTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/DolbyVisionColorInfoExtractorsFactoryTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/LetterboxInsetTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/LibassPlayerReleaseContractTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackColorRangeFallbackTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackPublicationSettlementIntegrationTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackSessionManagerSeekReanchorTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackSessionManagerStagedReplanTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackTrackSelectionWriteCoordinatorTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/SubDiagGateTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/SubtitleManagerAppearanceTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/SubtitleManagerTrackSelectionTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/SubtitleMountResolverTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/TitleSafeInsetTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/subtitle/Media3PgsParserProbeTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/subtitle/Media3PgsSupportProbeTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/subtitle/PgsSupExtractorTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/video/VideoTrackSelectionCoordinatorTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/settings/ServerDrivenConfigRefresherTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/settings/SubtitleSyncOverridesTest.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/MobileFreshSubtitleRestore.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/MobilePlayerLoadOwner.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/MobileSubtitleAutoSelection.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/MobileSubtitleTransactionAdapter.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/MobileVideoPlaybackStarter.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/PlayerScreen.kt
  • androidApp/src/androidMain/kotlin/org/siloserver/silo/android/ui/screens/player/PlayerViewModel.kt
  • androidApp/src/androidUnitTest/kotlin/org/siloserver/silo/android/ui/screens/player/MobileFreshSubtitleRestoreTest.kt
  • androidApp/src/androidUnitTest/kotlin/org/siloserver/silo/android/ui/screens/player/MobilePlayerLoadOwnerTest.kt
  • androidApp/src/androidUnitTest/kotlin/org/siloserver/silo/android/ui/screens/player/MobileSubtitleAutoSelectionTest.kt
  • androidApp/src/androidUnitTest/kotlin/org/siloserver/silo/android/ui/screens/player/MobileSubtitleTransactionAdapterTest.kt
  • androidApp/src/androidUnitTest/kotlin/org/siloserver/silo/android/ui/screens/player/PlayerViewModelLoadOwnershipIntegrationTest.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerHud.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerLoadOwner.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerSubtitlePolicy.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerViewModel.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleHudState.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleIdentity.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleRemountReselection.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleTransactionAdapter.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/data/preferences/LegacyTvPrefsMigrationTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/SubtitleRemountReselectionTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/SubtitleTransactionIntegrationTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TestPlaybackWriteScope.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlaybackFreshLoadOwnershipTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerSubtitleIntegrationPolicyTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleFinalRollbackTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleHudStateTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleMountDeadlineTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleMountPriorityTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleRefreshOwnershipTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleSettlementOwnershipTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleTransactionAdapterTest.kt
  • docs/superpowers/plans/2026-07-27-pr108-hosted-ci-recovery.md
  • docs/superpowers/plans/2026-07-27-pr108-slice-e-transactional-subtitles.md
  • libass-bridge/src/main/java/org/siloserver/silo/libass/LibassBridge.java
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/catalog/CatalogModels.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/playback/PlaybackModels.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/playback/PlaybackProtocolV3.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/playback/PlaybackSubtitleChoices.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/playback/SubtitleTrackMerge.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/playback/SubtitleTransition.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/settings/PlaybackSettingsKeys.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/settings/SubtitleAppearance.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/playback/SubtitleCodecFamily.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/playback/SubtitleLanguage.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/playback/TrackSelectionFingerprint.kt
  • shared/src/commonMain/kotlin/org/siloserver/silo/repository/port/UserItemStatePort.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/catalog/CatalogTrackSerializationTest.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/playback/PlaybackModelsV2SerializationTest.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/playback/PlaybackProtocolV3Test.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/playback/SubtitleTrackMergeTest.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/playback/SubtitleTransitionTest.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/settings/SubtitleAppearanceTest.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/playback/TrackSelectionFingerprintTest.kt
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch split/108-e-subtitles

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Base automatically changed from split/108-d-player-foundation to main July 27, 2026 16:39
@RXWatcher
RXWatcher marked this pull request as ready for review July 27, 2026 16:40
@RXWatcher
RXWatcher merged commit 14dab30 into main Jul 27, 2026
2 checks passed
@RXWatcher
RXWatcher deleted the split/108-e-subtitles branch July 27, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant