Round Cloud Save
Lets a signed-in user save a whole round (the tournament/debaters/judges wrapper around a set of flows) to their account and load it back on any device.
- Nav:
FlowHistoryDialog's "Rounds" tab — a cloud-upload icon per round, "Save all rounds" and "Save flows not in a round" buttons - Package:
debate-round(dialog + validation + fetch client),apps/debate-ai.com(/api/rounds,saved_roundsD1 table)
What it does
A Round only references its flows indirectly via flowIds, so saving a
round also saves each flow it references first. "Save all rounds" and
"Save flows not in a round" cover the bulk cases. The "Saved to account"
tab's Flows section badges a flow "via round" when it was only saved as
part of a round's cascade.
The round save is optimistic-concurrency checked, mirroring Flow Cloud
Save: it sends along the updatedAt of
the cloud copy this browser last knew about (from the last list/load/save
response it saw). If that doesn't match what's actually saved — someone
else saved a newer version since — the save is rejected with a conflict
instead of silently overwriting it, and the round's cloud icon turns into a
warning that a second click (an explicit "save anyway") resolves. This
covers the round row itself; each referenced flow's own save still goes
through flow cloud save's own conflict check independently.
Pinned ("Featured") debates follow the account too: pinning a round is stored
as a pinnedDebates tool record ({ id: "<round id>", pinnedAt }, via
/api/tool-records/pinnedDebates), so the Featured section on the start screen
matches across devices. Pins from before this change are plain numbers in
localStorage; they are still read, and are upgraded (and start syncing) the
next time any pin is toggled on that browser.
Data flow
state/bulkRoundSave.ts (pure) — collectFlowsForRounds / collectUnreferencedFlows
state/savedRounds.ts (pure) — isValidRound / deriveRoundLabel / hasRoundSaveConflict
round/saved-rounds-client.ts (fetch) — list/fetch/save/delete
apps/debate-ai.com/app/api/rounds/[route.ts, [clientId]/route.ts]Dirty tracking on bulk saves
"Save all rounds" and "Save flows not in a round" skip re-PUTting a flow or
round whose content hasn't changed since it was last saved successfully this
session: state/bulkRoundSave.ts's hashFlowContent/hashRoundContent
fingerprint each item's JSON payload, and filterDirtyFlows/
filterDirtyRounds compare that against a hash recorded after each
successful save (FlowHistoryDialog's lastSavedFlowHashes/
lastSavedRoundHashes state, which — unlike the per-item save-status maps —
survives the dialog closing and reopening). A clean item is reported as
"saved" in the bulk summary without a network round-trip. The per-item cloud
icon is unaffected and always saves, since that's an explicit user action.
This closes the "no dirty tracking" half of the gap this section used to
record (#810); the hash cache only lives for the current page session, so a
fresh page load re-saves everything once, same as before.
Pinned debates follow your account
The star on a round in the history dialog (and the Featured section of the
debate start screen it feeds) used to live only in one browser. Pins are now
{ id, roundId, pinnedAt } records under the pinnedDebates key, one entry in
the Tool Data Sync catalog (@debate/data-sync), so a signed-in user's
featured rounds appear on every device. A round's local id is also its
saved_rounds.client_id, so a pin resolves to the same round once that round
has been saved to the account. A pin whose round is not saved or present on the
current device is skipped rather than shown. The older pinned-debates id list
is read once as a fallback and replaced on the first pin change. When pins from
two devices add up to more than 12, the start screen shows the newest 12.
Flow editor settings follow your account
The flow editor's preferences - font, default zoom, theme, side colors, vim in
the RFD editor, paste/append behavior, scroll zoom, tooltips, CardMirror options
and your custom keyboard shortcuts - are stored as two records (display and
keymap) under the ebbSyncedSettings key, one entry in the Tool Data Sync
catalog. Signing in on another device applies them there, live. Settings that
describe a machine rather than you stay local: the flows folder, panel layout
(sidebar, RFD drawer) and the live-collab toggles, name and contacts. When a
device syncs, the account's copy of a record replaces the local one as a whole,
so the last device to sync wins for all synced settings at once.
