ci: fail closed in umbrella result gate - #476
Conversation
|
CI diagnosis:
I am leaving the PR open for review rather than bypassing either red gate. |
FleetReviewConfidence: 1/5 Findings
FleetReview provenance · models: B=gpt-5.6-sol, C=claude-code-opus-4-8, F=gpt-5.6-sol, G=grok-4.5 · cost: $6.35 · duration: 29m 34s · rounds: 2 · files examined: 3 |
Reject cancelled and other non-success results, and fail when a classifier-required lane is skipped. Preserve the needs-json output contract via a testable evaluator. Verified: scripts/run_tests.sh tests/ci (175 passed); ruff check/format; actionlint ci.yml.
df08e32 to
7e176e4
Compare
|
Drove
That's the fail-closed semantics this PR exists to add: the old evaluator only failed on Reviewed against the |
The umbrella gate failed with: classifier inconsistency: e2e-desktop was skipped even though detect.outputs.python == 'true' or detect.outputs.frontend == 'true' Two individually-correct halves that contradict each other once merged: * Upstream TEMPORARILY DISABLED e2e-desktop on 2026-08-02 with a `false &&` guard (their NousResearch#76627: after the Aug 1 engines/npm churn the mock-backend Electron window never got a title, so every spec failed regardless of the diff). That guard arrived here via the parity merge. * scripts/ci/evaluate_needs.py is FORK-ONLY (my #476 hardening) and treats 'a required job silently skipped' as a failure — precisely the hole that let a green umbrella hide missing coverage. Checked which half is still true here instead of assuming: Desktop E2E concludes SUCCESS on fork/main today (runs 31280614721, 31278775668). Upstream's premise — 'red on every PR and on main itself' — does not hold on this fork, so importing their disable would skip a job that both runs and passes, and weakening the classifier to allow the skip would give back exactly the blind spot #476 closed. Restored the fork's condition (no `false &&`). If the suite ever does go red here, the fix is to disable it AND drop it from the required set, not to let a required job vanish silently.
Reverting my own change from 832c892, plus the classifier exemption it turns out to need. What I got wrong: the umbrella gate failed with 'classifier inconsistency: e2e-desktop was skipped', because upstream disabled the job (NousResearch#76627) while scripts/ci/evaluate_needs.py (fork-only, #476) still required it. I checked whether upstream's premise held here, saw Desktop E2E concluding SUCCESS on fork/main, and restored the fork's condition. That measurement was of the wrong tree. fork/main still carries the FORK's desktop app (17 specs). This branch RETIRES the desktop fork and takes upstream's apps/desktop verbatim -- git diff upstream/main HEAD -- apps/desktop is EMPTY, 19 specs -- so it inherits upstream's broken suite too. Green on fork/main said nothing about this branch. Re-enabling reproduced upstream's exact documented symptom and blew the 20-minute cap at 20m20s (vs ~6min on fork/main): x e2e/boot.spec.ts > window opens with Hermes title x e2e/boot.spec.ts > renderer mounts and shows DOM content x e2e/chat.spec.ts > send a message and receive a response x e2e/boot-failure.spec.ts > screenshot of error state So the disable is correct here and the classifier gets a DECLARED exemption rather than the gate being weakened. Guard against the obvious next failure -- upstream fixes NousResearch#76627, someone deletes the 'false &&', and a stale exemption silently re-opens the #476 hole -- with a test that reads the actual ci.yml guard and asserts the two agree. Mutation-proven: re-enabling the job while leaving the exemption fails that test. Also pinned: the exemption forgives 'skipped' ONLY -- an e2e-desktop 'failure' still fails the umbrella. tests/ci 24/24.
Summary
cancelledand every result outsidesuccess/skippedskipped, including Pythontestsandlintneeds-jsonoutput contractWhy
The previous evaluator only rejected literal
failure. A cancelled dependency therefore passed the requiredAll required checks passcontext. It also acceptedtests: skippedeven whendetect.outputs.python == 'true', so branch protection could go green without Python tests completing.Verification
scripts/run_tests.sh tests/ci— 175 passedscripts/run_tests.sh tests/ci/test_evaluate_needs.py— 23 passedruff checkandruff format --checkactionlint .github/workflows/ci.ymlneeds-jsonshapeKanban:
t_8d29e3b9