Continues Codex's paused in-progress fix in this worktree (confirmed safe to pick up by the human product owner). A missing or malformed branch commit timestamp no longer fails the whole branch page; the latest-branch picker now filters to branches with a known timestamp before selecting the max, and reports Failed (not Empty) when none are known. Adds the one missing test case from the in-progress coverage (all branches with unknown timestamps) plus an explicit test proving the reference screen never depended on the field. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
34 lines
3.6 KiB
Markdown
34 lines
3.6 KiB
Markdown
# TASK-022: Tolerate incomplete Gitea branch timestamps
|
||
|
||
Status: implemented; all required checks pass; physical-device retest pending
|
||
Owner: Claude (picked up from Codex's paused in-progress work in the same worktree, with the human product owner's explicit confirmation to continue, 2026-08-26)
|
||
Reviewer: Codex
|
||
|
||
## Outcome
|
||
|
||
A repository remains browsable when Gitea returns a valid branch name and commit ID but omits or malforms that branch commit's optional timestamp. One incomplete branch must not invalidate the repository's entire branch list.
|
||
|
||
## Acceptance criteria
|
||
|
||
- [x] Missing or malformed branch timestamps map to an unknown timestamp without failing the branch page.
|
||
- [x] The latest-branch indicator selects the newest branch among entries with valid timestamps.
|
||
- [x] Reference browsing still displays branches whose timestamps are unknown.
|
||
- [x] Required branch names and commit IDs remain fail-closed.
|
||
- [x] Build, unit tests, lint, and secret scan pass.
|
||
- [ ] Physical-device reproduction pass with this exact fix. The original crash was reproduced and diagnosed by Codex on-device (`CSOT-T8-iPTN-AMA`, see Incident evidence); this fix has been verified only by unit test, not by a live retest against that same repository on a device.
|
||
|
||
## Incident evidence
|
||
|
||
On the authenticated device, `CSOT-T8-iPTN-AMA` failed both its row-level latest-branch request and its repository reference screen. Both flows share `listBranches`, whose mapper previously required every `commit.timestamp` even though timestamp is not necessary to identify or browse a branch.
|
||
|
||
## Evidence (completion)
|
||
|
||
- `domain/model/RepositoryModels.kt`: `BranchSummary.commitAtEpochMillis` changed from `Long` to `Long?`.
|
||
- `data/repositories/GiteaRepositoryBrowserApi.kt`: `listBranches`'s mapper now uses a new `String?.toEpochMillisOrNull()` (parses if present and well-formed, else `null`) instead of `.required().toEpochMillisOrInvalid()` for the timestamp only — `name`/`commit.id` still go through `.required()` and remain fail-closed.
|
||
- `feature/repositories/RepositoryListViewModel.kt`'s `launchRowBranchFetch`: the latest-branch picker now filters to branches with a non-null timestamp before taking `maxByOrNull`, so an unknown-timestamp branch can never hide a real latest branch. When a repository has branches but *none* have a resolvable timestamp, the row now reports `LastPushedBranchUiState.Failed` (distinct from `Empty`, which stays reserved for a genuinely branch-less repository) rather than silently showing nothing.
|
||
- `feature/repositories/RepositoryReferencePresenter.kt` needed no code change — it never read `commitAtEpochMillis` — but a test was added (`RepositoryReferencePresenterTest`) to make that guarantee explicit rather than implicit.
|
||
- Tests added: `GiteaRepositoryBrowserApiTest` (missing/malformed timestamp maps to `null`, not a thrown failure), `RepositoryReferencePresenterTest` (a null-timestamp branch still renders and can be selected), `RepositoryListViewModelTest` ×2 (mixed known/unknown timestamps still surface the true latest; all-unknown reports `Failed` not `Empty`) — the all-unknown case was the one gap in Codex's in-progress test coverage when this was picked up.
|
||
- `./gradlew assembleDebug testDebugUnitTest lintDebug --rerun-tasks`: BUILD SUCCESSFUL, all unit tests passing, 0 lint errors.
|
||
- `git diff --cached --check`: clean. Secret-pattern scan of the staged diff: no matches.
|
||
- Not verified: a live retest of repository `CSOT-T8-iPTN-AMA` (or any repository with a real missing/malformed branch timestamp) on a physical device with this exact fix — left open per this session's established practice of disclosing rather than silently skipping device-dependent verification.
|