Ubisam-MobileGit/tasks/022-tolerate-branch-timestamp-gaps.md
choiminyeong b46dd3a72b Complete TASK-022: tolerate incomplete Gitea branch timestamps
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>
2026-08-26 22:19:39 +09:00

3.6 KiB
Raw Permalink Blame History

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

  • Missing or malformed branch timestamps map to an unknown timestamp without failing the branch page.
  • The latest-branch indicator selects the newest branch among entries with valid timestamps.
  • Reference browsing still displays branches whose timestamps are unknown.
  • Required branch names and commit IDs remain fail-closed.
  • 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.