Notifications should describe changed state

D4U7 replaced activity pings with revision-aware digests that named decisions, blockers, conflicts, and deadlines without converting attention into a score.

The first D4U7 notification said: 12 new activities in Reading Plan.

It was accurate and nearly useless.

Eleven activities were replies clarifying one question. The twelfth moved the decision deadline. A person returning to the room needed to know that the question was answered and the deadline had changed. The count inverted their importance.

I had built notifications from event volume because events were easy to observe. The product was supposed to help people recover state after time away.

The notification system needed to describe what changed, not merely prove that something happened.

Activity is an implementation fact

D4U7 stored room transitions, contribution revisions, comments, acknowledgements, and membership changes. Turning each event into a notification required almost no product model.

The result treated unlike actions as equivalent:

  • A typo correction and a new decision rationale both counted as one edit.
  • Five replies answering one question counted as five items.
  • A changed deadline counted as one item even though it changed when every response was due.
  • A reaction competed with an offline draft conflict for attention.
  • A rebuilt projection could accidentally look like new activity if notification state followed derived rows.

The event log remained valuable for history and projection. Notification was a separate interpretation: which state transition matters to this recipient now?

I stopped triggering from raw row creation and derived notification candidates from domain transitions. A candidate named the before and after state, affected object, reason for relevance, and revision interval.

The extra model let twelve events become two understandable changes.

A timestamp such as “last opened at” was a weak cursor. A background tab could open without receiving every event. Clock disagreement could place an event on the wrong side. Loading a page did not mean a person understood it.

D4U7 tracked two room cursors:

  • Delivered through: the highest continuous revision the client had accepted.
  • Acknowledged through: the revision the person explicitly said they had caught up to for consequential rooms.

The digest summarized domain changes after the acknowledged revision up to a named current revision. It did not mark the range read merely because a notification was delivered or clicked.

For lightweight rooms, opening the digest and reaching its end could offer a simple Caught up action. For final decisions or assigned actions, acknowledgement remained explicit at the object level.

The cursor was not a productivity measure. D4U7 did not rank people by how quickly they advanced it. It existed to create a reliable return path and avoid repeating changes already understood.

Revision identity made the digest reproducible even when delivery occurred much later.

Time-window grouping alone would bundle nearby events and split one slow conversation across several notifications. I grouped by the state transition being produced.

Five responses and an evidence link could resolve one question. The digest item became:

The recording question blocking Proposal B was answered. Two responses and one new source support the answer.

Three proposal revisions could become:

Proposal B changed since revision 4: the session moved to T04P and added a recording constraint.

The full chronology remained one expansion away. The summary did not need to quote or replace the authored work.

Some changes resisted grouping. A changed decision deadline and a revoked room membership affected different actions and remained separate even if they occurred in the same minute.

The grouper used typed relationships: replies to question, evidence linked to proposal, revision superseding revision, and decision referencing proposal. It did not attempt general natural-language summarization.

Structure made attention summaries deterministic enough to test.

Relevance came from relationship, not engagement prediction

A room change did not matter equally to every participant. D4U7 used explicit relationships:

  • You authored the proposal whose blocker was answered.
  • You were asked to review this decision revision.
  • You accepted the action whose deadline changed.
  • Your local outbox operation now conflicts with current state.
  • You follow the room's final-decision transition.

I did not create a hidden score based on clicks, time on page, message frequency, or inferred interest. Such a model would be difficult to explain and easy to turn into an attention feedback loop.

Participants selected room-level delivery preferences and a small set of transition types. The system could recommend a quieter default but could not silently promote activity because it predicted engagement.

Explicit relevance occasionally missed something a person would have wanted. That limitation was visible and correctable. A learned black box could produce more clicks while making the product's interruption policy impossible to reason about.

Quiet notifications began with declared responsibility.

The first implementation sent every notification immediately. This guaranteed freshness and trained the study group to mute the channel.

I created delivery classes:

  • Immediate: a current action became blocked close to its agreed deadline, a decision or membership change affected current authority, or local work required recovery before it could be delivered.
  • Scheduled digest: proposal revisions, answered questions, new evidence, and ordinary comments.
  • In-room only: reactions, low-consequence commentary, and informational history changes.

The classes were defaults, not universal truths. A participant could choose immediate decision notices or a daily digest. Quiet hours applied according to their chosen timezone, with true deadline consequences stated explicitly.

