Commit b9b2bab
authored
autorevert: dispatch advisor on born-red test signals (#8107)
## Summary
Closes a structural blind spot in the autorevert lambda: a test
introduced by the same commit that breaks it (or by a recent commit that
re-enabled / moved / unsharded it) has no green observations in the
lookback window, so the existing green→red partition path returns
`Ineligible(NO_SUCCESSES)` and never asks the advisor.
This PR adds a "born-red" detection path that hands these cases to the
AI advisor with framing tailored for the introduction question.
## Motivation
[pytorch/pytorch#184104](pytorch/pytorch#184104)
(2026-05-21, "[Inductor] Fix flip on 0-d tensors in prims.rev lowering")
added two new tests to inductor codegen-dynamic-shapes and registered
them as `expectedFailure` on cuda/xpu. The lowering fix actually worked
on cuda → "Unexpected success" → FAILED. The lambda saw the failures on
every trunk run from the PR landing onward but emitted
`Ineligible(NO_SUCCESSES, "no successful commits present in window")`
for ~9h until a human revert. Verified from
`misc.autorevert_state.outcomes` JSON:
```
trunk:inductor/test_torchinductor_codegen_dynamic_shapes.py::test_flip_zero_dim_dynamic_shapes_cuda
→ Ineligible / reason="no_successes" / "no successful commits present in window"
```
The lambda was healthy on the same tick — it emitted an
`AutorevertPattern` (advisor verdict=revert, confidence=0.97) for an
unrelated `linux-jammy-cuda13.0-py3.10-gcc11` job-track signal. The
blind spot is per-signal, not lambda-wide.
## Approach
Three primitives, all reusing the existing data model:
1. **`Signal.partition_born_red()`** — returns a `PartitionedCommits`
only when the signal shape (newest→oldest) is exactly
`[FAIL...][EMPTY...]`. No interleaving, no pending-only commits in
between. The trailing empty-events commits act as the implicit baseline
("commits where this test signal was not observed").
2. **`Signal._handle_no_successes()`** — called from the existing
early-exit point in `process_valid_autorevert_pattern`. For test-track
signals where `partition_born_red()` succeeds and there are ≥2 distinct
failing commits (counted by commits, not events — retries / multiple
shards on a single commit are still one trunk observation), it either
lifts an existing advisor verdict into an `AutorevertPattern`
(revert/related) or dispatches a fresh advisor request alongside the
`Ineligible(NO_SUCCESSES)` outcome. Job-track no-success signals stay on
the original path (likely persistent infra or warm-up).
3. **`DispatchAdvisor.is_born_red` flag** — tells
`_build_signal_pattern_json` to relabel the SUCCESSFUL partition. The
new label asks the advisor to distinguish four causes from the suspect's
diff: (a) ADDED the test, (b) ENABLED / un-skipped / removed a TD
filter, (c) MOVED / RENAMED so the test identity is newly visible, (d)
sharding / job-selection change. Recommend revert only when the suspect
explicitly introduces or enables the failing test (cases a/b/c).
Reused infrastructure:
- `_check_advisor_verdict()` and `_build_autorevert_pattern()` from the
existing partition path — the born-red partition slots in cleanly.
- Advisor de-dup (`prior_advisor_exists`) and per-(workflow, commit) cap
of 8 in `SignalActionsLogger` — no new infra.
## What changes for the advisor prompt
When `is_born_red=True`, the SUCCESSFUL partition in
`signal_pattern.json` is labeled:
> **no_signal**: baseline commits where this test signal was NOT
OBSERVED (no extracted events). The suspect commit is the first commit
on which the test signal appears, and it fails. Possible causes —
distinguish from the suspect commit's diff: (a) the suspect ADDED this
test; (b) the suspect ENABLED/UN-SKIPPED an existing test or removed a
TD/skipping filter that previously masked it; (c) the suspect MOVED or
RENAMED the test so its identity is newly visible; (d) the suspect
changed sharding / job selection so an existing already-failing test
became visible. Recommend revert only if the suspect's diff explicitly
introduces or enables the failing test (cases a/b/c).
A top-level `is_born_red: true` flag is also surfaced in the JSON so the
advisor workflow can branch on it cleanly.
## Test plan
- [x] `pytorch_auto_revert/tests/test_signal.py::TestBornRedTestSignal`
— 11 new tests covering:
- canonical `[FAIL][EMPTY]` shape
- rejection of shapes that aren't born-red (has successes, no empty
tail, no failures, interleaved empty→fail, pending-only between, single
commit)
- end-to-end dispatch on the 2-failing-commits + 1-empty case
- threshold counts distinct commits, not raw events (single commit with
3 retries doesn't dispatch)
- job-track signals don't get the born-red path
- chronic `[FAIL...]` without empty tail stays on the original
`NO_SUCCESSES` path
- existing advisor verdict (revert) lifts the born-red partition into
`AutorevertPattern` with the right `suspected_commit` and
`older_successful_commit`
- `NOT_RELATED` verdict blocks (returns `ADVISOR_NOT_RELATED`)
- [x]
`pytorch_auto_revert/tests/test_signal_actions.py::test_born_red_relabels_baseline_partition`
— verifies the JSON relabel and the `is_born_red` top-level flag,
including all four ambiguity-cause cues.
- [x] Full local suite: `./venv/bin/python -m unittest discover -s
pytorch_auto_revert/tests -p "test_*.py"` — 175 tests, all pass.
## Notes
- Cross-model adversarial review (`gpt-5.5` via Codex CLI) flagged three
MEDIUM concerns; all three were addressed in this PR before submission:
the introduction-vs-enable framing in the JSON label, gating on distinct
failing commits (not raw events), and the verdict-key check (already
keyed by `signal_key + suspect_commit`, no fix needed).
- The advisor prompt template
(`.github/workflows/claude-autorevert-advisor.yml`) is not touched here
— the existing prompt already consumes the partition labels, so the
relabel propagates through without a workflow change. If the upstream
prompt benefits from explicitly branching on `is_born_red`, that can be
a follow-up.1 parent 92b7f03 commit b9b2bab
4 files changed
Lines changed: 540 additions & 23 deletions
File tree
- aws/lambda/pytorch-auto-revert/pytorch_auto_revert
- tests
Lines changed: 116 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
89 | 94 | | |
90 | 95 | | |
91 | 96 | | |
| |||
496 | 501 | | |
497 | 502 | | |
498 | 503 | | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
499 | 547 | | |
500 | 548 | | |
501 | 549 | | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
502 | 559 | | |
503 | 560 | | |
504 | 561 | | |
| |||
571 | 628 | | |
572 | 629 | | |
573 | 630 | | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
574 | 689 | | |
575 | 690 | | |
576 | 691 | | |
| |||
591 | 706 | | |
592 | 707 | | |
593 | 708 | | |
594 | | - | |
595 | | - | |
596 | | - | |
| 709 | + | |
597 | 710 | | |
598 | 711 | | |
599 | 712 | | |
| |||
Lines changed: 61 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
38 | 65 | | |
39 | 66 | | |
40 | 67 | | |
| |||
736 | 763 | | |
737 | 764 | | |
738 | 765 | | |
739 | | - | |
740 | | - | |
741 | | - | |
742 | | - | |
743 | | - | |
744 | | - | |
745 | | - | |
746 | | - | |
747 | | - | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
748 | 788 | | |
749 | 789 | | |
750 | 790 | | |
| |||
823 | 863 | | |
824 | 864 | | |
825 | 865 | | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
835 | | - | |
836 | | - | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
837 | 878 | | |
838 | 879 | | |
839 | 880 | | |
| |||
0 commit comments