fix: an imported backup no longer rolls progress back
The progress store merged like the mark stores do, keeping whichever copy had the earlier timestamp. That is right for a mark — `at` is when the reader made it, membership is the whole fact, and the oldest stamp is the truest one — and wrong here, because this record *is* the data. A status, an effort, a note and whether an event repeats all live in it, and `at` says when one of those last changed. So the earlier copy winning discarded every edit made after it, in both of the directions an import actually happens in: restoring a backup taken before an evening's work undid the evening, and importing an old file onto a device with newer progress rolled the device back. Neither is recoverable — there is no account and no server holding a second copy. The later record wins now. Nothing is removed in either direction, and taking the maximum of two timestamps is as order-independent and idempotent as the rule it replaces. `mergeProgress` came out of the hook to be tested, which is also how the ignored store's opposite rule is now written down rather than assumed. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7bb7dc843c
commit
f9ef21a366
+12
-1
@@ -563,7 +563,18 @@ event whose lane is missing.
|
||||
|
||||
Import **merges** every set: a mark present in either the file or the current device survives, and
|
||||
import never removes one. `daily` merges as a **union of days per ID** — every day either side
|
||||
recorded is a day the reader actually played. An export written before daily checklists existed
|
||||
recorded is a day the reader actually played.
|
||||
|
||||
**Which copy wins a conflict differs by store, and the difference is the shape of the data.** For
|
||||
`ignored` (and the legacy `completions`) the **earlier** mark wins: `at` records when the reader made
|
||||
it, membership in the set is the whole fact, and the oldest timestamp is the truest answer to when
|
||||
they said it. For `progress` the **later** record wins, because there the record *is* the data — a
|
||||
status, an effort, a note, whether it repeats — and `at` is when one of those last changed. Keeping
|
||||
the earlier copy there discards every edit made after it, in both directions an import happens in:
|
||||
restoring a backup taken before an evening's work would roll that evening back, and importing an old
|
||||
file onto a device with newer progress would roll the device back. Taking the maximum of the two
|
||||
timestamps keeps the merge order-independent and idempotent either way, and removes nothing.
|
||||
`mergeProgress` is pure and `test/progress.test.ts` pins it. An export written before daily checklists existed
|
||||
simply has no `daily` key, which is not an error. Losing a user's marks to a bad import is unrecoverable, so the merge is
|
||||
deliberately one-directional. A file whose `format` is unrecognised is refused outright rather than
|
||||
partly applied.
|
||||
|
||||
Reference in New Issue
Block a user