Skip to content

fix(scheduler): return midpoint for zero-range remap instead of silent to_min#1

Open
martial wants to merge 1 commit into
seethroughlab:mainfrom
martial:fix/apply-remap-zero-range
Open

fix(scheduler): return midpoint for zero-range remap instead of silent to_min#1
martial wants to merge 1 commit into
seethroughlab:mainfrom
martial:fix/apply-remap-zero-range

Conversation

@martial

@martial martial commented Mar 17, 2026

Copy link
Copy Markdown

Bug

In apply_remap() (src/runtime/scheduler.cpp), when from_min == from_max (zero input range), the fallback was:

float t = (range != 0.0f) ? (val - w.from_min) / range : 0.0f;

This silently forces t = 0.0f, which means the output is always to_min regardless of input. A wire with a collapsed input range will bias all downstream values to the minimum with no warning — very hard to diagnose in a live graph.

Fix

Change the fallback to t = 0.5f (output midpoint):

float t = (range != 0.0f) ? (val - w.from_min) / range : 0.5f;

This is a more neutral default and makes the failure mode visible rather than hiding it.

A follow-up could add a stderr warning or a graph-load diagnostic for wires where from_min == from_max.

— Michelle

…t to_min

When from_min == from_max, apply_remap() was silently returning to_min
for any input value. This caused wires with a collapsed input range to
always output the minimum value with no warning, making the issue very
hard to diagnose in a live graph.

Changed the degenerate-range fallback from t=0.0f to t=0.5f (output
midpoint), which is a more neutral default and makes the failure mode
visible in the UI rather than silently biasing outputs low.

A future follow-up could add a stderr warning or a graph-load diagnostic
for wires where from_min == from_max.
jeffcrouse added a commit that referenced this pull request Jul 1, 2026
Visuals params were global per op-type — every Plasma read the same warp/hue/
density/glow, ports drew only on first_node_of(op). Now each node owns its params.

- VisualNode gains a stable `id` (monotonic, persisted) + `params[4]`; mapping
  dests move from "uniform.<name>" to "node:<id>.<name>". render() drops the
  global pu/decay/radius args and reads each node's params (Feedback decay scaled
  0.82..0.98, Blur radius).
- NodeGraph: param ports render on EVERY node; param_port/nearest_param are
  per-(node,local); connect/disconnect use node_param_dest. New apply_params()
  resolves each node's params from the registry and republishes the canonical six
  viz.<name> return-path sources from the first node of each op-type (so P27's
  static map-source catalog is unchanged). fill_uniforms removed. The out-of-box
  master.level->glow seed moved to set_visual_graph (needs the default ids).
- Persistence: chain saves/loads node `id` so per-node mappings reattach. Old
  files degrade gracefully (default id=index; stale uniform.* mappings go unread).
- main: graph.apply_params() replaces fill_uniforms + the viz publish + pu/decay/
  radius; mapping overview decodes "node:<id>.<name>".

Builds clean; launches with no validation errors. Two Plasma nodes can now be
driven by different sources independently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jeffcrouse added a commit that referenced this pull request Jul 1, 2026
First platform step of P1 (ADR-0011): lift vivid-classic's operator ABI onto our
trunk so we can build an operator-based visuals model. Placed at
app/src/operator_api/ so classic's `#include "operator_api/..."` resolves verbatim.

- Lifted headers (in-process GPU-op subset): types.h, operator.h, value_model.h,
  value_view.h, gpu_operator.h, gpu_types.h, type_id.h, metronome_sync.h,
  gpu_common.h. Verified they compile against our pinned wgpu-native (the #1 risk
  — no WGPUStringView/vivid_sv incompatibility; ABI v10).
- Lifted operator_descriptor_validation.{h,cpp} (header+stdlib only → headless);
  compiled into both vivid_poc and the test lib.
- tests/test_descriptor_validation.cpp (HEADLESS, 17 checks): well-formed → clean;
  null/missing-name/missing-capability/null-params/param-missing-name/dup-param/
  port-missing-name/dup-port (per-direction) all fire their stable named codes.

Spike (P1.0) cleared its two scariest unknowns: the ABI compiles against our wgpu,
and a PlasmaOp authored in our toolchain yields the right collect_params/ports
metadata + GpuProcessable capability. Headless ctest 4/4; full app build green.

Co-Authored-By: Claude Opus 4.8 <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