You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(scratchlist): address HAPI Bot Major findings on PR tiann#896
Two real data-correctness paths the bot caught on the initial review.
1. Migration partial-failure data loss
The migration loop swallowed each failed POST and still wrote the
`migrated` flag, while the offline-cache effect mirrored the
(partial) hub state back into `hapi.scratchlist.v1.<sessionId>` -
so a transient error or cap rejection could leave entries neither
on the hub nor in localStorage. Fix:
- Track failed entries during migration and persist them back to
localStorage; do NOT advance the flag if any entry failed, so a
future mount retries.
- Gate the offline-cache effect on the migration flag. Pre-
migration, localStorage holds the v1 entries the migration
reads; mirroring an empty hub fetch over them was the wipe.
- Drop the "skip migration when hub is non-empty" gate. Combined
with the duplicate-idempotent POST short-circuit (below), a
retry against a session that another device already populated
is a safe union.
2. Duplicate POST returned 409 at cap
The route checked `count >= SCRATCHLIST_MAX_ENTRIES` BEFORE asking
the store whether the supplied `entryId` already existed, so an
idempotent migration retry against a 200-row session returned 409
instead of 200. Fix: check duplicate first via a new
`SyncEngine.getScratchlistEntry`, return the existing row with 200,
and only run the cap check for genuinely new ids.
Tests added:
- hub/routes: at-cap + duplicate entryId returns 200 (not 409); at-cap
+ new entryId still 409.
- web/hook: partial-failure persists the failed entries back to
localStorage and leaves the flag unset; offline-cache effect does
not wipe pre-migration localStorage.
Co-authored-by: Cursor <cursoragent@cursor.com>
0 commit comments