Skip to content

CI-able deterministic guard against committed-prefix re-render regressions #31

Description

@jonathanKingston

Type: testing · Area: src/streaming-frozen-tail.test.ts, scripts/bench-streaming.mts · Follow-up to #21 / #23

Summary

The only guard that the committed prefix isn't re-rendered per commit (the O(n²) #23 fixed) is the wall-clock scaling section in bench-streaming.mts, which is a manual script, not run in CI, and timing-based (noisy). A regression that reintroduces per-commit full-prefix rendering — e.g. a new fallback condition that fires every frame, degrading everything to fullMorph — passes the whole suite (output stays byte-identical, just quadratic) and ships silently. The #23 review found exactly this class of bug (a fallback storm on non-monotonic boundaries).

Proposal

A deterministic, timing-free CI test asserting per-commit rendering work is O(tail), not O(prefix). Options:

  1. Instrument FrozenTailRenderer with a counter of sanitized/rendered bytes per commit (or per stream), exposed for tests, and assert total bytes rendered across a stream is ~O(n), not O(n²) — stream N and 2N paragraphs, assert the ratio is near 2×, not 4×.
  2. Or a node-identity assertion strengthened to cover the fallback-storm case: stream a long doc and assert the number of distinct DOM node instances ever observed for early frozen blocks stays 1 (a fallback storm re-creates them).

Option 1 is the direct metric; the existing "frozen first paragraph keeps one node instance" test is a partial version of option 2 and already catches whole-prefix re-render + fallback storm, but not "tail silently grew".

Acceptance

  • A CI test fails if committed-prefix render bytes scale super-linearly with input across a doubling, independent of machine timing.
  • No production behavior change (any instrumentation is inert/opt-in).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions