Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
415 commits
Select commit Hold shift + click to select a range
83e23da
fix(test): share Room schemas across build variants
Quick104 Jul 30, 2026
ad3524b
feat(settings): adopt contract language catalogs (#154)
Quick104 Jul 30, 2026
349b347
fix(tv): keep the For You list selection, scroll, and a legible top b…
RXWatcher Jul 30, 2026
1ddbb7f
Merge Silo-Server/silo-android main (168 commits)
cursoragent Jul 31, 2026
3b2044c
build(android): target API 36 for Play updates (#155)
Quick104 Jul 31, 2026
519e135
fix(test): align season display order with specials-first sort
cursoragent Jul 31, 2026
4b06343
test(shared): cover onboarding and invitation helpers for Kover gate
cursoragent Jul 31, 2026
1d0ed3a
docs(tv): design Fire TV playback selection fixes
RXWatcher Jul 31, 2026
115a42c
docs(tv): plan Fire TV playback selection fixes
RXWatcher Aug 1, 2026
cd09d15
feat(tv): define semantic episode selection handoff
RXWatcher Aug 1, 2026
5b6805d
fix(tv): preserve episode source preference order
RXWatcher Aug 1, 2026
6e697b1
feat(tv): resolve episode selection during playback start
RXWatcher Aug 1, 2026
80fba3c
fix(tv): drop stale handoff subtitle indexes
RXWatcher Aug 1, 2026
e1d65bb
fix(tv): make detail selector focus legible
RXWatcher Aug 1, 2026
62e020a
fix(tv): scroll HUD pickers with focus
RXWatcher Aug 1, 2026
7f8dd7b
test(tv): scope HUD picker focus wiring regression
RXWatcher Aug 1, 2026
5024d64
fix(tv): preserve episode source and subtitle intent
RXWatcher Aug 1, 2026
f835d9c
fix(tv): preserve portable downloaded subtitle intent
RXWatcher Aug 1, 2026
35d2fce
fix(tv): retain selection across next-up detail refresh
RXWatcher Aug 1, 2026
cb97472
fix(tv): fence next-up selection races
RXWatcher Aug 1, 2026
a10df3d
chore(docs): fix Fire TV spec whitespace
RXWatcher Aug 1, 2026
3007eeb
fix(tv): address selection continuity review
RXWatcher Aug 1, 2026
a5a755f
fix(tv): secure next-episode handoff ownership
RXWatcher Aug 1, 2026
3abf58d
fix(tv): address playback selection review
RXWatcher Aug 1, 2026
c3aec98
fix(overlays): match web's card-badge rendering rules
Quick104 Aug 1, 2026
519dc78
Merge pull request #157 from RXWatcher/fix/firetv-playback-selection-ux
RXWatcher Aug 2, 2026
aea2405
fix(overlays): normalize show status values
RXWatcher Aug 2, 2026
981c7a4
Merge pull request #158 from Silo-Server/fix/card-overlays-contract
RXWatcher Aug 2, 2026
93f404b
docs(tv): design shared auth IME relocation
RXWatcher Aug 2, 2026
ba9d198
docs(tv): plan shared auth IME relocation
RXWatcher Aug 2, 2026
ebcbad9
fix(tv): add IME-aware auth field relocation
RXWatcher Aug 2, 2026
2f15b3e
fix(tv): keep auth fields clear of stock IME
RXWatcher Aug 2, 2026
a422b0f
fix(tv): preserve phone setup card body
RXWatcher Aug 2, 2026
493467f
fix(tv): keep pairing code inside card
RXWatcher Aug 2, 2026
2189a90
fix(tv): adapt pairing tiles to code length
RXWatcher Aug 2, 2026
6ccd8f8
docs(tv): design accessible player transport
RXWatcher Aug 2, 2026
550c10d
docs(tv): plan accessible player transport
RXWatcher Aug 2, 2026
2965e7f
fix(tv): focus player transport on dpad down
RXWatcher Aug 2, 2026
74ac277
fix(tv): enlarge player transport controls
RXWatcher Aug 2, 2026
e456b47
docs(tv): design subtitle picker dismissal and sizing
RXWatcher Aug 2, 2026
e0ec254
docs(tv): plan subtitle picker dismissal and sizing
RXWatcher Aug 2, 2026
d270681
fix(tv): dismiss player chrome after subtitle selection
RXWatcher Aug 2, 2026
563f5b2
fix(tv): use readable fixed subtitle sizes
RXWatcher Aug 2, 2026
be1a856
test(tv): cover subtitle picker and sizing seams
RXWatcher Aug 2, 2026
d060fe9
chore: remove subtitle review artifact
RXWatcher Aug 2, 2026
2e51f07
docs(tv): design mounted SRT fast switching
RXWatcher Aug 2, 2026
d17475d
docs(tv): plan mounted SRT fast switching
RXWatcher Aug 2, 2026
7a6078b
fix(tv): switch mounted SRT subtitles without rebuffering
RXWatcher Aug 2, 2026
326bbdf
test(tv): model mounted sidecar resolver state
RXWatcher Aug 2, 2026
2290caf
test(tv): model integration sidecar mounts
RXWatcher Aug 2, 2026
465257c
docs(playback): plan instant external SRT switching
RXWatcher Aug 2, 2026
a0624a5
docs(playback): correct shared test task names
RXWatcher Aug 2, 2026
9fa36e9
feat(playback): decode external text sidecar sets
RXWatcher Aug 2, 2026
b8e86b0
feat(playback): negotiate external text sidecars
RXWatcher Aug 2, 2026
af5e7f6
feat(player): mount negotiated external text sidecars
RXWatcher Aug 2, 2026
3041b94
fix(player): replan away from subtitle burn-in
RXWatcher Aug 2, 2026
a6f43e8
fix(tv): address Shield review feedback
RXWatcher Aug 2, 2026
aff2f77
Merge pull request #159 from RXWatcher/feature/shield-playback-and-in…
RXWatcher Aug 2, 2026
2b8a1f9
fix(ci): publish APK-only GitHub releases (#160)
RXWatcher Aug 3, 2026
46f60ee
fix(tv): address Fire TV rc.1+4 feedback (#161)
RXWatcher Aug 3, 2026
4f31dee
docs(tv): design late For You focus recovery
RXWatcher Aug 3, 2026
4e7da2e
docs(tv): plan late For You focus recovery
RXWatcher Aug 3, 2026
1d15883
fix(tv): recover late For You focus relocation
RXWatcher Aug 3, 2026
8a4bdb9
docs(tv): complete For You relocation plan
RXWatcher Aug 3, 2026
341a553
docs(tv): design Shield focus restoration
RXWatcher Aug 3, 2026
74db161
docs(tv): plan Shield focus restoration
RXWatcher Aug 3, 2026
f0c6240
fix(tv): resolve For You return targets
RXWatcher Aug 3, 2026
3ff277c
fix(tv): restore For You focus after detail
RXWatcher Aug 3, 2026
886ac12
fix(tv): stop disposed focus retries
RXWatcher Aug 3, 2026
d734820
fix(tv): route Calendar focus back to menu
RXWatcher Aug 3, 2026
50b8d84
fix(tv): clear Calendar message focus zone
RXWatcher Aug 3, 2026
dda9ca6
fix(tv): focus Diagnostics crash-report controls
RXWatcher Aug 3, 2026
362e7a8
fix(tv): stop Diagnostics focus retry after disposal
RXWatcher Aug 3, 2026
4d30fac
fix(tv): finalize Shield focus restoration
RXWatcher Aug 3, 2026
54723f1
docs(tv): design PR 164 review remediation
RXWatcher Aug 4, 2026
f602745
docs(tv): plan PR 164 review remediation
RXWatcher Aug 4, 2026
1cf10b8
fix(tv): preserve held Calendar shelf movement
RXWatcher Aug 4, 2026
3ecb2da
fix(tv): retry detached Diagnostics focus
RXWatcher Aug 4, 2026
3bca4f1
fix(tv): retain Home detail fallback through retry
RXWatcher Aug 4, 2026
cd6cd41
fix(tv): scope Home detail return fallback
RXWatcher Aug 4, 2026
901a92c
fix(tv): reset stale For You detail return
RXWatcher Aug 4, 2026
f7c2485
docs(android): design whole-app focus hardening
RXWatcher Aug 4, 2026
6d2800a
docs(android): plan focus foundations series
RXWatcher Aug 4, 2026
bff350f
feat(tv): add observed focus retry policy
RXWatcher Aug 4, 2026
9c59975
fix(tv): preserve focus request cancellation
RXWatcher Aug 4, 2026
2bf8238
fix(tv): bound dialog initial focus retries
RXWatcher Aug 4, 2026
e239650
fix(tv): remove disabled controls from focus
RXWatcher Aug 4, 2026
50c3f93
fix(tv): preserve disabled control visuals
RXWatcher Aug 4, 2026
d058314
fix(tv): key Cascade rows by library
RXWatcher Aug 4, 2026
8afa0ef
fix(tv): derive selectors from actionable options
RXWatcher Aug 4, 2026
b53b728
fix(tv): disable noninteractive selector triggers
RXWatcher Aug 4, 2026
ddf6583
fix(tv): clear stale selector expansion
RXWatcher Aug 4, 2026
ca35679
test(tv): cover Home detail retry branches
RXWatcher Aug 4, 2026
fc15f3a
fix(tv): correct focus-hardening regressions from review
RXWatcher Aug 4, 2026
bd331fc
fix(tv): close focus hardening review gaps
RXWatcher Aug 4, 2026
ea41897
fix(phone): keep TV setup dialog above bottom nav (#166)
Quick104 Aug 4, 2026
55000b6
chore(build): move compose ui-test artifacts into the version catalog
RXWatcher Aug 4, 2026
1cdee8c
refactor(tv): drop the unreachable Disposed focus state
RXWatcher Aug 4, 2026
8a932a4
fix(recommendations): identify keyless sections by singleton kind only
RXWatcher Aug 4, 2026
6275748
fix(tv): keep disabled overlay tiles out of the focus graph
RXWatcher Aug 4, 2026
93f2906
fix(tv): latch async content focus on acquisition, not on the attempt
RXWatcher Aug 4, 2026
fb5fe09
fix(phone): stop swallowing the IME Next action on every form
RXWatcher Aug 4, 2026
3ddd469
fix(tv): dismiss the stock keyboard on every surface that raises it
RXWatcher Aug 4, 2026
71ddc09
fix(tv): stop profile refresh dragging focus back to the first tile
RXWatcher Aug 4, 2026
ac424b7
fix(tv): keep pair-device focus on whatever is actually actionable
RXWatcher Aug 4, 2026
495a239
fix(tv): freeze held Up while Calendar is handing focus to its controls
RXWatcher Aug 4, 2026
a5fcc41
fix(tv): make the Browse filter sheet an actual modal focus owner
RXWatcher Aug 4, 2026
e322dd9
fix(tv): base pair-device focus on the resolved lookup, not on canSubmit
RXWatcher Aug 4, 2026
0364f7e
fix(tv): give audiobook panels focus ownership over a suppressed player
RXWatcher Aug 4, 2026
b4a5ff4
fix: require a resolved lookup before a device login can be approved
RXWatcher Aug 4, 2026
38b21f0
chore(phone): drop the unused SiloPasswordField
RXWatcher Aug 4, 2026
a7d1b74
Merge pull request #167 from RXWatcher/codex/app-focus-hardening
RXWatcher Aug 4, 2026
bbec8f0
fix(tv,shared): close a covered panel, and retire lookups a decision …
RXWatcher Aug 4, 2026
3ca438a
test: unflake the catalog letter-index suite, and unmask what it was …
RXWatcher Aug 4, 2026
fc6bd44
feat(tv): add the stable return-target contract Series D migrates onto
RXWatcher Aug 4, 2026
d31ffc5
fix(tv): restore Skyline focus to the card the viewer launched, not t…
RXWatcher Aug 4, 2026
e573b8d
fix(tv): restore library-grid focus by identity, through unloaded pages
RXWatcher Aug 4, 2026
82a5df8
refactor(tv): extract the flat-surface return restoration
RXWatcher Aug 4, 2026
5a609da
feat(tv): let the shared catalog grid restore focus to the launch card
RXWatcher Aug 4, 2026
0ce0c94
fix(shared): drop personal-list pages superseded by a refresh
RXWatcher Aug 4, 2026
99d98f3
feat(tv): sequence return restoration behind a replacing refresh
RXWatcher Aug 4, 2026
0841725
feat(tv): return focus to the launched row on My Requests
RXWatcher Aug 4, 2026
edaff4e
fix(tv,shared): close the last restoration and paging races
RXWatcher Aug 4, 2026
0c28b03
feat(tv): return focus to the launched card on Calendar
RXWatcher Aug 4, 2026
b610fa9
feat(tv): project Search returns across its two identity domains
RXWatcher Aug 4, 2026
cbdb0c7
fix(tv): stop return restoration reporting focus it never requested
RXWatcher Aug 4, 2026
e6417e0
feat(tv): return focus to the launched result on Search
RXWatcher Aug 4, 2026
07df233
feat(tv): search by voice from the remote
RXWatcher Aug 4, 2026
0abb084
fix(tv): put the search mic left of the field
RXWatcher Aug 4, 2026
0c7575e
fix(tv,shared): release loading flags by owner, abandon on a live rep…
RXWatcher Aug 4, 2026
243be7a
fix(tv): close a refresh loop, reach the search mic, correct a stale …
RXWatcher Aug 4, 2026
9c9c869
fix(tv): launch a specific recogniser instead of a chooser
RXWatcher Aug 4, 2026
b2e3c6e
fix(tv): reach the search mic from the field, not through the chips
RXWatcher Aug 4, 2026
9f1d5e1
fix(tv): keep the search keyboard down until it is asked for
RXWatcher Aug 5, 2026
ec0c3ca
fix(tv,shared): make Pending reachable on Home, and close review find…
RXWatcher Aug 5, 2026
d10fa17
fix(player): stop a bad caption killing playback, and stop sessions o…
RXWatcher Aug 5, 2026
fcc6ed1
fix(player): reject hostile subtitle bitmaps, and stop misreading tra…
RXWatcher Aug 5, 2026
597a5e7
fix(player): close four holes the previous batch opened
RXWatcher Aug 5, 2026
a81e14c
fix(player): take the frame baseline at mount, and own every session …
RXWatcher Aug 5, 2026
6bd3bd5
revert(player): drop the frame-baseline attempt, retain ownership at …
RXWatcher Aug 5, 2026
e99985b
fix(player): unbreak audio delay, subtitle encodings, and refresh rep…
RXWatcher Aug 5, 2026
95ab2bb
fix(tv): unbreak auto-play next episode
RXWatcher Aug 5, 2026
2c08db2
fix(tv): repair HUD row layout, version labels and stats naming
RXWatcher Aug 5, 2026
c30ee8d
fix(tv): label player audio by source identity, not delivered format
RXWatcher Aug 5, 2026
7ca4145
fix(tv): address audio by catalog ordinal, the server's actual contract
RXWatcher Aug 5, 2026
e9d9864
feat(player): shared identity matcher for mounted audio tracks
RXWatcher Aug 5, 2026
9c8b9dd
fix(tv): switch audio on the player when the stream already carries it
RXWatcher Aug 5, 2026
46f5b43
fix(tv): one owned audio intent for launch, restore, HUD and remote
RXWatcher Aug 5, 2026
c3c243f
fix(tv): make audio reapplication reissue, and carry pick provenance
RXWatcher Aug 5, 2026
060c035
test(tv): extract the audio reconcile decision and cover its failures
RXWatcher Aug 5, 2026
c729a12
fix(phone): address audio by ordinal, matching the server contract
RXWatcher Aug 5, 2026
dded373
refactor: share the audio reconcile decision and its intent types
RXWatcher Aug 5, 2026
971986b
fix(phone): switch audio on the player when the stream already carrie…
RXWatcher Aug 5, 2026
65ca623
Merge pull request #168 from RXWatcher/codex/focus-ownership-fixes
RXWatcher Aug 6, 2026
2f52e57
fix(playback): bind control-socket sends to the session that owns them
RXWatcher Aug 6, 2026
e1fa80c
fix(tv): stop auto-advance cutting off the end of an episode
RXWatcher Aug 6, 2026
14e1a4b
fix(review): address CodeRabbit findings on #170
RXWatcher Aug 6, 2026
0e4a4be
Merge pull request #170 from RXWatcher/codex/player-robustness
RXWatcher Aug 6, 2026
283a6ec
Merge pull request #171 from RXWatcher/pr/realtime-session-binding
RXWatcher Aug 6, 2026
24dc139
Merge pull request #172 from RXWatcher/pr/tv-auto-advance
RXWatcher Aug 6, 2026
d219d82
Merge remote-tracking branch 'upstream/main' into codex/player-audio-…
RXWatcher Aug 6, 2026
83ffd3c
test(player): stop the load-ownership suite failing on a busy machine
RXWatcher Aug 6, 2026
d321514
Merge pull request #173 from RXWatcher/codex/player-audio-selection
RXWatcher Aug 6, 2026
36cde17
fix(profiles): commit profile id and token as one identity
RXWatcher Aug 5, 2026
0a15564
fix(nav): stop launchSingleTop silently replacing detail and player e…
RXWatcher Aug 5, 2026
c780ee3
fix(nav): close the deep-link, tab-root and identity-read gaps
RXWatcher Aug 5, 2026
161f0ea
fix(nav): attribute external routes to the identity that created them
RXWatcher Aug 5, 2026
e860b50
Merge pull request #174 from RXWatcher/pr/deflake-load-ownership
RXWatcher Aug 6, 2026
6295608
fix(tv): return to the related item you opened, not the hero
RXWatcher Aug 5, 2026
aa09dc6
fix(tv): let the viewer's own input cancel a pending focus restore
RXWatcher Aug 6, 2026
035bca5
fix(tv): keep return-trip state out of shared saveable slots
RXWatcher Aug 6, 2026
d3ce1c6
fix(tv): validate restored return state against the surface that save…
RXWatcher Aug 6, 2026
3654729
fix(tv): carry the audio the viewer actually chose, not the plan's
RXWatcher Aug 6, 2026
adf3589
fix(nav): close the four review findings on this branch
RXWatcher Aug 6, 2026
b9c4fa2
Merge pull request #177 from RXWatcher/fix/audio-carry-and-replan
RXWatcher Aug 6, 2026
cf938ab
Merge remote-tracking branch 'upstream/main' into pr/profiles-and-nav…
RXWatcher Aug 6, 2026
71f96f3
fix(tv): typed keyed savers so a wrong-type payload cannot crash rest…
RXWatcher Aug 6, 2026
fcac707
fix(tv): make the return path reachable, and harden the keyed savers
RXWatcher Aug 6, 2026
07f48d0
fix(nav, profiles): close the second review round on this branch
RXWatcher Aug 6, 2026
21db4b1
Merge remote-tracking branch 'upstream/main' into pr/tv-detail-focus
RXWatcher Aug 6, 2026
b47e8f3
Merge pull request #175 from RXWatcher/pr/profiles-and-navigation
RXWatcher Aug 6, 2026
e54396c
Merge remote-tracking branch 'upstream/main' into pr/tv-detail-focus
RXWatcher Aug 6, 2026
ad6e9bb
Merge pull request #176 from RXWatcher/pr/tv-detail-focus
RXWatcher Aug 6, 2026
da7f2ef
fix(playback): make session ownership survive cancellation on both cl…
RXWatcher Aug 6, 2026
405fb79
fix(playback): snapshot the ownership token instead of deriving it
RXWatcher Aug 6, 2026
f82cdd5
fix(playback): scope position reports to the session that produced them
RXWatcher Aug 6, 2026
af64943
fix(playback): hold the allocation lease across the nested replan
RXWatcher Aug 6, 2026
3803dc5
fix(tv): resolve the teardown session after settlement, not before it
RXWatcher Aug 6, 2026
4efc14e
fix(admin): stop a non-owner profile seeing the admin surface
RXWatcher Aug 6, 2026
b52eb87
Merge pull request #178 from RXWatcher/pr/session-ownership
RXWatcher Aug 6, 2026
9eaeb4b
fix(tv): stop the profile menu labelling a household profile ADMIN
RXWatcher Aug 6, 2026
c5022db
fix(tv): show no account caption on a household profile
RXWatcher Aug 6, 2026
2230e0f
fix(admin): let the destination gate recover from an unresolved profile
RXWatcher Aug 6, 2026
833275a
test: deflake the polling waits across the suite
RXWatcher Aug 6, 2026
09b75c9
Merge pull request #180 from RXWatcher/pr/deflake-polling-waits
RXWatcher Aug 6, 2026
eaaa707
Merge branch 'main' into fix/acting-admin-fail-closed
RXWatcher Aug 6, 2026
75ec979
Merge pull request #179 from RXWatcher/fix/acting-admin-fail-closed
RXWatcher Aug 6, 2026
064c8a7
fix(tv): drop voice search from the TV search screen (#181)
RXWatcher Aug 6, 2026
b0b5489
fix(playback): stop an audio-route change killing playback (#182)
RXWatcher Aug 6, 2026
5e8c2a2
fix(tv): stop a For You detail return leaving the screen without focu…
RXWatcher Aug 6, 2026
e9e2bb6
fix(tv): let the playback selector menus reach every option (#184)
RXWatcher Aug 6, 2026
4d18a19
perf(tv): split the player overlays out of TvPlayerScreen (#185)
RXWatcher Aug 6, 2026
8f3a893
fix(playback): let the audio route settle before reselecting tracks (…
RXWatcher Aug 6, 2026
90d4370
fix(tv): stop a duplicate feed entry crashing the app (#188)
RXWatcher Aug 6, 2026
4ae38ab
fix(tv): release the screen while playback is paused (#189)
RXWatcher Aug 6, 2026
5d670ec
feat(android): polish foldable details and player UI (#190)
Quick104 Aug 7, 2026
c3b2c9b
fix(tv): register DownloadStorage so the orphaned-server purge can ru…
RXWatcher Aug 7, 2026
25b1d6b
fix: stop crashing at startup on Android 12 (API 31) (#195)
RXWatcher Aug 7, 2026
c9de96b
chore: gate API-level mistakes with lint in CI (#196)
RXWatcher Aug 7, 2026
a652b8b
test(player): await the stale candidate drained by stopping its owner…
RXWatcher Aug 7, 2026
1d17358
fix(tv): give content focus entry a second frame, and stop hiding whe…
RXWatcher Aug 8, 2026
bfe5eb6
chore(deps): bump json from 2.21.1 to 2.21.2 (#197)
dependabot[bot] Aug 10, 2026
cb26461
fix(tv): anchor chapter ticks to the start of the scrubber (#201)
evulhotdog Aug 10, 2026
1eee2f1
fix(tv): make the crash-report prompt reachable on a television (#202)
RXWatcher Aug 10, 2026
908466c
test(tv): ratchet against silently-failing focus claims in screens (#…
RXWatcher Aug 10, 2026
fc73d3f
feat(playback): adopt platform-neutral protocol v3 (#200)
Quick104 Aug 11, 2026
9dace7f
fix(auth): use native branding for server names (#192)
Quick104 Aug 11, 2026
8d32452
fix(diagnostics): stop the focus warning crashing, and name the endpo…
RXWatcher Aug 11, 2026
e71f086
fix(auth): refresh an expiring token before spending it, not after th…
RXWatcher Aug 11, 2026
8a29750
fix(tv): stop re-asking the server about every episode on every seaso…
RXWatcher Aug 11, 2026
4033ce5
fix(tv): make Back out of the top-bar chrome reach content, Home and …
RXWatcher Aug 11, 2026
7245c0f
fix(tv): make the seek rate mean what the chip says, and reach the en…
RXWatcher Aug 11, 2026
2c64da8
fix(playback): decide audio decode on the decoder's real channel limi…
RXWatcher Aug 11, 2026
dbe6d8f
fix(tv): Back out of a cascade lands on its own tab, without flashing…
RXWatcher Aug 11, 2026
0ac07f5
fix(tv): observe focus arrival per target, not per screen (#216)
RXWatcher Aug 11, 2026
8126fae
fix(phone): load More Like This eagerly with the detail page (#218)
Quick104 Aug 11, 2026
8d2e8b6
ci: cache Robolectric's Android runtimes (#217)
RXWatcher Aug 11, 2026
3efdbd9
fix(tv): make the player controls reachable, and Center mean pause (#…
RXWatcher Aug 11, 2026
c10e96d
feat: add hosted diagnostics uploads (#221)
Quick104 Aug 12, 2026
b8efb4f
fix(phone): preserve season chip selection during pager animation (#225)
Quick104 Aug 13, 2026
e240847
feat(playback): render recap and preview markers on the player timeli…
evulhotdog Aug 13, 2026
8c8b603
fix(tv): remove aliased hairline border on player transport controls …
evulhotdog Aug 13, 2026
43591b8
feat(client-identity): report build number and release channel to the…
Quick104 Aug 14, 2026
0393c43
Update launcher icons and TV art to the new vector artwork (#227)
Quick104 Aug 14, 2026
03fc36e
fix(tv): show one buffering indicator, even when the controls are hid…
evulhotdog Aug 14, 2026
f50429a
Rebuild the startup splash from the vector brand assets (#229)
Quick104 Aug 15, 2026
5fd7419
feat(diagnostics): re-vendor expanded attribute registry and align ho…
Quick104 Aug 15, 2026
128435d
feat(tv): sign-in flow, For You, player HUD, and subtitle selection/r…
Quick104 Aug 18, 2026
c5e758b
fix(diagnostics): preserve safe hosted crash frames (#231)
Quick104 Aug 18, 2026
15a7b6a
Fix release dependency verification (#235)
Quick104 Aug 18, 2026
5670f05
fix(browse): stop the library sort resetting to its default (#237)
Quick104 Aug 18, 2026
a071dea
fix(android): scale poster overlays with card width (#242)
blurbery Aug 25, 2026
4aec538
chore: centralize agent skills
Quick104 Aug 27, 2026
73d8979
feat: enhance Android system media controls (#252)
Quick104 Aug 27, 2026
4db4d4a
Merge Silo-Server/silo-android main (238 commits)
cursoragent Aug 28, 2026
823a5cb
fix(sync): finish Silo→Prairie renames after upstream merge
cursoragent Aug 28, 2026
c7b0d8f
docs: align exposure notes with upstream admin removal
cursoragent Aug 28, 2026
6925239
fix(ci): restore Kover plugin in version catalog after sync merge
cursoragent Aug 28, 2026
011bc66
fix(sync): restore Prairie auth keys and LAN health probe overload
cursoragent Aug 28, 2026
1c5e82d
fix(android): restore prairie_icon_background color resources
cursoragent Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 0 additions & 4 deletions .agents/skills/test-shield-playback/agents/openai.yaml

This file was deleted.

102 changes: 89 additions & 13 deletions .github/workflows/android-build.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
name: Android Builds

# CI gate: :shared debug unit tests + Kover line-coverage verify (commonMain).
# Floor is 95% line coverage across commonMain (androidMain / Koin / serializers
# excluded — see shared/build.gradle.kts). App-module unit tests (androidApp /
# androidTvApp / android-shared) are not part of this gate and are skipped here
# to keep the longest client CI focused on the shared coverage contract.
# Release artifacts (Play Store bundles, sideload APKs, GitHub releases) are
# owned by release.yml — triggered by v* tags or its workflow_dispatch.
# CI gate: unit tests + Kover line-coverage verify on :shared commonMain, plus
# lint. Floor is configured in shared/build.gradle.kts. Release artifacts
# (Play Store bundles, sideload APKs, GitHub releases) are owned by
# release.yml — triggered by v* tags or its workflow_dispatch.

on:
push:
Expand Down Expand Up @@ -47,20 +44,47 @@ jobs:
- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6

- name: Run :shared unit tests and coverage gate
# Robolectric does NOT resolve its Android runtimes through Gradle. At test
# execution time it fetches android-all-instrumented straight from Maven
# Central into ~/.m2, which setup-gradle's cache does not cover — so every
# run re-downloaded 85-204 MB per SDK level. On 2026-08-11 Maven Central
# answered 403 and took out 31 unrelated tests in android-shared, and the
# download time is a large part of this job.
#
# Which runtimes get fetched depends on the Robolectric version AND on the
# SDK each test resolves to, so the key hashes the version catalogue and
# the module build files (min/target SDK) together. A new @Config(sdk=NN)
# in a test is deliberately NOT in the key: hashing test sources would
# bust this cache on nearly every pull request, which costs more than it
# saves. The residual gap is bounded — that one runtime is re-fetched each
# run until something else moves the key — and the restore-key prefix
# still seeds from the previous cache rather than starting cold.
#
# A run-id-suffixed key would close the gap by saving every run, but this
# cache is hundreds of MB; a new entry per run would evict the Gradle
# cache against the repository's 10 GB budget.
- name: Cache Robolectric Android runtimes
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.m2/repository/org/robolectric
key: robolectric-${{ runner.os }}-${{ hashFiles('gradle/libs.versions.toml', '**/build.gradle.kts') }}
restore-keys: |
robolectric-${{ runner.os }}-

- name: Run unit tests and coverage gate
shell: bash
run: |
set -euo pipefail

# Only :shared debug unit tests feed the Kover commonMain gate.
# Release unit tests are disabled on :shared (see build.gradle.kts).
# App modules are intentionally out of this job.
# Debug-variant unit tests only. The release variant compiles and runs
# the exact same sources for no extra signal, and doubles CI time.
# :shared koverXmlReport/koverVerify enforce the commonMain coverage floor.
./gradlew \
-Dorg.gradle.jvmargs="-Xmx4g -Dfile.encoding=UTF-8" \
:shared:testDebugUnitTest \
testDebugUnitTest \
:shared:koverXmlReport \
:shared:koverVerify \
--max-workers=4 \
--max-workers=2 \
--no-configuration-cache

- name: Upload test reports
Expand All @@ -80,3 +104,55 @@ jobs:
path: |
**/build/reports/kover/**
if-no-files-found: ignore

lint:
name: Lint
runs-on: ubuntu-latest

steps:
- name: Check out sources
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
persist-credentials: false

- name: Set up JDK 21
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
with:
distribution: temurin
java-version: "21"

- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6

- name: Run lint
shell: bash
run: |
set -euo pipefail

# NewApi and InlinedApi are fatal here. Two startup crashes reached
# users because nothing checked API levels: a Spatializer call gated
# at 31 for a class introduced at 32, and an unguarded API 28 call.
# Existing findings are held in per-module lint-baseline.xml, so only
# NEW violations fail. If this job fails, fix the call — do not
# regenerate the baseline to make it pass.
#
# lintVitalRelease runs here too. checkReleaseBuilds makes it part of
# assembleRelease, which only ever runs from release.yml on a v* tag —
# so without this the release variant is gated by a check that no pull
# request exercises, and the first run would be mid-release. It also
# covers the release-only source sets that lintDebug never sees.
./gradlew \
-Dorg.gradle.jvmargs="-Xmx4g -Dfile.encoding=UTF-8" \
:android-shared:lintDebug :androidApp:lintDebug :androidTvApp:lintDebug \
:androidApp:lintVitalRelease :androidTvApp:lintVitalRelease \
--max-workers=2

- name: Upload lint reports
if: failure()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
with:
name: lint-reports
path: |
**/build/reports/lint-results-*.html
**/build/reports/lint-results-*.xml
if-no-files-found: ignore
29 changes: 23 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name: Release

# One release pipeline, playing the role of prairie-apple's TestFlight
# One release pipeline, playing the role of silo-apple's TestFlight
# (release.yml) and sideload (sideload-ipa.yml) workflows combined: a version
# tag or a manual dispatch publishes both App Bundles to Google Play, then
# builds the signed sideload APKs and attaches them to a GitHub release for
# the same version. Dispatch runs mint the v<version> tag when creating the
# GitHub release — no manual tagging is necessary (apple's sideload pattern).
#
# Versioning mirrors prairie-apple's marketing-version + build-number split.
# Versioning mirrors silo-apple's marketing-version + build-number split.
# Play itself has no such split — versionCode is the only monotonic counter,
# and versionName is a free-form display string that may repeat. So a build
# number is folded into the versionCode while versionName stays put, letting
Expand Down Expand Up @@ -125,6 +125,13 @@ jobs:
echo "::error::Tag must look like v1.2.3, v1.2.3+2, or v1.2.3-rc.1."
exit 1
fi
# A prerelease suffix deliberately does NOT feed the build counter.
# The counter is folded into the versionCode, so deriving it from
# -rc.N would make a sideloaded v1.2.3-rc.2 (base+2) outrank the
# official v1.2.3 (base+1) and block that upgrade on the device —
# and it would still not tell -rc.2 apart from +2, which resolve to
# the same counter. Prerelease artifacts are distinguished by their
# tag; see the note in the PR for the reporting limitation.
if [[ "${version}" == *+* ]]; then
build="${version##*+}"
else
Expand Down Expand Up @@ -187,6 +194,7 @@ jobs:

- name: Check build supply chain
run: |
./scripts/test-release-workflow.sh
./scripts/test-check-build-supply-chain.sh
./scripts/check-build-supply-chain.sh

Expand Down Expand Up @@ -316,7 +324,7 @@ jobs:
exit 1
fi

keystore_path="${RUNNER_TEMP}/prairie-release.jks"
keystore_path="${RUNNER_TEMP}/silo-release.jks"
printf '%s' "${KEYSTORE_B64}" | base64 -d > "${keystore_path}"
echo "PRAIRIE_RELEASE_KEYSTORE=${keystore_path}" >> "${GITHUB_ENV}"

Expand All @@ -343,24 +351,29 @@ jobs:
shell: bash
env:
PRAIRIE_VERSION_NAME: ${{ needs.setup.outputs.version_name }}
PRAIRIE_DISPLAY_VERSION: ${{ needs.setup.outputs.version }}
PRAIRIE_VERSION_CODE: ${{ needs.setup.outputs.version_code }}
PRAIRIE_RELEASE_KEYSTORE_PASSWORD: ${{ secrets.PRAIRIE_RELEASE_KEYSTORE_PASSWORD }}
PRAIRIE_RELEASE_KEY_PASSWORD: ${{ secrets.PRAIRIE_RELEASE_KEY_PASSWORD }}
PRAIRIE_RELEASE_KEY_ALIAS: ${{ secrets.PRAIRIE_RELEASE_KEY_ALIAS }}
PRAIRIE_BUILD_NUMBER: ${{ needs.setup.outputs.build_number }}
run: |
set -euo pipefail

./gradlew \
-Dorg.gradle.jvmargs="-Xmx4g -Dfile.encoding=UTF-8" \
":${{ matrix.module }}:assembleRelease" \
"-PprairieVersionName=${PRAIRIE_VERSION_NAME}" \
"-PprairieDisplayVersion=${PRAIRIE_DISPLAY_VERSION}" \
"-PprairieVersionCode=${PRAIRIE_VERSION_CODE}" \
"-PprairieBuildNumber=${PRAIRIE_BUILD_NUMBER}" \
"-PprairieReleaseChannel=sideload" \
--max-workers=2

- name: Collect release APKs
shell: bash
env:
PRAIRIE_VERSION_NAME: ${{ needs.setup.outputs.version_name }}
PRAIRIE_VERSION_NAME: ${{ needs.setup.outputs.version }}
run: |
set -euo pipefail

Expand Down Expand Up @@ -391,12 +404,16 @@ jobs:

# Create or update the GitHub release and attach the APKs. For dispatch
# runs the tag does not exist yet — gh release create mints it at the
# released commit (--target), mirroring prairie-apple's sideload workflow, so
# released commit (--target), mirroring silo-apple's sideload workflow, so
# no manual tagging is necessary. Tags created with GITHUB_TOKEN do not
# re-trigger workflows, so this cannot recurse.
publish-release:
name: Publish GitHub Release
needs: [setup, apks]
if: >-
${{ !cancelled() &&
needs.setup.result == 'success' &&
needs.apks.result == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -418,7 +435,7 @@ jobs:
set -euo pipefail
shopt -s globstar nullglob

release_title="Prairie Android ${RELEASE_TAG}"
release_title="Silo Android ${RELEASE_TAG}"
android_latest_url="https://github.com/${GH_REPO}/releases/latest/download/prairie-android-latest-universal-release.apk"
android_tv_latest_url="https://github.com/${GH_REPO}/releases/latest/download/prairie-android-tv-latest-universal-release.apk"
android_downloader_url="http://aftv.news/1051382"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ owner-driven cancellation remains silent.
### Credential boundary

The access token is still required to attempt the room socket but is no longer
placed in the request target. The existing same-origin Silo auth plugin adds
placed in the request target. The existing same-origin Prairie auth plugin adds
`Authorization`, `X-Profile-Id`, and `X-Profile-Token` headers. The server
currently still requires `room_token`, `profile_id`, and `profile_token` query
parameters; the client KDoc records that residual request-target exposure.
Expand Down Expand Up @@ -213,9 +213,9 @@ The exact-scope validation at connect start is not the final token read: the
auth plugin reads the scoped token again while building the request so it can
honor rotation. A credential scope can disappear between those reads. The
Watch Together connector now marks its pinned request with the internal,
opt-in `requireSiloAuth()` attribute. When that marked request's exact scoped
token is null or blank, `PrairieAuthPlugin` removes Silo headers and throws before
the engine runs. Unmarked public requests and `skipSiloAuth()` paths retain
opt-in `requirePrairieAuth()` attribute. When that marked request's exact scoped
token is null or blank, `PrairieAuthPlugin` removes Prairie headers and throws before
the engine runs. Unmarked public requests and `skipPrairieAuth()` paths retain
their existing behavior.

### Correction 2 TDD evidence
Expand Down
Loading
Loading