Instrumentation Loader
Obtains a live Instrumentation for the running JVM by loading a tiny java agent (see ratph6.tessera.agent.TesseraAgent). This is what lets TypeScript mixins rewrite Minecraft classes that are already loaded by the time a script runs — a static .mixins.json only gets a shot during early class loading.
Two attach strategies, tried in order:
Self-attach — fast, in-process. Only works when the JVM was launched with
-Djdk.attach.allowAttachSelf=true(the guard reads the startup property snapshot, so it can't be enabled at runtime). Set automatically for the dev run in build.gradle.kts.External-process attach — spawns a throwaway JVM (ratph6.tessera.agent.AttachHelper) that attaches to us by pid. A separate process attaching has no self-attach restriction, so this path needs no launch flag — the robust default for production.
Both paths require the Java runtime to include the jdk.attach module (any full JDK does; some stripped Minecraft runtime images do not). If neither works, mixins are disabled with a clear error and the rest of Tessera keeps running.
Failure is sticky: once attach fails we remember why and fail fast on subsequent calls instead of retrying the (slow) attach every time.
Functions
The instrumentation, attaching on first use. Throws (with a user-facing message) on failure.
The instrumentation if already attached, else null (does not attempt an attach).
Clear a remembered attach failure so the next instrumentation call retries (used by /te reload).