Skip to content

fix(ci): stop the revert oracle scoring an all-skipped baseline as pass - #4131

Open
BIMvoice wants to merge 4 commits into
mainfrom
fix-4108-all-skipped-baseline
Open

fix(ci): stop the revert oracle scoring an all-skipped baseline as pass#4131
BIMvoice wants to merge 4 commits into
mainfrom
fix-4108-all-skipped-baseline

Conversation

@BIMvoice

@BIMvoice BIMvoice commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

vitest's and node --test's summary lines count a skipped test into the same total as a passed one: vitest's Tests 2 skipped (2) parses through parseRunnerOutput to { passed: 0, failed: 0, total: 2 } — exactly the shape a describe.skipIf guard produces when its fixture is absent (AGENTS.md requires skipping, not throwing, in that case). verdict() only ever guarded baseline.total === 0, so a file that collected tests but executed none of them was scored kind: pass and used as a green baseline — matching this issue's own quoted CI output: packages/export (vitest) -> pass (pass 0, fail 0, total 2).

Worse than cosmetic: since the baseline was accepted as a legitimate PASS, the oracle went on to score an identically all-skipped reverted run as UNOBSERVED — "FINDING: ... all N test(s) still PASS. The branch's tests do not observe the branch's change." — a finding about the author's tests, when the truth is that nothing was ever measured.

Closes #4108

Part of the capability-gap-vs-finding family tracked by #4109 (referenced, not closed by this PR). This fix is narrowly scoped to #4108's specific all-skipped shape rather than #4109's larger proposed per-file execution attribution.

RED (before the fix)

baseline parse: {"kind":"pass","passed":0,"failed":0,"total":2,"evidence":[]}
baseline.kind === PASS: true
verdict: {
  "verdict": "UNOBSERVED",
  "exitCode": 1,
  "reason": "FINDING: with the production change fully reverted, all 2 test(s) still PASS. The branch's tests do not observe the branch's change.",
  ...
}

An all-skipped baseline was scored pass, and an identically all-skipped reverted run was reported as UNOBSERVED (exit 1) — a finding about the branch's tests, not a report that nothing was measured.

Fix

Adds a new ALL_SKIPPED kind (scripts/lib/revert-oracle-all-skipped.mjs — split out to keep revert-oracle.mjs at its recorded module-size budget, the same reason revert-oracle-python.mjs, revert-oracle-rust-features.mjs and revert-oracle-plan-runs.mjs exist) for collected > 0 && executed === 0 (passed === 0 && failed === 0).

It plugs into the oracle's existing verdict machinery rather than inventing a parallel one:

  • A baseline of kind ALL_SKIPPED is not PASS, so it falls through the existing baseline.kind !== PASS check into BASELINE-BROKEN (exit 3) — the same bucket NO_TESTS/LOAD_FAILURE/etc. baselines already use, and never UNOBSERVED.
  • A reverted run of kind ALL_SKIPPED falls through to the existing "unhandled reverted kind" INCONCLUSIVE fallback (exit 3) — also never UNOBSERVED or a pass.
  • KIND_SEVERITY (used by aggregate() across packages) gets ALL_SKIPPED inserted between ASSERTION_FAILURE and NO_TESTS, so one all-skipped package still poisons an otherwise-green multi-package aggregate.

No new exit code was needed — EXIT_UNOBSERVED (1) stays reserved for genuine findings, and the dispatcher (check-test-revert-oracle.mjs) already collapses every non-OBSERVED/non-UNOBSERVED verdict to EXIT_INCONCLUSIVE (3), which is exactly the right semantic bucket here.

GREEN (after the fix)

baseline parse: {"kind":"all-skipped","passed":0,"failed":0,"total":2,"evidence":["runner executed zero of 2 collected test(s) (all skipped)"]}
baseline.kind === PASS: false
verdict: {
  "verdict": "BASELINE-BROKEN",
  "exitCode": 3,
  "reason": "the branch's own tests do not pass before any revert (all-skipped: runner executed zero of 2 collected test(s) (all skipped)). Nothing can be concluded from reverting on top of a red baseline.",
  ...
}