A mention did not automatically bypass preferences. Otherwise anyone could create urgency by adding a name. Mentioning established relevance; delivery policy still decided the channel and time.

Every immediate notification named why it could not wait. If the reason field was empty, the event belonged in a digest or room.

Urgency became an accountable product decision.

The notification was a pointer, not a copy of the room

It was tempting to include full proposal text, comments, or decision evidence in email and push payloads. That made the notification convenient and duplicated private content into more systems, lock screens, and retention policies.

D4U7 notifications used minimal safe text:

A decision was recorded in Reading Plan. One action awaits your response.

The link opened the authenticated room at the relevant immutable revision and returned through the digest context. Sensitive evidence, participant names, and authored text remained inside the application unless the room policy explicitly allowed more detail.

Email subjects were similarly restrained. Push payloads did not carry room content that could appear on a locked device. A participant could opt into richer previews for low-sensitivity rooms, but privacy-safe text was the baseline.

The notification stored stable object and revision IDs, not mutable URLs with broad tokens. The application rechecked current authorization at open.

Convenience outside the product boundary should not silently expand the number of places private work lives.

Delivery, opening, and acknowledgement were different events

The notification service could know that it handed a message to an email or push provider. It could sometimes receive a delivery result. The browser could know a link opened. None proved the participant understood the state change.

D4U7 kept the distinctions:

  • Queued: selected for a channel and time.
  • Handed off: the external delivery attempt was accepted.
  • Failed: the channel returned a terminal or retryable error.
  • Opened: the link reached the application under an authenticated session.
  • Acknowledged: the person explicitly advanced a revision or accepted a consequential object.

I avoided a public read-receipt panel. Delivery diagnostics helped the recipient manage their own channel and helped me repair the study system. They did not become a surveillance surface for other participants.

An action deadline could still show that required acceptance was missing because that was room state. It did not need to expose when someone opened the notification or how many minutes they spent reading.

The product cared about durable handoff, not attention telemetry.

Changed state could supersede a queued notification

A digest item might be queued at noon and become obsolete before the evening delivery. A question could be answered and later reopened. A decision could be amended. A conflict could be resolved from another device.

Sending every historical candidate would make the channel narrate state the room had already left.

Before delivery, D4U7 refreshed the notification projection. It could:

  • Replace several candidates with one current summary.
  • Mark an earlier change as resolved and omit it from urgent delivery.
  • Update the target revision.
  • Retain a historical transition when its occurrence still mattered.

For example, “your draft has a conflict” disappeared if the same account resolved it elsewhere. “The final decision changed twice” became one digest item linking the amendment chain; it did not pretend the first decision never existed.

The delivery job used a stable candidate identity and current projection version. Retrying did not send duplicate messages for the same resulting state.

Notifications described the best current handoff, not an immutable queue of every momentary alert.

Deadline reminders were easy to schedule and easy to make wrong. A room deadline could move after the job was queued. A participant could accept an action from another device. A timezone could change. A room could close early.

The scheduled job stored the room and condition identity, not only a pre-rendered message. At execution it loaded current state and current participant preferences. It sent only if the condition remained open and the notification window still applied.

Relative text such as “due tomorrow” was rendered using the recipient's current timezone and accompanied by an absolute date in the opened room. I avoided putting ambiguous local times in terse subjects.

The reminder named the missing transition:

Your response to Question 3 is still requested before the review closes T04P.

It did not say “You have been inactive.” The product could observe an open request and deadline. It could not infer effort or intent.

Scheduled attention followed current domain state, not an old timer's memory.

Quiet hours were a correctness feature

Sending a low-consequence digest at an unwanted hour is more than a preference annoyance. It teaches people that the system's urgency model does not respect their time.

Participants selected a delivery window and timezone. D4U7 stored the timezone identity rather than one fixed UTC offset so daylight changes could be interpreted appropriately. A scheduled digest used the current preference at execution.

Immediate-class events could either respect quiet hours fully or use a participant-selected exception for named consequential transitions. The default study configuration had no overnight interruption because the synthetic rooms did not justify one.

If a deadline fell outside someone's window, the room creator could see the scheduling mismatch while setting the request. The product encouraged moving the deadline or choosing a delegate rather than relying on an interrupt.

I did not infer sleep from presence or historical behavior. The person authored the boundary.

Attention design became part of domain scheduling, not a final email setting.

