TASK-041: fix favorite star reverting after switching tabs
toggleFavorite kept starredCoordinatesCache in sync with a successful star/unstar but never patched repositorySnapshots (the per-mode full-repository-list cache), so a starred repository's count reverted to its pre-toggle cached value on the next visit to that mode, and a newly-starred repository could be silently missing from an already-cached favorites list. Fix: two new helpers (adjustCachedStarCounts, removeFromCachedSnapshot) patch every cached snapshot containing the toggled repository, and a star invalidates just the FAVORITES snapshot key if already cached. Chosen over a full cache-clear-and-refetch after live testing showed Gitea's own starsCount can lag slightly behind a star/unstar on its plain repository-listing endpoint. Also fixes a related gap: unstarring from the FAVORITES tab wasn't updating starredCoordinatesCache at all (only the two ALL-mode branches were). Two new regression tests; all existing tests pass unmodified. Build/test/lint green, live-verified on device. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
a07094e0a5
commit
39cbad522e
@ -319,19 +319,37 @@ class RepositoryListViewModel(
|
|||||||
when {
|
when {
|
||||||
alreadyStarredThisSession -> {
|
alreadyStarredThisSession -> {
|
||||||
favoritesApi.unstar(repository.coordinates)
|
favoritesApi.unstar(repository.coordinates)
|
||||||
// Keeps loadStarredCoordinatesOnce's cache consistent with what actually
|
// Keeps loadStarredCoordinatesOnce's cache, and every cached repositorySnapshots
|
||||||
// happened, without a network round trip just to confirm it -- only touches
|
// page that includes this repository, consistent with what actually happened --
|
||||||
// the cache when it's already populated; if it isn't, the next ALL-list load
|
// without a network round trip just to confirm it. Deliberately a local patch, not
|
||||||
// fetches a fresh one anyway.
|
// a cache-clearing forced refetch: Gitea's own starsCount for a repository was
|
||||||
|
// observed live to lag slightly behind a star/unstar (the /user/starred listing
|
||||||
|
// reflected a toggle before the plain repository listing did), so trusting a fresh
|
||||||
|
// fetch immediately after this call risks showing a value that undercounts what we
|
||||||
|
// already know just happened. A repository this session knows is no longer starred
|
||||||
|
// is also dropped from any cached FAVORITES snapshot, so that list stays consistent
|
||||||
|
// the next time it's opened without a repeat network call either.
|
||||||
starredCoordinatesCache = starredCoordinatesCache?.minus(repository.coordinates)
|
starredCoordinatesCache = starredCoordinatesCache?.minus(repository.coordinates)
|
||||||
|
adjustCachedStarCounts(repository.coordinates, delta = -1)
|
||||||
|
removeFromCachedSnapshot(RepositoryListMode.FAVORITES, organization = null, repository.coordinates)
|
||||||
}
|
}
|
||||||
mode == RepositoryListMode.ALL -> {
|
mode == RepositoryListMode.ALL -> {
|
||||||
favoritesApi.star(repository.coordinates)
|
favoritesApi.star(repository.coordinates)
|
||||||
starredCoordinatesCache = starredCoordinatesCache?.plus(repository.coordinates)
|
starredCoordinatesCache = starredCoordinatesCache?.plus(repository.coordinates)
|
||||||
|
adjustCachedStarCounts(repository.coordinates, delta = +1)
|
||||||
|
// The FAVORITES snapshot can't be surgically patched the same way (adding a row
|
||||||
|
// needs a full RepositorySummary this call site doesn't have) -- if it's already
|
||||||
|
// cached from an earlier visit this session, invalidate just that one entry so the
|
||||||
|
// next visit fetches it fresh and picks up the new star, rather than leaving it
|
||||||
|
// silently missing.
|
||||||
|
repositorySnapshots.remove(RepositorySnapshotKey(RepositoryListMode.FAVORITES, null))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
favoritesApi.unstar(repository.coordinates)
|
favoritesApi.unstar(repository.coordinates)
|
||||||
removeRow(repository.coordinates)
|
removeRow(repository.coordinates)
|
||||||
|
starredCoordinatesCache = starredCoordinatesCache?.minus(repository.coordinates)
|
||||||
|
adjustCachedStarCounts(repository.coordinates, delta = -1)
|
||||||
|
removeFromCachedSnapshot(RepositoryListMode.FAVORITES, organization = null, repository.coordinates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
@ -535,6 +553,29 @@ class RepositoryListViewModel(
|
|||||||
return loaded.also { repositorySnapshots[key] = it }
|
return loaded.also { repositorySnapshots[key] = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keeps every cached repositorySnapshots page that includes this repository showing the right
|
||||||
|
// starsCount after a star/unstar this session already confirmed happened -- otherwise a repository
|
||||||
|
// whose page was fetched before the toggle (e.g. the ALL list loaded once at app start) would keep
|
||||||
|
// showing its pre-toggle count on every later visit to that mode, since loadRepositorySnapshot
|
||||||
|
// only fetches once per key and then reuses whatever's cached.
|
||||||
|
private fun adjustCachedStarCounts(coordinates: RepositoryCoordinates, delta: Int) {
|
||||||
|
for ((key, page) in repositorySnapshots) {
|
||||||
|
if (page.none { it.coordinates == coordinates }) continue
|
||||||
|
repositorySnapshots[key] = page.map {
|
||||||
|
if (it.coordinates == coordinates) it.copy(starsCount = (it.starsCount + delta).coerceAtLeast(0)) else it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drops a repository from one cached snapshot (used for the FAVORITES list after this session
|
||||||
|
// confirms it's no longer starred) rather than clearing the whole cache -- the row itself doesn't
|
||||||
|
// need to be re-added anywhere else on unstar, since ALL/organization listings show every
|
||||||
|
// repository regardless of starred state.
|
||||||
|
private fun removeFromCachedSnapshot(mode: RepositoryListMode, organization: String?, coordinates: RepositoryCoordinates) {
|
||||||
|
val key = RepositorySnapshotKey(mode, organization)
|
||||||
|
repositorySnapshots[key]?.let { page -> repositorySnapshots[key] = page.filterNot { it.coordinates == coordinates } }
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun loadOrganizationsOnce(): List<OrganizationSummary> {
|
private suspend fun loadOrganizationsOnce(): List<OrganizationSummary> {
|
||||||
cachedOrganizations?.let { return it }
|
cachedOrganizations?.let { return it }
|
||||||
val loaded = try {
|
val loaded = try {
|
||||||
|
|||||||
@ -357,6 +357,55 @@ class RepositoryListViewModelTest {
|
|||||||
assertEquals(FavoriteActionUiState.Idle, reloaded.favoriteAction)
|
assertEquals(FavoriteActionUiState.Idle, reloaded.favoriteAction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `starring a repository keeps its incremented count after switching to favorites and back`() = runTest(dispatcher.scheduler) {
|
||||||
|
// Reproduces a live bug report: starring from the all-repositories list, visiting the
|
||||||
|
// favorites tab, then coming back showed the star filled but the count reverted to its
|
||||||
|
// pre-toggle value -- loadRepositorySnapshot caches the ALL page for the rest of the
|
||||||
|
// session, so switching modes and back was reusing that stale, never-repatched snapshot
|
||||||
|
// instead of the count toggleFavorite already knew was right.
|
||||||
|
val browser = FakeBrowser(repositories = listOf(page1Of(repo("repo", starsCount = 0))))
|
||||||
|
val viewModel = viewModel(browser)
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val row = (viewModel.state.value as RepositoryListUiState.Content).repositories.single()
|
||||||
|
viewModel.toggleFavorite(row)
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
viewModel.showFavorites()
|
||||||
|
advanceUntilIdle()
|
||||||
|
viewModel.showAllRepositories()
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val reloaded = (viewModel.state.value as RepositoryListUiState.Content).repositories.single()
|
||||||
|
assertEquals(FavoriteActionUiState.Starred, reloaded.favoriteAction)
|
||||||
|
assertEquals(1, reloaded.starsCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `un-starring keeps its decremented count after switching to favorites and back`() = runTest(dispatcher.scheduler) {
|
||||||
|
val browser = FakeBrowser(
|
||||||
|
repositories = listOf(page1Of(repo("repo", starsCount = 4))),
|
||||||
|
starred = listOf(page1Of(repo("repo", starsCount = 4))),
|
||||||
|
)
|
||||||
|
val viewModel = viewModel(browser)
|
||||||
|
advanceUntilIdle()
|
||||||
|
val row = (viewModel.state.value as RepositoryListUiState.Content).repositories.single()
|
||||||
|
assertEquals(FavoriteActionUiState.Starred, row.favoriteAction)
|
||||||
|
|
||||||
|
viewModel.toggleFavorite(row)
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
viewModel.showFavorites()
|
||||||
|
advanceUntilIdle()
|
||||||
|
viewModel.showAllRepositories()
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val reloaded = (viewModel.state.value as RepositoryListUiState.Content).repositories.single()
|
||||||
|
assertEquals(FavoriteActionUiState.Idle, reloaded.favoriteAction)
|
||||||
|
assertEquals(3, reloaded.starsCount)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `starring a repository from the all-repositories list marks it starred without removing it`() = runTest(dispatcher.scheduler) {
|
fun `starring a repository from the all-repositories list marks it starred without removing it`() = runTest(dispatcher.scheduler) {
|
||||||
val browser = FakeBrowser(repositories = listOf(page1Of(repo("repo"))))
|
val browser = FakeBrowser(repositories = listOf(page1Of(repo("repo"))))
|
||||||
|
|||||||
@ -797,3 +797,51 @@ This is the append-only implementation and handoff record shared by Codex and Cl
|
|||||||
- Next recommended task: continue the broader design-review pass (work-item/PR detail views with real
|
- Next recommended task: continue the broader design-review pass (work-item/PR detail views with real
|
||||||
content, file viewers) from where TASK-039 left off.
|
content, file viewers) from where TASK-039 left off.
|
||||||
- Next owner: Claude, continuing per the standing direction.
|
- Next owner: Claude, continuing per the standing direction.
|
||||||
|
|
||||||
|
## 2026-08-29 (continued) — TASK-041: favorite star reverted / missing from favorites after tab switch
|
||||||
|
|
||||||
|
- Agent and role: Claude, direct continuation of the same live session. Live bug report mid-turn while
|
||||||
|
reviewing another screen: "즐겨찾기 누르고나면 카운팅은 되는데 즐겨찾기 탭에 가면 방금 누른 항목이
|
||||||
|
안떠있다. 그리고 다시 원래 탭인 레포지토리로 가보면 다시 즐겨찾기가 풀려있어." Paused the in-progress
|
||||||
|
work and switched to reproducing and fixing this immediately, per the standing priority of live bug
|
||||||
|
reports over open-ended review work.
|
||||||
|
- Commit/diff: on `claude/task-015-notifications`; `RepositoryListViewModel.kt`'s `toggleFavorite`
|
||||||
|
reworked to patch `repositorySnapshots` (not just `starredCoordinatesCache`) on every successful
|
||||||
|
star/unstar; two new tests in `RepositoryListViewModelTest.kt`;
|
||||||
|
`tasks/041-favorite-star-reverts-after-tab-switch.md`.
|
||||||
|
- Root cause: `repositorySnapshots` (the per-mode full-repository-list cache, fetched once per session
|
||||||
|
and reused on every later visit to that mode) was never patched by `toggleFavorite` — only the
|
||||||
|
separate `starredCoordinatesCache` was. So the star icon correctly showed filled (from the patched
|
||||||
|
cache), but the displayed `starsCount` reverted to whatever was cached from the very first load of
|
||||||
|
that mode, and a favorites tab already cached from an earlier visit kept silently missing a
|
||||||
|
newly-starred repository.
|
||||||
|
- How it was diagnosed: reproduced live on-device (star a repository, switch to 즐겨찾기, switch back —
|
||||||
|
watched the star/count go wrong exactly as reported). Added temporary debug-only `Log.w` logging of
|
||||||
|
the star/unstar HTTP response directly in `GiteaRepositoryBrowserApi` to rule out a failed request —
|
||||||
|
confirmed `HTTP 204` (success) every time, isolating the bug to client-side caching, not the network
|
||||||
|
call. Removed the temporary logging once the root cause was confirmed.
|
||||||
|
- How it was fixed: tried a "clear the whole cache on every toggle, force a refetch" approach first;
|
||||||
|
reverted after live testing showed Gitea's own starsCount on the plain repository-listing endpoint
|
||||||
|
lags slightly behind a star/unstar (the /user/starred listing reflected a toggle sooner) — forcing a
|
||||||
|
refetch would trade one race condition for another. Switched to a local patch instead: two new
|
||||||
|
private helpers (`adjustCachedStarCounts`, `removeFromCachedSnapshot`) keep every cached snapshot
|
||||||
|
that includes the toggled repository consistent with what the app already knows happened, without a
|
||||||
|
network round trip. A star also invalidates just the FAVORITES snapshot key if it was already cached
|
||||||
|
(can't surgically insert a row without a full domain object at that call site) so the next visit
|
||||||
|
fetches it fresh instead of silently missing the new star.
|
||||||
|
- Files changed: `feature/repositories/RepositoryListViewModel.kt`,
|
||||||
|
`feature/repositories/RepositoryListViewModelTest.kt` (test file, actually under
|
||||||
|
`app/src/test/java/...`), `tasks/041-favorite-star-reverts-after-tab-switch.md`.
|
||||||
|
- Checks and results: `./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug`
|
||||||
|
BUILD SUCCESSFUL, every pre-existing favorite-toggle test passing unmodified plus two new regression
|
||||||
|
tests, 0 lint errors.
|
||||||
|
- Live verification: installed over wireless `adb`. Starred a never-before-touched repository
|
||||||
|
(`LGD-AP4-RPR`) from the ALL tab, confirmed it appeared in 즐겨찾기 (★1), switched back to 전체
|
||||||
|
저장소 and confirmed the star/count stayed correct (★1) instead of reverting — screenshots at each
|
||||||
|
step.
|
||||||
|
- Review findings and resolutions: None from a separate review pass.
|
||||||
|
- Known limitations: None outstanding for this task.
|
||||||
|
- Next recommended task: resume the design-review pass (TASK-039's known limitations: work-item/PR
|
||||||
|
detail views with real content, file viewers, extended dark-mode coverage) from where it was paused
|
||||||
|
for this bug fix.
|
||||||
|
- Next owner: Claude, continuing per the standing direction.
|
||||||
|
|||||||
113
tasks/041-favorite-star-reverts-after-tab-switch.md
Normal file
113
tasks/041-favorite-star-reverts-after-tab-switch.md
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# TASK-041: Favorite star reverted / missing from favorites after switching tabs
|
||||||
|
|
||||||
|
Status: implemented; all required checks pass; live-confirmed on the human product owner's device
|
||||||
|
Owner: Claude
|
||||||
|
Reviewer: Codex
|
||||||
|
|
||||||
|
## Outcome
|
||||||
|
|
||||||
|
Live bug report: "즐겨찾기 누르고나면 카운팅은 되는데 즐겨찾기 탭에 가면 방금 누른 항목이 안떠있다.
|
||||||
|
그리고 다시 원래 탭인 레포지토리로 가보면 다시 즐겨찾기가 풀려있어" (starring a repository counts up,
|
||||||
|
but it doesn't show up on the favorites tab, and going back to the repository tab the star looks
|
||||||
|
undone again).
|
||||||
|
|
||||||
|
Root cause: `RepositoryListViewModel` caches each mode's full repository list once per session
|
||||||
|
(`repositorySnapshots`, keyed by mode/organization) and reuses it on every later visit to that mode
|
||||||
|
without refetching. `toggleFavorite`'s success path already kept a *second*, separate cache
|
||||||
|
(`starredCoordinatesCache`, used only for the ALL list's "is this already starred" cross-reference) in
|
||||||
|
sync with a successful star/unstar — but never touched `repositorySnapshots` itself. So after starring
|
||||||
|
a repository from the ALL tab: the star icon correctly showed filled (from the patched
|
||||||
|
`starredCoordinatesCache`), but its `starsCount` reverted to whatever `repositorySnapshots` had cached
|
||||||
|
from the very first ALL-tab load, before the star happened — and the FAVORITES tab, if its snapshot was
|
||||||
|
already cached from an earlier visit, kept showing its own pre-star list, silently missing the new
|
||||||
|
star. Confirmed live: the actual `PUT /api/v1/user/starred/...` call was succeeding (`HTTP 204`, added
|
||||||
|
temporary debug logging to verify), and Gitea's `/user/starred` listing reflected the toggle almost
|
||||||
|
immediately, but its plain repository-listing endpoint (`/user/repos`) was observed to lag behind on
|
||||||
|
`starsCount` for a bit — both real UI symptoms trace to this same repositorySnapshots gap.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
- Included: `feature/repositories/RepositoryListViewModel.kt`'s `toggleFavorite` — patches
|
||||||
|
`repositorySnapshots` (not just `starredCoordinatesCache`) on every successful star/unstar; two new
|
||||||
|
private helpers (`adjustCachedStarCounts`, `removeFromCachedSnapshot`); the FAVORITES-mode unstar
|
||||||
|
branch now also updates `starredCoordinatesCache` (previously only the ALL-mode branches did).
|
||||||
|
- Excluded: no change to how `repositorySnapshots`/`starredCoordinatesCache` are populated or
|
||||||
|
invalidated elsewhere (`refreshRepositories()`, `logout()` already clear both correctly — untouched).
|
||||||
|
No change to the actual star/unstar HTTP calls themselves (confirmed already correct).
|
||||||
|
|
||||||
|
## Design notes
|
||||||
|
|
||||||
|
- **A local patch, not a cache-clearing forced refetch.** The tempting alternative — just call
|
||||||
|
`repositorySnapshots.clear()` on every successful toggle, forcing a fresh fetch next time each mode
|
||||||
|
is opened — was tried first and reverted after live testing showed Gitea's own `starsCount` on the
|
||||||
|
plain repository-listing endpoint lags slightly behind a star/unstar (the `/user/starred` listing
|
||||||
|
reflected a toggle before the plain repository listing did). Forcing a refetch would trade one race
|
||||||
|
condition (a frozen-forever local cache) for another (trusting a server response that hasn't caught
|
||||||
|
up yet) — and would have undone this app's own established "the client already knows the truth,
|
||||||
|
don't wait on the server to agree" philosophy from TASK-034's optimistic-UI fix. Patching the cached
|
||||||
|
count directly, the same way `starredCoordinatesCache` was already being patched, keeps the display
|
||||||
|
correct immediately and doesn't depend on Gitea's timing at all.
|
||||||
|
- **The FAVORITES snapshot's *membership* (not just count) is different**: removing a repository from
|
||||||
|
a cached FAVORITES snapshot on unstar is a simple filter (`removeFromCachedSnapshot`) since no new
|
||||||
|
data is needed. Adding one on star can't be done the same way — inserting a row into that cached list
|
||||||
|
would need a full `RepositorySummary`, which `toggleFavorite` only has as a `RepositoryRowUiModel` (a
|
||||||
|
UI projection, not the domain type, and not guaranteed to carry every field). Rather than
|
||||||
|
reconstructing one and risking a subtly-wrong synthetic entry, a star instead invalidates just the
|
||||||
|
FAVORITES snapshot key (`repositorySnapshots.remove(...)`) if it was already cached, so the next
|
||||||
|
visit fetches it fresh — a single, targeted extra network call only when that specific list was
|
||||||
|
already stale, not a blanket invalidation of everything.
|
||||||
|
- **`starredCoordinatesCache` now updates on the FAVORITES-mode unstar branch too.** It previously only
|
||||||
|
updated on the two ALL-mode branches — a real, separate gap: unstarring from the FAVORITES tab left
|
||||||
|
the ALL tab's "already starred" cross-reference stale for that repository until the next full
|
||||||
|
session-cache invalidation.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [x] Starring a repository from the ALL tab, then switching to FAVORITES, shows the newly-starred
|
||||||
|
repository there (not silently missing).
|
||||||
|
- [x] Switching back to ALL after that shows the correct, incremented star count — not reverted to the
|
||||||
|
pre-toggle cached value.
|
||||||
|
- [x] Unstarring (from either tab) keeps the count/membership consistent across the same round trip.
|
||||||
|
- [x] Every existing favorite-toggle test still passes unmodified.
|
||||||
|
- [x] Two new regression tests cover the exact reported scenario (star-then-switch-tabs-and-back,
|
||||||
|
unstar-then-switch-tabs-and-back), both asserting the count stays correct after the round trip.
|
||||||
|
- [x] Build, unit tests, and lint pass.
|
||||||
|
- [x] Live-confirmed on the human product owner's device: starred a never-before-touched repository,
|
||||||
|
confirmed it appeared correctly in 즐겨찾기, switched back to 전체 저장소, confirmed the star and
|
||||||
|
count (★1) both stayed correct instead of reverting.
|
||||||
|
|
||||||
|
## Required checks
|
||||||
|
|
||||||
|
```text
|
||||||
|
./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug
|
||||||
|
```
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
- `feature/repositories/RepositoryListViewModel.kt`: `toggleFavorite`'s three success branches now
|
||||||
|
each patch `repositorySnapshots` via the new `adjustCachedStarCounts`/`removeFromCachedSnapshot`
|
||||||
|
helpers, alongside the existing `starredCoordinatesCache` patch (now present on all three branches,
|
||||||
|
not just the two ALL-mode ones).
|
||||||
|
- `RepositoryListViewModelTest.kt`: two new tests — `starring a repository keeps its incremented count
|
||||||
|
after switching to favorites and back` and `un-starring keeps its decremented count after switching
|
||||||
|
to favorites and back` — plus every pre-existing favorite-toggle test (increment, repeat-tap-toggle,
|
||||||
|
round-trip, immediate-optimistic-update, rollback-on-failure for both directions, the existing
|
||||||
|
already-session-known-starred-cache test) passing unmodified.
|
||||||
|
- Live debugging: temporarily added debug-only `Log.w` logging of the star/unstar HTTP status directly
|
||||||
|
in `GiteaRepositoryBrowserApi.star`/`unstar` to confirm the actual server response
|
||||||
|
(`HTTP 204`, i.e. success) before concluding the bug was client-side caching, not a failed request;
|
||||||
|
removed once the root cause was confirmed.
|
||||||
|
- `./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug`:
|
||||||
|
BUILD SUCCESSFUL, all unit tests passing (including the two new ones), 0 lint errors.
|
||||||
|
- Live device: installed over wireless `adb`. Starred `LGD-AP4-RPR` (a repository never previously
|
||||||
|
touched this session) from the ALL tab (screenshot: ★1). Switched to 즐겨찾기 — confirmed it appears
|
||||||
|
there (screenshot: ★1, alongside the other already-starred repositories). Switched back to 전체
|
||||||
|
저장소 — confirmed it still shows ★1, not reverted to ☆0/★0 as before the fix (screenshot).
|
||||||
|
|
||||||
|
## Known limitations
|
||||||
|
|
||||||
|
None outstanding for this task.
|
||||||
|
|
||||||
|
## Review findings
|
||||||
|
|
||||||
|
None yet — pending Codex/human review.
|
||||||
Loading…
x
Reference in New Issue
Block a user