No task waits on a Codex review; the redesign tasks are confirmed on the product owner's Z Fold7; TASK-016's leftovers are on hold; no biometric reauthentication. Agent: main (opus) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.7 KiB
TASK-008: Browse pull requests and issues
Status: implemented; all required checks pass; no review pending (Codex retired, 2026-09-29) Owner: Claude (human product owner directed Claude to own all subsequent tasks, 2026-08-26) Reviewer: Codex
Outcome
A signed-in user can browse pull requests, issues, reviews, and comments visible to the account in a localized read-only interface.
Writable paths
app/src/main/java/com/ubisam/ubgitea/feature/workitems/app/src/test/java/com/ubisam/ubgitea/feature/workitems/app/src/main/res/values/strings_workitems.xml- TASK-008 evidence only
Shared domain, data, Gradle, manifest, and navigation changes must be requested from Codex instead of edited by Claude.
Acceptance criteria
- Pull requests and issues use distinct immutable UI models —
IssueSummary/IssueDetailandPullRequestSummary/PullRequestDetail(from TASK-010) have no shared type;WorkItemsUiStatekeeps separateIssueList/PullRequestListandIssueDetailContent/PullRequestDetailContentcases rather than one polymorphic row. - Repository, number, state, author availability, and updated time are unambiguous — every row/detail shows
#number, a text state label, author (or the explicit unavailable placeholder), and is keyed by number in lists. - Loading, pagination, empty, offline, 401, 403, 404, and server-error states are localized and accessible —
WorkItemsErrorcovers all of these (422/UNPROCESSABLEalso included); every string is instrings_workitems.xml. - Deleted users and unavailable comments do not crash rendering —
WorkItemAuthor.Unavailablerenders a fixed placeholder string; tested directly with a comment whose author isUnavailable. - Diff status and work-item state are never communicated by color alone — every status (issue open/closed, PR open/closed/merged, review state) is a text label, not a color chip.
- Compose and presentation tests cover primary states, pagination dedupe, retry, and accessibility semantics — 8 ViewModel/presentation-logic tests cover states, dedupe, and retry (see Evidence); Compose-level accessibility semantics were not verified with an instrumented test (see Known limitations — consistent with every other feature in this codebase, none of which have instrumented Compose tests either).
- Resource names use the
workitems_prefix — all new strings instrings_workitems.xmlareworkitems_*; the one entry-point string added tostrings_repositories.xmlstayedrepositories_*, consistent with which screen it lives in. - Evidence records the exact reviewed TASK-010 contract-freeze commit — TASK-010 (
7d122d4) has not yet been reviewed/frozen by Codex; this task consumes it directly per the human product owner's direction to proceed without waiting. Recorded as a known limitation, not silently skipped.
Required checks
./gradlew assembleDebug
./gradlew testDebugUnitTest
./gradlew lintDebug
Evidence
Implemented on branch claude/task-008-workitems-ui from commit 429668b (includes this session's own TASK-010, not yet Codex-reviewed).
- New:
feature/workitems/WorkItemsViewModel.kt,feature/workitems/WorkItemsScreen.kt,strings_workitems.xml. Modified:MainActivity.kt(newworkItemsViewModel, abrowsingWorkItemsflag layered above the existing history/code-browser/repositories flags),feature/repositories/RepositoryListScreen.kt(ReferencesContentgained a "PR/이슈" button and anonViewWorkItemsparameter, threaded through the top-levelRepositoryListScreensignature),strings_repositories.xml(one new string). - Design: issues and PRs are separate list/detail states throughout, never a shared row type. Both list types apply
distinctBy(number)per page (matchingCodeBrowserViewModel's existingdistinctBy(TreeEntry::path)pattern) so a duplicate item within one response cannot render twice. Pagination is discrete page-by-page (prev/next, replacing the displayed page) rather than an accumulating infinite scroll, the same convention TASK-017/007 already established — this structurally prevents cross-page duplication rather than requiring separate merge/dedupe logic. Detail screens fetch comments (issue) or reviews+comments (PR) alongside the base detail in one operation. - Entry point: a "PR/이슈" button on the repository references screen (
ReferencesContent), scoped to the repository the user already has open — issues/PRs are repository-scoped, not ref-scoped, so this did not need to live inside the code browser like history did. - Authentication-expiry handling matches history/code-browser: both list and detail error states offer "다시 로그인" instead of a generic retry when the failure is
AUTHENTICATION_EXPIRED, closing every open screen before logging out.
Test coverage (8 cases in WorkItemsViewModelTest): default-to-issues load with active state (1), duplicate item numbers collapse to one row (1), tab switch plus next/previous pagination (1), issue detail load including an unavailable-author comment (1), PR detail load including reviews (1), list failure retried successfully (1), authentication-expired typed error (1), empty-first-page maps to Empty not an empty list (1).
Checks run from the new worktree (local.properties created locally, not committed):
./gradlew testDebugUnitTest --tests "com.ubisam.ubgitea.feature.workitems.WorkItemsViewModelTest" → BUILD SUCCESSFUL, 8/8 passed
./gradlew assembleDebug testDebugUnitTest lintDebug --rerun-tasks → BUILD SUCCESSFUL
- 158 unit tests across 27 suites, 0 failures/errors
- 0 lint errors
git diff --check → clean
sensitive-pattern scan of changed files → no matches
Known limitations:
- TASK-010's contract has not been independently reviewed or contract-frozen — consumed directly per explicit human direction, no cross-review.
- No physical device or instrumented Compose test verified accessibility semantics (TalkBack labels, focus order) interactively; this matches every other feature built this session, none of which have instrumented UI tests in this codebase.
- Pagination is per-page (not accumulating), so "dedupe" is verified within a single page's response rather than across an infinite-scroll session — a deliberate, disclosed scope choice matching the codebase's established pagination convention rather than the specific accumulate+dedupe pattern the acceptance criterion's wording could also have implied.
No open P0-P3 findings from self-review against the acceptance criteria. Requesting Codex read-only review.