C.W.K.
Stream
Lesson 03 of 05 · published

Branch to Promote

~11 min · promotion, branching, continuity, reuse

Level 0Dead Zone
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Promotion isn't an upload. It's a branch — the same move the backend already knows, pointed at a phone-born conversation."

From a Quick Question to a Real Thread

Sometimes a question you fired off from the phone turns out to be the start of something bigger — you want to keep going in a full conversation, with branching and all the backend surfaces. In a draft-then-upload world this would be a scary export: package the phone's state, send it, hope it reconstructs faithfully. In Pippa Go it's almost anticlimactic, and that's the point. Because the phone-born conversation was already canonical, promoting it to an ordinary full conversation is just a branch in the backend — the exact operation the system already performs on any conversation.

Why 'Canonical From Birth' Makes Promotion Free

Notice how the earlier promise pays off here. If the phone conversation were a local draft, promotion would need a bespoke migration path: serialize, upload, map IDs, rebuild history, handle partial failures. Because it's canonical from birth, none of that exists. The conversation is already in the backend with full history; "promote" means "branch from it and continue," reusing the same branching machinery that every other conversation uses. The feature you'd expect to be the hardest — turning a phone snippet into a full thread — is nearly no code, because an earlier decision refused to create the gap that would have required it.

Reuse Over Reinvention

This is a general lesson wearing a specific costume. When a new capability (promote a phone Q/A) turns out to be an existing capability (branch a conversation) pointed at a new starting point, the right move is to reuse the existing machinery, not build a parallel path. A bespoke "phone promotion" pipeline would be a second way to do something the system already does — more code, more bugs, more drift. Branch-to-promote keeps one branching implementation serving every case. The elegance isn't cleverness; it's the payoff of having refused to fork the conversation in the first place.

Code

Promote = branch an already-canonical conversation·typescript
// A phone-born conversation is already canonical, so 'promote' reuses branching.
async function promoteToFullConversation(phoneConvId: string) {
  // No export, no upload, no ID remapping — it's already in the backend.
  return branchConversation(phoneConvId); // the SAME call any conversation uses
}

// Compare the draft-then-upload version you DON'T have to write:
//   serialize(phoneState) -> upload() -> remapIds() -> rebuildHistory()
//   -> handlePartialFailure() -> reconcile()
// All of that collapses to one existing branch() call.

External links

Exercise

List the steps a draft-then-upload client would need to promote a phone conversation to a full one (serialize, upload, remap, rebuild, reconcile). Then write the branch-to-promote version. Count the lines and the failure modes in each. Finally, name the earlier design decision that made the short version possible — and note that the elegance here was purchased back then, not here.
Hint
Every step in the long version exists to bridge a gap between two sources of truth. Canonical-from-birth removed the gap, so branch-to-promote inherits an empty bridge — one reused call instead of a migration pipeline. The savings were front-loaded into the earlier decision.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.