Skip to content

File UUID organization#208

Merged
matt-pharr merged 20 commits intodevelopfrom
file-uuid-organization
Apr 26, 2026
Merged

File UUID organization#208
matt-pharr merged 20 commits intodevelopfrom
file-uuid-organization

Conversation

@matt-pharr
Copy link
Copy Markdown
Owner

@matt-pharr matt-pharr commented Apr 22, 2026

Here's a PR summary:


UUID-based file storage and Python-initiated save/load

Summary

  • UUID-based file storage: Every file-backed tree node (PDVScript, PDVLib, PDVGui, PDVNote, PDVNamelist) now gets a 12-hex UUID and stores its backing file at <workdir>/tree/<uuid>/<filename>. Tree paths are fully decoupled from the filesystem — renames, moves, and restructures no longer require file copies or renames.
  • Python-initiated save/load: New pdv.save_project(), pdv.save_project_as(), pdv.open_project(), and pdv.add_file() APIs let users save, load, and import files directly from the console or scripts without going through the GUI.
  • Save deadlock fix: Python-initiated saves serialize the tree synchronously on the kernel side and push results to the main process, avoiding the comm round-trip that would deadlock while the shell is busy executing user code.
  • Orphan cleanup: _purge_orphaned_tree_files removes UUID directories in the save dir that no longer correspond to any live tree node, preventing stale files from accumulating across save cycles.
  • resolveNodePath / resolveNodeDir helpers: Centralized TS-side path resolution mirroring PDVFile.resolve_path() on the Python side. All hardcoded path.join(workingDir, "tree", ...) calls replaced.
  • Removed legacy code: working_dir_tree_path(), alias-based module scaffolding, stale PDVScriptRegisterPayload interface, and dead _relocate_files parameter all removed.

Version

0.0.12 (both electron/package.json and pdv-python/pyproject.toml)

Tests

  • Python: 355 passed, 2 skipped
  • TypeScript: 307 passed

Notable changes by area

Area What changed
pdv-python/pdv/tree.py PDVFile base class with UUID, filename, resolve_path(). All file-backed node types inherit it.
pdv-python/pdv/namespace.py PDVApp gains save_project, save_project_as, open_project, add_file methods
pdv-python/pdv/handlers/project.py Synchronous serialize_tree_to_dir, _early_module_setup for lib sys.path wiring during load, orphan purge
pdv-python/pdv/handlers/modules.py handle_module_reload_libs rewritten to walk PDVLib nodes via _iter_pdv_libs + resolve_path() instead of hardcoded alias paths
pdv-python/pdv/environment.py uuid_tree_path(), smart_copy(), generate_node_uuid(). Legacy working_dir_tree_path() removed
electron/main/pdv-protocol.ts resolveNodePath(), resolveNodeDir() helpers
electron/main/project-manager.ts Cached kernel results for deadlock-free Python-initiated saves, clearCachedKernelResults() on kernel stop
electron/main/ipc-register-project.ts save_completed push handler, save sequencing via chained promises
electron/main/project-file-sync.ts Load/save file copy uses resolveNodePath
ARCHITECTURE.md §6.3 documents the UUID storage design

matt-pharr and others added 11 commits April 21, 2026 03:47
Replace path-derived filesystem locations with stable UUIDs for all
file-backed tree nodes. Each node gets a 12-hex-char UUID at creation
time; files live at <dir>/tree/<uuid>/<filename> so renames, moves, and
tree restructuring never require file copies or path updates.

Key changes:
- PDVFile and subclasses (PDVScript, PDVNote, PDVGui, PDVLib,
  PDVNamelist) store uuid + filename instead of relative_path
- serialize_node / deserialize_node use uuid_tree_path() for all I/O
- Tree mutations (rename, move, duplicate) are O(1) for file nodes —
  only duplicate needs a fresh UUID and file copy
- Module import generates fresh UUIDs per file and copies to working dir
- Early module setup between load passes so custom serializers register
  before data deserialization
- Orphaned tree/<uuid>/ directories are purged after each save
- smart_copy() with optional reflink-copy for CoW on supported filesystems

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
writeModuleManifestsToSaveDir was overwriting each module's
pdv-module.json without carrying forward entry_point and default_gui.
These fields are set at import time and not tracked in the kernel tree,
so the kernel-side manifest collector cannot emit them. Without them,
project load could not import custom serializers (entry_point) and
modules did not appear in the activity bar (default_gui).

Now reads the existing project-local manifest before overwriting, with a
fallback to the globally installed module for projects saved before this
fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add §6.3 describing the UUID storage design — UUIDs, path resolution,
smart_copy, orphan cleanup, and the tree-index.json invariant. Update
§5.8–5.12 (PDVFile and subclasses) to reference uuid/filename instead
of relative_path. Update §6.1/§6.2 directory layouts and §7.3 storage
object format to reflect UUID-based paths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@matt-pharr
Copy link
Copy Markdown
Owner Author

Added pdv.save_project(), pdv.load_project(), but are flaky. Still have to debug.

matt-pharr and others added 9 commits April 22, 2026 22:08
Python-initiated saves (pdv.save_project()) deadlocked because the
kernel shell was busy executing user code when the comm round-trip
arrived. Serialize tree directly in Python and send results via a new
pdv.project.save_completed push, skipping the comm entirely.

Add __dir__/__getattr__ to the pdv package so Jedi autocomplete shows
PDVApp methods (save_project, save, open_project, etc.) alongside
module attributes. Add __getattr__ to PDVApp so module-level names
like PDVTree work whether pdv resolves as the instance or the module.

Also wrap the entire handle_project_save body in try/except and add a
serialization guard to prevent concurrent saves from racing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gs, add comments

- Add clearCachedKernelResults() to ProjectManager; call it on
  kernels:stop so abandoned Python-initiated saves don't leak stale
  serialization data into a new session.
- Demote save-path console.log calls to console.debug (7 sites across
  project-manager.ts and ipc-register-project.ts).
- Fix dangling JSDoc block on the _cachedKernelResults field.
- Add comment explaining the storage.value module_id fallback in
  _early_module_setup for pre-UUID project compat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@matt-pharr matt-pharr merged commit 9289520 into develop Apr 26, 2026
8 checks passed
@matt-pharr matt-pharr deleted the file-uuid-organization branch April 26, 2026 22:57
@matt-pharr matt-pharr linked an issue Apr 27, 2026 that may be closed by this pull request
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.

Refactor temp directory structure

1 participant