_safe_prefix flips from ASCII allowlist to Windows-illegal denylist:
only < > : " | ? * + control chars become _, everything else passes
verbatim. Adds reserved-device-name guard (CON/NUL/COM1-9/LPT1-9) and
trailing-dot/space strip per segment. All-Korean prefixes used to
dissolve to nothing -> silent 'Preview' fallback in output root; mixed
ones got mangled (te SEG st -> te_st). Traversal guards unchanged;
folder_paths' commonpath check still backs every save path.
New scripts/save_prefix_check.py locks behavior (31 cases, PREFIX PASS).
Covers save_mode=save, Save Output, Save Disk suggested name, XY Plot save.
The script used `from nodes._fx_adjust_engine import ...` which resolved to
ComfyUI's top-level nodes.py ("'nodes' is not a package") instead of the
plugin package. Import the engine directly off the nodes/ dir (it has no
relative imports). Gate now runs green: PARITY PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Variable fonts where available (Inter, Roboto, Montserrat, Oswald, Playfair, Lora, Caveat, JetBrains Mono), static for Bebas Neue and Anton. All SIL OFL or Apache 2.0, free for commercial use and redistribution.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the widgets-only Audio React Pixaroma node (PixaromaAudioReact)
and renames Audio Pulse Pixaroma's display label to 'AudioReact Pixaroma'.
Why: the editor-driven node fully supersedes the widgets-only one.
Shipping two nodes that share an engine but differ only in UX is more
confusing than helpful. Safe to delete since nothing was published with
the basic node.
What changed (user-facing):
- 'Audio Pulse' renamed to 'AudioReact' everywhere users look (display
name, button label, editor title, modal text, error messages, README,
CLAUDE.md docs, parity harness).
- Old basic 'Audio React Pixaroma' node removed.
What stayed for compatibility:
- Internal Python class name PixaromaAudioStudio (workflow class_type).
- File paths js/audio_studio/, nodes/node_audio_studio.py.
- Server route /pixaroma/api/audio_studio/, on-disk audio_studio/<id>/.
- DOM id pixaroma-audio-studio-editor + CSS prefix pix-as-.
- Engine file _audio_react_engine.py (its name happens to match the new
product name now).
- node.properties.audioStudioState cfg key.
REQUIRES COMFYUI RESTART to pick up the deleted module + new display name.
Cleaner entry point for the parity test — no need to instantiate a
PixaromaAudioReact node or load node_audio_react.py at all. The engine
is the public API; the node was just a thin wrapper that constructs
Params from kwargs.
Goldens unchanged (same math, same Params shape). 64/64 OK confirms
byte-identity.
Mechanical move — helpers now live in nodes/_audio_react_engine.py and the
node imports them. Parity check confirms byte-identical output.
Also updates scripts/audio_parity_check.py to load node_audio_react.py via
a synthetic 'nodes' package so the new \`from ._audio_react_engine import ...\`
relative imports resolve correctly.
Code-review feedback from Task A1:
- Drop unused `import math` (nothing in the file references it).
- Thread `fps` into synthesize_audio() instead of hardcoding 30 — keeps
audio.fps and shared_params.fps drift-free if either ever changes.
- Add startup assert that audio.fps == shared_params.fps so a manifest
edit-mistake fails fast instead of silently relocating onset spikes.
- Document why np.random.RandomState (not default_rng) is required.
- Document the kwarg-contract fragility on render_frames.
- Add JSON-comment keys explaining the two tolerance fields — the
pre_refactor=0.0 is deferred-use (A3-A6), the python_release=1.0
intentionally covers PyTorch float-precision drift across releases.
Diff still passes 64/64 OK, exit 0.
These goldens lock the current PixaromaAudioReact output. Running the
parity script after the upcoming engine extraction must produce zero diffs
-- that's the regression test for the refactor.