diff --git a/framework/src/test/java/org/checkerframework/framework/test/junit/DisabledIntersectionBoundAnnosTest.java b/framework/src/test/java/org/checkerframework/framework/test/junit/DisabledIntersectionBoundAnnosTest.java
new file mode 100644
index 000000000000..be7a7c2e58a5
--- /dev/null
+++ b/framework/src/test/java/org/checkerframework/framework/test/junit/DisabledIntersectionBoundAnnosTest.java
@@ -0,0 +1,49 @@
+package org.checkerframework.framework.test.junit;
+
+import org.checkerframework.framework.test.CheckerFrameworkPerDirectoryTest;
+import org.checkerframework.framework.testchecker.util.EvenOddChecker;
+import org.junit.Ignore;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Disabled regression test for per-bound annotation preservation on intersection-type upper bounds.
+ *
+ *
An intersection-type bound such as {@code } homogenizes its
+ * per-bound annotations: {@code AnnotatedIntersectionType.copyIntersectionBoundAnnotations} feeds
+ * the summarized primary annotation through {@code addAnnotations}, whose intersection override
+ * calls {@code fixupBoundAnnotations} and copies that primary back onto every bound. The
+ * unannotated bound therefore loses its default (top) qualifier and appears to carry the other
+ * bound's qualifier, order-dependently. The test inputs in {@code
+ * tests/disabled-intersection-bounds} assert the fixed, per-bound behavior.
+ *
+ * This test is {@link Ignore}d because the narrowest fix (not writing the primary back onto the
+ * bounds) changes intersection-bound defaulting and subtyping semantics that the standard Nullness
+ * Checker tests deliberately rely on (see {@code checker/tests/nullness/Issue868.java} and {@code
+ * Issue3349.java}), so it is out of scope for a contained bug fix. See {@code
+ * cf-tasks/task-2-findings.md} for the full diagnosis and proposed patch.
+ */
+@Ignore("Fix changes intersection-bound semantics relied on by the Nullness Checker; see findings.")
+public class DisabledIntersectionBoundAnnosTest extends CheckerFrameworkPerDirectoryTest {
+
+ /**
+ * Creates a new DisabledIntersectionBoundAnnosTest.
+ *
+ * @param testFiles the files containing test code, which will be type-checked
+ */
+ public DisabledIntersectionBoundAnnosTest(List testFiles) {
+ super(testFiles, EvenOddChecker.class, "disabled-intersection-bounds");
+ }
+
+ /**
+ * Returns the directories containing test code.
+ *
+ * @return the directories containing test code
+ */
+ @Parameters
+ public static String[] getTestDirs() {
+ return new String[] {"disabled-intersection-bounds"};
+ }
+}
diff --git a/framework/tests/disabled-intersection-bounds/IntersectionBoundAnnos.java b/framework/tests/disabled-intersection-bounds/IntersectionBoundAnnos.java
new file mode 100644
index 000000000000..d61d306a2e44
--- /dev/null
+++ b/framework/tests/disabled-intersection-bounds/IntersectionBoundAnnos.java
@@ -0,0 +1,37 @@
+import org.checkerframework.framework.testchecker.util.Odd;
+
+// DISABLED regression test: run by DisabledIntersectionBoundAnnosTest, which is
+// @Ignore'd. The fix it verifies changes intersection-bound defaulting/subtyping
+// semantics that the standard Nullness Checker tests deliberately rely on, so it
+// is out of scope for a contained bug fix. See cf-tasks/task-2-findings.md.
+//
+// Regression test for per-bound annotation preservation on intersection-type
+// upper bounds. The unannotated bound must retain its default (top) qualifier
+// instead of being homogenized to the other bound's explicit @Odd. Both bounds
+// are interfaces so the two declarations can differ only in bound order.
+// See AnnotatedIntersectionType.copyIntersectionBoundAnnotations.
+public class IntersectionBoundAnnos {
+
+ interface IfaceA {}
+
+ interface IfaceB {}
+
+ void oddFirst(T t) {
+ // The IfaceA bound is @Odd; t is assignable to @Odd IfaceA.
+ @Odd IfaceA ok = t;
+ // IfaceB is unannotated, so t viewed as IfaceB is top, not @Odd. Before
+ // the fix this spuriously type-checked because the IfaceB bound was
+ // homogenized to the other bound's @Odd.
+ // :: error: (assignment.type.incompatible)
+ @Odd IfaceB bad = t;
+ }
+
+ // Order-dependence guard: the @Odd bound comes second. The unannotated IfaceB
+ // bound must still default to top, independent of the bound order and of the
+ // order in which methods (and thus type parameters) are processed.
+ void oddSecond(T t) {
+ @Odd IfaceA ok = t;
+ // :: error: (assignment.type.incompatible)
+ @Odd IfaceB bad = t;
+ }
+}