chore(knowledge): move canonical docs to shared SoMC wiki
CI / build (push) Successful in 3m9s
Release / release (push) Successful in 2m12s

This commit is contained in:
dmg
2026-09-09 23:18:05 -04:00
parent 320c8ce193
commit 54e7f306ed
12 changed files with 10 additions and 345 deletions
+9
View File
@@ -0,0 +1,9 @@
# spigot-getgud agent entrypoint
The canonical stories, engineering guidance, and **all process documents** are in the private [SoMC OKF wiki](https://git.garvis.dev/dmg/somc-okf/src/branch/main/index.md).
Before work, read the sibling `../somc-okf/index.md`, `../somc-okf/processes/index.md`, `../somc-okf/projects/spigot-getgud/index.md`, `engineering.md` in that project section, and relevant `../somc-okf/user-stories/spigot-getgud/` stories. Also follow the parent workspace `AGENTS.md` when present.
For standalone checkouts, start at the [project page](https://git.garvis.dev/dmg/somc-okf/src/branch/main/projects/spigot-getgud/index.md) and [shared process](https://git.garvis.dev/dmg/somc-okf/src/branch/main/processes/development.md). Obtain wiki access before feature work; do not recreate a local knowledge bundle. Source builds do not require private wiki access.
Development follows [Development cycle](https://git.garvis.dev/dmg/somc-okf/src/branch/main/runbooks/development-cycle.md): approved stories, failing tests, passing implementation, verification, then source/wiki commit and push. GitOps updates are committed locally **without pushing**; only [Do release](https://git.garvis.dev/dmg/somc-okf/src/branch/main/runbooks/do-release.md) authorizes a reviewed GitOps push.
+1 -1
View File
@@ -2,7 +2,7 @@
Leaf is a Spigot 26.2 plugin that lets non-aggressive players opt into visible Resistance and Strength protection.
The approved behavior is specified in the [OKF design bundle](design/index.md).
The approved behavior is specified in the [SoMC OKF wiki](https://git.garvis.dev/dmg/somc-okf/src/branch/main/projects/spigot-getgud/index.md).
## Requirements
-12
View File
@@ -1,12 +0,0 @@
---
okf_version: "0.1"
---
# Leaf Design
This bundle documents Leaf, a Spigot plugin that lets players opt into visible Resistance and Strength boosts while requiring them to relinquish that protection when they attack another player.
## Explore
- [User stories](user-stories/index.md)
- [Design log](log.md)
-105
View File
@@ -1,105 +0,0 @@
# Leaf Design Log
## 2026-08-10
### Initial protection design
- Leaf is available to any player who opts in; the seven-day period applies only to onboarding reminders.
- Protection grants Resistance I by default and remains active until the player opts out, attacks another player, an administrator disables it for the player, or Leaf is globally disabled.
- Receiving an attack does not remove protection, but retaliating does, including attributable Thorns damage.
- PvP attribution covers melee, projectiles, potions, owned animals, Thorns, and indirect damage when Spigot exposes a reliable responsible player.
- Opted-in players receive a leaf prefix in tab, overhead names, and chat where supported.
- New players receive an onboarding reminder on every login for seven calendar days after first joining.
- Global disablement suppresses effects, prefixes, and reminders without erasing player choices.
- Administration uses the permission-aware `/leaf` command tree with autocomplete.
- Builds and releases follow the neighboring Spigot Base Gradle and Gitea pipeline.
- The design bundle is committed together; later implementation work is committed separately for each user story.
### Implementation started
- Established the Java 17 Gradle project, strict compilation, JUnit test lifecycle, Leaf plugin metadata, Gradle wrapper, and Gitea CI and semantic-release workflows.
- Verified the initial pipeline with `./gradlew clean check jar` and produced `build/libs/leaf-0.1.0-SNAPSHOT.jar`.
- US-007 remains in progress until the story-by-story implementation commit requirement has been verified.
### Configuration and persistence checkpoint
- Added validated settings with Resistance I and seven-day onboarding defaults.
- Added defensive UUID-keyed YAML player state with RFC 3339 timestamps, forward-field preservation, and atomic replacement where supported.
- Added safe plugin initialization and periodic dirty-state persistence.
- US-006 remains in progress pending live runtime setting commands and Leaf effect ownership behavior.
### US-001 player protection completed
- Added permission-aware player commands with idempotent choice changes and detailed status reporting.
- Added immediate durable opt-in persistence, join-time restoration, and quiet infinite Resistance reconciliation.
- Leaf tracks its live Resistance fingerprint and conservatively preserves a visibly distinct Resistance effect.
- Verified player choice, lock, persistence, command, autocomplete, and build behavior with `./gradlew clean check jar`.
### US-003 identity presentation checkpoint
- Added configurable, color-compatible prefixes to standard chat display names and player-list names.
- Added conservative main-scoreboard team prefixes for overhead names without displacing unrelated teams.
- Name cleanup restores only values Leaf installed; third-party changes are preserved.
- Documented scoreboard, custom chat, tab-list, and per-viewer scoreboard limitations.
- US-003 remains in progress until combat and global administration paths are verified.
### US-002 combat opt-out completed
- Added modern Spigot damage-source attribution for direct attacks, projectiles, thrown potions, area clouds, tamed animals, TNT, Thorns, and other reliably attributed sources.
- Ambiguous, cancelled, zero-damage, environmental, and self damage do not opt out a player.
- Combat opt-out bypasses administrative locks, immediately reconciles effect and prefix state, persists once, and sends one explanatory message.
- Verified attribution, victim safety, lock bypass, duplicate suppression, and the full build with `./gradlew clean check jar`.
### US-004 onboarding completed
- Join observation now sends the configurable welcome message on each login before the original first-join instant plus the configured calendar-day window.
- The exact expiration boundary and globally disabled behavior suppress reminders without resetting first-join state.
- The default message names all player commands and explains automatic combat opt-out.
- Verified repeated joins, expiration, global suppression, first-join retention, and the full build with `./gradlew clean check jar`.
### US-005 administration and US-003 identity completed
- Added the complete `leaf.admin` command tree for global state, live strength, player status, saved choice, and locks.
- Runtime global and strength changes persist before activation and immediately reconcile all online players.
- Target resolution prefers exact online/current names, retains prior names, accepts UUIDs, and rejects ambiguous reused names.
- Added position-specific administrative autocomplete and mutation/no-change reporting with validation before mutation.
- Verified global effect and prefix suppression/restoration, live strength, targets, locks, command permissions, completion, durable aliases, and the full build with `./gradlew clean check jar`.
### US-006 configuration and persistence completed
- Runtime global and Resistance-level changes are written through Bukkit configuration before becoming active and survive restart.
- Failed runtime setting persistence leaves the active settings unchanged.
- Leaf records only effects it successfully installs, removes them only while the visible fingerprint matches, and preserves distinct Resistance effects; Spigot's identical-effect ownership limitation is documented.
- Durable player state now retains prior names in addition to the required UUID, latest name, choice, lock, and RFC 3339 first-join timestamp.
- Verified settings failure safety, durable aliases, existing defensive YAML behavior, strict compilation, and the full build with `./gradlew clean check jar`.
### US-007 build and release completed
- Verified dedicated conventional implementation commits for protection, identity, combat, onboarding, administration, configuration verification, and logout cleanup in addition to the existing build foundation.
- Kept reserved OKF index and log documents in their specification-defined structures.
- Verified all user stories are done, all acceptance criteria are checked, the repository has no remote, and no push was performed.
- Final verification passed with `./gradlew clean check jar` and `okflint` validation.
### US-003 sticky-prefix regression fixed
- Reproduced the cleanup failure that occurred when another plugin changed a Leaf-decorated display name.
- Leaf now removes exact managed-prefix text without discarding surrounding third-party formatting, clears stale prefixes after reload, and normalizes repeated prefixes before applying one leaf.
- Added regression coverage for wrapped names, duplicate stale prefixes, untracked stale prefixes, unrelated formatting, tab names, and scoreboard cleanup.
- Verified the fix with `./gradlew clean check jar`.
### Strength protection added
- Opted-in players now receive quiet, infinite Strength I alongside Resistance I by default; both effects must be active for Leaf status to report active protection.
- Added independent `resistance-level` and `strength-level` settings with live `/leaf effect <resistance|strength> <1-5>` administration and positional autocomplete.
- Retained `/leaf strength <1-5>` as a deprecated compatibility alias for changing Resistance.
- Opt-out, combat, administrative disablement, and global disablement remove both Leaf-managed effects while conservatively preserving distinct external effects.
- Minecraft calculates the initiating PvP hit before Leaf can process the damage event, so that first hit can include the configured Strength bonus before automatic opt-out.
- Verified settings, runtime reconciliation, status, combat cleanup, persistence, command compatibility, autocomplete, and the complete build with `./gradlew clean check jar`.
### Automatic effect recovery added
- Leaf now reconciles opted-in online players every 20 ticks so death, milk, commands, and plugins cannot permanently clear configured protection.
- Recovery remains disabled for opted-out players and while Leaf is globally disabled.
- A temporary external Resistance or Strength effect is preserved instead of overwritten; the leaf prefix remains visible and Leaf restores its configured effect after the external effect ends.
- Added regression coverage for the one-second recovery task and eligibility-aware online-player reconciliation.
- Verified the complete build with `./gradlew clean check jar`.
-9
View File
@@ -1,9 +0,0 @@
# Leaf User Stories
1. [US-001: Opt into Leaf protection](us-001-opt-into-leaf-protection.md)
2. [US-002: Relinquish protection when attacking](us-002-relinquish-protection-when-attacking.md)
3. [US-003: Identify protected players](us-003-identify-protected-players.md)
4. [US-004: Introduce new players to Leaf](us-004-introduce-new-players-to-leaf.md)
5. [US-005: Administer Leaf](us-005-administer-leaf.md)
6. [US-006: Configure and persist Leaf](us-006-configure-and-persist-leaf.md)
7. [US-007: Build and release Leaf](us-007-build-and-release-leaf.md)
@@ -1,32 +0,0 @@
---
type: User Story
title: "US-001: Opt into Leaf protection"
description: Let players voluntarily receive and relinquish a persistent Resistance boost.
status: done
---
# US-001: Opt into Leaf protection
As a **player**, I want to opt into Leaf protection so that I can receive a modest defensive boost while playing on a hard server.
## Acceptance criteria
- [x] Players with the `leaf.use` permission, granted by default, can use `/leaf on`, `/leaf off`, and `/leaf status`.
- [x] `/leaf on` records the player's opt-in choice and grants Resistance I while Leaf is globally enabled.
- [x] Resistance remains continuously effective without distracting expiry or renewal messages or particles.
- [x] `/leaf off` records the player's opt-out choice and immediately removes only the Resistance effect managed by Leaf.
- [x] `/leaf status` clearly distinguishes the player's saved choice, active protection, administrative lock, and global Leaf state.
- [x] Repeating an already-satisfied `on` or `off` command is safe and explains that no change was needed.
- [x] Opt-in choices are keyed by UUID and survive logout and server restart.
- [x] A player who joins while opted in regains protection when Leaf is enabled.
- [x] Player-command autocomplete suggests only valid next arguments available to the sender.
- [x] Opted-in players receive quiet Strength I alongside Resistance I by default.
- [x] Player status reports active protection only when both configured Leaf effects are effective.
- [x] Missing Leaf effects are restored for opted-in online players within approximately one second after death, milk, commands, or plugins clear them.
- [x] Recovery remains suppressed while Leaf is globally disabled or the player is opted out.
## Related
- [US-002: Relinquish protection when attacking](us-002-relinquish-protection-when-attacking.md)
- [US-003: Identify protected players](us-003-identify-protected-players.md)
- [US-005: Administer Leaf](us-005-administer-leaf.md)
@@ -1,31 +0,0 @@
---
type: User Story
title: "US-002: Relinquish protection when attacking"
description: Remove Leaf protection when an opted-in player attacks another player.
status: done
---
# US-002: Relinquish protection when attacking
As a **player facing PvP**, I want Leaf protection to belong only to non-aggressors so that protected players cannot keep its advantage after fighting back.
## Acceptance criteria
- [x] When an opted-in player damages another player, Leaf automatically changes the attacker's saved choice to opted out.
- [x] Automatic opt-out immediately removes Leaf-managed Resistance and the attacker's leaf prefix.
- [x] Automatic opt-out also immediately removes Leaf-managed Strength.
- [x] The attacker receives a clear chat message explaining that attacking another player disabled Leaf and that they may opt in again when permitted.
- [x] Receiving player-caused damage without retaliating does not change the protected player's choice or Resistance.
- [x] Retaliatory damage counts as attacking, including Thorns damage attributable to the protected player.
- [x] Direct melee attacks and player-fired projectiles are attributed to the attacking player.
- [x] Harmful splash or lingering potion damage is attributed to the player who threw the potion.
- [x] Damage caused by a tamed animal is attributed to its player owner when Spigot exposes that ownership.
- [x] TNT, fire, and other indirect damage trigger opt-out only when Spigot exposes a reliable responsible player; ambiguous environmental damage does not opt out an innocent player.
- [x] PvP-triggered opt-out applies even when an administrator has locked the player's preference.
- [x] A single attack produces no duplicate state changes or duplicate notifications.
## Related
- [US-001: Opt into Leaf protection](us-001-opt-into-leaf-protection.md)
- [US-003: Identify protected players](us-003-identify-protected-players.md)
- [US-005: Administer Leaf](us-005-administer-leaf.md)
@@ -1,30 +0,0 @@
---
type: User Story
title: "US-003: Identify protected players"
description: Mark actively protected players with a visible leaf prefix wherever Spigot supports it.
status: done
---
# US-003: Identify protected players
As a **server participant**, I want protected players to be visibly identified so that their Leaf status is clear before I interact with them.
## Acceptance criteria
- [x] An actively protected player has a configurable leaf prefix before their name in the player list.
- [x] An actively protected player has the same prefix before their overhead name where Spigot supports it.
- [x] An actively protected player has the same prefix in standard Spigot chat where the active chat format supports it.
- [x] The default prefix uses a leaf symbol with readable spacing and Minecraft-compatible formatting.
- [x] The prefix is removed immediately when the player opts out or is opted out by PvP or an administrator.
- [x] Prefixes are suppressed while Leaf is globally disabled and restored for online opted-in players when it is re-enabled.
- [x] Prefix updates do not overwrite unrelated display-name text where the Spigot API allows the values to coexist.
- [x] Scoreboard-team and third-party chat-plugin compatibility limitations are documented, and unsupported integrations fail without affecting protection state.
- [x] Repeated opt-in or reconciliation never produces multiple Leaf prefixes.
- [x] Opt-out removes every managed Leaf prefix while preserving unrelated name formatting.
- [x] A stale Leaf prefix left by an earlier plugin instance is normalized instead of duplicated.
## Related
- [US-001: Opt into Leaf protection](us-001-opt-into-leaf-protection.md)
- [US-002: Relinquish protection when attacking](us-002-relinquish-protection-when-attacking.md)
- [US-006: Configure and persist Leaf](us-006-configure-and-persist-leaf.md)
@@ -1,27 +0,0 @@
---
type: User Story
title: "US-004: Introduce new players to Leaf"
description: Remind players how to control Leaf during their first seven calendar days on the server.
status: done
---
# US-004: Introduce new players to Leaf
As a **new player**, I want a brief explanation of Leaf when I join so that I know protection is available and understand how to control it.
## Acceptance criteria
- [x] Leaf records the first observed join time for each player by UUID as an RFC 3339 UTC timestamp.
- [x] On every login before the first-join timestamp plus seven calendar days, the player receives a concise welcome message explaining Leaf protection.
- [x] The welcome message tells the player to use `/leaf on`, `/leaf off`, and `/leaf status`.
- [x] The message makes clear that attacking another player automatically opts the attacker out.
- [x] Players no longer receive the welcome message once their seven-day onboarding period expires.
- [x] Existing first-join timestamps are not reset by logout, restart, opt-in changes, or global disablement.
- [x] No onboarding reminders are shown while Leaf is globally disabled.
- [x] Re-enabling Leaf allows reminders to resume on subsequent logins only for players whose original seven-day period has not expired.
## Related
- [US-001: Opt into Leaf protection](us-001-opt-into-leaf-protection.md)
- [US-005: Administer Leaf](us-005-administer-leaf.md)
- [US-006: Configure and persist Leaf](us-006-configure-and-persist-leaf.md)
@@ -1,35 +0,0 @@
---
type: User Story
title: "US-005: Administer Leaf"
description: Give administrators command-based control over global and per-player Leaf behavior.
status: done
---
# US-005: Administer Leaf
As a **server administrator**, I want to control Leaf globally and per player so that I can support players, prevent misuse, and suspend protection for server events.
## Acceptance criteria
- [x] Administrative commands require `leaf.admin`, which server operators receive by default.
- [x] `/leaf enabled <on|off>` globally enables or disables Leaf.
- [x] Global disablement immediately suppresses Leaf-managed Resistance, prefixes, and onboarding reminders without erasing player opt-in choices.
- [x] Global enablement immediately restores protection and prefixes for eligible online opted-in players.
- [x] `/leaf player <name|uuid> status` reports the player's identity, saved opt-in choice, active-protection state, lock state, and first-join time.
- [x] `/leaf player <name|uuid> enabled <on|off>` changes the player's saved opt-in choice and immediately reconciles their online effect and prefix.
- [x] `/leaf player <name|uuid> locked <on|off>` controls whether that player can change their own saved choice.
- [x] A locked player receives a clear explanation when `/leaf on` or `/leaf off` is denied.
- [x] PvP-triggered opt-out remains authoritative even for a locked player.
- [x] Player targets resolve online names, previously known names, and UUIDs without confusing two players who used the same name.
- [x] `/leaf strength <1-5>` remains a deprecated compatibility alias that changes the live Resistance level.
- [x] `/leaf effect resistance <1-5>` changes the live Resistance level and immediately updates protected online players.
- [x] `/leaf effect strength <1-5>` changes the live Strength level and immediately updates protected online players.
- [x] Effect-command autocomplete suggests effect names and valid levels for the current argument position.
- [x] Administrative autocomplete is permission-aware and suggests valid subcommands, known player targets, properties, levels, and `on` or `off` values for the current argument position.
- [x] Every successful mutation reports exactly what changed, and invalid requests make no partial changes.
## Related
- [US-001: Opt into Leaf protection](us-001-opt-into-leaf-protection.md)
- [US-002: Relinquish protection when attacking](us-002-relinquish-protection-when-attacking.md)
- [US-006: Configure and persist Leaf](us-006-configure-and-persist-leaf.md)
@@ -1,33 +0,0 @@
---
type: User Story
title: "US-006: Configure and persist Leaf"
description: Provide validated configuration and durable, defensive storage for Leaf behavior.
status: done
---
# US-006: Configure and persist Leaf
As a **server operator**, I want Leaf settings and player state to be validated and durable so that protection remains predictable across restarts.
## Acceptance criteria
- [x] Configuration supports the global enabled state, Resistance and Strength levels, leaf prefix, onboarding duration, and player-facing messages.
- [x] Resistance strength defaults to level I and accepts only Minecraft Resistance levels I through V.
- [x] Strength defaults to level I and accepts only Minecraft Strength levels I through V.
- [x] Runtime changes made through `/leaf enabled` and `/leaf effect` are persisted for subsequent restarts.
- [x] UUID-keyed player state persists the latest known name, saved opt-in choice, administrative lock, and first-join timestamp.
- [x] Date-times use RFC 3339 UTC notation with a `Z` suffix.
- [x] State is saved safely so that a failed write does not replace valid persisted state with a partial document.
- [x] Invalid required configuration prevents partial plugin initialization and produces a clear server log message.
- [x] Corrupt or invalid player records are handled defensively and cannot silently grant protection or privileges.
- [x] Removing Leaf-managed Resistance or Strength does not remove a distinct corresponding effect that Leaf does not own when the API provides enough information to distinguish it.
- [x] A temporary external Resistance or Strength effect is preserved instead of overwritten, and Leaf restores its configured effect after the external effect ends.
- [x] The leaf prefix remains visible while an external effect temporarily replaces a Leaf-managed effect.
- [x] Unknown forward-compatible configuration and player-state fields are preserved where practical.
## Related
- [US-001: Opt into Leaf protection](us-001-opt-into-leaf-protection.md)
- [US-004: Introduce new players to Leaf](us-004-introduce-new-players-to-leaf.md)
- [US-005: Administer Leaf](us-005-administer-leaf.md)
- [US-007: Build and release Leaf](us-007-build-and-release-leaf.md)
@@ -1,30 +0,0 @@
---
type: User Story
title: "US-007: Build and release Leaf"
description: Give maintainers repeatable Spigot builds, automated verification, and versioned Gitea releases.
status: done
---
# US-007: Build and release Leaf
As a **plugin maintainer**, I want automated builds and releases modeled on Spigot Base so that tested, correctly versioned Leaf artifacts can be distributed consistently.
## Acceptance criteria
- [x] The Gradle project compiles against Spigot API `26.2-R0.1-SNAPSHOT` using a Java 17 toolchain.
- [x] Compiler lint warnings fail the build.
- [x] Automated JUnit 5 tests run as part of the Gradle check lifecycle.
- [x] Pushes and pull requests build and test Leaf in Gitea Actions.
- [x] Pull requests validate conventional commit messages.
- [x] CI stores a development Leaf JAR as a workflow artifact.
- [x] Main-branch conventional commits drive semantic versioning.
- [x] A successful release builds a versioned Leaf JAR and attaches it to the corresponding Gitea release.
- [x] Build files, Gradle wrapper, workflows, and release behavior follow `../spigot-base/` where applicable while using Leaf names and identifiers.
- [x] The initial approved user-story bundle is kept in one documentation commit.
- [x] Subsequent implementation work is organized into a separate conventional commit for each implemented user story.
- [x] No remote push is performed until the maintainer confirms that the Gitea repository and release token secret are ready.
## Related
- [US-006: Configure and persist Leaf](us-006-configure-and-persist-leaf.md)
- [User-story catalog](index.md)