mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-09-14 00:55:08 +00:00
fix: kind 1619 was in the lowercase-e engagement filter, where it matched nothing
NIP-34's PR Update example carries only `["E", <pull-request-event-id>]` — there is no lowercase `e` tag on a 1619 at all, and GitPullRequestUpdateEvent.build() writes only RootEventTag to match. Listing 1619 in RepliesAndReactionsKinds2 (the `#e` filter's kind list) therefore never pulled a single PR revision, and the comment claiming it was "rooted at the target patch/PR/issue via a `root`-marked `e` tag" was wrong for that kind (it is correct for the 1630-1633 statuses beside it). The `#E` filter added in the previous commit is what actually makes a PR's revision chain reachable from an on-screen PR row, so 1619 moves there and comes out of the `e` list. Nip34NotificationCoverageTest asserted the false half, which is how this survived: it now checks each kind against the filter that can actually match it, and pins 1619 out of the `e` list so it cannot drift back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ARAmQQWbT2gGVo9tysdAgM
This commit is contained in:
+39
-10
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.dal
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.account.nip01Notifications.NotificationsPerKeyKinds2
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.event.watchers.RepliesAndReactionsKinds2
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.event.watchers.RootScopedRepliesKinds
|
||||
import com.vitorpamplona.amethyst.service.notifications.NotificationDispatcher
|
||||
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
|
||||
@@ -32,6 +33,7 @@ import com.vitorpamplona.quartz.nip34Git.status.GitStatusAppliedEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.status.GitStatusClosedEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.status.GitStatusDraftEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.status.GitStatusOpenEvent
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
@@ -116,25 +118,30 @@ class Nip34NotificationCoverageTest {
|
||||
|
||||
/**
|
||||
* A status/update event's discovery path when a repo or PR is on screen: the
|
||||
* [`e`=<targetId>][RepliesAndReactionsKinds2] engagement subscription. Without
|
||||
* this the closed/merged pill on a repo listing can never populate — the
|
||||
* status event's only other route to the device is the `#p`=me subscription,
|
||||
* which only fires for accounts that were pre-tagged as participants.
|
||||
* Patches/issues/PRs are self-anchored (they ARE the target, not events
|
||||
* about the target), so they are intentionally NOT expected here.
|
||||
* engagement subscription. Without this the closed/merged pill on a repo
|
||||
* listing can never populate — the status event's only other route to the
|
||||
* device is the `#p`=me subscription, which only fires for accounts that were
|
||||
* pre-tagged as participants. Patches/issues/PRs are self-anchored (they ARE
|
||||
* the target, not events about the target), so they are intentionally NOT
|
||||
* expected here.
|
||||
*
|
||||
* Which of the two engagement filters carries a kind depends on how that kind
|
||||
* anchors itself, so the two halves are asserted separately below: statuses
|
||||
* and replies use a `root`-marked lowercase `e`, PR revisions use NIP-22's
|
||||
* uppercase `E`. Asserting the wrong half passes the kind list while matching
|
||||
* nothing on the wire.
|
||||
*/
|
||||
@Test
|
||||
fun `status and PR-update kinds are pulled by the engagement subscription`() {
|
||||
val threadedActivityKinds =
|
||||
fun `status kinds are pulled by the lowercase-e engagement subscription`() {
|
||||
val eAnchoredActivityKinds =
|
||||
setOf(
|
||||
GitPullRequestUpdateEvent.KIND,
|
||||
GitReplyEvent.KIND,
|
||||
GitStatusOpenEvent.KIND,
|
||||
GitStatusAppliedEvent.KIND,
|
||||
GitStatusClosedEvent.KIND,
|
||||
GitStatusDraftEvent.KIND,
|
||||
)
|
||||
val missing = threadedActivityKinds - RepliesAndReactionsKinds2.toSet()
|
||||
val missing = eAnchoredActivityKinds - RepliesAndReactionsKinds2.toSet()
|
||||
assertTrue(
|
||||
"Kinds $missing are missing from RepliesAndReactionsKinds2. When a repo/PR row is " +
|
||||
"on screen the app fetches replies + reactions targeting the visible events — " +
|
||||
@@ -144,4 +151,26 @@ class Nip34NotificationCoverageTest {
|
||||
missing.isEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 1619 has no lowercase `e` tag at all — NIP-34's PR Update example carries
|
||||
* only `["E", <pull-request-event-id>]` — so it can only ever arrive through the
|
||||
* uppercase root-scope filter. It sat in [RepliesAndReactionsKinds2] for a while
|
||||
* and matched nothing there.
|
||||
*/
|
||||
@Test
|
||||
fun `PR-update kind is pulled by the uppercase-E engagement subscription`() {
|
||||
assertTrue(
|
||||
"GitPullRequestUpdateEvent (1619) is missing from RootScopedRepliesKinds. It anchors " +
|
||||
"at the PR it revises with NIP-22's uppercase `E` and carries no lowercase `e`, " +
|
||||
"so the `#e` engagement filter can never surface a PR's revision chain.",
|
||||
GitPullRequestUpdateEvent.KIND in RootScopedRepliesKinds,
|
||||
)
|
||||
assertFalse(
|
||||
"GitPullRequestUpdateEvent (1619) is back in RepliesAndReactionsKinds2, the `#e` " +
|
||||
"filter's kind list. 1619 has no lowercase `e` tag, so the entry matches nothing " +
|
||||
"and only makes the filter look like it covers PR updates.",
|
||||
GitPullRequestUpdateEvent.KIND in RepliesAndReactionsKinds2,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -81,7 +81,9 @@ val RepliesAndReactionsKinds =
|
||||
val RootScopedRepliesKinds =
|
||||
listOf(
|
||||
CommentEvent.KIND,
|
||||
// NIP-34 PR revisions point at the PR they revise through `E`.
|
||||
// NIP-34 kind 1619 carries the PR it revises in `E` and has no lowercase
|
||||
// `e` at all (see the spec's PR Update example), so this filter is the
|
||||
// only engagement route to a PR's revision chain.
|
||||
GitPullRequestUpdateEvent.KIND,
|
||||
)
|
||||
|
||||
@@ -92,12 +94,12 @@ val RepliesAndReactionsKinds2 =
|
||||
NIP90StatusEvent.KIND,
|
||||
TorrentCommentEvent.KIND,
|
||||
GitReplyEvent.KIND,
|
||||
// NIP-34 PR revision (1619) and status events (1630/1631/1632/1633).
|
||||
// Rooted at the target patch/PR/issue via a `root`-marked `e` tag, so
|
||||
// an `e=<targetId>` engagement fetch surfaces the PR's revision chain
|
||||
// and every open/applied/closed/draft transition — the signal
|
||||
// GitStatusIndex needs to answer isClosedOrResolved() for repo rows.
|
||||
GitPullRequestUpdateEvent.KIND,
|
||||
// NIP-34 status events (1630/1631/1632/1633). Rooted at the target
|
||||
// patch/PR/issue via a `root`-marked `e` tag, so an `e=<targetId>`
|
||||
// engagement fetch surfaces every open/applied/closed/draft transition —
|
||||
// the signal GitStatusIndex needs to answer isClosedOrResolved() for
|
||||
// repo rows. PR revisions (1619) anchor with `E` instead and are pulled
|
||||
// by [RootScopedRepliesKinds]; listing them here matched nothing.
|
||||
GitStatusOpenEvent.KIND,
|
||||
GitStatusAppliedEvent.KIND,
|
||||
GitStatusClosedEvent.KIND,
|
||||
|
||||
Reference in New Issue
Block a user