Skip to content

Autosave#217

Open
matt-pharr wants to merge 5 commits intodevelopfrom
autosave
Open

Autosave#217
matt-pharr wants to merge 5 commits intodevelopfrom
autosave

Conversation

@matt-pharr
Copy link
Copy Markdown
Owner

Summary

  • Adds automatic periodic saving of project state (tree data + code cells) to a .autosave/ subdirectory, with configurable interval (default 5 minutes)
  • Uses a checksum cache on the kernel side to skip re-serializing unchanged data nodes, keeping autosaves fast and incremental
  • Defers autosave when the kernel is busy executing and triggers it once the kernel returns to idle
  • Clears autosave data on explicit save so it doesn't accumulate stale snapshots
  • Adds autosave interval setting and a "Clear autosave data" button to the Settings dialog

How it works

Timer tick (main) → kernel idle? → push trigger to renderer → renderer sends code cells back → main writes .autosave/
                                   kernel busy? → set pending flag → trigger on next idle transition

The Python kernel reuses xxh3_128 checksums from previous autosaves to skip serialization of unchanged ndarray, DataFrame, and binary nodes. Explicit saves clear both the .autosave/ directory and the kernel-side cache.

Test plan

  • Open a project, wait for the autosave interval to elapse, confirm .autosave/ directory appears with tree-index.json and code-cells.json
  • Modify tree data, wait for next autosave, confirm only changed nodes are re-serialized (check file mtimes or debug log timing)
  • Start a long-running script, confirm autosave defers until execution completes
  • Save explicitly (Cmd+S), confirm .autosave/ is deleted and timer resets
  • Change autosave interval in Settings, restart kernel, confirm new interval takes effect
  • Click "Clear autosave data" in Settings, confirm .autosave/ is removed
  • Run pytest tests/ -v in pdv-python/ — checksum rename is covered
  • Run npm test in electron/ — config defaults and IPC handler mocks updated

matt-pharr and others added 5 commits April 27, 2026 05:30
Expose node_digest() as public API in checksum.py for per-node XXH3-128
comparison. Add autosave_cache parameter to serialize_node() that skips
file I/O for data nodes (ndarray, DataFrame, binary, etc.) whose content
hash hasn't changed since the last autosave. File-backed nodes (scripts,
notes) continue to use smart_copy() which already deduplicates.

The cache is a module-level dict in handlers/project.py, threaded through
_collect_nodes → serialize_tree_to_dir → handle_project_save. It is
activated when is_autosave=True in the save payload and cleared on
explicit saves.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Timer-driven autosave that serializes the tree to .autosave/ inside the
project directory (or working dir for unsaved projects). The timer fires
at a configurable interval (default 300s, min 30s) and only triggers
when the kernel is idle — deferred autosaves run as soon as the kernel
goes idle.

Key changes:
- kernel-manager: track executionState from iopub status messages, emit
  kernel:executionState events
- project-manager: autosave timer lifecycle, autosave() method that
  sends is_autosave=true to the kernel, static helpers for checking and
  clearing .autosave/ directories
- config: add autoSaveIntervalSeconds field
- ipc/preload: add autosave channel group (run, clear, check,
  scanWorkingDirs) and push.autosaveTrigger
- pdv-protocol: extend save payload with is_autosave and clear_cache
- index: wire timer to kernel lifecycle, clear .autosave/ on explicit
  save, handle deferred autosave on idle transition
- ipc-register-project: onExplicitSaveCompleted callback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Autosave section to Settings/General with a configurable interval
input (default 300s, min 30s) and a button to clear autosave data for
the current project.

Subscribe to the autosave trigger push in app/index.tsx — when the main
process requests an autosave, the renderer sends its current code-cell
state back via window.pdv.autosave.run().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The autosave interval is now re-applied immediately when the user saves
a new value in Settings/General, without requiring a kernel restart.
Adds an onConfigChanged callback to the app-state IPC handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When opening a project that has .autosave/ data, show a confirmation
dialog offering to restore the autosaved changes or discard them.

Recovery load flow:
- Copy baseline files from the main save dir to the working dir
- Overlay autosaved files on top (changed nodes take precedence)
- Use .autosave/tree-index.json and code-cells.json for the load
- Clean up .autosave/ after successful restore or on discard

Python handler accepts optional tree_index_dir in the load payload so
the kernel reads from the autosave directory while save_dir stays
pointed at the real project for future saves.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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