Partial-skip decision

A partially skipped file (some tests ran, some were skipped) is left as an ordinary PASS — it still has at least one executed assertion with real evidentiary value that could have gone red on the revert. Verified: { passed: 1, failed: 0, total: 2 } still classifies as PASS, and a revert that turns that one real assertion red still scores OBSERVED. The threshold is passed === 0 && failed === 0 (not "any skip"), matching the issue's explicit instruction not to fail on any skip — AGENTS.md's own skip-not-throw convention for missing fixtures depends on partial skips staying unremarkable.

pytest and cargo don't share this gap: parsePython already collapses an all-skipped pytest run to total: 0 (routing through the existing NO_TESTS path), and cargo's summary line does not fold ignored into its total at all. Only vitest and node --test count skipped tests into total.

Mutation testing (both directions)

  1. Disabled the new detection (short-circuited the ALL_SKIPPED branch in revert-oracle-all-skipped.mjs): node --test scripts/lib/revert-oracle.test.mjs went from 58/58 passing to 56 pass / 2 fail — the ALL_SKIPPED-kind test and the BASELINE-BROKEN verdict test both caught it.
  2. Genuinely-passing, zero-skip baseline (vitest, 12 passed, 0 skipped) still classifies PASS, and a revert that turns 3 of those 12 red still scores OBSERVED (exit 0) — no false positive introduced.

Test plan

  • node --test scripts/lib/revert-oracle*.test.mjs: 100 → 104 tests, all passing (0 fail, 0 skipped)
  • node scripts/check-module-size.mjs: OK (revert-oracle.mjs at its 528-line budget, no headroom — no budget raised)
  • node scripts/check-test-wiring.mjs: OK
  • node scripts/check-source-text-assertions.mjs: OK
  • Mutation test, both directions (above)

🤖 Generated with Claude Code

https://claude.ai/code/session_01QPHChk3Ve9N519A4kY7436

Summary by CodeRabbit

  • Bug Fixes
    • Test result reporting now distinguishes runs where every test was skipped from runs with no tests.
    • Partially skipped test runs continue to be treated as passing when the executed tests succeed.
    • All-skipped baseline runs are now correctly reported as broken.
    • Result aggregation gives all-skipped outcomes higher priority than successful results.
  • Tests
    • Added coverage for wholly skipped, partially skipped, and baseline scenarios.

vitest's and node --test's summary lines count a skipped test into the
same `total` as a passed one: `Tests  2 skipped (2)` parses through
parseRunnerOutput to `{ passed: 0, failed: 0, total: 2 }`, exactly the
shape a `describe.skipIf` guard produces when its fixture is absent.
`verdict()` only ever guarded `baseline.total === 0`, so a file that
collected tests but executed none of them was scored `kind: pass` and
used as a green baseline -- and then went on to render an identically
skipped reverted run as an UNOBSERVED "finding about the author's
tests" when nothing was ever measured.

Adds a new `ALL_SKIPPED` kind (`scripts/lib/revert-oracle-all-skipped.mjs`,
split out to keep revert-oracle.mjs at its recorded module-size budget)
for the case `collected > 0 && executed === 0`. It plugs into the
existing verdict machinery rather than a new one: a baseline of this
kind falls through the existing `baseline.kind !== PASS` check into
BASELINE-BROKEN, and a reverted run of this kind falls through to the
existing "unhandled reverted kind" INCONCLUSIVE fallback -- both already
model "nothing can be concluded," and neither is UNOBSERVED or a pass.

A PARTIALLY skipped file (some tests ran, some skipped) is left as an
ordinary PASS: it still has at least one executed assertion with real
evidentiary value, and AGENTS.md's skip-not-throw convention for missing
fixtures depends on that staying unremarkable.

