Living documentation
SplitSheet scenario storyboard
Each scenario is a recipe e2e test, replayed as a storyboard: the setup, then every user action and the exact Telegram screen it produced, with the test's assertions shown where they hold. Pick one from the left.
onboarding: bot added to a group
command: /start
expense: add by reply (RULE 1)
expense: base change converts every amount (bare, currencied, settlement)
acceptance: 6250 HUF on a € sheet (bug 372390c7)
clarification: redelivered callback is deduped
expense: currencied (frozen rate via world.fx)
expense: edit re-parses (RULE 3)
expense: legacy symbol base
expense: modify by reply (RULE 2)
expense: multi-currency rendering
expense: duplicate update is deduped
expense: simplify-debts toggle (action route)
clarification: ask and pick
clarification: answer by replying with text
resolution: new-member notice lists the expenses they were left out of
resolution: @mention resolves when the user acts
menu: welcome language navigation
menu: set currency from the inline button
webapp: change currency
webapp: debts teaser badge
webapp: desktop two-column layout
webapp: add expense
- a chat reply to the announcement modifies the same expense
- a currencied add freezes its setRate, converts, and stays computable
- adds a new expense over HTTP: the bot replies to the sheet, its id becomes the replyTreeId, the pin updates
- adds even when the sheet has no pinned message, sending the announcement unanchored
- blocks an add at the cap with the expense-cap shape; the unlock payment lifts it
- escapes HTML-hostile description in the announcement and the pin, keeps raw text in storage
- fails with 409 when the bot cannot post the announcement, persisting nothing
- never cap-blocks edits, removes or restores of existing expenses
- rejects an add from a non-member with 403 and persists nothing
- rejects an invalid add with 400 (share for a non-member)
webapp: edit announcements
- a chat reply to the edit announcement reconciles against the announced body
- a chat reply-modify pushes the next webapp edit downthread (replies to the user message)
- a remove announced in place is re-rendered back on undo restore
- a webapp remove posts a struck-through announcement; restoring right after deletes it (undo)
- an in-place announcement edit failure falls back to the invisible write
- an in-place edit by the adder keeps the plain added label (Telegram badge marks the edit)
- chat-created: the first webapp edit replies to the source message, the second edits that reply in place
- remove → restore (undo) → remove again posts a fresh announcement
- webapp-created, untouched: an edit by another member rewrites the announcement in place
- when the undo delete fails (48h window), a normal restored announcement is posted
webapp: expense edit / remove / restore
- edits an expense over HTTP (amount, payers, shares, description change)
- edits to a new currency, seeding its setRate and keeping totals computable
- edits with an exact (unequal) split that round-trips over HTTP
- edits with two payers (multi-payer) that round-trip over HTTP
- persists an UNANNOUNCED webapp edit invisibly, then a later telegram edit re-parses
- reconciles a 1-cent share drift via processExpense instead of rejecting
- rejects a guest (non-member) save and remove with 403
- rejects a share sum that drifts beyond what processExpense can reconcile
- rejects an invalid payload with 400 (share for a non-member)
- removes an expense over HTTP (tombstoned, excluded from totals)
- restores a bare expense by re-sending its detected base currency, value-preserving
- restores a removed expense (save after remove, same body, removedAt cleared)
- stamps source: webapp on the modify and remove events
webapp: idempotency-keyed add
webapp: live updates while the view is open
webapp: paid-by card
- censors amounts and offers an Unlock-balances CTA when balances are locked
- expands in place via "Show all" when the payer list overflows
- lists each payer with amounts, biggest first, in the sheet currency
- stays hidden until there is a verdict to summarize
- tapping a redacted amount also opens the Debts payment methods