Address review feedback from Kosinkadink:
1. Move JSON loading logic from nodes.py into NodeReplaceManager as
load_from_json() method for better encapsulation and testability
2. Tests now exercise the real NodeReplaceManager (no duplicated logic)
3. Defer `import nodes` in apply_replacements to avoid torch at import
4. nodes.py call site simplified to one line:
PromptServer.instance.node_replace_manager.load_from_json(...)
Two fixes from code review:
1. Only load node_replacements.json from directory-based custom nodes.
Single-file .py nodes share a parent dir (custom_nodes/), so checking
there would incorrectly pick up a stray file.
2. Skip entries with missing or empty new_node_id instead of registering
a replacement pointing to nothing.
Custom node authors can now ship a `node_replacements.json` in their
repo root to define replacements declaratively. During node loading,
ComfyUI reads these files and registers entries via the existing
NodeReplaceManager — no Python registration code needed.
This enables two use cases:
1. Authors deprecate/rename nodes with a migration path for old workflows
2. Authors offer their nodes as drop-in replacements for other packs