Skip to content

MLP225: features that close the local fork's fast paths (cost-report explanation)

MLP225 is not a normal warning. It is the causal explanation layer of the fork-aware cost report: under a local-fork knowledge profile it states, per play, which feature keeps which of the fork's fast paths closed — "fork-per-play is serial fallback because of this Scene updater", "the packed interpolation gate is closed by this updater-bearing family" — and never recommends removing a feature. Scene updaters, foreground registration, custom rate functions, stop conditions, sounds, sections and transparent output can all be correct expression; the report explains the render-path consequence and nothing else.

  • Default severity: info
  • Minimum confidence: high (every reported loss cites a statically proven blocker from the overlay's curated list)
  • Implementation phase: 3
  • default_enabled: false — a normal check run never registers the rule
  • required_capabilities: ("cost-report", "local-fork-overlay")
  • Fix: none, by design (removal advice would change scene meaning)

Where it evaluates

The rule's home is the cost command: qual cost renders a "fork fast paths" section per scene whenever the loaded knowledge profile declares fork_capabilities (the local_0_20_1_4d25c031 overlay does; upstream_0_20 does not, and the section — like the rule — is then absent entirely).

An explicit check --select MLP225 is the only other way to evaluate it: the exact rule ID must appear in select (the MLP family prefix never enables it), and the cost-report capability then pulls in the full cost fact stack. Under an upstream profile even the explicit opt-in stays inert.

What it audits

Three curated gates, read from the overlay's fork_capabilities block (never invented from rule prose):

  • fork-per-play (cairo_fork_workers): reported only when the active profile requests it with at least the curated min_workers (2). Workers 0 is unrequested, never a reported loss. The overlay's monotonic_disable fact is modeled: the first play that provably renders serially opens the parent partial-movie encoder, and every later play — otherwise eligible or not — renders serially too. Per-play independence is never assumed; a later clear play is reported as "monotonically disabled" with the causal chain back to the first serial play.
  • static layers (cairo_static_layers): the z-ordered layer plan, evaluated per play against the curated blocker list and the 3-frame amortization floor. A frozen static wait is "not applicable" (already optimal), not a loss.
  • packed interpolation: the bulk fast path (Transform/_MethodAnimation only, 12-frame floor); an updater-bearing family in the scene provably closes it.

A blocker is reported only when statically proven (a Scene updater registered on every path before the play, an animation type resolved entirely outside the exact-type allowlist, a lambda rate_func, ...). Anything unresolvable is "not statically auditable" — never a fabricated loss and never a fabricated eligibility.

Example report rows

fork-per-play (cairo_fork_workers 4):
  demo.py:8:9 play #1: no static blocker found (fork-eligible pending the runtime audit)
  demo.py:10:9 play #2: serial fallback because a Scene updater is registered at demo.py:9:9 (blocker scene_updaters)
  demo.py:11:9 play #3: no static blocker found, but play #2 (demo.py:10:9) fell back to the serial path (scene_updaters) and a rendered serial play opens the parent encoder: fork disabling is renderer-wide and monotonic (blocker parent_encoder_opened)

The measured calibration evidence quoted with fork losses (for example the fork-per-play A/B 7.55 -> 3.95 s / 12.13 -> 7.50 s, and the packed-path 130.658 -> 33.004 ms/play) comes from docs/research/perf-evidence.md and is machine-specific evidence, not portable truth.