pytest and cargo do not share this gap: parsePython already collapses
an all-skipped pytest run to `total: 0` (routing through the existing
NO_TESTS path), and cargo's summary line does not fold `ignored` into
its total. Only vitest and node --test count skips into `total`.

Verified both directions: disabling the new detection makes two tests
fail (the ALL_SKIPPED-kind test and the BASELINE-BROKEN verdict test);
a genuinely-passing, zero-skip vitest baseline (12 passed, 0 skipped)
still scores PASS/OBSERVED exactly as before.

node --test scripts/lib/revert-oracle*.test.mjs: 100 -> 104 tests, all
passing.

Closes #4108

Part of the capability-gap-vs-finding family tracked by #4109 (not
closed by this PR) -- the fifth instance in that family, this one
narrowly scoped to the all-skipped shape rather than #4109's proposed
structural per-file attribution fix.
@BIMvoice
BIMvoice requested a review from louistrue as a code owner September 8, 2026 03:37
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for 56b89b7d6

Reviewed this diff and found nothing to flag.

@github-actions github-actions Bot added the llm-reviewed A review was verified as posted for this PR's head. label Sep 8, 2026
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

  • Run on-demand review

This review includes 3 billable files and costs up to $0.75.

Or wait 3 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 4bbd7447-fae0-43ac-b0df-128c58f47527

📥 Commits

Reviewing files that changed from the base of the PR and between 56b89b7 and 4fef891.

📒 Files selected for processing (3)
  • scripts/lib/revert-oracle-all-skipped.mjs
  • scripts/lib/revert-oracle.mjs
  • scripts/lib/revert-oracle.test.mjs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: d2c3218d-33bd-4b4d-8fee-057268b76d80

📥 Commits

Reviewing files that changed from the base of the PR and between 4638f74 and 56b89b7.

📒 Files selected for processing (3)
  • scripts/lib/revert-oracle-all-skipped.mjs
  • scripts/lib/revert-oracle.mjs
  • scripts/lib/revert-oracle.test.mjs

Included review availability: Your plan provides up to 2 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The oracle now classifies collected runs with zero executed tests as ALL_SKIPPED. The result propagates through parsing, baseline verdicts, exit status handling, and package aggregation. Tests cover wholly skipped, partially skipped, and passing runs.

Changes

All-skipped classification

Layer / File(s) Summary
Execution result classifier
scripts/lib/revert-oracle-all-skipped.mjs
Adds ALL_SKIPPED and classifyExecuted(parsed). Failed runs remain ASSERTION_FAILURE; runs with no passed or failed tests and a positive total become ALL_SKIPPED; other runs remain PASS.
Oracle integration and validation
scripts/lib/revert-oracle.mjs, scripts/lib/revert-oracle.test.mjs
Routes parsed results through classifyExecuted, re-exports ALL_SKIPPED, updates aggregation severity, and tests skipped-run classification, baseline handling, exit status, and aggregation.

Priority: ➖ Normal — Impact reflects medium issue severity.

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

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to e734b

The oracle now distinguishes wholly skipped test runs from passing runs, preventing skipped baselines from being treated as valid observations while retaining passing behavior for partially skipped files. No current merge-readiness risk remains.

