Skip to content

feat(ydoc): a damaged document now looks damaged inside the app (3.12) - #465

Merged
th3-br41n merged 1 commit into
mainfrom
feat/3-12-damaged-doc-in-app
Aug 3, 2026
Merged

th3-br41n merged 1 commit into
mainfrom
feat/3-12-damaged-doc-in-app

Conversation

@th3-br41n

Copy link
Copy Markdown
Contributor

The shell knew a doc was missing content and told nobody, so "your writing is gone" and "you have not written yet" rendered identically. That ambiguity is what made the 329 audit read F-488 as a render fault for a day.

Getting the signal to the app

YDocTransport.load takes an optional report callback — optional on both sides, so a transport that knows nothing about document health ignores it and the resolver treats silence as healthy. The shell's accessor calls it with pendingStructs from the loadDoc reply, which it was already receiving and throwing away.

Two details that are load-bearing:

  • The resolver keeps the finding in a set held outside entries. The damage outlives the replica, so releasing and reopening a doc must not make it look healed.
  • useYDocDamaged subscribes rather than reading once. The load that discovers the damage resolves after first render, so a component that only read isDamaged would paint the doc as ordinary-empty and never correct itself — the exact failure this exists to end.

The affordance

EmptyStateTone.Damaged extends the existing shared primitive rather than forking a new component, and is sized like Compact rather than Hero on purpose: a damaged document stays open and editable, so the notice sits with the content instead of replacing it. Taking the pane away would stop the user writing new entries, which still save fine.

Journal is the reference consumer.

Two bugs caught in my own work

  • Journal's noteId had to move above the early return so the hook runs unconditionally — I briefly wrote it below one, which breaks the Rules of Hooks.
  • A missing type import surfaced only in typecheck:apps, not typecheck:packages — the exact split the conventions warn about.

Also

Formats apps/files/src/types/entity.test.ts, which landed unformatted in #462 and left main's lint red — that was reddening every open PR, not just this one.

Verification

Five tests written failing first · 341 pass across react-yjs / empty-state / journal · typecheck:packages and typecheck:apps clean · bun run lint green (incl. the CSS-token check, since the notice uses the real --color-state-warning).

Closes plan rung 3.12.

🤖 Generated with Claude Code

The shell knew a doc was missing content and told nobody, so "your writing is
gone" and "you have not written yet" rendered identically. That ambiguity is
what made the 329 audit read F-488 as a render fault for a day.

The signal now reaches the app. `YDocTransport.load` takes an optional
`report` callback — optional on BOTH sides, so a transport that knows nothing
about document health ignores it and the resolver treats silence as healthy.
The shell's accessor calls it with `pendingStructs` from the `loadDoc` reply,
which it was already receiving and discarding.

The resolver keeps the finding in a set held OUTSIDE `entries`, deliberately:
the damage outlives the replica, so releasing and reopening a doc must not
make it look healed. `useYDocDamaged` subscribes rather than reading once,
because the load that discovers the damage resolves AFTER first render — a
component that only read `isDamaged` would paint the doc as ordinary-empty and
never correct itself, which is the exact failure this exists to end.

`EmptyStateTone.Damaged` is sized like Compact rather than Hero on purpose. A
damaged document stays open and editable, so the notice sits WITH the content
instead of replacing it: taking the pane away would stop the user writing new
entries, which still save fine.

Journal is the reference consumer. Its `noteId` moved above the early return
so the hook runs unconditionally — it was briefly written below one, which
would have broken the Rules of Hooks.

Also formats apps/files/src/types/entity.test.ts, which landed unformatted in
#462 and left `main`'s lint red.

Five tests written failing first. 341 pass across react-yjs, empty-state and
journal; typecheck:packages AND typecheck:apps clean (the missing type import
showed up only in the apps half); lint green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@th3-br41n
th3-br41n merged commit dd5c112 into main Aug 3, 2026
3 checks passed
@th3-br41n
th3-br41n deleted the feat/3-12-damaged-doc-in-app branch August 3, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant