{
  "_class" : "hudson.model.FreeStyleBuild",
  "actions" : [
    {
      "_class" : "hudson.model.CauseAction",
      "causes" : [
        {
          "_class" : "hudson.triggers.SCMTrigger$SCMTriggerCause",
          "shortDescription" : "Started by an SCM change"
        }
      ]
    },
    {
      
    },
    {
      "_class" : "hudson.plugins.git.util.BuildData",
      "buildsByBranchName" : {
        "refs/remotes/origin/master" : {
          "_class" : "hudson.plugins.git.util.Build",
          "buildNumber" : 328,
          "buildResult" : null,
          "marked" : {
            "SHA1" : "9fe5731a229f180386880ad1fbc289808650b558",
            "branch" : [
              {
                "SHA1" : "9fe5731a229f180386880ad1fbc289808650b558",
                "name" : "refs/remotes/origin/master"
              }
            ]
          },
          "revision" : {
            "SHA1" : "9fe5731a229f180386880ad1fbc289808650b558",
            "branch" : [
              {
                "SHA1" : "9fe5731a229f180386880ad1fbc289808650b558",
                "name" : "refs/remotes/origin/master"
              }
            ]
          }
        }
      },
      "lastBuiltRevision" : {
        "SHA1" : "9fe5731a229f180386880ad1fbc289808650b558",
        "branch" : [
          {
            "SHA1" : "9fe5731a229f180386880ad1fbc289808650b558",
            "name" : "refs/remotes/origin/master"
          }
        ]
      },
      "remoteUrls" : [
        "https://github.com/mcMMO-Dev/mcMMO.git"
      ],
      "scmName" : ""
    },
    {
      
    },
    {
      
    },
    {
      
    },
    {
      "_class" : "org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction"
    }
  ],
  "artifacts" : [
    {
      "displayPath" : "mcMMO.jar",
      "fileName" : "mcMMO.jar",
      "relativePath" : "target/mcMMO.jar"
    },
    {
      "displayPath" : "original-mcMMO.jar",
      "fileName" : "original-mcMMO.jar",
      "relativePath" : "target/original-mcMMO.jar"
    }
  ],
  "building" : false,
  "description" : null,
  "displayName" : "#328",
  "duration" : 53553,
  "estimatedDuration" : 135282,
  "executor" : null,
  "fullDisplayName" : "mcMMO #328",
  "id" : "328",
  "inProgress" : false,
  "keepLog" : false,
  "number" : 328,
  "queueId" : 198,
  "result" : "SUCCESS",
  "timestamp" : 1783409649554,
  "url" : "https://popicraft.net/jenkins/job/mcMMO/328/",
  "builtOn" : "Builder",
  "changeSet" : {
    "_class" : "hudson.plugins.git.GitChangeSetList",
    "items" : [
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/skills/salvage/SalvageTest.java",
          "src/main/java/com/gmail/nossr50/skills/salvage/Salvage.java"
        ],
        "commitId" : "fc4fcddd3cd0d6961a5a80ca852b4827a184a1a1",
        "timestamp" : 1783397859000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix Salvage yielding nothing for damaged items with low max quantity\u000a\u000aSalvage.calculateSalvageableAmount floored the salvageable amount to\u000azero for any damaged item when the configured maximum quantity was 1,\u000aso such items could only be salvaged at full durability. Damaged items\u000anow salvage at least one material unless fully broken.\u000a\u000aFixes #4760\u000a",
        "date" : "2026-07-06 21:17:39 -0700",
        "id" : "fc4fcddd3cd0d6961a5a80ca852b4827a184a1a1",
        "msg" : "Fix Salvage yielding nothing for damaged items with low max quantity",
        "paths" : [
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/skills/salvage/SalvageTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/skills/salvage/Salvage.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/resources/locale/locale_en_US.properties",
          "src/main/resources/skillranks.yml"
        ],
        "commitId" : "ea309678096dbee0c83c0aa3539dd65743544a95",
        "timestamp" : 1783397859000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix wrong unlock levels in Leaf Blower and Catalysis guide text\u000a\u000aAlso removes the unused Leaf Blower Rank_2 and Rank_3 entries from\u000askillranks.yml; the subskill only defines a single rank.\u000a\u000aFixes #4847\u000a",
        "date" : "2026-07-06 21:17:39 -0700",
        "id" : "ea309678096dbee0c83c0aa3539dd65743544a95",
        "msg" : "Fix wrong unlock levels in Leaf Blower and Catalysis guide text",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/resources/locale/locale_en_US.properties"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/skillranks.yml"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardManagerTest.java",
          "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java"
        ],
        "commitId" : "b14183fea45e2ad3c2fec0a770a1dc586c662855",
        "timestamp" : 1783397878000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix skill scoreboards not updating for child skills\u000a\u000aXP and level events only fire for parent skills, so a kept Salvage or\u000aSmelting sidebar never matched the event skill and never refreshed\u000auntil the command was run again. Boards displaying a child skill now\u000arefresh when one of its parent skills changes.\u000a\u000aFixes #5184\u000a",
        "date" : "2026-07-06 21:17:58 -0700",
        "id" : "b14183fea45e2ad3c2fec0a770a1dc586c662855",
        "msg" : "Fix skill scoreboards not updating for child skills",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardManagerTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdaterTest.java",
          "src/main/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdater.java",
          "src/test/java/com/gmail/nossr50/util/scoreboards/backend/BukkitScoreboardBackendTest.java",
          "src/main/java/com/gmail/nossr50/util/scoreboards/backend/BukkitScoreboardBackend.java",
          "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java"
        ],
        "commitId" : "df1570de49b72e7b700f717f608e4190f2867b86",
        "timestamp" : 1783397878000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix power level tags dropping updates and leftover objectives\u000a\u000aThe power level heartbeat cleared all pending refreshes even when a\u000aplayer's profile had not loaded yet, leaving their below-name tag at 0\u000auntil the next level-up. Pending names now stay queued until they can\u000abe resolved. Also removes a persisted mcmmo_pwrlvl objective left in\u000aworld scoreboard data by older versions when the packet or noop\u000abackend is active, which otherwise kept rendering stale tags.\u000a\u000aFixes #5003\u000a",
        "date" : "2026-07-06 21:17:58 -0700",
        "id" : "df1570de49b72e7b700f717f608e4190f2867b86",
        "msg" : "Fix power level tags dropping updates and leftover objectives",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdaterTest.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/backend/BukkitScoreboardBackendTest.java"
          },
          {
            "editType" : "add",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdater.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/backend/BukkitScoreboardBackend.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/listeners/PlayerListener.java",
          "src/test/java/com/gmail/nossr50/listeners/PlayerListenerCommandAliasTest.java"
        ],
        "commitId" : "5a6692a026fa3e3b8e4dd1152ed95dda6ad1d5a1",
        "timestamp" : 1783397901000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix localized skill commands being blocked by command whitelist plugins\u000a\u000aThe locale alias rewrite ran at LOWEST priority, tying with command\u000awhitelist plugins listening on the same event, so which name they saw\u000adepended on plugin load order. The rewrite now runs at LOW priority and\u000aignores cancelled events, letting whitelist plugins deterministically\u000asee the command exactly as the player typed it.\u000a\u000aFixes #5250\u000a",
        "date" : "2026-07-06 21:18:21 -0700",
        "id" : "5a6692a026fa3e3b8e4dd1152ed95dda6ad1d5a1",
        "msg" : "Fix localized skill commands being blocked by command whitelist plugins",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/listeners/PlayerListener.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/listeners/PlayerListenerCommandAliasTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java",
          "src/test/java/com/gmail/nossr50/skills/salvage/SalvageManagerTest.java",
          "src/test/java/com/gmail/nossr50/listeners/PlayerListenerSalvageInteractTest.java",
          "src/main/java/com/gmail/nossr50/listeners/PlayerListener.java",
          "src/test/java/com/gmail/nossr50/skills/repair/RepairManagerTest.java",
          "src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java"
        ],
        "commitId" : "a6079cf951b37081a91326c47442e9365211b0b6",
        "timestamp" : 1783397902000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix salvage and repair confirmations acting on the wrong item\u000a\u000aThe confirmation window was time based only, so armor swapped into the\u000ahand by a mis-click could be salvaged with no new prompt, including\u000aworn armor via the vanilla quick-swap. Confirmations are now bound to\u000athe prompted item and re-prompt when the held item changes. Also denies\u000aitem use while a confirmation is pending, closing the path where the\u000afollow-up use-item interact event equipped the armor instead when the\u000aserver's re-raytrace missed the anvil.\u000a\u000aFixes #5268\u000aFixes #4896\u000a",
        "date" : "2026-07-06 21:18:22 -0700",
        "id" : "a6079cf951b37081a91326c47442e9365211b0b6",
        "msg" : "Fix salvage and repair confirmations acting on the wrong item",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/listeners/PlayerListener.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/skills/repair/RepairManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/skills/salvage/SalvageManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/skills/salvage/SalvageManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/listeners/PlayerListenerSalvageInteractTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapper.java",
          "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapperStatsPowerLevelTest.java"
        ],
        "commitId" : "29a65b9fb7b201d0caa112dd3846e5e8ea545d6e",
        "timestamp" : 1783397902000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix stats scoreboard power level counting permission-hidden skills\u000a\u000aThe stats sidebar summed every skill into its power level line while\u000ahiding rows for skills the player lacked permission for, disagreeing\u000awith chat stats and the power level cap, which both use the\u000apermission-aware total.\u000a\u000aFixes #3790\u000a",
        "date" : "2026-07-06 21:18:22 -0700",
        "id" : "29a65b9fb7b201d0caa112dd3846e5e8ea545d6e",
        "msg" : "Fix stats scoreboard power level counting permission-hidden skills",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapper.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapperStatsPowerLevelTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java",
          "src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java",
          "src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java",
          "src/test/java/com/gmail/nossr50/database/SQLDatabaseManagerTest.java"
        ],
        "commitId" : "d0ad3ad67515426da787c1fdc4bde3114e859813",
        "timestamp" : 1783397902000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix database purge never removing inactive users\u000a\u000aThe SQL purge compared a seconds-based last login delta against a\u000amilliseconds cutoff, requiring roughly 83 years of inactivity per\u000aconfigured month. The flatfile purge had an inverted check that only\u000aremoved users with an unknown last login while keeping genuinely\u000ainactive ones.\u000a\u000aFixes #4251\u000a",
        "date" : "2026-07-06 21:18:22 -0700",
        "id" : "d0ad3ad67515426da787c1fdc4bde3114e859813",
        "msg" : "Fix database purge never removing inactive users",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/database/SQLDatabaseManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java",
          "src/test/java/com/gmail/nossr50/util/player/UserManagerTest.java",
          "src/test/java/com/gmail/nossr50/util/text/TextComponentFactoryTest.java"
        ],
        "commitId" : "d171e20b7c0af2689aea34e3e164d532dd9f790c",
        "timestamp" : 1783397902000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Add regression tests for previously fixed defects\u000a\u000aCovers the UserManager shutdown null guard (#4131), legacy color codes\u000aleaking into level-up notification components (#5125), the Green Thumb\u000aprobability guarantee at max bonus level (#4365), and dynamic subskill\u000achance caps for the levels reported against Dodge (#5210).\u000a",
        "date" : "2026-07-06 21:18:22 -0700",
        "id" : "d171e20b7c0af2689aea34e3e164d532dd9f790c",
        "msg" : "Add regression tests for previously fixed defects",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/util/player/UserManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/util/text/TextComponentFactoryTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "Changelog.txt"
        ],
        "commitId" : "9044066e4fd7a3da549ef52a9d28ca2b1dd5656d",
        "timestamp" : 1783397999000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Update changelog\u000a",
        "date" : "2026-07-06 21:19:59 -0700",
        "id" : "9044066e4fd7a3da549ef52a9d28ca2b1dd5656d",
        "msg" : "Update changelog",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "Changelog.txt"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/config/AdvancedConfig.java",
          "src/main/resources/advanced.yml",
          "src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java",
          "src/test/java/com/gmail/nossr50/skills/mining/MiningManagerTest.java"
        ],
        "commitId" : "9e29417042a8d8bf9798134830342bcaaaf3ded8",
        "timestamp" : 1783399261000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Add config option to limit Blast Mining remote detonation distance\u000a\u000aServer admins can now set Skills.Mining.BlastMining.RemoteDetonationDistance\u000ain advanced.yml to control how far away players can remotely detonate TNT.\u000aDefaults to 100, matching the previous hardcoded limit, and is added to\u000aexisting advanced.yml files automatically on startup. Values below 1 fail\u000aconfig validation.\u000a\u000aFixes #4330\u000a",
        "date" : "2026-07-06 21:41:01 -0700",
        "id" : "9e29417042a8d8bf9798134830342bcaaaf3ded8",
        "msg" : "Add config option to limit Blast Mining remote detonation distance",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/resources/advanced.yml"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/config/AdvancedConfig.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/skills/mining/MiningManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/resources/plugin.yml",
          "src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java",
          "src/test/java/com/gmail/nossr50/MMOTestEnvironment.java",
          "src/test/java/com/gmail/nossr50/commands/player/InspectCommandTest.java"
        ],
        "commitId" : "13e1dcb9d6eca7b97f4c64f4a436740473a19d11",
        "timestamp" : 1783399414000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Make /inspect on offline players respect inspect permissions\u000a\u000aInspecting an offline player previously skipped the permission checks\u000athat gate inspecting distant online players. /inspect now requires\u000amcmmo.commands.inspect.far (default: op) to view players who are\u000aoffline, and vanished players hidden from the sender are gated the same\u000away so they stay indistinguishable from offline players. Grant\u000amcmmo.commands.inspect.far to any ranks that should keep inspecting\u000aoffline players.\u000a\u000aFixes #4399\u000a",
        "date" : "2026-07-06 21:43:34 -0700",
        "id" : "13e1dcb9d6eca7b97f4c64f4a436740473a19d11",
        "msg" : "Make /inspect on offline players respect inspect permissions",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/resources/plugin.yml"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/commands/player/InspectCommandTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/MMOTestEnvironment.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/util/player/NotificationManager.java",
          "src/main/resources/advanced.yml",
          "src/test/java/com/gmail/nossr50/util/player/NotificationManagerTest.java"
        ],
        "commitId" : "8dc2c7e4a87710cbbbc307d03d54062a3a17e27b",
        "timestamp" : 1783399435000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix ActionBarNotifications.SubSkillUnlocked settings being ignored\u000a\u000aSkill rank unlock messages were always sent to chat, ignoring the\u000aFeedback.ActionBarNotifications.SubSkillUnlocked settings in\u000aadvanced.yml. Unlock notifications now use the same routing as other\u000anotification types: setting\u000aFeedback.ActionBarNotifications.SubSkillUnlocked.Enabled to true sends\u000athem to the action bar, and\u000aFeedback.ActionBarNotifications.SubSkillUnlocked.SendCopyOfMessageToChat\u000acontrols whether the chat still receives a copy. The shipped default for\u000aEnabled is now false so unlock messages stay in chat out of the box.\u000aThese notifications also fire McMMOPlayerNotificationEvent, matching the\u000aother notification types.\u000a\u000aFixes #4091\u000a",
        "date" : "2026-07-06 21:43:55 -0700",
        "id" : "8dc2c7e4a87710cbbbc307d03d54062a3a17e27b",
        "msg" : "Fix ActionBarNotifications.SubSkillUnlocked settings being ignored",
        "paths" : [
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/util/player/NotificationManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/player/NotificationManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/advanced.yml"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java",
          "src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java",
          "src/main/java/com/gmail/nossr50/party/PartyManager.java",
          "src/main/resources/plugin.yml",
          "src/main/resources/locale/locale_en_US.properties",
          "src/test/java/com/gmail/nossr50/datatypes/player/McMMOPlayerLevelUpSoundTest.java",
          "src/main/java/com/gmail/nossr50/commands/McLevelUpSoundCommand.java",
          "src/main/java/com/gmail/nossr50/datatypes/party/Party.java"
        ],
        "commitId" : "c3018f1be5b8caa23c3d693685b3854433b05d1b",
        "timestamp" : 1783399697000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Add /mclevelupsound to toggle the level-up sound per player\u000a\u000aPlayers can now silence the mcMMO level-up sound for themselves with\u000a/mclevelupsound (alias /levelupsound) without touching notifications\u000aor the server-wide General.LevelUp_Sounds config setting. The toggle\u000aalso mutes the party level-up sound for that player.\u000a\u000aPermission node: mcmmo.commands.mclevelupsound (granted by\u000amcmmo.commands.defaults). Like /mcnotify, the preference is\u000aper-session and resets to on at login.\u000a\u000aFixes #5307\u000a",
        "date" : "2026-07-06 21:48:17 -0700",
        "id" : "c3018f1be5b8caa23c3d693685b3854433b05d1b",
        "msg" : "Add /mclevelupsound to toggle the level-up sound per player",
        "paths" : [
          {
            "editType" : "add",
            "file" : "src/main/java/com/gmail/nossr50/commands/McLevelUpSoundCommand.java"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/datatypes/player/McMMOPlayerLevelUpSoundTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/party/PartyManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/plugin.yml"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/datatypes/party/Party.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/locale/locale_en_US.properties"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/resources/locale/locale_en_US.properties",
          "src/main/java/com/gmail/nossr50/commands/XprateCommand.java",
          "src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java",
          "src/test/java/com/gmail/nossr50/commands/XprateCommandTest.java"
        ],
        "commitId" : "31902ccd1e5be8bbe00cefb3e6b8654fcbb9601a",
        "timestamp" : 1783399928000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Allow decimal values in /xprate\u000a\u000aThe XP rate argument now accepts positive decimal numbers such as 1.5\u000ainstead of integers only. Zero, negative, and non-finite rates are\u000arejected, and an invalid rate no longer toggles the XP event state.\u000aWhole-number rates still display without a trailing .0 in broadcasts\u000aand admin notifications.\u000a\u000aFixes #3390\u000a",
        "date" : "2026-07-06 21:52:08 -0700",
        "id" : "31902ccd1e5be8bbe00cefb3e6b8654fcbb9601a",
        "msg" : "Allow decimal values in /xprate",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/commands/XprateCommand.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/locale/locale_en_US.properties"
          },
          {
            "editType" : "add",
            "file" : "src/test/java/com/gmail/nossr50/commands/XprateCommandTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java",
          "src/main/resources/locale/locale_en_US.properties",
          "src/main/resources/plugin.yml",
          "src/main/java/com/gmail/nossr50/commands/XprateCommand.java",
          "src/main/java/com/gmail/nossr50/util/Permissions.java",
          "src/test/java/com/gmail/nossr50/commands/XprateCommandTest.java"
        ],
        "commitId" : "35adf1110a8f818f6ab8626128decb20864d6c80",
        "timestamp" : 1783399928000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Show the current XP rate with /xprate\u000a\u000aRunning /xprate with no arguments now tells the sender the current\u000aglobal XP rate. Access is controlled by the new permission node\u000amcmmo.commands.xprate.show, granted to players by default through\u000amcmmo.commands.defaults since the rate is already broadcast publicly\u000awhen events start and shown on login.\u000a\u000aFixes #4602\u000a",
        "date" : "2026-07-06 21:52:08 -0700",
        "id" : "35adf1110a8f818f6ab8626128decb20864d6c80",
        "msg" : "Show the current XP rate with /xprate",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/commands/XprateCommand.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/locale/locale_en_US.properties"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/plugin.yml"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/Permissions.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/commands/XprateCommandTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "Changelog.txt"
        ],
        "commitId" : "93b005500fe88d648cb9a1b0fe6a1c2fb12e59fd",
        "timestamp" : 1783400030000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Update changelog\u000a",
        "date" : "2026-07-06 21:53:50 -0700",
        "id" : "93b005500fe88d648cb9a1b0fe6a1c2fb12e59fd",
        "msg" : "Update changelog",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "Changelog.txt"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/commands/XprateCommand.java",
          "src/test/java/com/gmail/nossr50/commands/XprateCommandTest.java"
        ],
        "commitId" : "bc023b15ef65ba7651943d2d0f0f2a1a98d2f098",
        "timestamp" : 1783404622000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix /xprate rate display using a shared DecimalFormat across threads\u000a\u000aThe formatted XP rate came from a single static DecimalFormat, which is\u000anot thread safe. Regionized servers like Folia execute player commands\u000aon multiple region threads, and every player can run /xprate to view\u000athe rate, so simultaneous use could garble the broadcast or displayed\u000arate. The format is now created per call, matching how locale strings\u000aalready build a fresh MessageFormat per message.\u000a",
        "date" : "2026-07-06 23:10:22 -0700",
        "id" : "bc023b15ef65ba7651943d2d0f0f2a1a98d2f098",
        "msg" : "Fix /xprate rate display using a shared DecimalFormat across threads",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/commands/XprateCommand.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/commands/XprateCommandTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/resources/plugin.yml",
          "src/main/resources/locale/locale_en_US.properties"
        ],
        "commitId" : "3c6ab95d01e9a0e9a1059b6a5d11c37770b953fc",
        "timestamp" : 1783404741000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Mention viewing the current rate in the /xprate command descriptions\u000a\u000aThe /xprate description in plugin.yml and the\u000aCommands.Description.xprate locale entry only mentioned modifying the\u000arate, but the command now also shows the current XP rate when run with\u000ano arguments.\u000a",
        "date" : "2026-07-06 23:12:21 -0700",
        "id" : "3c6ab95d01e9a0e9a1059b6a5d11c37770b953fc",
        "msg" : "Mention viewing the current rate in the /xprate command descriptions",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/resources/plugin.yml"
          },
          {
            "editType" : "edit",
            "file" : "src/main/resources/locale/locale_en_US.properties"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "Changelog.txt"
        ],
        "commitId" : "9aa347b58d56652798be2f5c28cc429f3ff4442c",
        "timestamp" : 1783404741000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Correct 2.2.055 changelog entries\u000a\u000aThe Salvage note used wooden tools as an example of items that salvage\u000ainto a single material, but most wooden tools return more than one\u000amaterial in the default salvage.vanilla.yml; wooden shovels are the\u000aaccurate example. Also moves the skillranks.yml removal line ahead of\u000athe locale entries to match the usual entry ordering, and documents the\u000aupdated /xprate locale entries, the rank unlock notifications now\u000afiring McMMOPlayerNotificationEvent, and the new regression tests.\u000a",
        "date" : "2026-07-06 23:12:21 -0700",
        "id" : "9aa347b58d56652798be2f5c28cc429f3ff4442c",
        "msg" : "Correct 2.2.055 changelog entries",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "Changelog.txt"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdater.java",
          "src/test/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdaterTest.java"
        ],
        "commitId" : "295647a85e5f9252d93c04ef2833074bd9cf08a3",
        "timestamp" : 1783404871000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix power level tag re-marks being lost during a heartbeat write\u000a\u000aThe heartbeat removed a pending name after resolving and writing it, so\u000aa level-up that re-marked the same player mid-write was erased along\u000awith the processed entry, leaving the below-name tag stale until the\u000aplayer's next level-up. Names are now removed before resolving so a\u000aconcurrent re-mark always survives to the next pass.\u000a",
        "date" : "2026-07-06 23:14:31 -0700",
        "id" : "295647a85e5f9252d93c04ef2833074bd9cf08a3",
        "msg" : "Fix power level tag re-marks being lost during a heartbeat write",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdater.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/PowerLevelTagUpdaterTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardManagerTest.java",
          "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java"
        ],
        "commitId" : "1f28520b892cdc7273d8887ae46299094d415209",
        "timestamp" : 1783404871000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix inspect stats boards never refreshing on the watched player's level up\u000a\u000aThe otherboard scan in handleLevelUp found stats boards inspecting the\u000aleveling player but then checked and refreshed the leveling player's\u000aown board instead of the matching one, so an inspect board kept showing\u000astale levels until re-run while the watched player's board could be\u000aredrawn spuriously. The scan now refreshes the board it matched.\u000a",
        "date" : "2026-07-06 23:14:31 -0700",
        "id" : "1f28520b892cdc7273d8887ae46299094d415209",
        "msg" : "Fix inspect stats boards never refreshing on the watched player's level up",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardManagerTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapperStatsPowerLevelTest.java",
          "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapper.java"
        ],
        "commitId" : "c41387bb8fdd55c4804962e2d120b05df32978e8",
        "timestamp" : 1783404871000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix stats scoreboard power level line vanishing for full-permission players\u000a\u000aThe stats sidebar appended the power level line after sorting the skill\u000arows, so once 15 or more skill rows were shown (a player permitted all\u000a17 skills) the line cap truncated it away entirely. The line now takes\u000apart in the sort; the sum is never smaller than any single row, so it\u000aranks first and always survives truncation, matching the old\u000ascore-sorted Bukkit board where the highest score displayed on top.\u000a",
        "date" : "2026-07-06 23:14:31 -0700",
        "id" : "c41387bb8fdd55c4804962e2d120b05df32978e8",
        "msg" : "Fix stats scoreboard power level line vanishing for full-permission players",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapperStatsPowerLevelTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardWrapper.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/listeners/PlayerListener.java",
          "src/test/java/com/gmail/nossr50/listeners/PlayerListenerSalvageInteractTest.java"
        ],
        "commitId" : "95babed7bb3140658a4bddf813cb7ad567ef3c88",
        "timestamp" : 1783405137000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix anvil confirmation item-use denial never applying to right-click air\u000a\u000aThe deny guard ran inside onPlayerInteractLowest, which is registered\u000awith ignoreCancelled. A PlayerInteractEvent with no clicked block\u000areports itself as cancelled from the moment it is constructed, so the\u000afollow-up use-item interaction that equips armor mid-confirmation never\u000areached the guard. Clicking the anvil could also override the denial,\u000abecause the use-item allowance for anvil blocks is applied after it.\u000a\u000aThe guard now runs in its own handler at LOW priority without ignoring\u000acancelled events, so it sees right-click-air interactions and takes\u000aprecedence over the anvil use-item allowance. The listener tests now\u000adispatch through the interact handlers honoring their real EventHandler\u000asettings, which is what exposed the dead path.\u000a",
        "date" : "2026-07-06 23:18:57 -0700",
        "id" : "95babed7bb3140658a4bddf813cb7ad567ef3c88",
        "msg" : "Fix anvil confirmation item-use denial never applying to right-click air",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/listeners/PlayerListenerSalvageInteractTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/listeners/PlayerListener.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java",
          "src/test/java/com/gmail/nossr50/skills/repair/RepairManagerTest.java"
        ],
        "commitId" : "53b16a5a0e67c5cfe274df04d28a565407e4891f",
        "timestamp" : 1783405137000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix repair confirmations re-prompting after every partial repair\u000a\u000aRepair confirmations are bound to the prompted item, but a repair\u000achanges the item's damage, so the pending confirmation stopped matching\u000aas soon as the repair completed. Partial repairs are the norm, so\u000acontinuing to repair the same item re-prompted after every repair\u000ainstead of only when the held item actually changed.\u000a\u000aA matching confirmation is now rebound to the item's repaired state, so\u000arepairing the same item within the confirmation window keeps going\u000awithout new prompts. This also keeps the use-item denial covering the\u000ajust-repaired item, which unlike salvage stays in the player's hand.\u000a",
        "date" : "2026-07-06 23:18:57 -0700",
        "id" : "53b16a5a0e67c5cfe274df04d28a565407e4891f",
        "msg" : "Fix repair confirmations re-prompting after every partial repair",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/skills/repair/RepairManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/skills/repair/RepairManagerTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java",
          "src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java"
        ],
        "commitId" : "3885c1c07f2177a58c1c35cd2d4924ced4a93867",
        "timestamp" : 1783405243000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix database purge deleting flatfile users with unreadable last login\u000a\u000aAn unparseable last-login value was treated as a real timestamp of 0,\u000aso the user looked ancient and was removed even though their last login\u000acould not be determined. Unreadable values are now treated like an\u000aunknown last login: the purge tries to recover a real timestamp from\u000athe server's offline player data and keeps the user otherwise.\u000a",
        "date" : "2026-07-06 23:20:43 -0700",
        "id" : "3885c1c07f2177a58c1c35cd2d4924ced4a93867",
        "msg" : "Fix database purge deleting flatfile users with unreadable last login",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java"
          },
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java",
          "src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java"
        ],
        "commitId" : "8e2a45dced709f7f110076528ec0e92f488ce04a",
        "timestamp" : 1783405243000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Fix powerless user purge deleting comments from the flatfile database\u000a\u000aPurging powerless users treated every line in mcmmo.users as a user,\u000aso the generated comment header had no skill data, counted as a\u000apowerless user, and was removed while inflating the purged total.\u000aComments and empty lines are now preserved like the other file\u000arewrites.\u000a",
        "date" : "2026-07-06 23:20:43 -0700",
        "id" : "8e2a45dced709f7f110076528ec0e92f488ce04a",
        "msg" : "Fix powerless user purge deleting comments from the flatfile database",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "src/test/java/com/gmail/nossr50/database/FlatFileDatabaseManagerTest.java"
          },
          {
            "editType" : "edit",
            "file" : "src/main/java/com/gmail/nossr50/database/FlatFileDatabaseManager.java"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "Changelog.txt"
        ],
        "commitId" : "9fe5731a229f180386880ad1fbc289808650b558",
        "timestamp" : 1783405342000,
        "author" : {
          "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
          "fullName" : "nossr50"
        },
        "authorEmail" : "nossr50@gmail.com",
        "comment" : "Update changelog\u000a",
        "date" : "2026-07-06 23:22:22 -0700",
        "id" : "9fe5731a229f180386880ad1fbc289808650b558",
        "msg" : "Update changelog",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "Changelog.txt"
          }
        ]
      }
    ],
    "kind" : "git"
  },
  "culprits" : [
    {
      "absoluteUrl" : "https://popicraft.net/jenkins/user/nossr50",
      "fullName" : "nossr50"
    }
  ]
}