feat(runtimed): daemon-owned notebook loading infrastructure (#598)#601
Merged
feat(runtimed): daemon-owned notebook loading infrastructure (#598)#601
Conversation
) Phase 1 of daemon-owned notebook loading: - Add Handshake::OpenNotebook { path } variant - Add Handshake::CreateNotebook { runtime, working_dir } variant - Add NotebookConnectionInfo response struct with: - notebook_id (derived by daemon) - cell_count (for progress indication) - needs_trust_approval (for untrusted deps) - error (for failures) - Add placeholder handlers in daemon.rs (return "not implemented") - Add serialization tests The daemon will derive notebook_id from path (for existing files) or generate env_id (for new notebooks), eliminating duplicate derivation logic in Tauri.
Phase 2 of daemon-owned notebook loading: - Add `load_notebook_from_disk()` - loads .ipynb file and populates NotebookDoc with cells and metadata - Add `create_empty_notebook()` - creates new notebook with one code cell and runtime-specific metadata - Add `build_new_notebook_metadata()` - builds NotebookMetadataSnapshot for new notebooks (Python/Deno, UV/Conda) - Add `parse_metadata_from_ipynb()` - extracts metadata using existing `NotebookMetadataSnapshot::from_metadata_value()` Reuses existing `parse_cells_from_ipynb()` for cell parsing. These functions will be called by the OpenNotebook/CreateNotebook handshake handlers.
Implement the actual daemon-side handlers for the new handshake types: - handle_open_notebook: Canonicalizes path to derive notebook_id, creates room, loads from disk if first connection, checks trust, sends NotebookConnectionInfo, then continues with sync - handle_create_notebook: Generates UUID as notebook_id, creates room, populates empty notebook with one code cell, sends NotebookConnectionInfo Multi-window support: Second window joining same notebook skips disk load and joins existing room via Automerge sync. Also updated create_empty_notebook to accept optional env_id parameter to avoid double UUID generation.
Initialize conda notebooks with ["conda-forge"] instead of empty channels to match the launch logic normalization. Prevents false channel-drift detection that would trigger unnecessary restart-required behavior.
…ng (#598) Add new connection methods for the OpenNotebook and CreateNotebook handshakes: - connect_open_split: Opens existing notebook file via daemon, returns NotebookConnectionInfo with notebook_id and trust status - connect_create_split: Creates new notebook via daemon, returns NotebookConnectionInfo with generated notebook_id Also adds: - init_open_notebook: Generic init for OpenNotebook handshake - init_create_notebook: Generic init for CreateNotebook handshake - do_initial_sync: Extracted common Automerge sync logic Both Unix and Windows platforms are supported.
Fixes two issues found in review: 1. Race condition: The cell_count check is now done atomically under the write lock. Previously, two concurrent opens could both see cell_count == 0 (checked with read lock), then both load, duplicating cells. 2. Stale room on failure: On load failure, the room is now removed from the rooms map before returning. Previously, the room would persist with potentially incorrect trust state (computed at room creation), which could bypass trust checks on later retries.
The new OpenNotebook/CreateNotebook handshakes return NotebookConnectionInfo which includes the protocol version. Sending ProtocolCapabilities again after that would break the client which expects AutomergeSync frames next. Added skip_capabilities parameter to handle_notebook_sync_connection: - false for legacy NotebookSync handshake (sends ProtocolCapabilities) - true for OpenNotebook/CreateNotebook (protocol already in response)
1. CreateNotebook: Clean up room on failure for consistency with OpenNotebook (prevents stale UUID-keyed rooms from leaking) 2. Client: Add protocol version validation for NotebookConnectionInfo in init_open_notebook and init_create_notebook (defensive check) 3. Tests: Add unit tests for build_new_notebook_metadata (3 branches: deno, python-uv, python-conda) and create_empty_notebook (python, deno, custom env_id) The sync loop duplication between init and do_initial_sync is noted for follow-up refactoring but not addressed here.
rgbkrk
pushed a commit
that referenced
this pull request
Mar 8, 2026
…601) Update both audit documents to cover new protocol surfaces introduced by the daemon-owned notebook loading infrastructure (OpenNotebook and CreateNotebook handshakes) and dead code removal from the local-first migration. New findings: - OpenNotebook accepts arbitrary file paths for reading (medium) - Error paths drain unbounded reader data (medium) - do_initial_sync uses 100ms timeout for convergence (medium) - CreateNotebook runtime field not validated (low) - load_notebook_from_disk has no file size limit (low) Positive changes noted: - Trust verification fallback branches removed (#595) - Daemon-side doc population reduces CRDT merge complexity - Atomic check-and-load prevents duplicate cell population - Client-side protocol version validation in new handshakes https://claude.ai/code/session_01ToG68d36uTowAeraL5CF7R
This was referenced Mar 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implement the daemon-side infrastructure for daemon-owned notebook loading (issue #598). This PR completes Phases 1-3 and 5, providing all the building blocks for the Tauri integration in a follow-up PR.
Phase 1: Protocol Extension
OpenNotebook { path }andCreateNotebook { runtime, working_dir }handshake variantsNotebookConnectionInforesponse with notebook_id, cell_count, needs_trust_approval, and error fieldsPhase 2: Daemon-Side Loading Functions
load_notebook_from_disk()- parses .ipynb and populates NotebookDoc with cells and metadatacreate_empty_notebook()- creates new notebook with one code cell and runtime-specific metadatabuild_new_notebook_metadata()- generates metadata for Python (uv/conda) or Deno runtimesparse_cells_from_ipynb()for cell parsingPhase 3: Connection Handlers
handle_open_notebook: Canonicalizes path → derives notebook_id → creates room → loads from disk (if first connection) → checks trust → returns NotebookConnectionInfo → continues with synchandle_create_notebook: Generates UUID notebook_id → creates room → populates empty notebook → returns NotebookConnectionInfo → continues with syncPhase 5: NotebookSyncClient Extension
connect_open_split()- opens existing notebook via daemon, returns NotebookConnectionInfoconnect_create_split()- creates new notebook via daemon, returns NotebookConnectionInfoinit_open_notebook()/init_create_notebook()/do_initial_sync()- internal init helpersWhat's Next
Phase 4-7 (Tauri integration) in a follow-up PR:
connect_open_split/connect_create_splitNotebookState-based loadingTest Plan
Closes #598 (daemon-side infrastructure complete; Tauri integration to follow)