Skip to content
C.W.K.
Stream
Lesson 03 of 05 · published

The Journal Before the Screen

~12 min · journal, replay, retention, sequencing, daemon

Level 0Spark
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Live Is a Subscriber, Not the Store

A terminal you walk away from has to remember what happened while you were gone. The naive design writes bytes to the screen and hopes the screen is still there. That design is a projection pretending to be a store. Smolder sequences output into a bounded journal first, then publishes to whoever is attached. The journal is the ordered record. The screen is a subscriber. If you reverse those, a crash of the window becomes a hole in history, and a phone that reconnects has nothing honest to catch up on.

Bounded is not a performance footnote. An unbounded journal is a disk that grows until the daemon is no longer small. A bound — a ring of retained output, old chunks dropped — is how the owner stays restartable. You do not get infinite scrollback as a side effect of ownership. You get a truthful prefix of what the process has emitted lately, and you know it is a prefix.

Storage Failure Must Not Kill Live

If the journal cannot write — disk full, permission, a volume that went away — live output still has to reach an attached projection. Retention degrades. The fire does not. A daemon that refuses to print because it cannot file is a daemon that has confused bookkeeping with the job. The operator should see that retention is degraded. They should not see a frozen pane because a log file argued.

That split is the same ownership split as the first lesson, applied to bytes. The process is alive. The drawing surface may be gone. The store may be limping. Only the process's death is allowed to end the stream. Everything else is a subscriber having a bad day, and a subscriber's bad day is not a kill.

Replay Is Not Re-running

When a projection attaches, it replays the retained journal into the emulator so the screen looks like a place, not a blank. Replay suppresses side effects. It does not re-send the bytes to the child. It does not re-fire bells as if they were happening now. It does not re-run commands. It paints history. A replay that talks back to the process is how you duplicate a prompt, or worse, duplicate a submit.

An incomplete prefix is not "in sync." If the journal dropped the oldest chunk, the screen starts in the middle of a line, or in the middle of a TUI frame, or after a clear that you no longer have. The honest UI names that. A spinner that says "caught up" over a truncated ring is how people start trusting a reconstructed screen that was never complete. Catch-up means "this is what we still have," not "this is everything that ever happened."

Sequence into the journal, then publish to the screen. Live continues if storage limps. Replay paints; it does not talk back. An incomplete prefix is a prefix, not a sync badge.

Code

Order of bytes, and what replay is allowed to do·text
child PTY  -->  sequencer  -->  bounded journal  -->  attached projections
                     |
                     +-- if journal write fails: still publish live
                         mark retention degraded, do not freeze the pane

# Attach / reconnect
  1. replay retained prefix into the emulator   (paint only)
  2. subscribe to live                          (from here on)
  3. never tell the child that replay happened

# Replay must suppress
  bells, title-as-event, bracketed-paste replies,
  anything that would look like input or a fresh side effect

# Honest catch-up
  prefix_complete == false  =>  "retained output, not full history"
  prefix_complete == true   =>  still not "everything since boot"
                                only "everything still in the ring"

External links

Exercise

List three things that must happen when a projection attaches after ten minutes away, and three things that must not. At least one "must not" should be a side effect (bell, title, input). At least one "must" should name what you say if the retained prefix is incomplete.
Hint
If your "must" list includes talking to the child, you have confused replay with re-run. If your "must not" list has no words for the operator, you have confused a truncated ring with being in sync.

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.