Skip to content

[compositor] Выражать reconstruction error в единицах результата #223

Description

@lemone112

Пользовательский результат

Потребитель или build-time compiler может задать максимальную ошибку spring-реконструкции в единицах анимируемого значения. Compositor гарантирует этот предел математически, независимо от амплитуды перехода, не вводя скрытых предположений про «типичные 100 px».

Подтверждённая проблема

Текущий DEFAULT_TOLERANCE = 1/400 выражен в нормализованном progress [0..1]. Для аффинного numeric mapping:

value(t) = from + progress(t) · (to - from)

ошибка результата:

|Δvalue| <= |to - from| · toleranceProgress

Следовательно, один default означает:

span = 100  -> max error 0.25 value units
span = 1000 -> max error 2.5 value units

Комментарий в compositor уже признаёт зависимость и предлагает вручную уменьшать tolerance для крупных амплитуд. Но compileSpringPlan() уже знает from/to, а build-time compiler знает статические tracks; пользователь не должен вручную переводить абсолютный budget в progress там, где это можно вывести точно.

Закон преобразования

Для span = |to-from| > 0:

toleranceProgress <= maxValueError / span

Если одновременно заданы normalized и absolute budgets:

effectiveTolerance = min(normalizedTolerance, maxValueError / span)

Для вырожденного span движение отсутствует; деление не выполняется.

Это не perceptual heuristic. Число maxValueError задаётся caller/compiler в единицах конкретного numeric channel.

API / архитектура

Низкоуровневый compositor

Сохранить tolerance как normalized expert API и добавить явно названный absolute contract, например:

compileSpringPlan({
  from,
  to,
  maxValueError: 0.25,
})

Точное имя выбирается по conventions репозитория, но семантика обязательна:

  • конечное maxValueError > 0;
  • единицы совпадают с numeric from/to до format;
  • effective tolerance вычисляется один раз до cache/segmenter;
  • cache key содержит фактический effective tolerance, а не два эквивалентных authoring inputs;
  • одинаковая физическая кривая + одинаковый effective tolerance дают один artifact.

Multi-channel / animate/compiler

Для группы каналов с общей нормализованной spring-кривой:

effectiveTolerance = min по всем каналам с absolute budget

Так один native effect соблюдает самый строгий channel contract.

  • numeric/affine codecs могут дать абсолютную гарантию;
  • non-affine format, color/perceptual space, unknown CSS interpolation и geometry-dependent scale не получают выдуманный absolute default;
  • при неизвестной метрике остаётся normalized tolerance либо явный caller budget;
  • никаких layout reads ради определения «видимой» ошибки;
  • compiler может вычислить effective tolerance build-time для статических spans и не поставлять эту арифметику в browser.

Precision manifest

Если параметр входит в compiler/portable MotionProgram:

  • wire/JSON corpus фиксирует effective normalized tolerance либо точный absolute authoring field + canonical lowering;
  • TS/reference/browser исполнители используют один закон;
  • version/feature mask обновляются явно;
  • старые программы сохраняют текущий normalized default.

RED / доказательства

  1. Scaling RED: одна spring-кривая на spans 1/100/1000; текущая normalized-only ошибка результата растёт линейно.
  2. Property: reconstructed output на плотной независимой сетке соблюдает maxValueError для under/critical/over и v0 domain.
  3. Formula oracle: effective=min(normalized, absolute/span); zero/near-zero span без NaN/Infinity.
  4. Multi-channel: общий artifact выбирает строгий minimum; каждый канал проходит свой bound.
  5. Cache: эквивалентные effective tolerances hit одного artifact; разные — не collide.
  6. Serialization: округление progress/percent уже входит в доказанный общий error budget и не нарушает absolute bound.
  7. Browser: Chromium/Firefox/WebKit sample фактически serialized кривой, а не raw nodes.
  8. Compiler: static span lowering исключает conversion math из browser graph; dynamic positive-control остаётся runtime.
  9. Mutation: span/abs/min/zero/cache-key/rounding mutants убиты.

Размер и производительность

  • nano byte-identical <=1024 B gzip; nano API не расширяется;
  • no per-frame work: преобразование выполняется compile/preflight один раз;
  • hot cache-hit не аллоцирует;
  • existing compositor/animate gates не повышаются;
  • compiler common fixtures остаются в ceiling [0.4] Epic: compiler-driven common motion ≤ 5 KB без третьего runtime-tier #220;
  • сгенерированная linear() может стать плотнее только когда caller запросил более строгую доказанную точность; cost отражается diagnostics/manifest.

Не входит

  • автоматический выбор «невидимой» ошибки по DPI, viewing distance или вкусу;
  • layout reads;
  • perceptual color metric;
  • изменение физического solver;
  • новый runtime tier.

Связано: #95, #106, #220, #221.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions