listEntries({ parentId: X }) now applies the top-level rule relative to X: this user's
live entries on descendants of X (up to three levels) with no live-entry work strictly
between them and X, so it agrees with childSummary. Restoring an engagement's re-parenting
onto a soft-deleted entry throws ValidationError("entryId", "target entry is deleted").
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- upsertEntry inserts with ON CONFLICT DO NOTHING and patches through the update path,
so a concurrent creator never aborts the caller's transaction on Postgres.
- Undoing a move deletes the forward alias and writes no reverse alias.
- Merging into an existing entry keeps 'user' field_sources on combined fields, carries
the moved entry's field_sources as-is when reviving a deleted target, concatenates
differing review/private notes, records a dropped rating in history, and writes history
for re-parented engagements (restorable).
- Moves re-point this user's copies (with history) and list items to the target work.
- rejectSuggestion requires a pending suggestion; engagements of a deleted entry are not
editable; restoring an entry does not re-check custom fields against current definitions.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Engagements store partial dates as value + precision and track field_sources;
lists (list/grouping/thread, grouping-only rating/review) keep dense item
order and snapshot items in history; copies store price in cents. All three
restore through restoreVersion.
Co-Authored-By: Claude Opus 5.5 <[email protected]>