Skip to content

Confidence indicators - #450

Open
chentex wants to merge 16 commits into
cloud-bulldozer:mainfrom
chentex:confidence-indicators
Open

Confidence indicators#450
chentex wants to merge 16 commits into
cloud-bulldozer:mainfrom
chentex:confidence-indicators

Conversation

@chentex

@chentex chentex commented Jul 29, 2026

Copy link
Copy Markdown
Member

Type of change

  • Refactor
  • New feature
  • Bug fix
  • Optimization
  • Documentation Update

Description

Every detected changepoint is automatically annotated with a statistical confidence indicator based on:

  • Cohen's d effect size — magnitude of the shift relative to data variability (primary indicator)
  • Welch's t-test p-value — included as descriptive context only; it is not calibrated for post-selection inference since the changepoint was already selected from this same data

Labels

Labels are driven by Cohen's d thresholds (Cohen 1988), with p-value shown inline for reference:

Label Meaning
Large shift (d=1.20, p=0.001) d >= 0.8 — strong evidence of a meaningful metric shift
Moderate shift (d=0.60, p=0.03) 0.5 <= d < 0.8 — moderate-magnitude shift
Small shift (d=0.30, p=0.02) 0.2 <= d < 0.5 — small but detectable effect
Negligible shift (d=0.10, p=0.85) d < 0.2 — negligible practical impact
Degenerate variance — shift detected but effect size undefined Both segments have zero variance with different means
Insufficient data Fewer than 2 data points on either side of the changepoint
Anomaly detection — shift confidence not applicable IsolationForest detects outliers, not sustained shifts

Segment boundaries

For E-Divisive, before/after segments are bounded by raw detector boundaries (all changepoints found by Otava before Orion applies direction/threshold/ACK/correlation filtering). This prevents a filtered recovery changepoint from dilating the comparison win
dow and masking a genuine earlier shift.
For CMR, confidence is computed against the original (uncollapsed) dataframe, preserving the baseline standard deviation across all historical runs rather than collapsing to a single averaged row.

Per-metric is_changepoint

Each metric object in JSON output now includes an explicit is_changepoint boolean field, replacing the previous inference from percentage_change != 0.

Additional changes

  • ci_95 field is always present in JSON output (set to null when confidence cannot be computed)
  • SciPy added as a runtime dependency (pyproject.toml, requirements.txt, setup.py)
  • test.bats: removed tests duplicated with test-local.bats
  • test-local.bats: assertions updated to match new label format and percent formatting
  • test_matcher_batch.py: added pylint: disable=protected-access suppression for TestGetNested
  • Full documentation in docs/usage.md

Related Tickets & Documents

  • Related Issue #
  • Closes #

Checklist before requesting a review

  • I have performed a self-review of my code.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please describe the System Under Test.
  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added per-changepoint confidence indicators for detected changepoints (label, statistical significance, effect size, sample sufficiency, and sample counts).
    • Confidence is now shown in text summaries, standalone reports, and serialized JSON, and included in generated JUnit results.
  • Documentation

    • Documented the confidence categories, thresholds, and how “Insufficient data” is determined, including algorithm-specific before/after splitting.
  • Bug Fixes / Output Improvements

    • Improved changepoint highlighting logic and standardized JUnit percent formatting.
  • Chores

    • Added SciPy as a runtime dependency.

Output Examples

Text

Regression(s) found :
--------------------------------------------------
Test: udn-density-pods:
Changepoint at:      5.0.0-0.nightly-2026-08-14-034145
Previous version:    5.0.0-0.nightly-2026-08-13-145619

Affected Metrics
+-----------------+----------+------------+---------------------------------+-----------------------------------------+
| Metric          |    Value | % Change   | Confidence                      | Labels                                  |
+=================+==========+============+=================================+=========================================+
| ovnCPU-sbdb_avg | 0.792783 | 22.01%     | Large shift (d=3.88, p=7.8e-05) | ['[Jira: Networking / ovn-kubernetes]'] |
+-----------------+----------+------------+---------------------------------+-----------------------------------------+