🚥 Pre-merge checks | ✅ 7 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (7 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #4108. They classify collected-but-unexecuted runs as ALL_SKIPPED, prevent all-skipped baselines from passing, preserve partial-skip behavior, and integrate the result into a…
Out of Scope Changes check ✅ Passed The changes are limited to all-skipped classification, verdict integration, aggregation ordering, and related tests. No unrelated code changes are identified.
Changeset Bump Matches The Api Surface ✅ Passed The PR does not add or edit any file under .changeset/. The commit diff contains only scripts/lib/revert-oracle-all-skipped.mjs, scripts/lib/revert-oracle.mjs, and `scripts/lib/revert-oracle.tes…
Verification Evidence Is Present ✅ Passed The description provides direct verification evidence. It records RED and GREEN parser/verdict outputs, including kind: all-skipped and BASELINE-BROKEN. It names the exact command `node --test scr…
One Defect Class Per Pr ✅ Passed The PR addresses one defect class: a collected run with zero executed tests. The parent used one inline final classifier in parseRunnerOutput; the PR replaces that decision with the shared `classify…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: preventing the revert oracle from classifying an all-skipped baseline as passing.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-4108-all-skipped-baseline

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

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
ifc-lite-dev Ignored Ignored Sep 8, 2026 10:41am UTC
ifc-lite-viewer-embed Ignored Ignored Sep 8, 2026 10:41am UTC

…ence in the revert oracle

#4131 (closes #4108) correctly stops an all-skipped baseline from being
scored a pass, but `aggregate()`'s severity walk ranked ALL_SKIPPED above
PASS and ASSERTION_FAILURE unconditionally. CI's revert-oracle job installs
Python/ifcopenshell only when Python files changed, so a TS-only PR touching
even one env-gated all-skip file (e.g.
packages/export/src/ifcopenshell-schema-conformance.test.ts) now aggregates
to ALL_SKIPPED across the whole run, and verdict() falls into
BASELINE-BROKEN/exit 3 -- blocking a PR whose other packages produced real,
executed assertions that went red on revert.

Adds severityCandidates() in revert-oracle-all-skipped.mjs: when at least
one result in the run has kind PASS or ASSERTION_FAILURE, ALL_SKIPPED
entries are dropped from the severity walk (their counts/evidence still
fold into aggregate()'s totals, unfiltered). With no real evidence anywhere,
every result stays a candidate, so a single all-skipped package, or a run
where every package is all-skipped, still aggregates to ALL_SKIPPED and
still blocks -- #4108's own case is unchanged.

Verified both directions with synthetic aggregate()/verdict() calls before
fixing: a PASS-plus-ALL_SKIPPED run aggregated to ALL_SKIPPED/BASELINE-BROKEN
(exit 3) pre-fix, and to PASS/OBSERVED (exit 0) post-fix; a single- or
every-package all-skipped run stayed ALL_SKIPPED/BASELINE-BROKEN (exit 3) in
both cases.

Mutated to confirm the tests hold: reverting the aggregate() change back to
scanning `results` directly turns exactly the three new multi-package tests
red; reverting severityCandidates() to unconditionally filter ALL_SKIPPED
(dropping the single-signal guard) turns exactly the two single/every
all-skipped tests red. All other tests stayed green in both mutations.

scripts/lib/revert-oracle.mjs stays within its 528-line module-size budget
(now flush against it); the new logic lives in the existing
revert-oracle-all-skipped.mjs sibling module instead of growing the budget.

node --test scripts/lib/revert-oracle*.test.mjs: 104 -> 108 tests, all
passing.
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for e734b0c6c

Reviewed this diff and found nothing to flag.

@github-actions github-actions Bot added llm-reviewed A review was verified as posted for this PR's head. and removed llm-reviewed A review was verified as posted for this PR's head. labels Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for adb2bbc02

Reviewed this diff and found nothing to flag.

@github-actions github-actions Bot added llm-reviewed A review was verified as posted for this PR's head. and removed llm-reviewed A review was verified as posted for this PR's head. labels Sep 8, 2026
…d-baseline

Resolves a textual conflict in scripts/lib/revert-oracle.mjs between
this branch's ALL_SKIPPED bucket/severityCandidates work and #4140's
inert-path classification: both imports kept, isInertPath wired after
the existing TEST_* checks in classifyPath so precedence is preserved.
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for 4fef891e6

Reviewed this diff and found nothing to flag.

@github-actions github-actions Bot added llm-reviewed A review was verified as posted for this PR's head. and removed llm-reviewed A review was verified as posted for this PR's head. labels Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llm-reviewed A review was verified as posted for this PR's head.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

revert-oracle: an all-skipped baseline scores as pass, so a skipped test file reads as a measured green

2 participants