LearnNewsExamplesServices
Frontmatter
id15947
titleFrame-delta flicker census: the isolation matrix''s measurement instrument
stateClosed
labels
enhancementaitesting
assigneesneo-kimi-iris
createdAtJul 26, 2026, 1:00 AM
updatedAtJul 26, 2026, 2:56 AM
githubUrlhttps://github.com/neomjs/neo/issues/15947
authorneo-kimi-iris
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 26, 2026, 2:56 AM

Frame-delta flicker census: the isolation matrix's measurement instrument

Closed Backlog/active-chunk-10 enhancementaitesting
neo-kimi-iris
neo-kimi-iris commented on Jul 26, 2026, 1:00 AM

Context

Filed during take-15's aftermath (2026-07-25 late): the operator's v0.5 verdict needed a flicker count, and no instrument existed to produce one. A hand-rolled frame-delta census (downsample + mean-abs frame diff per consecutive pair, spike pairs = events) found ~7 flash events with timestamps in ~2 minutes — but it lived in a one-off shell heredoc, and #15927's isolation matrix needs it as a repeatable measurement layer: run a candidate fix, census the boot/repro, get a number, not an eyeball.

The defect itself is not this ticket — #15927 (scene-1 presented-frame continuity, @neo-gpt-emmy) owns it. This ticket is the instrument the matrix consumes, and the take-16 acceptance gate will consume it again.

The Problem

One-frame presentation blanks are invisible to the specs that guard the film path (assertions hold worker truth, never camera truth — the take-15 review established this), and they are invisible to 1fps sampling (my first handback claimed "one flash" from a sample that structurally cannot count one-frame events). The measurement that works is position-independent frame-delta analysis: a flash is a boundary, and boundaries show up as mean-abs-diff spikes regardless of where on screen they happen — no window geometry, no color keying (screencapture's pipeline softens saturated colors, so color masks miss; delta energy does not).

The Architectural Reality

  • The probe core is a pure video-file analyzer: ffmpeg rawvideo gray frames → per-pair mean-abs delta → spike list → event pairing, with the median-relative threshold tonight's census used (> max(25, median×6)).
  • Two consumption shapes named at creation; the engine is shared: (a) standalone script (take-16 acceptance on any .mov/.webm), (b) spec-util the #15927 isolation matrix calls per boot. Shape finalized with @neo-gpt-emmy (the matrix owner) before implementation; the two-layer shape (script as engine, util as wrapper) is the default unless she rules otherwise.
  • Precedent for placement: test/playwright/util/ (RmaHelpers.mjs — harness utilities) for the spec-side wrapper; the standalone form as a sibling or a test/playwright/util/ export with a CLI shim. No ai/ surface.
  • Grain proven tonight: whole-frame at 53.8fps (one-frame events). Whether half-frame exposure flickers matter is @neo-gpt-emmy's call (question on record).

The Fix

  1. The probe engine with its threshold contract documented (median-relative, not absolute — absolute thresholds lie across content brightness).
  2. A spec pinning it against a known-blank fixture (synthesized: N clean frames + K injected black frames → exactly the injected events detected) and a clean control (a motion-heavy clip with no flashes → zero events).
  3. The wrapper the matrix consumes, per the shape call.

Contract Ledger

Surface Owner Consumers Contract
detectFlickerFrames({frames, width, height, fps, times?, absFloor?, relFactor?, pairGapSec?, pairGapMax?}) test/playwright/util/flickerCensus.mjs censusRawGrayFile · censusVideoFlicker · the #15927 isolation matrix (direct import) Pure detector over decoded consecutive gray frames. With times (source PTS), timestamps + the ~0.1s fusion window run in elapsed source time; without it, index/fps (CFR-only). Returns events (fusion view) + the COMPLETE spikes list (frame, sec, delta) — fusion never hides a spike.
censusRawGrayFile({filePath, width, height, fps, times?}) same the unit suite Raw-gray disk adapter; no ffmpeg anywhere in the path — the CI-owned adapter contract.
censusVideoFlicker({videoPath, scale?}) same CLI, take-16 acceptance, local receipts ffmpeg adapter: -fps_mode passthrough (never synthesized cadence) + showinfo PTS parse (source time, never one average). Detector throws on PTS/frame-count mismatch — loud, never a silent fps fallback.
CLI node test/playwright/util/flickerCensus.mjs <video> [--scale WxH] same operators, the roll script Prints every spike (sec, frame, delta) and the fused events. --scale parsed and honored.

Acceptance Criteria

  • The probe detects injected one-frame blanks at 53.8fps with zero misses AND zero false positives on a motion-heavy control (spec-pinned).
  • Against take-15's raw reel, it reproduces the hand-census event count (~7 events) within ±1 — the fixture with a known ground truth.
  • Threshold is documented as median-relative with the rationale (absolute thresholds fail across content brightness classes).
  • The isolation-matrix consumption path is named with @neo-gpt-emmy's sign-off in the PR review.

Out of Scope

  • The defect itself (#15927) and any fix for it — this ticket measures, it does not repair.
  • The vessel tokens-vs-skin gap (#15945, Grace's lane from the same verdict).
  • The take-16 roll-script sticky-hide (banked with Fable).

Avoided Traps

  • fps-sampling as measurement — catches a flash by luck, never counts it; the false precision is worse than no number.
  • Color-keyed detection — capture pipelines soften saturated UI accents (the film cursor's 255,90,0 reads as ~200-230 red on screencapture); delta energy has no color to soften.
  • Absolute delta thresholds — a dark-themed app and a bright desktop live in different energy classes; the threshold must derive from the clip's own median.

Decision Record impact

none — test-harness measurement tooling; no runtime surface.

Related

  • #15927 (the matrix this serves) · #15252 (the film) · #15945 (the vessel-parity sibling from the same verdict) · take-15 receipts (session a76464c2)

Live latest-open sweep: checked latest 20 open issues at 2026-07-25T23:00Z; KB semantic + local content grep found no equivalent (flicker-adjacent tickets #15137/#15136/#14653/#14660 are different surfaces). A2A in-flight sweep: no claim on a measurement probe; #15927's defect lane is Emmy's and untouched by this.

Origin Session ID: a76464c2-c4b7-48b4-a2cc-30ae42ab3dd0 Retrieval Hint: query_raw_memories("flicker census frame-delta take-15 flash events measurement")