JSON

      "ovnCPU-sbdb_avg": {
        "value": 0.7927828041,
        "percentage_change": 22.006700959322767,
        "is_changepoint": true,
        "labels": [
          "[Jira: Networking / ovn-kubernetes]"
        ],
        "confidence": {
          "p_value": 7.767061601173493e-05,
          "cohens_d": 3.881568911408574,
          "label": "Large shift (d=3.88, p=7.8e-05)",
          "sufficient_data": true,
          "sample_size_before": 37,
          "sample_size_after": 6,
          "mean_before": 0.6904412324213095,
          "mean_after": 0.8423845697401298,
          "std_before": 0.038994230333000604,
          "std_after": 0.04021246475662423,
          "ci_95": [
            0.10977912382081302,
            0.1941075508168275
          ]
        }
      },

JUNIT

		<testcase name="[Jira: Networking / ovn-kubernetes] ovnCPU-sbdb_avg regression detection" timestamp="1787224031">
			<failure>
+----+--------------------------------------+----------------------+-------------------+------------------+---------------------+---------------------------------+
|    | uuid                                 | timestamp            |   ovnCPU-sbdb_avg | is_changepoint   | percentage_change   | Confidence                      |
|----+--------------------------------------+----------------------+-------------------+------------------+---------------------+---------------------------------|
|  0 | 7101150f-56f8-4a43-891d-56957c659b59 | 2026-07-31T11:50:24Z |          0.715141 | False            | 0.00%               |                                 |
...                              |
| 36 | 1bd7a246-5e73-46fa-9e9e-1ce755ff6a0e | 2026-08-13T17:28:48Z |          0.763616 | False            | 0.00%               |                                 |
| 37 | c288d7bc-d5d5-42ba-952f-e4edaca5298c | 2026-08-14T06:32:55Z |          0.792783 | True             | 22.01%              | Large shift (d=3.88, p=7.8e-05) | -- changepoint
...
| 42 | afda75e1-78a9-423b-b6c5-8857b2058d62 | 2026-08-20T05:25:43Z |          0.859382 | False            | 0.00%               |                                 |
+----+--------------------------------------+----------------------+-------------------+------------------+---------------------+---------------------------------+
         </failure>
		</testcase>

@openshift-ci
openshift-ci Bot requested review from afcollins and rsevilla87 July 29, 2026 13:46
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f965765a-9264-4ef2-8de9-e8a8fac730a5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Confidence indicators are computed per changepoint using Welch’s t-test and Cohen’s d, stored in analysis results, serialized through output and reporting paths, documented, and covered by new statistical and formatter tests.

Changes

Confidence Indicators

