feat: finish the migration to the be stack and delete the old block stack (#117)

* feat: migrate the logic game

The logic game's progress is a be-model document: one list of solutions,
each naming its challenge and the grid that attempts it, a Map from
challenge to whether it is completed, and a Map from quiz problem and row
to the answers given. Every built-in challenge is a level whether or not
anything was written for it, so two devices never race to create one. The
editor reads a flattened LogicGame and keeps speaking LogicGameOperation,
which LogicGameProgress::edit_for turns into edits; a deleted or replaced
solution grid is dropped or repointed through the child bridge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate the logic grid and compiled logic

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: presence in the new block stack

Live sessions relay ephemeral presence values between peers as encrypted
session messages that are never saved. Late joiners are shown what is
already present and a leaving peer's presence is dropped. Plugins show
presence with Editor::show and read peers with Editor::peers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate the infinite canvas

Entities are objects in a list whose order is their layering, so a move
and a restyle of one entity merge field by field. Cursors and selections
are shared through new-stack presence and carry their own colour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: a grid field and pixel art in the new block stack

The grid is a dense block of fixed-size cells addressed by coordinates.
Paints merge and undo cell by cell, a burst of strokes undoes as one
step, and a resize only moves the grid's bounds, so a paint made during
a resize lands where it was painted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate text

The text editor keeps its bytes and per-byte anchors locally, pushes its
edits to the block's content as insert and delete operations, and adopts
edits from elsewhere by diffing them in, so cursors stay where they were.
Undo steps are located by anchors and skip text someone else has changed
since. Block URLs are parsed in be-block so text content reports the
blocks it links from its own workspace. Cursors travel as new-stack
presence with their colour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* docs: presence, the grid field and editors with their own model in the block stack guide

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* chore: lint fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate the logic game

The logic game's progress is a be-model document: one list of solutions,
each naming its challenge and the grid that attempts it, a Map from
challenge to whether it is completed, and a Map from quiz problem and row
to the answers given. Every built-in challenge is a level whether or not
anything was written for it, so two devices never race to create one. The
editor reads a flattened LogicGame and keeps speaking LogicGameOperation,
which LogicGameProgress::edit_for turns into edits; a deleted or replaced
solution grid is dropped or repointed through the child bridge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate the logic grid and compiled logic

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: presence in the new block stack

Live sessions relay ephemeral presence values between peers as encrypted
session messages that are never saved. Late joiners are shown what is
already present and a leaving peer's presence is dropped. Plugins show
presence with Editor::show and read peers with Editor::peers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate the infinite canvas

Entities are objects in a list whose order is their layering, so a move
and a restyle of one entity merge field by field. Cursors and selections
are shared through new-stack presence and carry their own colour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: a grid field and pixel art in the new block stack

The grid is a dense block of fixed-size cells addressed by coordinates.
Paints merge and undo cell by cell, a burst of strokes undoes as one
step, and a resize only moves the grid's bounds, so a paint made during
a resize lands where it was painted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate text

The text editor keeps its bytes and per-byte anchors locally, pushes its
edits to the block's content as insert and delete operations, and adopts
edits from elsewhere by diffing them in, so cursors stay where they were.
Undo steps are located by anchors and skip text someone else has changed
since. Block URLs are parsed in be-block so text content reports the
blocks it links from its own workspace. Cursors travel as new-stack
presence with their colour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* docs: presence, the grid field and editors with their own model in the block stack guide

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* chore: lint fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* refactor: remove version control and repo-relative block references

Version control never worked reliably and is to be rebuilt later, so its
blocks, editors, checkout and commit code go. Without it a reference is
always a block id: BlockRef, eternal ids and the reference resolution
and classification queues every editor carried are gone, and block URLs
always name their workspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: sealed block metadata and workspace-wide graph events

A block node carries metadata the client seals with the workspace's
content key, so the server stores names without reading them. A
connection that opens a workspace can list every block in it and hears
BlockChanged and BlockRemoved whenever a block is created, moved,
relinked, renamed or collected, which is what lets a client mirror the
workspace graph without polling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: migrate settings, folders, the pixel ray tracer and stateless blocks to be-block

Every block type now keeps its content in the new stack. RootSettings reads
and writes the settings document through a SettingsStore, which the app's be
worker and the plugin editor both implement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* feat: accounts, invitations and per-member graph views on be-server

be-server takes over what block-server did for accounts: registration can be
disabled, accounts can be added from the command line, members can be invited
to a workspace, and sessions can log out. Graph announcements are computed per
member, so an editor only hears about blocks they can see, with access
inherited through parents and know-exists for referenced blocks and ancestors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* refactor: move the app and plugins onto the block graph and delete the old stack

A block's type is now its content type. The app keeps a mirror of the be
graph, fed by the server's block events, and plugins reach it through new
plugin protocol messages (WatchBlocks, CreateBlock, SetParent, SetName)
instead of a tunnelled block client. Names live in encrypted block metadata.
Local graph changes hold back server echoes until they are acknowledged, so a
stale echo cannot undo a rename.

The block, block-client, block-server, block-reactive and block-e2e crates
are deleted along with version control and the compat helpers that bridged
the two stacks. The scripts build and run be-server instead of block-server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* test: drop "migrated" from test names now that every block is on be

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* docs: describe the be stack as the only block stack

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* refactor: remove be-server's adopt path, the bridge block-server used

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* fix: version graph summaries so a stale event cannot undo a newer change

The worker awaits a command's reply while graph events queue behind it, so an
event sent before a rename could be applied after the rename's reply and put
the old name back. Every graph change on the server now advances the block's
version, and the app ignores a summary older than the one it holds.

Also points the block stack guide at the buck2 web-serve target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* perf: turn off Nagle's algorithm on be connections

Session traffic is small frames that want to go out at once. With Nagle on,
an operation waited on the peer's delayed ACK before it left, so an edit took
about 40 ms to reach another peer over loopback. It now takes well under a
millisecond.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* fix: show a content edit in the frame that made it

ContentProjection::operate applied an edit to what the editor shows but left
running its watchers to the next frame's pump. The canvas clears a gesture's
preview in the frame the gesture ends, so a moved entity was drawn at its old
position for one frame. operate now notifies the watchers it touched at once.

The database snapshots change for the same reason: the frame after a click now
lays out what the click did, so the pointer hovers what is under it now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

* fix: push block graph changes to editors instead of polling for them

The graph an editor watches now carries a revision signal, bumped whenever an
answer arrives or the editor creates a block; an answer that arrives between
frames is pushed into the signal at the start of the next one. Lists and block
info read through it, so memos and effects that read them re-run when the
graph changes.

The file tree built its rows by polling every frame and only started watching
a folder's children from that poll, so expanding a folder did nothing until
some other input drew another frame. It now builds its rows in an effect on
the expanded folders and the graph. watch_blocks and block labels follow the
graph the same way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016D2MXiSb7TrGBEdVe69fBM

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: be3-merge-queue[bot] <332166134+be3-merge-queue[bot]@users.noreply.github.com>
574c8afda8pfg committed on 9/25/2026, 3:46:41 AM· committed by GitHubparentef4e716
64 files changedLine totals unavailable