Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9f6cc7f
feat(push): read each push from the server and profile it names (#556)
Quick104 Oct 13, 2026
ca38716
fix(tv): let Down leave the search field after Back hides the keyboar…
Rhainland Oct 13, 2026
c73770f
fix(requests): remove request moderation from the phone and TV apps (…
Rhainland Oct 13, 2026
7631c58
fix(player): tell AI translations from AI transcriptions in subtitle …
Rhainland Oct 13, 2026
13b660d
fix(player): show why an AI subtitle job failed after its dialog clos…
Rhainland Oct 13, 2026
0e8a6cc
fix(tv): keep long values in TV dialog rows on one line (#546)
Rhainland Oct 13, 2026
3bf2f68
fix(player): leave playback when an administrator ended the session (…
Rhainland Oct 13, 2026
63a007a
fix(player): keep AI transcription in the spoken language when transl…
Rhainland Oct 13, 2026
a36f4af
feat(requests): let viewers get notified when someone else's request …
Rhainland Oct 13, 2026
68a9817
fix(android): open detail pages without popping or layout shifts (#574)
Quick104 Oct 14, 2026
e98a043
ci(release): tag tester builds and promote the tested build to Play (…
Quick104 Oct 14, 2026
98c6fd8
test(home): keep HomeViewModelCacheIdentityTest's requests on the tes…
Quick104 Oct 14, 2026
9c4636e
ci(release): keep the newest tester build under fixed APK names (#576)
Quick104 Oct 14, 2026
883f1c5
ci(release): make publishing re-runnable and swap beta APKs safely (#…
Quick104 Oct 14, 2026
b5bf859
docs: list the new store and beta Downloader codes (#578)
Quick104 Oct 14, 2026
a4dd216
fix(watch-party): converge drift by small rate changes like web and A…
neurekadev Oct 15, 2026
578eedf
feat(network): use the server's local address automatically at home (…
Quick104 Oct 15, 2026
debb18f
fix(player): tell the viewer when an administrator ended playback (#604)
Quick104 Oct 16, 2026
337bd7f
docs(contributing): require evidence on phones, tablets, and foldable…
Quick104 Oct 16, 2026
4ab4e63
docs(contributing): accept any Android foldable for evidence (#607)
Quick104 Oct 16, 2026
aa20e74
feat(onboarding): list Silo servers found on the local network during…
Quick104 Oct 17, 2026
dbe1ca8
feat(profiles): set a child's rating and libraries on phone and TV (#…
Quick104 Oct 17, 2026
62be1a2
fix(profiles): let regular accounts manage household profiles (#595)
Quick104 Oct 17, 2026
c63c951
fix(tv): decode SVG profile avatars (#590)
RXWatcher Oct 17, 2026
b849911
fix(player): steady volume swipe with on-screen and haptic feedback (…
Quick104 Oct 17, 2026
887766d
feat(artwork): request artwork at the size each screen draws it (#612)
Quick104 Oct 17, 2026
3993161
feat(playback): retire Original quality and add a cellular quality se…
Quick104 Oct 17, 2026
33945a0
feat(player): play embedded subtitles from the transcode's HLS rendit…
Rhainland Oct 17, 2026
314cc65
fix(tv): stop re-reading Home while the player covers it (#626)
Quick104 Oct 18, 2026
b1e5774
fix(libraries): let the phone library picker scroll (#627)
Quick104 Oct 18, 2026
21855e9
Merge upstream Silo-Server/silo-android b1e5774f3a into main
JonahMMay Oct 18, 2026
ec86206
Use playbackQualityValueLabel for stats quality after upstream remove…
JonahMMay Oct 18, 2026
991215f
Drop Prairie test asserting the Original preset upstream retired
JonahMMay Oct 18, 2026
3e55a63
Fix post-merge compile errors: TV quality preference mapping, Playbac…
JonahMMay Oct 19, 2026
8368c15
Exclude shared/androidMain local-route glue from the commonMain cover…
JonahMMay Oct 19, 2026
5f80b17
Pass LanDiscovery in ServerListViewModelRemovalTest after the first-r…
JonahMMay Oct 19, 2026
722631d
Test local-route TLS pinning instead of excluding it from Kover
JonahMMay Oct 19, 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
  •  
  •  
  •  
15 changes: 15 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Groups the release notes GitHub generates by the labels prairie-triage puts on
# pull requests. Store notes keep only the Features and Fixes sections
# (scripts/release-version.py). See docs/releasing.md.
changelog:
categories:
- title: 🚀 Features
labels: [enhancement]
- title: 🐛 Fixes
labels: [bug]
- title: 📚 Documentation
labels: [documentation]
- title: 📦 Dependencies
labels: [dependencies]
- title: Other changes
labels: ["*"]
111 changes: 111 additions & 0 deletions .macroscope/check-run-agents/visible-change-evidence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: Visible change evidence
model: gpt-6-luna
reasoning: high
input: full_diff
tools:
- browse_code
- git_tools
- github_api_read_only
- modify_pr
exclude:
- ".agents/**"
- "docs/superpowers/**"
conclusion: neutral
maxRuns: 3
maxBudgetPerRun: 0.50
maxBudgetPerPR: 3.00
---

Prairie requires evidence in every pull request that changes what a user sees. Reviewers should be
able to see the change without building the branch. Your job is to decide whether this PR changes
what a user sees, on which devices, and, if it does, whether its Evidence section shows that change
on each of them. You report; you do not judge whether the change is good.

The rules are in `CONTRIBUTING.md` under "Show visible changes". Read that section first; it is the
authority if this prompt and it disagree.

## Decide whether the change is visible

Read the PR title, body, and full diff. Trace changed code to what a user would see; do not match
on file names alone. A change is visible when it alters any of these:

- app UI in the phone app (`androidApp/`), the TV app (`androidTvApp/`), or the code they share
(`android-shared/`, `shared/`), including strings and resources: layout, styling, copy,
navigation, focus, empty and error states;
- which items a screen shows, or in what order: search results, home sections, recommendations,
library browsing, collections, sorting, or filtering;
- what an item shows: titles, artwork, descriptions, ratings, badges, episode grouping, or
availability;
- playback behavior a user notices: default audio or subtitle tracks, markers, controls, or resume
position.

These are not visible on their own: unit and instrumented tests, CI, fastlane, Gradle and baseline
profile changes that do not change what ships, internal refactors with identical output, logging,
and documentation. When the path to the user is real but uncertain, say so and treat the change as
visible.

## Work out which devices it reaches

The devices are an Android phone, an Android tablet, an Android foldable folded and open (any
model, such as a Galaxy Z Fold or Pixel Fold), and Android TV. The phone app runs on the first
three; the TV app runs on Android TV; shared modules reach both apps unless the changed code is only
called from one. Then trace the layout checks around the changed code:

- `smallestScreenWidthDp`, `widthDp` and `heightDp` thresholds, `isExpandedWindow`, and
`isExpandedDetailLayout` decide whether a screen takes its phone or wide layout. A folded
foldable behaves like a phone; an open one takes the wide layouts a tablet does.
- `FoldingFeature` and `isTabletopPlayerPosture` reach only a foldable, open or half-folded.

List each device the change reaches. When you cannot tell whether a device is reached, count it.

## Check the evidence

Find the `## Evidence` section of the PR body. For a visible change, it passes when it has:

- before-and-after images, a recording, or a line starting with `Evidence:
https://evidence.prairieserver.org/`;
- evidence that matches the change: a UI change needs screenshots or a recording; a change to which
items appear or their order needs a before and an after of the same screen with the same data;
- captures for every device the change reaches, with the foldable both folded and open, or a
reason the PR gives for each device it leaves out;
- a recording when the change is about motion, timing, focus movement, or a multi-step flow;
- the device and build or commit the captures came from.

Evidence on `evidence.prairieserver.org` is private, and you cannot open it. For a section that links
a page there, count the link as evidence, do not ask for the devices or build in the body, and list
the devices the page should show so the reviewer can check it.

An explanation of why evidence could not be captured is acceptable; report it so the reviewer can
decide, and do not count it as a pass. A reason for leaving out a device is acceptable when the code
you traced agrees with it; when it does not, say which code reaches that device.

For a change that is not visible, the section should say `Evidence: none, no user-visible change`.
If it is empty or still holds the template table, suggest that line.

You cannot open images. Judge them from their placement, alt text, captions, and surrounding text.
Never claim an image shows something you could not read.

## How to report

Always write the check run summary. Start with one line: `visible` or `not visible`, and `evidence
complete`, `evidence incomplete`, `evidence missing`, or `evidence explained as unavailable`. Then
list the user-visible effects you found, each with the file that causes it and the devices it
reaches, and what the evidence covers or lacks.

Post one conversation comment on the PR only when a visible change has missing or incomplete
evidence, or when a change that is not visible has no Evidence line. Name each visible effect that
lacks evidence, the devices it is missing on, and the kind of evidence it needs, in one line each.
If the author has replied that evidence is not needed or has explained why it is unavailable,
accept that and do not raise it again unless new commits change what users see.

## Rules

- Do not change the PR title, body, labels, assignees, or reviewers. Do not @-mention anyone.
- Comments are public. Do not include hostnames, IP addresses, local paths, credentials, or personal
data.
- If you see private details in the evidence, such as hostnames, URLs, account names, or personal
library contents, say that the evidence needs redacting without repeating the details.
- Write plainly: lead with the finding, use active voice, and skip praise and filler.
- End every comment with `<sub>Automated check: Macroscope check run agent (gpt-6-luna). Evidence was
not reviewed for correctness.</sub>`
9 changes: 6 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This repository contains only the Prairie Android clients. Shared Kotlin logic l
- Android TV navigation is Home, available media-type tabs from server libraries, For You (with its Watchlist/Favorites dropdown, mirroring tvOS `.recommendations`), Calendar, and Requests while the server enables it (mirroring tvOS `.requests`), plus search and profile actions. Reading/ebooks are excluded.
- Live TV (Prairie-only) is live on phone and TV, gated by `LiveTvFeatureStore` (the server has channels), and reached from the profile menu (phone `ProfileMenu` via `LocalLiveTvMenuAction`; TV profile dropdown). It is not a bottom-nav or top-menu tab.
- Upstream Silo syncs have silently dropped Prairie-only code. `scripts/check-prairie-invariants.sh` (CI job "Prairie invariants") anchors it; see `docs/upstream-sync.md`. When restoring dropped code, add an anchor.
- Requests is live on phone and TV, server-gated by `requests_enabled` (phone: profile menu + search; TV: a top-bar tab + search, matching Apple). Admins who can moderate requests approve, decline, and retry them in the Requests screens, as on Apple; limits and auto-approval stay in web admin. Other admin surfaces are not exposed in the Android clients — no STATS dashboard, and none of the richer admin screens (users/sessions/logs/scans). Session management (seeing where you are signed in and signing other devices out) is not exposed either; device pairing stays. This is a deliberate divergence from Apple, which does surface the STATS dashboard. Do not add any of it back to menus without an explicit product decision.
- Requests is live on phone and TV, server-gated by `requests_enabled` (phone: profile menu + search; TV: a top-bar tab + search, matching Apple). Request administration (approve, decline, retry, limits, auto-approve) is web-admin only: the Requests screens offer users request, cancel of their own pending request, and status, and never moderation (a source guard test enforces this). Other admin surfaces are not exposed in the Android clients — no STATS dashboard, and none of the richer admin screens (users/sessions/logs/scans). Session management (seeing where you are signed in and signing other devices out) is not exposed either; device pairing stays. This is a deliberate divergence from Apple, which does surface the STATS dashboard. Do not add any of it back to menus without an explicit product decision.
- Watch Party (synchronized playback) is experimental on phone and TV. Its entry points (profile menu, the detail page's party action, and phone `prairie://watch-party` invitations) appear only while Settings → Experimental → Watch Party is on, a device-local toggle that defaults on in debug builds and off in release builds, and it works only when the server advertises the room and playback capabilities. Keep it behind the toggle until the qualification matrix in `docs/watch-party-implementation-plan.md` passes.

## Skills & review agents
Expand All @@ -32,7 +32,7 @@ repos are under `.agents/code-review-kit/`.

## Coding Style & Naming Conventions

Use Kotlin 2.1, Java 21 targets, and Compose idioms. The Prairie package root is `org.prairieserver.prairie`. Both the phone and TV apps share a single `applicationId`, `org.prairieserver.prairie`, so they publish as one Google Play listing (Play routes each build by manifest feature filtering — the phone build requires `android.hardware.touchscreen`; the TV build requires `android.software.leanback`). The Gradle `namespace` stays distinct per module (`org.prairieserver.prairie.android`, `org.prairieserver.prairie.tv`) so generated `R`/`BuildConfig` classes don't collide. The two artifacts use distinct versionCodes (`base*2` for phone, `base*2+1` for TV), so each release bumps both by 2 with no reuse. Releases derive the base from the marketing version plus a build number (`base = 100_000_000 + (major*10000 + minor*100 + patch)*1000 + build`), so the same version can ship repeatedly as build 1, 2, 3 the way TestFlight does — bump the build number rather than inventing a new patch version for a re-release. This repo is on the full Prairie namespace cut, so do not add legacy package IDs, legacy storage names, or old-brand symbols. Kotlin classes and composables use `PascalCase`; functions and properties use `camelCase`.
Use Kotlin 2.1, Java 21 targets, and Compose idioms. The Prairie package root is `org.prairieserver.prairie`. Both the phone and TV apps share a single `applicationId`, `org.prairieserver.prairie`, so they publish as one Google Play listing (Play routes each build by manifest feature filtering — the phone build requires `android.hardware.touchscreen`; the TV build requires `android.software.leanback`). The Gradle `namespace` stays distinct per module (`org.prairieserver.prairie.android`, `org.prairieserver.prairie.tv`) so generated `R`/`BuildConfig` classes don't collide. The two artifacts use distinct versionCodes (`base*2` for phone, `base*2+1` for TV), so each release bumps both by 2 with no reuse. `scripts/release-version.py` derives the base from the store version and a repository-wide build number (`base = 100_000_000 + (major*10000 + minor*100 + patch)*1000 + build`), so a version ships as many tester builds as it needs before its store release. See `docs/releasing.md`. This repo is on the full Prairie namespace cut, so do not add legacy package IDs, legacy storage names, or old-brand symbols. Kotlin classes and composables use `PascalCase`; functions and properties use `camelCase`.

## Testing Guidelines

Expand Down Expand Up @@ -74,7 +74,10 @@ follow-up work.
covers UI and UX changes and changes to which items appear or what they show,
such as search results, home sections, recommendations, sorting, filtering,
metadata, or artwork. Use before-and-after captures of the same screen with the
same data, and a short recording when motion, timing, or focus matters. Write
same data, and a short recording when motion, timing, or focus matters.
Capture each device the change can reach: an Android phone, an Android
tablet, an Android foldable (folded and open), and Android TV, or say why a
device is unaffected. Write
`Evidence: none, no user-visible change` only when that is true.
- Attach evidence on GitHub under the PR body's Evidence heading, or publish it
with `npx @prairie-server/evidence publish <folder> --pr <number>` and put its
Expand Down
8 changes: 4 additions & 4 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A detailed inventory of what the Android **phone** and **TV** clients do today.

File pointers are repository-relative.

> **Important exposure note:** Requests is live on both Android surfaces, gated by the server's `requests_enabled` flag (`/api/v2/requests/status`), and reached from the profile menu and search on phone and from a top-bar tab and search on TV — matching the Apple clients. Admins who can moderate approve, decline, and retry requests there. The richer admin screens (users/sessions/logs/scans) remain inaccessible. Watch Party is experimental, behind Settings → Experimental → Watch Party.
> **Important exposure note:** Requests is live on both Android surfaces, gated by the server's `requests_enabled` flag (`/api/v2/requests/status`), and reached from the profile menu and search on phone and from a top-bar tab and search on TV — matching the Apple clients. Request administration (approve, decline, retry, limits, auto-approve) stays in web admin. The admin screens (users/sessions/logs/scans) remain inaccessible. Watch Party is experimental, behind Settings → Experimental → Watch Party.

---

Expand Down Expand Up @@ -88,7 +88,7 @@ Shown only while Settings → Experimental → Watch Party is on (default on in
| Release calendar | ✅ | ✅ | Top-level mobile tab and TV top-menu tab |
| Live home refresh (events websocket) | ✅ | ✅ | `HomeRealtimeCoordinator`: user_state/catalog channels, 2s debounce; TV also refreshes on resume |
| System "Watch Next" row integration | ➖ | ✅ | `WatchNextRepository` (tvprovider) |
| Requests | ✅ | ✅ | Server-gated by `requests_enabled`; phone: profile menu + search; TV: top-bar tab + search; admin approve/decline/retry |
| Requests | ✅ | ✅ | Server-gated by `requests_enabled`; phone: profile menu + search; TV: top-bar tab + search; "Notify me when available" on titles someone else requested (when the server reports `follow_supported`); request administration stays in web admin |

## Reading (ebooks)

Expand Down Expand Up @@ -135,7 +135,7 @@ Shown only while Settings → Experimental → Watch Party is on (default on in
| Favorites & watchlist | ✅ | ✅ | TV: from Settings |
| Ratings | ✅ | ✅ | |
| Watch history | ✅ | ✅ | |
| Content requests (browse/search TMDB, status tracking) | ✅ | ✅ | Four-step status track, My Requests, admin approvals; see Requests above |
| Content requests (browse/search TMDB, status tracking) | ✅ | ✅ | Four-step status track, My Requests, notify me when someone else's request becomes available; see Requests above |
| Release calendar | ✅ | ✅ | |
| Notifications inbox (paginated, realtime updates, mark-read) | ✅ | ✅ | REST + WebSocket |

Expand All @@ -160,6 +160,6 @@ Shown only while Settings → Experimental → Watch Party is on (default on in

**TV** is a 10-foot, D-pad client focused on browsing and playback, including audiobooks, calendar, the subtitle suite, person detail, and system Watch Next integration. It intentionally omits ebooks/reading and downloads management.

**Not currently exposed on either Android surface:** the admin stats dashboard and full admin management (users/sessions/logs/scans). **Experimental:** Watch Party, behind Settings → Experimental. Request moderation (approve, decline, retry) is the one admin action the Requests screens offer.
**Not currently exposed on either Android surface:** the admin stats dashboard, full admin management (users/sessions/logs/scans), and request moderation (approve, decline, retry), which stays in web admin. **Experimental:** Watch Party, behind Settings → Experimental.

Both apps share the same networking, auth, repositories, most ViewModels, and the entire Media3 playback/capability stack.
Loading
Loading