D4U7
An asynchronous decision space built for intermittent attention, weak connections, durable handoffs, and humane recovery.
Project brief
- Period
- 2020
- Status
- Archived
- Focus
- Asynchronous collaboration
- Constraint
- Decisions had to survive delayed attention and unreliable connectivity.
- Result
- Versioned rooms preserved evidence, dissent, drafts, and handoffs.
D4U7 was a 2020 personal project for making small group decisions across delayed attention, weak connections, and incompatible schedules. W93H had taught me that a good handoff preserves observations, open questions, recent actions, and the next safe step. D4U7 applied that lesson outside incident response.
A collaboration tool that did not demand presence
The remote-work shift made synchronous collaboration tools newly visible, but I was interested in the gaps between calls. A video meeting could produce energy and still leave no durable account of what had been decided, which alternatives had been rejected, or what a person returning tomorrow needed to read. Chat preserved messages and often buried the decision inside them.
I built the project for a small invited study circle using synthetic topics and low-consequence planning. It was not an employer tool or a claim about managing a real distributed organization. The personal setting let me experiment with attention and recovery without inventing business outcomes.
Each “room” held one decision or bounded piece of work. It had a brief, evidence, proposals, questions, a decision record, and follow-up actions. Live presence could help, but the room remained complete when nobody else was online.
The hard problem was not messaging. It was designing state that survived time.
The promise of a quiet room
I wrote a product contract:
- A person could understand the room’s purpose and current state without reading every message.
- Contributions remained attributable, versioned, and linkable.
- A tab left open overnight could recover without overwriting newer work.
- Drafting and reading supported intermittent connectivity.
- Notifications summarized meaningful state changes rather than reporting every keystroke.
- Decisions named their evidence, dissent, author, and revision.
- Keyboard and screen-reader workflows were complete, including after conflict or reconnect.
The project did not promise general real-time document editing. Avoiding that scope was deliberate. D4U7 optimized for thoughtful contributions and explicit transitions, not cursors moving in the same paragraph.
Compared with W93H, the system could not treat the record as a mostly append-only incident timeline. People would revise proposals, answer questions, and develop one document across hours or days. The model needed durable history and a humane way to handle concurrent edits.
A room was not a chat channel
The earliest prototype looked like chat with a pinned description. Test users responded conversationally, repeated questions, and treated the newest message as the current state. The structure reinforced the behavior I claimed to avoid.
I replaced the stream with typed contributions:
- Brief: what decision is being made, why now, and by when.
- Evidence: a source, observation, constraint, or result.
- Proposal: one possible course with tradeoffs.
- Question: a named gap that blocks or changes a decision.
- Response: an answer linked to the exact question version.
- Decision: selected proposal, rationale, dissent, and review trigger.
- Action: follow-up work with an owner label and state.
Each type had a distinct visual form and lifecycle. A question could be open, answered, or superseded. A proposal could be active, withdrawn, or incorporated. A decision could be amended without erasing its earlier version.
The room overview projected these contributions into a compact status: purpose, active proposals, open questions, latest decision, and outstanding actions. The full chronology remained available when sequence mattered.
Typed structure did not eliminate prose. It gave prose a durable relationship to the work.
Versioned documents instead of last-write-wins
Every editable contribution carried an immutable revision history. Saving a change submitted the base revision the editor had started from. If the server still held that revision, it accepted a new one. If not, it returned the current revision and both changes.
The first conflict strategy used field-level last-write-wins. It converged quickly and could silently remove a paragraph written in another tab. X8B6 had already shown why convergence without preserved intent was not enough.
D4U7 handled conflicts by contribution type. Short titles and status fields used explicit choice. Long Markdown bodies received a three-way merge proposal based on the shared base, with both revisions preserved. A person reviewed the result before it became current.
Comments and evidence references were anchored to immutable revision ranges, not only mutable character offsets. When a new revision changed the referenced text, the interface showed the original excerpt and attempted to reattach it. Uncertain anchors became visible rather than drifting silently.
The decision record always referenced the exact proposal and evidence revisions considered. Later edits could improve those documents without rewriting the basis of an earlier decision.
The tab left open overnight
The most revealing scenario was intentionally mundane. I opened a room, drafted part of a proposal, closed the laptop, edited the same proposal from another device, and returned the next morning.
The first implementation resumed its network connection and submitted the old draft as if no time had passed. The server rejected the base revision, but the interface displayed a generic save failure. It knew a conflict existed and did not help the writer recover.
The redesigned client tracked four independent facts:
connection: offline | connecting | online
document: current | behind | reconciling
draft: clean | local | saving | conflict
outbox: empty | pending | attentionOn visibility return or reconnect, the client fetched the current room revision before sending edits. If the local draft shared the current base, it continued normally. If the room had changed, the editor showed what changed and let the writer merge, copy, or abandon the local draft.
The interface never replaced the local text merely because the server was newer. It also never labeled the room current merely because the socket had reopened.
This scenario turned “long-lived tab” into a release test. Browser background throttling, expired sessions, new schema versions, removed permissions, and server deployments all entered the recovery path.
An outbox with fewer automatic promises
Reading and drafting worked offline after a room had been opened. IndexedDB stored room snapshots, immutable revisions needed for current work, local drafts, and an outbox of contributions.
Not every action was safe to send automatically later. Adding a standalone piece of evidence could usually enter the outbox. Casting a final decision after the deadline passed or after the room state changed required fresh review.
Outbox entries declared a delivery policy:
- Auto-deliver if the base room revision remains current.
- Revalidate and ask if relevant state changed.
- Online-only because the consequence requires current authority.
This was more conservative than treating offline support as a universal queue. It preserved the project’s central value: delayed work should remain meaningful, not merely deliverable.
Each entry used a stable operation ID and server receipt, inheriting X8B6’s safe-retry design. A timeout kept the outcome unknown until the same operation could be checked or retried.
The outbox UI grouped waiting, delivered, and attention-required contributions in ordinary language. A user could export local drafts before clearing storage or signing out.
A service worker with a narrow job
By 2020, service workers were a mature way to support a resilient application shell, but X8B6 and M31V had taught me not to equate a cache with offline correctness.
D4U7’s service worker cached versioned static assets and a minimal navigation fallback. It did not treat cached API responses as authoritative document state. IndexedDB held explicitly versioned room data and outbox operations.
After a deployment, the new worker waited until open tabs could acknowledge the update. A forced immediate activation could leave a running editor using code that expected one schema while the background worker wrote another.
The update banner explained that a new version was ready and whether local drafts were safe. Refresh became disabled only during the small critical section where a draft transaction was being committed locally.
Captured database fixtures tested upgrades from earlier releases. A device offline for several versions had to migrate its drafts and outbox before the new application claimed readiness.
This separation kept asset caching, document state, and local intent from collapsing into one vague offline layer.
The first notification model reported every new contribution. A busy room produced a sequence of messages that conveyed activity and not what had changed for the recipient.
D4U7 generated digests around state transitions:
- A question blocking your proposal was answered.
- Evidence referenced by the current decision changed.
- A decision was proposed or amended.
- A room deadline moved.
- Your offline contribution needs reconciliation.
The digest grouped changes since the person’s last acknowledged room revision. Opening it showed a concise change summary and allowed expansion into the full chronology.
Mentions existed but did not override notification preferences by default. A person could choose immediate delivery for a small set of consequential transitions and receive the rest in a scheduled digest.
Read state was explicit and per room, not inferred from whether a notification had been delivered. “Seen” did not imply agreement or understanding.
The interface avoided presence dots. Knowing that another browser was open did not make a contribution more important and created pressure to respond synchronously. A transient “someone is editing this proposal” warning appeared only when it could prevent a likely conflict.
J05N supplied the component contracts, but D4U7 tested them inside a dense stateful product. The room needed a stable heading structure, direct links to contributions, predictable focus after state changes, and useful announcements without turning every live update into noise.
New remote content did not steal focus. A compact update notice announced how many meaningful changes were available. Activating it moved to a summary, not blindly to the newest DOM node.
Conflict resolution used a full page rather than a cramped dialog. The page identified the shared base, server revision, local draft, and proposed merge. Keyboard users could move among changed regions and copy either version without losing the original.
Status used text and structure as well as color. Decision amendments included an explicit change summary. Drag-and-drop evidence ordering had button alternatives.
I ran manual screen-reader scenarios for creating a proposal, returning to a changed room, resolving a conflict, and reviewing a digest. Automated checks remained useful and could not judge whether the recovery narrative made sense.
Decision records with an expiry condition
The decision type held more than a selected proposal. It named the question, chosen revision, rationale, evidence references, acknowledged dissent, author, effective time, and review trigger.
A review trigger could be a date, a changed constraint, or new evidence. This prevented a decision from becoming permanent simply because nobody remembered its context.
Amending a decision created a new record linked to the prior one. The room overview showed the current decision and the chain behind it. Earlier evidence remained attached to the version that used it.
I added a “no decision” outcome. A room could close because evidence was insufficient, the question became irrelevant, or no option met the constraints. Forcing every room to produce an affirmative choice would have rewarded false completion.
The structure later influenced V0M3’s governed document workflow. A model-generated proposal would need the same distinction between draft, reviewed evidence, decision, and revision.
Sync protocol and projections
The server stored immutable contribution revisions and room events in PostgreSQL. A room projection provided the current overview. Clients synchronized from a room revision cursor.
If the event window contained every missing revision, the server returned a delta. Otherwise it returned a snapshot plus the current immutable documents needed to explain active state. This reused T04P’s continuity handshake with a much richer domain.
Projection rebuild tests replayed room events from zero and compared the result with the stored projection. A failed projection update did not make the underlying revision disappear. Repair could rebuild it from the log.
The system did not use event sourcing for every transient UI state. It preserved domain transitions that mattered to explanation and recovery. Draft cursor position and expanded panels stayed local.
Schema versions applied to events, document bodies, and client storage separately. The server accepted a bounded older event shape during rollout and rejected unknown future writes.
The first search index stored only the latest text of each contribution. A result could quote a sentence that had been amended and then open a page where the sentence no longer existed. That was confusing in ordinary use and damaging when the result had supported a decision.
I indexed immutable revisions with their room, contribution type, status, and effective interval. Ordinary search preferred current revisions. A history filter could include superseded material, labeled with the revision and the current replacement.
Decision records indexed the exact evidence excerpts they referenced. Opening a result moved to the immutable revision first and offered the current version separately. Search therefore preserved the difference between “this is true now” and “this was part of the record then.”
Room access was applied before search results left the server. The index did not send broad hits to the browser for filtering. Deleting a test account or room triggered removal jobs with receipts, reusing Q2F8’s lifecycle discipline.
The study circle used mostly synthetic subjects, but the content could still include personal writing. Exports collected one room’s current state, revision history, evidence links, and decision records in a readable package. A person could leave without trapping their contributions inside an opaque event log.
Archive was a deliberate room transition. An archived room became read-only, retained its stable URLs, and stopped routine notifications. Reopening created a visible event and required a reason, preventing old decisions from silently becoming active discussions again.
This gave the project a complete temporal path: create, develop, decide or close without decision, review, archive, and possibly reopen. A collaboration tool that optimizes only for creation accumulates an attention debt of rooms that never clearly end.
D4U7 did not advertise global activity feeds, popularity scores, or read receipts. Those features would have made the small study circle feel monitored and shifted attention toward response performance.
The event model retained actions needed for document history and recovery. It did not retain cursor movement, typing cadence, focus changes, or time-on-page. Q2F8 had made the question unavoidable: which evidence supports a named product need, and what can remain absent?
Room membership controlled content access. Stable links were unguessable but not treated as authorization. Attachment downloads used short-lived scoped URLs. Rendered Markdown passed through a strict element and attribute policy; pasted HTML could not create scripts, forms, or hidden tracking resources.
Remote images were not loaded automatically in contribution bodies because they could leak viewing behavior. Evidence used uploaded files or explicit links that a person chose to open. Link previews were fetched by a constrained server process and stored only the title and safe metadata needed for display.
Audit history distinguished content edits from access events. The project did not show a dramatic “who viewed this” panel. Security-relevant membership and export actions were retained; ordinary reading remained private.
Rate limits and bounded attachment sizes protected the small service from accidental overload. The system surfaced when an upload was rejected before a long offline draft attempted to depend on it. Attachments themselves were online-only; local drafts could reference a pending local file and required confirmation when reconnecting.
These choices were not ancillary policy. They shaped the social experience. Quiet collaboration required the software to preserve work without turning every moment of attention into another record.
Measuring recovery instead of engagement
I avoided fabricated engagement metrics. The useful evaluation came from task scenarios and recovery outcomes.
For each study session, I noted whether a returning participant could identify the room’s question, latest decision state, open blocker, and relevant changes without reading the complete chronology. I recorded where the interface forced a person into raw history and revised the overview accordingly.
Offline scenarios measured whether a local draft survived reload, whether an outbox retry produced one server contribution, and whether changed room state triggered review. Conflict scenarios measured whether both versions remained recoverable after resolution.
Notification review asked whether each digest item could name the recipient’s reason to care. If a message only said that activity occurred, it was either grouped into a lower-priority summary or removed.
Accessibility scenarios remained release requirements, not aggregate scores. A successful run meant a person could complete a named flow with keyboard or screen-reader navigation and retain context after async updates.
The most valuable qualitative signal was explanation. After a scenario, I asked the test participant to describe what the system believed was current and what still required attention. A quiet interface that produced the wrong mental model was not successful merely because it generated fewer notifications.
Where quiet collaboration still failed
The chat-shaped prototype made chronology the only structure and buried decisions. Typed contributions and a room projection corrected it.
Last-write-wins silently removed concurrent prose. Immutable revisions and base-aware merge preserved both intentions.
Automatic outbox delivery treated every delayed action as timeless. Delivery policies introduced fresh review for consequential state changes.
Presence indicators created response pressure without improving the record. I removed them except for narrowly useful edit-collision warnings.
The first notification system measured activity. Digesting meaningful transitions made attention part of the product model.
I also tried to handle conflict inside a modal because it seemed like an exceptional interruption. Complex reconciliation needed space, persistent URLs, and an escape path. It became a page.
D4U7 combined the hardest ideas from the earlier projects in a human-centered form: offline intent, versioned artifacts, typed states, replayable projections, accessible migration, finite attention, and honest uncertainty.
Its new difficulty was temporal collaboration. The system had to remain understandable when different people encountered different versions at different times. It could not rely on one meeting, one chat scroll, or one always-connected browser to supply context.
The result was a personal collaboration laboratory in which a room could explain what it was for, what had changed, what remained open, what had been decided, and why. Live behavior enhanced the experience without becoming the source of truth.
Z29C, the next project, would take the outbox and projection lessons into longer automated workflows. A human contribution had one main side effect. Z29C would coordinate several external steps whose outcomes could be accepted, rejected, timed out, or unknown—and still need a safe path forward.
What the study circle could not simulate
D4U7 used a small invited study group and low-consequence topics. It did not reproduce a large organization’s politics, compliance requirements, or scale. Its merge strategy worked for bounded Markdown documents, not arbitrary collaborative media.
Offline support applied to provisioned rooms and named contribution types. Decision quality still depended on participants. The system could preserve evidence and dissent without ensuring that anyone reasoned well from them.
Technology: React, a service worker for versioned application assets, IndexedDB for drafts and outbox operations, PostgreSQL revision and event storage, base-aware Markdown merging, server-rendered room entry points, and accessible conflict and digest workflows.