There are many versions and abstraction levels in play, so here's a summary.

## Gradle

### Project's Gradle version
There's a Gradle version that is being used to build the project.
This is the standard `gradle/wrapper/gradle-wrapper.properties`.

This version executes:
 * the compilation tasks
 * calls the JUnit runner when running tests
 * runs the POM generation and publishing tasks

Through `id("org.gradle.java-gradle-plugin")` and `gradleApi()`/`gradleApiWithoutKotlin()` dependency it also becomes part of the compile-classpath of production and test code.

The runtime-classpath of production code depends on who is running the plugin's code.

In this project's tests this version is accessible with `GradleVersion.current()`, but it'll be always the same in every CI matrix split.

### Tests' Gradle versions
When running unit tests the above version is in play via `projects.test.internal` on the test's runtime-classpath.

When running integration tests, the same is true, but `GradleRunnerRule` will use a delegated version from `net.twisterrob.gradle.runner.gradleVersion`. So while the test classpath is the same as the project, the Gradle build being executed as part of the test will have the specific version from the properties or `-P` override.

This version is accessible from JUnit test code via `val gradle: GradleRunnerRule`'s `gradle.gradleVersion` property. This will contain what's in the property, if any.

### GradleVersion.current()
When accessing this, it should be done with `GradleVersion.current().baseVersion`, so that `<=` and similar comparisons work correctly.
They would otherwise break on rc/snapshot versons.

### Testception
There's some craziness happening in `TestPluginTest`, it uses `GradleRunnerRule` to set up a Gradle project that uses `GradleRunnerRule`. This applies `TestPlugin` which adds `gradleApi()` to the classpath. Since this test build is running via an outer `GradleRunnerRule`, that project's Gradle version will be added to the inner build's classpath.

## Android Gradle Plugin

### Project's AGP versions
Yes, there are multiple, each `:compat:agp-xxx` module uses its own as `compileOnly` to prevent this project from playing in the dependency resolution hell. Using this approach allows to strictly compile against Android Gradle Plugin versions without having to use reflection and other weird hacks.

The project is built in a way that's compatible with every supported version of AGP/Gradle.

In production code `AGPVersions.CLASSPATH` will return the version that exists during runtime of the plugins.

### Tests' AGP versions
JUnit tests have the latest version on their runtime classpath, so `AGPVersions.CLASSPATH` will always be the latest in tests.
For the matrix's split version, which is defined by `net.twisterrob.test.android.pluginVersion` property or `-P` override, access the `AGPVersions.UNDER_TEST` variable.

Note: `AGPVersions.UNDER_TEST` in test code will be the same as `AGPVersions.CLASSPATH` in production code.

In `"""` strings or in test resource files which describe the project under test, use `AGPVersions.CLASSPATH` if necessary, or use the `@net.twisterrob.test.android.pluginVersion@` placeholder which will be replaced during build.
