Skip to content

feat(visual-verification): Phase 0 engine-agnostic eye-test harness - #226

Draft
IanFrelinger wants to merge 2 commits into
masterfrom
cursor/visual-verification-harness-6079
Draft

feat(visual-verification): Phase 0 engine-agnostic eye-test harness#226
IanFrelinger wants to merge 2 commits into
masterfrom
cursor/visual-verification-harness-6079

Conversation

@IanFrelinger

Copy link
Copy Markdown
Owner

Summary

Implements Phase 0 of the visual verification vertical: an engine-agnostic harness that runs a target under a virtual display, replays deterministic scripted scenarios, captures frames, and emits Ed25519-signed eye-test session records.

Changes

  • Nexo.VisualVerification — core records, canonical scenario hashing, dHash perceptual tier (ε=5), frame content store, golden witness storage, Ed25519 signing (parallel sibling to CertifiedTransition)
  • Nexo.VisualVerification.ProvidersIDisplayProvider / ITargetAppProvider seams, SimulatedDisplayProvider (CI path), XvfbDisplayProvider (integration trait), EyeTestHarness with mandatory double-run determinism gate
  • Nexo.ToyRenderer — deterministic toy target (xoshiro256** PRNG, spawn/despawn/pause channels, software RGBA renderer) + self-playing demo entry point
  • Nexo.VisualVerification.Tests — seven rejection tests (R1–R7) plus engine-agnostic core scan and checked-in demo scenario
  • samples/visual-verification/demo-scenario.json — seeded demo scenario for CI
  • README — threat model, determinism prerequisites, explicit presentation-stability scope

Design decisions (open questions resolved)

Question Decision
CertifiedTransition subtype? Parallel EyeTestSessionRecord with same Ed25519 authority via NSec
Perceptual hash + epsilon dHash (9×8), Hamming ε=5, pinned by R7_PerceptualEpsilonBoundary
Frame storage Hash-referenced raw RGBA8888 at {storageRoot}/{sha256}.raw
Golden isolation GoldenRecordStore / GoldenEyeTestRecord witness-only; harness uses FrameExpectationSet

Testing

dotnet test tests/Nexo.VisualVerification.Tests/Nexo.VisualVerification.Tests.csproj
dotnet run --project tools/Nexo.ToyRenderer/Nexo.ToyRenderer.csproj -- /tmp/nexo-eye-demo
  • 10/10 tests pass on headless Linux with no Xvfb (simulated provider path)
  • Xvfb integration test skips cleanly when Xvfb/xwd/convert unavailable
  • Commit history: rejection tests committed before implementation (f91bb3e54677476f)

Rejection tests (R1–R7)

  1. Tampered frame bytes → verification fails
  2. Wrong scenario vs golden → Mismatch
  3. Nondeterministic target → NonDeterministic, signing throws
  4. Hollow capture (identical blank frames) → CaptureFailure
  5. Golden isolation source scan (providers + toy renderer)
  6. Signature binding on field mutation
  7. Perceptual epsilon boundary pinned

Checklist

  • dotnet test tests/Nexo.VisualVerification.Tests passes locally (headless, no Xvfb)
  • Documentation updated (src/Nexo.VisualVerification/README.md)
  • No unresolved TODO / NotImplementedException
  • Conventional commits; rejection tests precede implementation in history
Open in Web Open in Cursor 

cursoragent and others added 2 commits July 8, 2026 15:27
Rejection tests R1-R7 authored before implementation:
- tampered frame detection
- wrong scenario golden mismatch
- nondeterminism gate teeth
- hollow-capture detection
- golden isolation source scan
- Ed25519 signature binding
- perceptual epsilon boundary

Co-authored-by: IanFrelinger <IanFrelinger@users.noreply.github.com>
- Core records, canonical hashing, dHash perceptual tier, Ed25519 signing
- SimulatedDisplayProvider (CI path) and XvfbDisplayProvider (integration trait)
- EyeTestHarness with mandatory double-run determinism gate
- Deterministic ToyRenderer with xoshiro256** PRNG
- Self-playing demo via dotnet run on Nexo.ToyRenderer
- README with threat model and determinism prerequisites

Co-authored-by: IanFrelinger <IanFrelinger@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants