Skip to content

E2E: Add configurable AV sync tolerance for effect-heavy scenarios#93

Merged
chrisgleissner merged 2 commits into
fix/e2e-avsync-pop-detectionfrom
copilot/sub-pr-89
Jan 13, 2026
Merged

E2E: Add configurable AV sync tolerance for effect-heavy scenarios#93
chrisgleissner merged 2 commits into
fix/e2e-avsync-pop-detectionfrom
copilot/sub-pr-89

Conversation

Copilot AI commented Jan 13, 2026

Copy link
Copy Markdown
Contributor

Heavy CRT effects (afterglow, bloom, scanlines) in scenarios like ntsc_vintage_tv and ntsc_classic_crt can cause pop detection issues on CI, leading to false AV sync failures. The existing code treated all sync failures as hard errors.

Changes:

  • Scenario configuration: Added av_sync tolerance entry under existing tolerances section in scenario YAML files

    tolerances:
      frame_progression:
        ci: 0.4
      av_sync:
        ci: lenient  # New: treat sync failures as warnings on CI
  • Loading logic (e2e.py): Parse tolerances.av_sync.{ci,local} and pass mode to validation pipeline. Maintains backward compatibility with numeric av_sync_tolerance_ms.

  • Validation (results.py): When av_sync_tolerance_mode == 'lenient' and env.is_ci, treat sync failures as warnings instead of errors. Local runs remain strict.

Applied lenient mode to ntsc_vintage_tv and ntsc_classic_crt scenarios. Other scenarios unaffected.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: chrisgleissner <3969147+chrisgleissner@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix AV sync issues in E2E tests E2E: Add configurable AV sync tolerance for effect-heavy scenarios Jan 13, 2026
Copilot AI requested a review from chrisgleissner January 13, 2026 21:55
@chrisgleissner chrisgleissner marked this pull request as ready for review January 13, 2026 21:57
Copilot AI review requested due to automatic review settings January 13, 2026 21:57
@chrisgleissner chrisgleissner merged commit 0d9c049 into fix/e2e-avsync-pop-detection Jan 13, 2026
37 checks passed
@chrisgleissner chrisgleissner deleted the copilot/sub-pr-89 branch January 13, 2026 21:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds configurable AV sync tolerance for E2E test scenarios experiencing false failures due to heavy CRT effects interfering with pop detection on CI. The solution introduces a "lenient" mode that treats sync failures as warnings instead of errors specifically for CI environments.

Changes:

  • Added tolerances.av_sync configuration to scenario YAML files supporting both ci and local environment-specific settings
  • Implemented loading logic in e2e.py with backward compatibility for the legacy av_sync_tolerance_ms format
  • Updated validation logic in results.py to support lenient mode, treating all-pops-out-of-sync as warnings on CI when lenient mode is enabled
  • Applied lenient CI tolerance to ntsc_vintage_tv and ntsc_classic_crt scenarios

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/e2e/scenarios/ntsc_vintage_tv/scenario.yaml Added av_sync.ci: lenient tolerance for heavy CRT effects
tests/e2e/scenarios/ntsc_classic_crt/scenario.yaml Added av_sync.ci: lenient tolerance for heavy CRT effects
tests/e2e/e2e.py Implemented tolerance loading logic with CI/local detection and backward compatibility
tests/e2e/framework/orchestrator.py Updated to pass av_sync_tolerance_mode to validator
tests/e2e/framework/validation/results.py Added lenient validation logic that treats sync failures as warnings on CI

Comment thread tests/e2e/e2e.py
Comment on lines +158 to +159
is_ci = os.environ.get('CI', '').lower() in ('1', 'true', 'yes') or \
os.environ.get('GITHUB_ACTIONS', '').lower() in ('1', 'true', 'yes')

Copilot AI Jan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI detection logic is duplicated here and at line 172. The Environment class already has a _detect_ci() method that checks multiple CI indicators comprehensively. Consider reusing the Environment's CI detection logic or instantiating Environment earlier to access its is_ci property for consistency.

