code wiki / _hdl_build / nx_converge_lib.nx
nx_converge_lib.nx
buildroot/runtime/_hdl_build/nx_converge_lib.nx
about
nx_converge_lib.nx -- THE CONVERGENCE CONTROLLER: hit a RETENTION TARGET instead of guessing a denoise.
THE PROBLEM. Reference-conditioned generation has one continuous knob (denoise strength) and one
thing you actually care about (how much of the reference survived). Today an operator guesses a
denoise, waits 25-50s for the GPU, eyeballs the result, and guesses again. The guess is the whole
workflow, and it is neither reproducible nor auditable.
THE INSIGHT THAT MAKES THIS EXACT, NOT HEURISTIC. nx_refbench_gate's T4 proves the ruler ORDERS
correctly, and the measured curve falls monotonically with denoise (859 -> 647 -> 359). A monotonic
function on a bounded interval is exactly the case where BISECTION IS GUARANTEED TO CONVERGE, and to
do so in ceil(log2(range/tolerance)) steps. So this is not a tuned heuristic with magic gains -- it
is a bracketing search with a proof behind it, and its step count is known BEFORE the first render.
Retention DECREASES as denoise rises, so the bracket updates are inverted relative to a naive search:
measuring ABOVE target means we kept too much and must push denoise UP.
WHY IT IS STATELESS. The render happens on the GPU host; only the DECISION belongs in the sovereign
organ. So `next` takes the whole bracket as arguments and returns the next probe -- an agent, a
workflow, or a human can drive it one render at a time over MCP with nothing persisted between calls.
State that lives in a daemon cannot be replayed; state that travels in the arguments can.
NO-FLOAT: every quantity is permil (0..1000) integer, per the sovereign arithmetic law.
license_tier: ORIGINAL
dependencies 1 imports · 2 importers
imports: nx_syscalls.nx
imported by: nx_converge.nxnx_converge_gate.nx
structs
| none |
consts
| 25 | const CV_MIN: i64 = 0 // denoise floor, permil (0 = return the source untouched) |
| 26 | const CV_MAX: i64 = 1000 // denoise ceiling, permil (1000 = ignore the source entirely) |
| 27 | const CV_MAX_STEPS: i64 = 12 // ceil(log2(1000)) = 10, +2 slack; a HARD bound so a non-monotonic |
| 29 | const CV_DONE: i64 = 0 - 1 // sentinel returned instead of a probe when the search has finished |
| 32 | const CV_OK: i64 = 0 // converged: |measured - target| <= tol |
| 33 | const CV_CONTINUE: i64 = 1 // keep going, a new probe is available |
| 34 | const CV_EXHAUSTED: i64 = 2 // step budget spent without landing inside tolerance |
| 35 | const CV_UNREACHABLE: i64 = 3 // target lies outside what the knob can produce |
| 93 | const CV_K0_D: i64 = 0 |
| 94 | const CV_K0_R: i64 = 1000 |
| 95 | const CV_K1_D: i64 = 350 |
| 96 | const CV_K1_R: i64 = 859 |
| 97 | const CV_K2_D: i64 = 550 |
| 98 | const CV_K2_R: i64 = 647 |
| 99 | const CV_K3_D: i64 = 750 |
| 100 | const CV_K3_R: i64 = 359 |
| 101 | const CV_K4_D: i64 = 1000 |
| 102 | const CV_K4_R: i64 = 200 |
functions
| 39 | func cv_first_probe() -> i64 |
| 46 | func cv_reachable(target: i64) -> i64 |
| 59 | func cv_step(target: i64, tol: i64, lo: i64, hi: i64, probe: i64, measured: i64, |
| 105 | func cv_lerp(d: i64, d0: i64, r0: i64, d1: i64, r1: i64) -> i64 called by 1: cv_oracle |
| 111 | func cv_oracle(denoise: i64) -> i64 |
| 124 | func cv_run(target: i64, tol: i64, out_denoise: *i64, out_ret: *i64, out_steps: *i64) -> i64 |