# Dependency notes for Java and Kotlin

A `pom.xml` or a Gradle build file says which version of a library a service uses. It does not say that the Jackson modules have to move together, that the service is held on an older line until a migration lands, or which integration tests show an upgrade is safe. An XML comment or a `//` line has room for a phrase, not for that history.

Depos keeps a note for each dependency beside its build file — `.depos/maven/DEPENDENCY-NOTES.md` for Maven, `.depos/gradle/DEPENDENCY-NOTES.md` for Gradle — and shows it on the dependency in the editor. Gradle builds in the Groovy and the Kotlin DSL are both read.

## What Depos reads

### Maven

- **Manifest:** `pom.xml`
- **Notes file:** `.depos/maven/DEPENDENCY-NOTES.md`
- **Section heading:** `groupId:artifactId`: `## org.slf4j:slf4j-api`

Depos reads the `<dependencies>` of the project and its profiles, not `<dependencyManagement>` or plugin dependencies. Parent POMs are not read.

### Gradle

- **Manifest:** `build.gradle`, `build.gradle.kts`
- **Notes file:** `.depos/gradle/DEPENDENCY-NOTES.md`
- **Section heading:** `group:name` or the catalog alias: `## org.slf4j:slf4j-api`, `## libs.junit.jupiter`

Depos reads module coordinates and `libs.*` aliases in a `dependencies` block, not plugins, constraints, `project(…)`, `files(…)` or catalog bundles. The script is never run, so a dependency added by code is not seen.

Depos never runs Maven or Gradle, and it does not resolve parent POMs, BOMs or `libs.versions.toml`. A note belongs to the dependency as the build file writes it.

## Example

```xml
<dependencies>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.18.2</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.18.2</version>
  </dependency>
</dependencies>
```

`.depos/maven/DEPENDENCY-NOTES.md`:

```md
## com.fasterxml.jackson.core:jackson-databind

JSON for the REST API and the Kafka payloads. Upgrade every Jackson artifact together.

### Agent notes

- purpose: JSON mapping for the REST API and the Kafka message payloads
- bump-with: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
- verify: `mvn -pl api test` and the contract tests (`mvn -Pcontract verify`)
- verified: 2.18.2
```

In a Gradle build, a version-catalog alias is a note key of its own:

```kotlin
dependencies {
    implementation("org.slf4j:slf4j-api:2.0.16")
    testImplementation(libs.junit.jupiter)
}
```

Its sections in `.depos/gradle/DEPENDENCY-NOTES.md` are `## libs.junit.jupiter` and `## org.slf4j:slf4j-api`.

## Comments in pom.xml and Gradle builds

```xml
<dependencies>
  <!-- jackson-databind: upgrade every Jackson artifact together -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.18.2</version>
  </dependency>
</dependencies>
```

A comment in `pom.xml` is an XML comment, `<!-- … -->`, and it cannot contain `--`. A comment that mentions a command-line flag breaks the build: with `<!-- build with --offline -->`, Maven stops with `Non-parseable POM … in comment after two dashes (--) next character must be > not o`. For the same reason, a block that already holds a comment cannot be commented out.

Gradle build files take `//` and `/* */` comments, and the version catalog, `gradle/libs.versions.toml`, takes `#`. Gradle can also carry a reason of its own, which `gradle dependencyInsight` prints as `Was requested: …`:

```kotlin
dependencies {
    implementation("org.slf4j:slf4j-api") {
        version { strictly("2.0.16") }
        because("the logging backend is certified against 2.0.16 (OPS-41)")
    }
}
```

## Pinning a version

In Maven, `<version>2.18.2</version>` is a soft requirement. The nearest declaration in the dependency tree wins, so the version in your own pom beats the versions your dependencies ask for, unless one of them makes a hard requirement. `[2.18.2]` is a hard requirement: that version only, ahead of any soft one, and two hard requirements that disagree stop the build. `<dependencyManagement>` sets the version of a transitive dependency, but not of a direct one that names its own.

In Gradle, `implementation("org.slf4j:slf4j-api:2.0.16")` declares a required version, which conflict resolution may raise. `strictly("2.0.16")`, or the shorthand `"org.slf4j:slf4j-api:2.0.16!!"`, rules out every other version; `require`, `prefer` and `reject` set softer limits, and the version catalog takes the same rich versions.

A hard requirement or a `strictly` says that a version is held, not why. The reason goes in the dependency's note as `constraint:`, with `verify:` for what to run once it moves.

## For AI coding agents

An agent reads a dependency's section before it adds, upgrades or removes it. `bump-with:` lists the artifacts that have to move with it, and `verify:` the Maven or Gradle tasks to run afterwards. See [the rules agents follow](https://depos.dev/agents/).