A long digest could reproduce the same wall of chronology it was meant to replace. I organized it by consequence:

  1. Decisions and amendments.
  2. Actions requiring this participant.
  3. Blockers answered or introduced.
  4. Material proposal and evidence changes.
  5. Other followed updates.

Within each section, items grouped by room and transition. The digest stated its revision range and offered a direct path to acknowledge the room after review.

The interface used headings, lists, and links whose labels named the destination. It did not rely on color dots or collapse every item into a card grid. Keyboard focus returned predictably when expanding history.

Email was a simpler projection of the same model, not a separately authored summary. Plain-text output remained complete. Links used signed short-lived navigation state only where necessary and still required normal authorization.

The hierarchy made “what needs me?” answerable before “what else happened?”

Failure should not create more noise than the notification

External delivery can fail temporarily or permanently. Retrying every failure aggressively could send duplicates after ambiguous provider responses.

Each delivery had a stable ID, channel, rendered-content digest, and attempt history. Retry policy used bounded backoff and provider-specific outcome classes. A timeout remained unknown until the channel's semantics or deduplication boundary allowed another safe attempt.

For scheduled digests, a delayed retry re-projected current state before sending. It did not deliver an outdated snapshot merely because rendering had succeeded earlier.

Permanent email failure disabled that address for D4U7 delivery and surfaced the issue privately to the participant inside the application. It did not announce their channel problem to the room. Push subscription expiration removed the subscription after a defined response.

Notification-system failure never blocked room changes. Domain state remained durable and visible on the next visit.

The channel was a convenience for returning attention, not the source of truth.

Labels such as “important updates” forced a participant to guess what the product considered important.

D4U7 described preferences with transition examples:

  • Decisions: a decision is recorded, amended, or reopened.
  • My actions: an accepted action changes scope, becomes blocked, or approaches its deadline.
  • Questions for me: a direct question is created, answered, or changed materially.
  • Followed proposals: the proposal or evidence set changes.
  • Conversation: comments and reactions, included only in the in-room feed by default.

Each category showed whether delivery was immediate, in the scheduled digest, or in-room only. A test notification verified the chosen channel without creating fake room activity.

Settings changes applied to future delivery projections and did not rewrite acknowledged state. Unsubscribing from email did not mark rooms read.

The examples made the attention contract inspectable without requiring knowledge of the underlying event schema.

I measured recovery, not clicks

The easiest notification metrics were open rate, click rate, and time to response. Optimizing them would reward urgency and volume.

The study evaluation asked different questions:

  • Could a returning participant identify the room's current decision state?
  • Did the digest expose the blocker or action that required them?
  • Did grouped updates preserve enough context to expand only when needed?
  • Did a notification ever describe state already superseded?
  • Could a participant distinguish delivery from acknowledgement?
  • Did quiet-hour and preference choices behave as stated?

I inspected notification volume as a cost, not an engagement goal. A release that cut pings while preserving recovery was an improvement. No fabricated adoption or productivity metric appeared.

One useful qualitative test asked a participant to explain why each received notification deserved its channel. If the answer was only “someone posted,” the policy needed revision.

Attention was a budget the product spent, not a funnel it tried to maximize.

Some changes should remain silent

The final design intentionally did not notify for every revision.

Typo corrections, reaction changes, projection rebuilds, read-state updates, and many comments stayed in room history. A participant could follow a high-interest conversation more closely, but the default respected the difference between available information and interruption.

Silence did not mean the event was lost. It remained in the chronology and could contribute to a later meaningful transition. Three clarifying comments might eventually answer a question; that answer would appear.

This reduced the fear that every edit would bother someone. Authors could improve prose without performing notification calculus. Consequential changes still received an explicit summary.

The system became quieter by modeling more, not by discarding history.

The final message carried a reason to return

The original “12 new activities” had one virtue: it proved the room was alive. D4U7 did not need to prove activity. It needed to help a person resume.

The revised digest said:

The recording question blocking Proposal B was answered. The review deadline moved to T04P. You have no unresolved draft conflicts.

Each sentence described changed state, linked to its revision, and implied what—if anything—the recipient needed to do. The eleven replies remained available behind the answered question.

Notifications could not replace reading or judgment. They could reduce the distance between an old mental model and current work without demanding continuous presence.

The product stopped counting activity as a reason to interrupt. It began treating every notification as a small handoff: what changed, why it matters to you, and where the durable state now lives.