Copilot uses AI. Check for mistakes.
Comment thread tests/e2e/e2e.py
Comment on lines +160 to +165

# Check for CI-specific or local-specific tolerance
if is_ci and 'ci' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['ci']
elif not is_ci and 'local' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['local']

Copilot AI Jan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When tolerances.av_sync is specified but neither 'ci' nor 'local' keys match the current environment, av_sync_tolerance_mode remains None. This could result in unexpected default behavior. Consider adding a fallback to handle cases where the YAML has tolerances.av_sync but doesn't specify the appropriate environment key, or at least add a comment explaining the intended behavior.

Suggested change
# Check for CI-specific or local-specific tolerance
if is_ci and 'ci' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['ci']
elif not is_ci and 'local' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['local']
# Allow both simple scalar and environment-specific mappings for av_sync tolerance
if isinstance(av_sync_tol, (int, float, str)):
# Single value applies to all environments
av_sync_tolerance_mode = av_sync_tol
elif isinstance(av_sync_tol, dict):
# Check for CI-specific or local-specific tolerance first
if is_ci and 'ci' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['ci']
elif not is_ci and 'local' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['local']
# Fallbacks when environment-specific key is missing
elif 'default' in av_sync_tol:
av_sync_tolerance_mode = av_sync_tol['default']
elif 'ci' in av_sync_tol:
# Use CI value for all environments if it's the only one provided
av_sync_tolerance_mode = av_sync_tol['ci']
elif 'local' in av_sync_tol:
# Use local value for all environments if it's the only one provided
av_sync_tolerance_mode = av_sync_tol['local']
else:
logging.warning(
"Scenario YAML 'tolerances.av_sync' is present but does not define "
"'ci', 'local', or 'default'; using orchestrator default tolerance."
)

Copilot uses AI. Check for mistakes.
network_simulation: Optional[Dict] = None,
full_frame_pop: bool = False,
av_sync_tolerance_ms: int = 40):
av_sync_tolerance_mode = None):

Copilot AI Jan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The av_sync_tolerance_mode parameter is missing a type hint. Based on the usage in the code (checking for 'lenient' string and numeric values), it should be typed as Optional[Union[str, int, float]] for clarity and type safety.

Copilot uses AI. Check for mistakes.
verbose: bool = False,
full_frame_pop: bool = False,
av_sync_tolerance_ms: int = 40):
av_sync_tolerance_mode = None):

Copilot AI Jan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The av_sync_tolerance_mode parameter is missing a type hint. Based on the usage in the code (checking for 'lenient' string and numeric values), it should be typed as Optional[Union[str, int, float]] for clarity and type safety.

Copilot uses AI. Check for mistakes.
results['av_sync'] = {'status': status_str, 'details': msg}
errors.append(f"AV Sync: All {analyzed_count} analyzed pops out of sync - {msg}")
# All pops are out of sync
# If lenient mode is enabled and we're on CI, treat as warning instead of error

Copilot AI Jan 13, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lenient mode currently only takes effect when both use_lenient_validation is True AND env.is_ci is True. This means if a scenario YAML specifies tolerances.av_sync.local: lenient, it will have no effect since local runs always remain strict. Consider either: (1) documenting this limitation clearly in a comment, or (2) removing support for tolerances.av_sync.local: lenient to avoid confusion, since lenient mode only applies to CI runs.

Suggested change
# If lenient mode is enabled and we're on CI, treat as warning instead of error
# NOTE: Lenient AV sync validation is intentionally CI-only.
# - We only downgrade "all pops out of sync" from error to warning when BOTH
# `use_lenient_validation` is True AND the environment is CI (`env.is_ci`).
# - Local runs always remain strict, even if a scenario YAML specifies
# `tolerances.av_sync.local: lenient`; that setting has no effect on local runs.
# This is by design to keep local debugging stricter than CI.

Copilot uses AI. Check for mistakes.
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.

3 participants