/** * Deterministic executable model for the XZBT 0.1 GC3 resolution contract. * * This is a Phase 0 contract oracle, not the production runtime resolver. */ export function clamp(value, minimum, maximum) { return Math.min(maximum, Math.max(minimum, value)); } export function bindingValue(source, { scale = 1, offset = 0, clamp: limits } = {}) { let result = source * scale + offset; if (limits) result = clamp(result, limits[0], limits[1]); return result; } export function smoothBinding(previous, input, dtSeconds, tauSeconds) { if (tauSeconds === 0 || previous === undefined) return input; const alpha = 1 - Math.exp(-dtSeconds / tauSeconds); return previous + alpha * (input - previous); } export function easingValue(name, t) { const bounded = clamp(t, 0, 1); switch (name) { case 'linear': return bounded; case 'ease-in': return bounded * bounded; case 'ease-out': return 1 - (1 - bounded) * (1 - bounded); case 'ease-in-out': return bounded < 0.5 ? 2 * bounded * bounded : 1 - ((-2 * bounded + 2) ** 2) / 2; default: throw new RangeError(`Unsupported easing: ${name}`); } } export function lerp(from, to, amount) { return from + (to - from) * amount; } export function attackValue(origin, target, progress, easing = 'linear') { return lerp(origin, target, easingValue(easing, progress)); } export function releaseValue(releaseStart, currentLower, progress, easing = 'linear') { return lerp(currentLower, releaseStart, 1 - easingValue(easing, progress)); } export function selectWinningOverride(overrides) { return overrides .filter((override) => override.live !== false) .reduce((winner, candidate) => { if (!winner) return candidate; if (candidate.priority !== winner.priority) { return candidate.priority > winner.priority ? candidate : winner; } return candidate.activationSequence > winner.activationSequence ? candidate : winner; }, null); } export function resolveNumericTarget({ base, binding, automation, overrides = [], modulation = 0, safetyClamp = [-Infinity, Infinity] }) { const afterBinding = binding ?? base; const lower = automation ?? afterBinding; const winner = selectWinningOverride(overrides); const afterOverride = winner ? winner.value : lower; const beforeClamp = afterOverride + modulation; return { base, afterBinding, lower, winner: winner?.id ?? null, afterOverride, beforeClamp, resolved: clamp(beforeClamp, safetyClamp[0], safetyClamp[1]) }; }