Repository navigation
Delta Comparison Policy
This document defines deterministic semantics for Phase 3 delta analytics.
-
baseline_run_id: reference run used as the comparison anchor. -
current_run_id: run being evaluated against baseline. - Delta formula:
absolute_delta = current_value - baseline_value-
relative_delta_pct = ((current_value - baseline_value) / baseline_value) * 100when baseline is non-zero.
-
improvement: metric moved in a favorable direction. -
regression: metric moved in an unfavorable direction. -
neutral: no change (absolute_delta == 0), or a duration change within timing noise (see below). -
unknown: metric cannot be compared due to missing or incompatible data.
| Metric | Group | Better Direction | Notes |
|---|---|---|---|
total_tests |
reliability | higher | More executed tests means broader reliability signal. |
passed |
reliability | higher | More passing tests is better. |
failed |
reliability | lower | More failed tests is worse. |
broken |
reliability | lower | More broken tests is worse. |
skipped |
reliability | lower | More skipped tests is treated as worse coverage quality. |
health_pct |
reliability | higher | Higher health percentage is better. |
wall_duration_ms |
performance | lower | Lower wall-clock duration is better. |
metrics_duration_ms |
performance | lower | Lower aggregate metrics duration is better. |
avg_case_ms |
performance | lower | Lower average case duration is better. |
Two identical runs never take exactly the same time, so a duration metric (unit: ms) is only a regression or an improvement when the change is at least 5 % of the baseline and at least the metric's floor: 100 ms for wall_duration_ms and metrics_duration_ms, 5 ms for avg_case_ms. A smaller change is neutral with reason within_noise; its absolute_delta and relative_delta_pct are still reported, and Compare shows it as "Within noise". The dashboard's duration trend uses the same rule (delta_service.within_noise, 100 ms floor) and reads "flat". Test counts and health have no noise floor: one more failed test is always a regression. The constants are NOISE_RELATIVE_PCT and _MetricPolicy.noise_floor_ms in qasight/services/delta_service.py.
-
missing_current_metric: current run has no value. -
missing_baseline_metric: baseline run has no value. -
zero_baseline_for_relative: absolute delta can be computed, relative percent cannot. -
incompatible_test_kind: run pair has differenttest_kind. -
within_noise: not unknown, but the reason aneutralduration is neutral despite a non-zero delta.
GET /api/v1/analytics/delta also returns stage_deltas: one entry per stage name present on either run's stage_health, matched by name (no archive extraction — reuses the stage_health already loaded on each CompletedRunView). Classification uses the same higher_is_better rule as health_pct above, applied to each stage's own health_pct. A stage present on only one side (renamed/added/removed since the baseline ran) gets classification: "unknown" with the missing side's fields null, rather than being dropped — mirrors the metric-level missing_*_metric reasons in spirit, but stage deltas don't carry a reason field.
GET /api/v1/analytics/delta/cases returns the full per-test breakdown — the API/UI equivalent of qasight diff's non---metrics-only output. Each test case is matched across the two runs by historyId → fullName → uuid (first present, in that order) and classified as:
-
added: present in current, not in baseline. -
removed: present in baseline, not in current. -
regression:passedin baseline →failed/brokenin current. -
fix:failed/brokenin baseline →passedin current. -
status_change: any other status transition. - (
unchangedcases are computed but dropped from the response — only actual changes are returned.)
Same suite, recorded two ways (added 2026-11-01). The key comes from the source: Allure's historyId for qasight run, a hash of tool and name for qasight ingest and pytest --qasight. So one suite recorded by qasight run and then by qasight ingest would read as every test removed and added again. Before classifying, a key found on only one side is paired with a key on the other side whose name matches once #, ::, / and > are folded to . (align_case_keys() in qasight/services/report_archive_diff.py), when exactly one test on each side has that name; ambiguous names (parametrized cases without their ids) stay unpaired. The pull request comment and qasight try also say when the stages changed since the compared run, since durations and flaky history stay per stage.
Unlike the run/stage-level deltas, this is computed on demand from each run's live artifact snapshot every request, with no caching — see CLI-UI Parity - Pyramid, Graphs, Deep Diff - 2026-07-23 for why (archives aren't large enough yet to justify the cache-invalidation work) and for why this reads from each run's snapshot directory rather than the separate ReportArchive table (qasight report list/diff's id space, which has no link to run-history run ids).
Generated from docs/Specs & ADRs/Delta Comparison Policy.md. Edit it there; changes made in the wiki are overwritten.
Architecture
CLI Commands
Processes & Guides
- CI-CD Pipeline Setup
- E2E Harness Operations Guide
- GitLab Pages Demo
- Publishing Docker Images
- Publishing to Artifactory
- Publishing to PyPI
- Setup Snippets
- Shared Resource Pools
- Team Server
Prompts & Snippets
Roadmap & Strategy
- Feature Gaps and Quick Wins - 2026-10-31
- New User Journey Audit - 2026-11-01
- Paid Features to Offer Free - 2026-10-31
- Product Roadmap
Specs & ADRs
- Affected Test Selection - 2026-10-30
- Alerts Where Developers Look - 2026-10-22
- Architecture Consolidation - 2026-10-06
- Architecture Review - 2026-10-31
- BehaveX Reports - 2026-10-21
- Better Flaky Signal - 2026-11-01
- Command Adapter and JUnit Import - 2026-09-25
- Config JSON Schema - 2026-10-22
- Crash Detection - 2026-10-31
- Delta Comparison Policy
- Docs Site - 2026-10-19
- Docs Vault and Wiki Sync - 2026-10-07
- Easy Setup - 2026-11-01
- Engine Fixes - 2026-11-01
- Engineering Health Review - 2026-10-31
- Exporting Results - 2026-11-01
- Flaky Test Issues - 2026-11-01
- Flaky Test Quarantine - 2026-10-22
- Free Copies of Paid Features - 2026-11-01
- GitHub Action PR Comment - 2026-10-19
- Human-Run Resource Provider - 2026-10-30
- Importer and Integration Bug Hunt - 2026-10-31
- Ingest and Team Server - 2026-10-22
- Interview Readiness Fixes - 2026-10-07
- Library Packaging
- Lifecycle Fixes - 2026-11-02
- MCP Server - 2026-11-01
- New User Journey Automation - 2026-11-01
- Open Source Features - 2026-10-19
- OpenTelemetry Export - 2026-10-30
- Phase 3 Delta Comparison Engine Plan
- Phase 3 Unified Dashboard Plan
- Phase 4 BYOK and Failure Analysis
- Phase 5 UI Redesign - Cycles-First Navigation
- Playwright Adapter - 2026-10-19
- Playwright JSON Import - 2026-10-22
- Plugin API - 2026-10-19
- Product Roadmap Work - 2026-10-25
- Product to Ten - 2026-10-25
- Project Health - 2026-10-26
- QASight Logo - 2026-11-05
- Qualflare Follow-ups - 2026-10-26
- Quarantine From the UI - 2026-11-01
- Specs & ADRs
- Rename to QASight - 2026-11-04
- Repository Pattern - Database-Agnostic Refactor
- Resource Lifecycle Hooks - 2026-10-26
- Resource Pools and Leases - 2026-10-26
- Run Deletion and Stop - 2026-11-02
- Runner Coverage - 2026-10-26
- Scale Runs and Stages - 2026-10-24
- Security and Install Review - 2026-10-31
- Switchable Team Features - 2026-10-24
- Test Delivery Metrics - 2026-11-02
- Test Labels, Environments and Releases - 2026-11-02
- Test Source in AI Summaries - 2026-11-01
- Throwaway Stage Containers - 2026-10-24
- Tidy Cards and Demo Examples - 2026-11-05
- UI Design Review - 2026-10-31
- UI Polish - 2026-11-08
- UI Restyle - 2026-10-19
- UI Review Fixes - 2026-11-01
Testing Workflows
Vault