Layer / File(s) Summary
Confidence statistics
orion/confidence.py
Defines confidence results, algorithm-specific segmentation, Welch’s t-test, Cohen’s d, labels, and insufficient-data handling.
Analysis result integration
orion/pipeline/analysis_result.py, orion/run_test.py
Computes and stores confidence data across initial, window-expansion, and changepoint-clearing paths.
Formatter and report propagation
orion/pipeline/formatters/*, orion/reporting/*, orion/utils.py
Adds confidence data to JSON, regression records, summaries, standalone reports, and JUnit output.
Validation and usage documentation
orion/tests/test_confidence.py, orion/tests/test_formatters.py, orion/tests/test_matcher_batch.py, docs/usage.md
Adds statistical and output coverage, documents confidence indicators, and updates a lint suppression.
Statistical dependency wiring
pyproject.toml, requirements.txt, setup.py
Adds the bounded SciPy runtime dependency to project packaging declarations.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: mohit-sheth, afcollins, vishnuchalla

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.93% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the pull request's main change: adding confidence indicators to detected changepoints.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chentex
chentex force-pushed the confidence-indicators branch from c72c140 to a45c679 Compare July 29, 2026 13:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
orion/utils.py (1)

843-856: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Inconsistent percentage_change formatting between rows with and without confidence data.

base_record["percentage_change"] is left as a raw float unless a confidence label exists, in which case it becomes a formatted string (f"{pct:.2f}% ({conf['label']})"). This means the JUnit tabular output shows unformatted numeric values for some rows and a nicely formatted "%" + label string for others in the same column, which looks inconsistent to a reader of the generated table.

💚 Proposed fix: format percentage_change consistently regardless of confidence presence
         base_record = {
             uuid_field: record[uuid_field],
             "timestamp": datetime.fromtimestamp(record["timestamp"], timezone.utc).strftime(
                 "%Y-%m-%dT%H:%M:%SZ"
             ),
             metric_name: record["metrics"][metric_name]["value"],
             "is_changepoint": bool(record["metrics"][metric_name]["percentage_change"]),
-            "percentage_change": record["metrics"][metric_name]["percentage_change"],
+            "percentage_change": f"{record['metrics'][metric_name]['percentage_change']:.2f}%",
         }
         conf = record["metrics"][metric_name].get("confidence")
         if conf and conf.get("label"):
-            pct = base_record["percentage_change"]
-            base_record["percentage_change"] = f"{pct:.2f}% ({conf['label']})"
+            base_record["percentage_change"] = (
+                f"{record['metrics'][metric_name]['percentage_change']:.2f}% "
+                f"({conf['label']})"
+            )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/utils.py` around lines 843 - 856, Update create_record so
base_record["percentage_change"] is consistently formatted to two decimal places
with a percent sign for every row, then append the confidence label when
available. Preserve the existing confidence lookup and label behavior while
ensuring rows without confidence data use the same percentage formatting.
🧹 Nitpick comments (4)
orion/run_test.py (1)

252-254: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Confidence is computed unconditionally up front, then re-computed again when window expansion runs.

confidence_by_metric is computed at Lines 252-254 immediately after the initial analysis. If has_early_changepoint_raw triggers window expansion, confidence_by_metric is unconditionally recomputed again in every sub-branch (Lines 324-327, 337-340, 354-357), making the first computation wasted work whenever expansion happens.

Consider deferring the initial compute_confidence call until after the expansion decision is finalized (or guard it behind the else path that skips expansion).

Also applies to: 324-327, 337-340, 354-357

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/run_test.py` around lines 252 - 254, Defer the initial
compute_confidence call that assigns confidence_by_metric until the
window-expansion decision is finalized, or execute it only on the path that
skips expansion. Ensure expansion branches reuse their existing recomputation
and avoid calculating confidence before has_early_changepoint_raw triggers
expansion.
orion/tests/test_confidence.py (1)

162-212: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Missing edge-case coverage for NaN values preceding a changepoint.

None of these compute_confidence tests exercise a dataframe with NaN gaps in the metric column before the changepoint index — the scenario that surfaces the dropna()/positional-index misalignment flagged in orion/confidence.py. Based on path instructions ("Ensure test coverage for edge cases"), consider adding a regression test for this once the underlying fix lands.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/tests/test_confidence.py` around lines 162 - 212, Add a regression test
to TestComputeConfidence for a metric column containing NaN values before a
changepoint, invoking compute_confidence and asserting the result remains
correctly aligned with that changepoint and does not misclassify or crash. Use
the existing ConfidenceResult assertions and CMR/EDIVISIVE setup as appropriate,
preserving the expected behavior after the confidence.py indexing fix.

Source: Path instructions

orion/tests/test_formatters.py (1)

607-607: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer next(...) over single-element list slicing (Ruff RUF015).

Static analysis flags [r for r in parsed if r["is_changepoint"]][0] at Lines 607, 639, and 655; next(r for r in parsed if r["is_changepoint"]) avoids building the full filtered list.

Also applies to: 639-639, 655-655

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/tests/test_formatters.py` at line 607, Replace the single-element list
comprehensions indexed with [0] in the changepoint lookups at the affected test
cases with next(...) over the filtered generator. Preserve the existing
selection of the first record where r["is_changepoint"] is true.

Source: Linters/SAST tools

orion/confidence.py (1)

58-90: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Weight Cohen’s d pooled standard deviation by sample size.

Use sqrt(((n_before - 1) * std_before**2 + (n_after - 1) * std_after**2) / (n_before + n_after - 2)) before dividing by pooled std. The current unweighted average only matches Cohen’s d when n_before == n_after; with unequal windows it can shift cohens_d by roughly 25–40% or more, changing the confidence label.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/confidence.py` around lines 58 - 90, Update _compute_stats to calculate
pooled_std using the sample-size-weighted formula with n_before and n_after,
dividing by n_before + n_after - 2 before computing cohens_d. Preserve the
existing zero-pooled-standard-deviation handling and subsequent confidence-label
logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/usage.md`:
- Around line 323-331: Update the fenced code block containing the “Affected
Metrics” table to declare the text language, using the existing table content
unchanged.

In `@orion/confidence.py`:
- Around line 7-8: Add SciPy as an explicit pinned dependency in each project
dependency declaration: pyproject.toml, requirements.txt, and setup.py’s
install_requires. Keep the version consistent across all declarations so the
direct scipy.stats import in orion/confidence.py installs deterministically.
- Around line 103-130: Update compute_confidence so changepoint positions remain
aligned with the original dataframe after removing NaN values: preserve the
original row positions or translate each cp.index to its corresponding position
in the filtered data before calling _get_segments. Ensure non-Isolation Forest
changepoints split at the correct dataframe position and retain their associated
confidence results.

---

Outside diff comments:
In `@orion/utils.py`:
- Around line 843-856: Update create_record so base_record["percentage_change"]
is consistently formatted to two decimal places with a percent sign for every
row, then append the confidence label when available. Preserve the existing
confidence lookup and label behavior while ensuring rows without confidence data
use the same percentage formatting.

---

Nitpick comments:
In `@orion/confidence.py`:
- Around line 58-90: Update _compute_stats to calculate pooled_std using the
sample-size-weighted formula with n_before and n_after, dividing by n_before +
n_after - 2 before computing cohens_d. Preserve the existing
zero-pooled-standard-deviation handling and subsequent confidence-label logic.

In `@orion/run_test.py`:
- Around line 252-254: Defer the initial compute_confidence call that assigns
confidence_by_metric until the window-expansion decision is finalized, or
execute it only on the path that skips expansion. Ensure expansion branches
reuse their existing recomputation and avoid calculating confidence before
has_early_changepoint_raw triggers expansion.

In `@orion/tests/test_confidence.py`:
- Around line 162-212: Add a regression test to TestComputeConfidence for a
metric column containing NaN values before a changepoint, invoking
compute_confidence and asserting the result remains correctly aligned with that
changepoint and does not misclassify or crash. Use the existing ConfidenceResult
assertions and CMR/EDIVISIVE setup as appropriate, preserving the expected
behavior after the confidence.py indexing fix.

In `@orion/tests/test_formatters.py`:
- Line 607: Replace the single-element list comprehensions indexed with [0] in
the changepoint lookups at the affected test cases with next(...) over the
filtered generator. Preserve the existing selection of the first record where
r["is_changepoint"] is true.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fc77f491-75e0-4f5e-895c-b8d0e4e6f3fc

📥 Commits

Reviewing files that changed from the base of the PR and between 28c5c2f and c72c140.

📒 Files selected for processing (12)
  • docs/usage.md
  • orion/confidence.py
  • orion/pipeline/analysis_result.py
  • orion/pipeline/formatters/base.py
  • orion/pipeline/formatters/json_formatter.py
  • orion/reporting/standalone.py
  • orion/reporting/summary.py
  • orion/run_test.py
  • orion/tests/test_confidence.py
  • orion/tests/test_formatters.py
  • orion/tests/test_matcher_batch.py
  • orion/utils.py

Comment thread docs/usage.md Outdated
Comment thread orion/confidence.py
Comment thread orion/confidence.py Outdated
@chentex

chentex commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai please review again

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

@chentex: I’ll review the updated changes.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chentex

chentex commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
orion/tests/test_formatters.py (2)

662-717: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Growing duplication of inline ConcreteFormatter stub.

TestRegressionDataConfidence adds two more copies of the identical ConcreteFormatter stub class (lines 674-686, 700-712), on top of the three already in TestExtractRegressionData (lines 80-91, 109-120, 129-140). Any future change to the BaseFormatter ABC surface now requires updating 5 identical stubs across this file. Consider hoisting a single shared stub (module-level class or a pytest fixture) once, for reuse across all these tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/tests/test_formatters.py` around lines 662 - 717, Hoist the repeated
ConcreteFormatter implementation into one shared module-level test stub or
pytest fixture, then update the five tests in TestExtractRegressionData and
TestRegressionDataConfidence to reuse it instead of defining inline classes.
Preserve the existing no-op method behavior and BaseFormatter interface.

593-660: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use next() instead of list-comprehension-then-index (Ruff RUF015).

Static analysis flags the [r for r in parsed if r["is_changepoint"]][0] pattern at lines 607, 639, and 655. Using next() avoids materializing the full list and is the idiomatic fix Ruff suggests.

🧹 Proposed fix
-        cp_record = [r for r in parsed if r["is_changepoint"]][0]
+        cp_record = next(r for r in parsed if r["is_changepoint"])

(apply the same change at lines 639 and 655)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orion/tests/test_formatters.py` around lines 593 - 660, Replace the
list-comprehension-then-index lookups for changepoint records in
TestJsonConfidence methods test_changepoint_has_confidence_object,
test_no_confidence_data_no_key, and test_insufficient_data_in_json with next()
lookups, preserving the existing record selection and assertions.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@orion/tests/test_confidence.py`:
- Around line 174-182: The test_index_aligned_with_changepoints assertion only
checks the result count, not alignment. Update it to assert the ordered
changepoint-to-sample-size pairs are [(3, 7), (5, 5)], preserving the existing
compute_confidence invocation.

---

Nitpick comments:
In `@orion/tests/test_formatters.py`:
- Around line 662-717: Hoist the repeated ConcreteFormatter implementation into
one shared module-level test stub or pytest fixture, then update the five tests
in TestExtractRegressionData and TestRegressionDataConfidence to reuse it
instead of defining inline classes. Preserve the existing no-op method behavior
and BaseFormatter interface.
- Around line 593-660: Replace the list-comprehension-then-index lookups for
changepoint records in TestJsonConfidence methods
test_changepoint_has_confidence_object, test_no_confidence_data_no_key, and
test_insufficient_data_in_json with next() lookups, preserving the existing
record selection and assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 79acabe9-4d7a-491c-82c7-51d4376b4780

📥 Commits

Reviewing files that changed from the base of the PR and between c72c140 and 8a439c7.

📒 Files selected for processing (15)
  • docs/usage.md
  • orion/confidence.py
  • orion/pipeline/analysis_result.py
  • orion/pipeline/formatters/base.py
  • orion/pipeline/formatters/json_formatter.py
  • orion/reporting/standalone.py
  • orion/reporting/summary.py
  • orion/run_test.py
  • orion/tests/test_confidence.py
  • orion/tests/test_formatters.py
  • orion/tests/test_matcher_batch.py
  • orion/utils.py
  • pyproject.toml
  • requirements.txt
  • setup.py
🚧 Files skipped from review as they are similar to previous changes (10)
  • orion/pipeline/formatters/json_formatter.py
  • orion/reporting/standalone.py
  • orion/reporting/summary.py
  • orion/pipeline/formatters/base.py
  • orion/pipeline/analysis_result.py
  • docs/usage.md
  • orion/utils.py
  • orion/tests/test_matcher_batch.py
  • orion/run_test.py
  • orion/confidence.py

Comment thread orion/tests/test_confidence.py Outdated
@chentex
chentex force-pushed the confidence-indicators branch from 0d75679 to ea82944 Compare July 29, 2026 15:29
chentex and others added 9 commits July 30, 2026 08:55
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
@chentex
chentex force-pushed the confidence-indicators branch from ea82944 to 6d06dc7 Compare July 30, 2026 06:55
chentex added 4 commits July 30, 2026 10:01
Removes duplicated scenarios from test.bats

Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
@chentex chentex added enhancement New feature or request ok-to-test labels Jul 30, 2026
@vishnuchalla

Copy link
Copy Markdown
Collaborator

I like this change, can we have a flag to output the change points only after a certain confidence score? That way integration in CI will be simple.

@sjug
sjug self-requested a review July 30, 2026 19:01
@jtaleric

Copy link
Copy Markdown
Member

I like this change, can we have a flag to output the change points only after a certain confidence score? That way integration in CI will be simple.

I think regardless of the confidence score we let CI stay with all found regressions - i think the additional context will help Chaibot make better decisions long term.

@vishnuchalla

Copy link
Copy Markdown
Collaborator

I like this change, can we have a flag to output the change points only after a certain confidence score? That way integration in CI will be simple.

I think regardless of the confidence score we let CI stay with all found regressions - i think the additional context will help Chaibot make better decisions long term.

Correct, but more precise we are the better it is. From the token usage reduction standpoint 💸

@jtaleric

Copy link
Copy Markdown
Member

I like this change, can we have a flag to output the change points only after a certain confidence score? That way integration in CI will be simple.

I think regardless of the confidence score we let CI stay with all found regressions - i think the additional context will help Chaibot make better decisions long term.

Correct, but more precise we are the better it is. From the token usage reduction standpoint 💸

yeah - that could help reduce the token aspect -- we could pass that via orion-mcp

@jtaleric

jtaleric commented Jul 30, 2026

Copy link
Copy Markdown
Member

@chentex this looks great! One aspect I think we can change (not here, but on a follow-on) is the term labels - maybe we just update the JIRA Labels to call it specific to JIRA so we don't overload a single term. We will have Confidence labels and JIRA lables... 🤢

@jtaleric

Copy link
Copy Markdown
Member

/lgtm
tested locally. 🚀

@sjug sjug left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Requesting changes mainly because of two issues in how confidence is calculated: the current approach can make random noise look like a real change, and can label a real change as noise. Details are in the inline comments, along with smaller suggestions on output format, code structure, and tests.

This PR also removes roughly 600 lines from test.bats and adds an unrelated pylint suppression in test_matcher_batch.py. The deleted scenarios remain in test-local.bats, so coverage is preserved, but these cleanups should be acknowledged in the PR description or moved to a separate change.

Comment thread orion/confidence.py Outdated
std_after=float(np.std(after, ddof=1)) if n_after > 1 else None,
)

_, p_value = stats.ttest_ind(before, after, equal_var=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The changepoint was selected from these same values, so testing it again with an ordinary Welch test makes random noise look significant too often. The reported ci_95 has the same problem. Please calibrate by resampling the full detector-and-selection pipeline or by using separate confirmation data. Otava's existing window statistics may be reusable descriptively, but only if their selection guarantees are understood.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Otava's existing window statistics may be reusable

that would be nice! are there suggestions on how we could adjust the existing windowing?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yes. For the Otava changepoints, I would reuse the local before/after statistics already attached to ChangePoint.stats, or preserve the exact segment boundaries and sample sizes Otava used before Orion filters changepoints. That fixes the current prefix/suffix problem. We should not derive the boundaries from the filtered changepoint list because a neighboring boundary may already have been removed.

This only fixes the comparison window. Otava's p-value is also involved in selecting the changepoint, so it is not independently calibrated. In the short term, I would report the local means, standard deviations, and effect size as descriptive context without presenting the p-value or interval as calibrated confidence. Fully calibrated inference would require rerunning the complete detector-and-selection process on resampled data that contains no real change, or using held-out runs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

changing the underlying algo could introduce new regressions in the pipeline, right? where the current implementation will categorize the regressions likelihood.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No algorithm change needed. The suggestion is to reuse statistics Otava already computes internally when it finds each changepoint, purely for the confidence annotation. Detection results would be identical.

Comment thread orion/confidence.py Outdated
"""Split data into before/after segments based on algorithm type."""
if algorithm_name == cnsts.CMR:
return data[:-1], data[-1:]
return data[:changepoint_index], data[changepoint_index:]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This replaces the detector's local window with the entire prefix and suffix. A later recovery or reversal can therefore cancel a genuine earlier shift and label it "Noise." Please compare segments bounded by neighboring changepoints, or reuse the detector's window statistics.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The neighboring-window change is directionally right, but cp_indices is built from cps after Orion filters changepoints by direction, threshold, ACK state, and correlation. If a recovery changepoint is filtered out, its boundary disappears and the original dilution problem returns.

I reproduced this with a 0 -> +10 -> -10 series. With only the reported first changepoint, the comparison gives d=0.002 and p=0.992. With both detector boundaries, it gives d=120.65 and p=5.4e-69.

Please preserve the raw detector boundaries or local statistics before Orion filters the changepoints, and use those raw boundaries for the comparison windows.

Comment thread orion/confidence.py Outdated
Comment thread orion/confidence.py Outdated
Comment thread orion/confidence.py Outdated
Comment thread orion/pipeline/formatters/base.py Outdated
Comment thread test-local.bats Outdated
Comment thread orion/tests/test_confidence.py Outdated
Comment thread orion/tests/test_confidence.py
Comment thread orion/confidence.py
Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
Comment thread orion/tests/test_confidence.py
Comment thread orion/confidence.py Outdated
@sjug

sjug commented Aug 5, 2026

Copy link
Copy Markdown

Thanks for the follow-up. Most of the original presentation, serialization, and maintainability concerns are addressed. I am keeping changes requested for the two original statistical blockers: post-selection calibration and comparison boundaries lost during changepoint filtering. The CMR raw-data issue also needs correction.

Before merge, please also refresh the PR description. It still shows the old "Likely real"/"Noise" labels and old JUnit layout, and it does not mention the test.bats deduplication or unrelated pylint suppression.

@afcollins afcollins left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

I like it. Improves our understanding of identified changepoints.

@sjug I see a lot of comments from you. Are they required or nits?

The is_changepoint reliability seems rather serious.

@sjug

sjug commented Aug 12, 2026

Copy link
Copy Markdown

@afcollins Requested changes, not comments. As I summarized in the comment prior to yours.

@sjug sjug removed the lgtm label Aug 12, 2026
@jtaleric

Copy link
Copy Markdown
Member

@chentex Curious when we think you can address @sjug's feedback? Thanks!

Updates test scenarios
CMR data is now used with the original dataframe
is_changepoint is included as a per metric value also

Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
@openshift-ci

openshift-ci Bot commented Aug 20, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from afcollins. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Signed-off-by: Vicente Zepeda Mas <vzepedam@redhat.com>
@chentex
chentex requested review from afcollins and sjug August 20, 2026 17:34

@afcollins afcollins left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm happy with the [output], but will leave approval to sjug

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

Labels

enhancement New feature or request ok-to-test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants