jdaugherty commented on code in PR #16725:
URL: https://github.com/apache/grails-core/pull/16725#discussion_r4361095096


##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |

Review Comment:
   This row describes only the Flapdoodle backend. The subproject has two: 
`InMemoryMongoBackend` over `de.bwaldvogel:mongo-java-server`, which is an 
`api` dependency (`embedded/build.gradle:48`, commented "the default backend, 
so it ships with the module"), and `FlapdoodleMongoBackend` for a real 
`mongod`, which is `compileOnly`. `EmbeddedMongoInitializer` picks flapdoodle 
when it is on the classpath and in-memory otherwise, and 
`embedded.mongodb.backend` selects one explicitly (its javadoc, lines 87-88). 
As written, an agent would tell a user they must add Flapdoodle to get an 
embedded server. Please name both backends and the default.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).

Review Comment:
   `discriminator-based` understates what `MongoDatastore` handles: `DATABASE` 
(`getDatastoreForTenantId` routes to the per-connection datastore, line 2871), 
`SCHEMA` (the resolver is wrapped in an `AllTenantsResolver` at line 376, and 
the collection lookup at line 1693 honours it) and `DISCRIMINATOR` (line 1851). 
The module's own `multiTenancy/configuration.adoc` uses `mode: DATABASE` as its 
example, and `grails-test-examples/mongodb/database-per-tenant` exercises it. 
Please list the three modes.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).
+
+### Not implemented — do not document or rely on these
+
+- **`shard "name"` in the mapping DSL is a no-op.** There is no `shard` method 
on `Collection`/`MongoCollection`. The call silently falls through to the 
generic `Entity.methodMissing` catch-all, which just records it as an ad hoc 
property config — it never issues a MongoDB `shardCollection` command. 
Verified: zero `shardCollection` calls anywhere in `core/src/main`. If you see 
`shard "..."` in a mapping block, treat it as dead syntax, not a real feature.
+- **Capped collections** — not implemented anywhere in this module.
+
+## Testing Rules
+
+The module's own tests use a real MongoDB via Testcontainers; the `embedded` 
subproject is a runtime feature for applications, not a test fallback. Docker 
or Podman must be running on the host.
+
+- **`GrailsDataTckSpec<GrailsDataMongoTckManager>`** is the dominant pattern 
(111+ specs) — the same shared TCK harness the Hibernate modules use 
(`grails-datamapping-tck`), parameterized with `GrailsDataMongoTckManager` 
(`core/src/test/groovy/.../GrailsDataMongoTckManager.groovy`), which starts a 
real `MongoDBContainer` in `setupSpec()`/stops it in `cleanupSpec()`. Its 
`destroy()` after each feature deletes the documents of every non-system 
database but keeps the collections and their indexes, so a later feature in the 
same fork can inherit an index an earlier one created; a spec that creates an 
index has to drop it itself.
+  ```groovy
+  class DocumentMappingSpec extends 
GrailsDataTckSpec<GrailsDataMongoTckManager> {
+      void setupSpec() {
+          manager.registerDomainClasses(CustomMapping)
+      }
+      void "test custom document mapping"() { ... }
+  }
+  ```
+  Domain classes are top-level classes in the same spec file, registered via 
`manager.registerDomainClasses(...)` in `setupSpec()` — same convention as 
`HibernateGormDatastoreSpec`.
+- **`AutoStartedMongoSpec`** (`grails-testing-support-mongodb`) — a 
lighter-weight base used by a handful of specs; a Spock global extension 
auto-injects `@Shared MongoDBContainer dbContainer` and auto-constructs a 
`@Shared MongoDatastore` field if present.

Review Comment:
   `a handful` undersells it: 44 specs extend `AutoStartedMongoSpec`, 41 in 
`core` and the 3 in `boot-plugin`, so roughly a quarter of core's specs. Worth 
saying, since this line is what an agent reads when choosing a base class.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).
+
+### Not implemented — do not document or rely on these
+
+- **`shard "name"` in the mapping DSL is a no-op.** There is no `shard` method 
on `Collection`/`MongoCollection`. The call silently falls through to the 
generic `Entity.methodMissing` catch-all, which just records it as an ad hoc 
property config — it never issues a MongoDB `shardCollection` command. 
Verified: zero `shardCollection` calls anywhere in `core/src/main`. If you see 
`shard "..."` in a mapping block, treat it as dead syntax, not a real feature.
+- **Capped collections** — not implemented anywhere in this module.
+
+## Testing Rules
+
+The module's own tests use a real MongoDB via Testcontainers; the `embedded` 
subproject is a runtime feature for applications, not a test fallback. Docker 
or Podman must be running on the host.
+
+- **`GrailsDataTckSpec<GrailsDataMongoTckManager>`** is the dominant pattern 
(111+ specs) — the same shared TCK harness the Hibernate modules use 
(`grails-datamapping-tck`), parameterized with `GrailsDataMongoTckManager` 
(`core/src/test/groovy/.../GrailsDataMongoTckManager.groovy`), which starts a 
real `MongoDBContainer` in `setupSpec()`/stops it in `cleanupSpec()`. Its 
`destroy()` after each feature deletes the documents of every non-system 
database but keeps the collections and their indexes, so a later feature in the 
same fork can inherit an index an earlier one created; a spec that creates an 
index has to drop it itself.
+  ```groovy
+  class DocumentMappingSpec extends 
GrailsDataTckSpec<GrailsDataMongoTckManager> {
+      void setupSpec() {
+          manager.registerDomainClasses(CustomMapping)
+      }
+      void "test custom document mapping"() { ... }
+  }
+  ```
+  Domain classes are top-level classes in the same spec file, registered via 
`manager.registerDomainClasses(...)` in `setupSpec()` — same convention as 
`HibernateGormDatastoreSpec`.
+- **`AutoStartedMongoSpec`** (`grails-testing-support-mongodb`) — a 
lighter-weight base used by a handful of specs; a Spock global extension 
auto-injects `@Shared MongoDBContainer dbContainer` and auto-constructs a 
`@Shared MongoDatastore` field if present.
+- **`grails.test.mongodb.MongoSpec`** — a separate, *app-facing* base class 
shipped via `testFixtures` in `grails-plugin/`, for Grails-application-level 
Mongo integration tests. Don't confuse it with the two internal patterns above 
— a spec being both a `MongoSpec` and an `AutoStartedMongoSpec` is explicitly 
forbidden.
+- The MongoDB image version comes from `-PmongodbContainerVersion`, which CI 
always passes; see `gradle/mongodb-forked-test-config.gradle`.
+- `core` applies `gradle/mongodb-forked-test-config.gradle` (`maxParallelForks 
= rootProject.ext.configuredTestParallel`, the forked, parallel layout); every 
other subproject (`bson`, `ext`, `embedded`, `spring-data`, `boot-plugin`, 
`grails-plugin`, `gson-templates`) applies `gradle/mongodb-test-config.gradle`, 
which runs serially (`maxParallelForks = 1`). Check which file a subproject 
applies before changing its parallelism.
+- `-PskipMongodbTests` / `-PonlyMongodbTests` gate these tests at the root, 
matching the `Container missing` row in root `AGENTS.md`'s Common Issues table 
— use `-PskipMongodbTests` when Docker isn't available.

Review Comment:
   Nit: the root table's `Container missing` row says `-PskipTests`, not 
`-PskipMongodbTests`, so "matching" is not right. `-PskipMongodbTests` is the 
narrower switch; say that instead of claiming a match.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).
+
+### Not implemented — do not document or rely on these
+
+- **`shard "name"` in the mapping DSL is a no-op.** There is no `shard` method 
on `Collection`/`MongoCollection`. The call silently falls through to the 
generic `Entity.methodMissing` catch-all, which just records it as an ad hoc 
property config — it never issues a MongoDB `shardCollection` command. 
Verified: zero `shardCollection` calls anywhere in `core/src/main`. If you see 
`shard "..."` in a mapping block, treat it as dead syntax, not a real feature.
+- **Capped collections** — not implemented anywhere in this module.

Review Comment:
   Not quite. `MongoExtensions.createAndGetCollection(db, name, options)` in 
`ext/` maps the options onto the driver's `CreateCollectionOptions` 
(`MongoExtensions.groovy:215-217`), so `[capped: true, sizeInBytes: n]` creates 
a capped collection, and `MongoExtensionsSpec:187` tests exactly that. What is 
missing is a mapping-DSL option on `MongoCollection`. Please narrow this to the 
mapping DSL, or an agent asked for a capped collection will answer that nothing 
supports it.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).
+
+### Not implemented — do not document or rely on these
+
+- **`shard "name"` in the mapping DSL is a no-op.** There is no `shard` method 
on `Collection`/`MongoCollection`. The call silently falls through to the 
generic `Entity.methodMissing` catch-all, which just records it as an ad hoc 
property config — it never issues a MongoDB `shardCollection` command. 
Verified: zero `shardCollection` calls anywhere in `core/src/main`. If you see 
`shard "..."` in a mapping block, treat it as dead syntax, not a real feature.
+- **Capped collections** — not implemented anywhere in this module.
+
+## Testing Rules
+
+The module's own tests use a real MongoDB via Testcontainers; the `embedded` 
subproject is a runtime feature for applications, not a test fallback. Docker 
or Podman must be running on the host.
+
+- **`GrailsDataTckSpec<GrailsDataMongoTckManager>`** is the dominant pattern 
(111+ specs) — the same shared TCK harness the Hibernate modules use 
(`grails-datamapping-tck`), parameterized with `GrailsDataMongoTckManager` 
(`core/src/test/groovy/.../GrailsDataMongoTckManager.groovy`), which starts a 
real `MongoDBContainer` in `setupSpec()`/stops it in `cleanupSpec()`. Its 
`destroy()` after each feature deletes the documents of every non-system 
database but keeps the collections and their indexes, so a later feature in the 
same fork can inherit an index an earlier one created; a spec that creates an 
index has to drop it itself.
+  ```groovy
+  class DocumentMappingSpec extends 
GrailsDataTckSpec<GrailsDataMongoTckManager> {
+      void setupSpec() {
+          manager.registerDomainClasses(CustomMapping)
+      }
+      void "test custom document mapping"() { ... }
+  }
+  ```
+  Domain classes are top-level classes in the same spec file, registered via 
`manager.registerDomainClasses(...)` in `setupSpec()` — same convention as 
`HibernateGormDatastoreSpec`.
+- **`AutoStartedMongoSpec`** (`grails-testing-support-mongodb`) — a 
lighter-weight base used by a handful of specs; a Spock global extension 
auto-injects `@Shared MongoDBContainer dbContainer` and auto-constructs a 
`@Shared MongoDatastore` field if present.
+- **`grails.test.mongodb.MongoSpec`** — a separate, *app-facing* base class 
shipped via `testFixtures` in `grails-plugin/`, for Grails-application-level 
Mongo integration tests. Don't confuse it with the two internal patterns above 
— a spec being both a `MongoSpec` and an `AutoStartedMongoSpec` is explicitly 
forbidden.
+- The MongoDB image version comes from `-PmongodbContainerVersion`, which CI 
always passes; see `gradle/mongodb-forked-test-config.gradle`.
+- `core` applies `gradle/mongodb-forked-test-config.gradle` (`maxParallelForks 
= rootProject.ext.configuredTestParallel`, the forked, parallel layout); every 
other subproject (`bson`, `ext`, `embedded`, `spring-data`, `boot-plugin`, 
`grails-plugin`, `gson-templates`) applies `gradle/mongodb-test-config.gradle`, 
which runs serially (`maxParallelForks = 1`). Check which file a subproject 
applies before changing its parallelism.
+- `-PskipMongodbTests` / `-PonlyMongodbTests` gate these tests at the root, 
matching the `Container missing` row in root `AGENTS.md`'s Common Issues table 
— use `-PskipMongodbTests` when Docker isn't available.
+
+## Change Workflow
+
+1. Identify which layer owns the behavior: mapping 
(`MongoMappingContext`/`MongoCollection`/`MongoAttribute`) vs. codec/runtime 
(`BsonPersistentEntityCodec`/`PersistentEntityCodec`) vs. datastore-level 
(`MongoDatastore`, index/transaction handling).
+2. Check whether the change affects the general `bson/` codec machinery (used 
by any BSON-backed consumer) or is genuinely Mongo-specific (`core/`) — don't 
put Mongo-only logic in `bson/`.
+3. Update or add specs via `GrailsDataTckSpec<GrailsDataMongoTckManager>`, 
registering any new domain classes as top-level classes in the same spec file.
+4. Run the affected subproject's tests with Docker/Podman running; expect 
`core` tests to run serially.

Review Comment:
   This contradicts line 97. `core` applies 
`gradle/mongodb-forked-test-config.gradle`, whose `maxParallelForks = 
rootProject.ext.configuredTestParallel` is 4 on CI and half the logical 
processors locally (`build.gradle:62-63`), and each fork's 
`GrailsDataMongoTckManager` starts its own container. The `core` tests run in 
parallel; `-PmaxTestParallel=1` is what makes them serial.



##########
build-logic/AGENTS.md:
##########
@@ -0,0 +1,56 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for build-logic
+
+> **IMPORTANT**: `build-logic` is the Gradle convention-plugin layer that the 
root build, `grails-gradle` and
+> `grails-forge` consume through `includeBuild`. It is build tooling, not 
Grails application code, so two of the
+> root rules do not apply here (see below). Root [`AGENTS.md`](../AGENTS.md) 
still governs PR, branch and review
+> conventions and repository-wide policy.
+
+## Quick Reference
+
+Run from inside `build-logic/`:
+
+```bash
+./gradlew build                     # all three projects
+./gradlew :build-logic:test         # the convention plugins (Spock and 
TestKit specs)
+./gradlew :grails-docs-core:test    # the documentation engine
+```
+
+## Rules That Differ From Root
+
+1. **Use plain `@CompileStatic`, not `@GrailsCompileStatic`.** Nothing here is 
a Grails artefact; no source under this directory uses `@GrailsCompileStatic`.
+2. **`javax.inject.Inject` is correct here.** Gradle's constructor injection 
uses JSR-330's `javax.inject`, which is unrelated to the Jakarta EE migration. 
Do not change it to `jakarta.*`.
+3. **Versions are not pinned here.** `plugins/build.gradle` and 
`docs-core/build.gradle` apply the root's `dependencies.gradle`; do not 
hardcode a version in this build.
+4. **There is no dedicated CI job for this build.** Every other build includes 
it and exercises the plugins through its own CI runs, so a missing job is not a 
sign of neglect.
+
+## Project Structure
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `plugins/` | `:build-logic` | The convention plugins (19 plugin ids 
registered in `plugins/build.gradle`), the repository-conventions and 
violation-aggregation tasks |
+| `docs-core/` | `:grails-docs-core` | The user-guide generation engine and 
the BOM extraction used by the documentation builds |
+| `vulnerability-scan/` | `:vulnerability-scan` | The dependency vulnerability 
scan run by the Vulnerability Scan workflow |
+
+The `gradle-developer` skill (`../.agents/skills/gradle-developer/SKILL.md`) 
covers the convention plugins, the BOM
+platforms and the Gradle 9 task-configuration rules; read it before changing a 
plugin.
+
+## Keep Other Documents In Step
+
+Root `AGENTS.md` and the `hibernate-developer` and `violation-fixer` skills 
describe behaviour implemented by plugins in

Review Comment:
   `hibernate-developer` does not describe anything these plugins implement; it 
has no mention of JaCoCo, the violation reports, code analysis or the 
repository-conventions check. The skills that do are `gradle-developer` and 
`violation-fixer`. Please swap `hibernate-developer` for `gradle-developer`.



##########
build-logic/AGENTS.md:
##########
@@ -0,0 +1,56 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for build-logic
+
+> **IMPORTANT**: `build-logic` is the Gradle convention-plugin layer that the 
root build, `grails-gradle` and
+> `grails-forge` consume through `includeBuild`. It is build tooling, not 
Grails application code, so two of the
+> root rules do not apply here (see below). Root [`AGENTS.md`](../AGENTS.md) 
still governs PR, branch and review
+> conventions and repository-wide policy.
+
+## Quick Reference
+
+Run from inside `build-logic/`:
+
+```bash
+./gradlew build                     # all three projects
+./gradlew :build-logic:test         # the convention plugins (Spock and 
TestKit specs)
+./gradlew :grails-docs-core:test    # the documentation engine
+```
+
+## Rules That Differ From Root
+
+1. **Use plain `@CompileStatic`, not `@GrailsCompileStatic`.** Nothing here is 
a Grails artefact; no source under this directory uses `@GrailsCompileStatic`.
+2. **`javax.inject.Inject` is correct here.** Gradle's constructor injection 
uses JSR-330's `javax.inject`, which is unrelated to the Jakarta EE migration. 
Do not change it to `jakarta.*`.
+3. **Versions are not pinned here.** `plugins/build.gradle` and 
`docs-core/build.gradle` apply the root's `dependencies.gradle`; do not 
hardcode a version in this build.

Review Comment:
   Two corrections. `vulnerability-scan/build.gradle:28` applies 
`dependencies.gradle` too, so list it. And "do not hardcode a version in this 
build" is contradicted by the build itself: `docs-core/build.gradle:47-48` and 
`62-65` pin `grails-gdoc-engine:1.0.1`, `snakeyaml:2.4` and the JUnit 5.12.2 / 
Platform 1.12.2 coordinates literally (none of them is in 
`dependencies.gradle`), and `settings.gradle` pins its three settings plugins. 
Either state those as the exceptions, or an agent will try to "fix" them. If 
they should move into `dependencies.gradle`, that is a separate change.



##########
grails-gradle/AGENTS.md:
##########
@@ -0,0 +1,55 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for grails-gradle
+
+> **IMPORTANT**: `grails-gradle` holds the Grails Gradle plugins that 
applications apply. It has its own
+> `settings.gradle` and its own CI jobs, but it shares the root's dependency 
management: `build.gradle` applies the
+> root's `dependencies.gradle`, so versions are managed there. It is build 
tooling, not Grails application code, so
+> two of the root rules do not apply here (see below). Root 
[`AGENTS.md`](../AGENTS.md) still governs PR, branch and
+> review conventions and repository-wide policy.
+
+## Quick Reference
+
+Run from inside `grails-gradle/`:
+
+```bash
+./gradlew build --continue
+./gradlew build -PskipTests -PskipCodeStyle
+./gradlew validateDependencyVersions --continue
+```
+
+## Rules That Differ From Root
+
+1. **Use plain `@CompileStatic`, not `@GrailsCompileStatic`.** The plugins are 
Gradle code, not Grails artefacts; the only `@GrailsCompileStatic` mentions in 
this build are documentation of what a plugin configures for an application.
+2. **`javax.inject.Inject` and `javax.xml.*` are correct here.** They are 
JSR-330 and JDK APIs, not Jakarta EE packages. The `jakarta.*` references in 
this build configure a downstream application's dependencies.
+3. **Versions are not pinned here.** `gradle.properties` holds daemon and 
cache settings only; `build.gradle` applies the root's `dependencies.gradle`. 
Bump versions in the root file.
+4. **Tests are Gradle TestKit tests.** Plugin specs extend 
`GradleSpecification` 
(`plugins/src/test/groovy/org/grails/gradle/plugin/core/GradleSpecification.groovy`)
 and run a real Gradle build against a generated project, not a mocked Grails 
application.
+
+## Project Structure
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `bom/` | `:grails-gradle-bom` | A `java-platform` constraining the sibling 
projects |
+| `common/` | `:grails-gradle-common` | Shared utilities |
+| `model/` | `:grails-gradle-model` | The subset of Grails runtime classes the 
plugins need at build time, before the framework is on the classpath |
+| `plugins/` | `:grails-gradle-plugins` | The `Plugin<Project>` 
implementations |
+| `tasks/` | `:grails-gradle-tasks` | The task classes |

Review Comment:
   Nit: `buildSrc/` is missing from the table. It has its own `build.gradle` 
and `settings.gradle`, applies `org.apache.grails.buildsrc.properties` and 
`dependencies.gradle`, and is the one part of this build that is not an 
included project.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).
+
+### Not implemented — do not document or rely on these
+
+- **`shard "name"` in the mapping DSL is a no-op.** There is no `shard` method 
on `Collection`/`MongoCollection`. The call silently falls through to the 
generic `Entity.methodMissing` catch-all, which just records it as an ad hoc 
property config — it never issues a MongoDB `shardCollection` command. 
Verified: zero `shardCollection` calls anywhere in `core/src/main`. If you see 
`shard "..."` in a mapping block, treat it as dead syntax, not a real feature.
+- **Capped collections** — not implemented anywhere in this module.
+
+## Testing Rules
+
+The module's own tests use a real MongoDB via Testcontainers; the `embedded` 
subproject is a runtime feature for applications, not a test fallback. Docker 
or Podman must be running on the host.
+
+- **`GrailsDataTckSpec<GrailsDataMongoTckManager>`** is the dominant pattern 
(111+ specs) — the same shared TCK harness the Hibernate modules use 
(`grails-datamapping-tck`), parameterized with `GrailsDataMongoTckManager` 
(`core/src/test/groovy/.../GrailsDataMongoTckManager.groovy`), which starts a 
real `MongoDBContainer` in `setupSpec()`/stops it in `cleanupSpec()`. Its 
`destroy()` after each feature deletes the documents of every non-system 
database but keeps the collections and their indexes, so a later feature in the 
same fork can inherit an index an earlier one created; a spec that creates an 
index has to drop it itself.
+  ```groovy
+  class DocumentMappingSpec extends 
GrailsDataTckSpec<GrailsDataMongoTckManager> {
+      void setupSpec() {
+          manager.registerDomainClasses(CustomMapping)
+      }
+      void "test custom document mapping"() { ... }
+  }
+  ```
+  Domain classes are top-level classes in the same spec file, registered via 
`manager.registerDomainClasses(...)` in `setupSpec()` — same convention as 
`HibernateGormDatastoreSpec`.
+- **`AutoStartedMongoSpec`** (`grails-testing-support-mongodb`) — a 
lighter-weight base used by a handful of specs; a Spock global extension 
auto-injects `@Shared MongoDBContainer dbContainer` and auto-constructs a 
`@Shared MongoDatastore` field if present.
+- **`grails.test.mongodb.MongoSpec`** — a separate, *app-facing* base class 
shipped via `testFixtures` in `grails-plugin/`, for Grails-application-level 
Mongo integration tests. Don't confuse it with the two internal patterns above 
— a spec being both a `MongoSpec` and an `AutoStartedMongoSpec` is explicitly 
forbidden.
+- The MongoDB image version comes from `-PmongodbContainerVersion`, which CI 
always passes; see `gradle/mongodb-forked-test-config.gradle`.
+- `core` applies `gradle/mongodb-forked-test-config.gradle` (`maxParallelForks 
= rootProject.ext.configuredTestParallel`, the forked, parallel layout); every 
other subproject (`bson`, `ext`, `embedded`, `spring-data`, `boot-plugin`, 
`grails-plugin`, `gson-templates`) applies `gradle/mongodb-test-config.gradle`, 
which runs serially (`maxParallelForks = 1`). Check which file a subproject 
applies before changing its parallelism.
+- `-PskipMongodbTests` / `-PonlyMongodbTests` gate these tests at the root, 
matching the `Container missing` row in root `AGENTS.md`'s Common Issues table 
— use `-PskipMongodbTests` when Docker isn't available.
+
+## Change Workflow
+
+1. Identify which layer owns the behavior: mapping 
(`MongoMappingContext`/`MongoCollection`/`MongoAttribute`) vs. codec/runtime 
(`BsonPersistentEntityCodec`/`PersistentEntityCodec`) vs. datastore-level 
(`MongoDatastore`, index/transaction handling).
+2. Check whether the change affects the general `bson/` codec machinery (used 
by any BSON-backed consumer) or is genuinely Mongo-specific (`core/`) — don't 
put Mongo-only logic in `bson/`.
+3. Update or add specs via `GrailsDataTckSpec<GrailsDataMongoTckManager>`, 
registering any new domain classes as top-level classes in the same spec file.
+4. Run the affected subproject's tests with Docker/Podman running; expect 
`core` tests to run serially.
+
+## Pitfalls to Avoid
+
+- Do not treat `shard "name"` as a functioning DSL keyword — it's a documented 
no-op (see above). Don't build new features assuming it works, and flag it if 
you're asked to "fix" sharding — the DSL surface exists but the implementation 
doesn't.
+- Do not change a subproject's test parallelism without reading the test 
config file it applies; the serial ones share one container.

Review Comment:
   The seven subprojects on `mongodb-test-config.gradle` do not share one 
container. `bson` (31 specs), `ext` (1) and `grails-plugin` (1) extend plain 
`Specification` and start nothing; `embedded` and `spring-data` start an 
embedded server (`EmbeddedReplicaSetSpec` runs `EmbeddedMongoInitializer` with 
the Flapdoodle backend), and no file under their `src/test` references 
Testcontainers; only `boot-plugin`'s three `AutoStartedMongoSpec` specs get a 
container from `MongoContainerHolder`, one per thread. Please drop the clause 
or replace it with what those subprojects actually run.



##########
.agents/skills/mongodb-developer/SKILL.md:
##########
@@ -0,0 +1,122 @@
+---
+name: mongodb-developer
+description: Guide for working in the grails-data-mongodb module (GORM for 
MongoDB) — codec-based document mapping, GeoJSON, embedded documents, TTL 
indexes, multi-tenancy, and Testcontainers-backed tests. Use this when changing 
code or tests under grails-data-mongodb.
+license: Apache-2.0
+---
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed to the Apache Software Foundation (ASF) under one or more contributor 
license agreements; and to You under the Apache License, Version 2.0.
+-->
+
+## What I Do
+
+- Provide repository-specific guidance for the `grails-data-mongodb` project 
(GORM for MongoDB — a document-database GORM implementation, not a relational 
one; do not bring Hibernate/binder mental models here).
+- Guide changes around `MongoMappingContext`, 
`BsonPersistentEntityCodec`/`PersistentEntityCodec`, and the 
codec-registry-based encode/decode pipeline.
+- Keep changes aligned with the Testcontainers-backed testing pattern this 
module actually uses.
+
+## When to Use Me
+
+Activate this skill when working on the MongoDB module, especially for:
+
+- Changes under `grails-data-mongodb/**` (any of its 9 subprojects — see 
Module Structure).
+- Document/collection mapping, codec, or GeoJSON-type work.
+- Index (including TTL) creation/reconciliation logic.
+- Multi-tenancy or multi-connection MongoDB work.
+
+## Module Context
+
+`grails-data-mongodb` has no `settings.gradle` of its own — it's part of the 
root aggregate build, same as `grails-data-hibernate7`. All of root 
`AGENTS.md`'s rules (jakarta, `@GrailsCompileStatic`, 
CodeNarc/Checkstyle/PMD/SpotBugs, `dependencies.gradle`/BOM) apply here 
unmodified.
+
+Nine Gradle projects live under this directory, mapped to real Gradle project 
names (not always `grails-data-mongodb-<dirname>` — check before assuming):
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `core/` | `:grails-data-mongodb-core` | The actual GORM-for-MongoDB 
implementation: `MongoDatastore`, `MongoMappingContext`, `MongoQuery`, GeoJSON 
types |
+| `bson/` | `:grails-data-mongodb-bson` | Low-level, GORM-independent BSON 
codec machinery (`BsonPersistentEntityCodec`, per-type property codecs, 
hand-rolled JSON tokenizer) |
+| `ext/` | `:grails-data-mongodb-ext` | A single file, Groovy extension 
methods on the raw MongoDB driver (`distinct`, `watch`/change streams, 
`deleteMany`) |
+| `boot-plugin/` | `:grails-data-mongodb-spring-boot` | Spring Boot 
auto-configuration (`MongoDbGormAutoConfiguration`) |
+| `spring-data/` | `:grails-data-mongodb-spring-data` | Lets GORM-for-MongoDB 
and Spring Data MongoDB share a `MongoClient`/codecs/transaction |
+| `grails-plugin/` | `:grails-data-mongodb` (note: not `-grails-plugin` 
suffixed) | Classic Grails plugin descriptor (`MongodbGrailsPlugin`); also 
ships the app-facing `grails.test.mongodb.MongoSpec` test base via 
`testFixtures` |
+| `gson-templates/` | `:grails-data-mongodb-gson-templates` | JSON Views 
(`.gson`) for `ObjectId` and GeoJSON types |
+| `embedded/` | `:grails-data-mongodb-embedded` | Starts a real `mongod` 
(Flapdoodle, a `compileOnly` dependency the application adds itself) before the 
application context refreshes and publishes its URL into the configured 
properties; for applications, not for this module's own tests |
+| `docs/` | `:grails-data-mongodb-docs` | Asciidoc manual + groovydoc 
aggregation only, no source |
+
+## Key Classes and Responsibilities
+
+There is no single `GrailsDomainBinder`-equivalent class — the responsibility 
splits across three cooperating layers:
+
+### Mapping (the binder equivalent)
+
+- `MongoMappingContext` (`core/.../mongo/config/MongoMappingContext.java`) — 
owns the private inner `MongoDocumentMappingFactory extends 
AbstractGormMappingFactory<MongoCollection, MongoAttribute>`, which is the 
actual binder: forces the `_id` field name, applies the global 
`stringIdDefaultStoredAs` default, wires codec-registry-backed custom types, 
and registers all GeoJSON custom types.
+- `MongoCollection` (`core/.../config/MongoCollection.groovy`) — entity-level 
mapping (collection name, database, `writeConcern`, indices, sort).
+- `MongoAttribute` (`core/.../config/MongoAttribute.groovy`) — property-level 
mapping (`reference` for DBRef vs. plain identifier, `field`, `geoIndex`, 
`index`, `indexAttributes`).
+- `MappingBuilder.document { ... }` 
(`core/.../grails/mongodb/mapping/MappingBuilder.groovy`) — the programmatic 
DSL entry point.
+
+### Codec pipeline (the runtime read/write engine)
+
+- `BsonPersistentEntityCodec` (`bson/.../BsonPersistentEntityCodec.groovy`) 
and its Mongo subclass `PersistentEntityCodec` 
(`core/.../engine/codecs/PersistentEntityCodec.groovy`) — a static 
`ENCODERS`/`DECODERS` registry keyed by `PersistentProperty` subtype 
(`Identity`, `TenantId`, `Simple`, `Embedded`, `EmbeddedCollection`, `Custom`, 
`Basic`, plus Mongo-specific `OneToOne`/`ManyToOne`/`OneToMany`/`ManyToMany`). 
`encode`/`decode` walk `entity.persistentProperties` and dispatch per property 
kind. `PersistentEntityCodec` also implements MongoDB's partial-update path 
(`encodeUpdate`) via `DirtyCheckable`, producing `$set`/`$unset` documents 
directly rather than rewriting the whole document.
+
+### Datastore
+
+- `MongoDatastore` (`core/.../mongo/MongoDatastore.java`) — owns index 
creation/reconciliation against live MongoDB and transaction-capability 
detection based on cluster topology.
+
+## Confirmed MongoDB-Specific Concepts (implemented — don't assume beyond this 
list)
+
+- **Embedded documents & embedded collections** — 
`Embedded`/`EmbeddedCollection` property kinds, with dedicated in-place 
`$set`/`$unset` update logic distinct from top-level property updates.
+- **GeoJSON types** — 
`grails.mongodb.geo.{Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon,GeometryCollection,Box,Circle,Sphere,Shape}`,
 each with a custom-type marshaller. Query support: `near`, `nearSphere`, 
`withinCircle`, `withinBox`, `withinPolygon`, `geoWithin`, `geoIntersects`. 
Legacy `2d`/`2dsphere` indexes via `MongoAttribute.geoIndex(String)`.
+- **TTL indexes** — property-level `indexAttributes: [expireAfterSeconds: N]` 
materializes a MongoDB TTL index, reconciled in place via `collMod` rather than 
drop/rebuild (see Pitfalls).
+- **DBRef vs. plain identifier** — `MongoAttribute.reference` selects how a 
`ToOne`/`ToMany` association is stored: `true` writes a `com.mongodb.DBRef`, 
`false` (the default) writes the associated identifier. It does not embed; 
embedding is `static embedded = [...]`, a different property kind (see the 
first bullet). An agent that sets `reference: false` to embed a document will 
store an id instead.
+- **Schemaless/dynamic attributes** — `DynamicAttributes` trait support baked 
into `BsonPersistentEntityCodec` and `MongoEntity`.
+- **Change streams** — `MongoExtensions.watch(...)`, a thin Groovy-extension 
wrapper over the driver's native `watch()`, not a GORM-level abstraction.
+- **Multi-document transactions** — opt-in via `grails.mongodb.transactional`, 
gated on cluster topology (`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED` supported; 
`STANDALONE` falls back with a one-time warning).
+- **Multi-tenancy / multiple named connections** — supported 
(discriminator-based multi-tenancy, `grails.mongodb.connections`).
+
+### Not implemented — do not document or rely on these
+
+- **`shard "name"` in the mapping DSL is a no-op.** There is no `shard` method 
on `Collection`/`MongoCollection`. The call silently falls through to the 
generic `Entity.methodMissing` catch-all, which just records it as an ad hoc 
property config — it never issues a MongoDB `shardCollection` command. 
Verified: zero `shardCollection` calls anywhere in `core/src/main`. If you see 
`shard "..."` in a mapping block, treat it as dead syntax, not a real feature.
+- **Capped collections** — not implemented anywhere in this module.
+
+## Testing Rules
+
+The module's own tests use a real MongoDB via Testcontainers; the `embedded` 
subproject is a runtime feature for applications, not a test fallback. Docker 
or Podman must be running on the host.
+
+- **`GrailsDataTckSpec<GrailsDataMongoTckManager>`** is the dominant pattern 
(111+ specs) — the same shared TCK harness the Hibernate modules use 
(`grails-datamapping-tck`), parameterized with `GrailsDataMongoTckManager` 
(`core/src/test/groovy/.../GrailsDataMongoTckManager.groovy`), which starts a 
real `MongoDBContainer` in `setupSpec()`/stops it in `cleanupSpec()`. Its 
`destroy()` after each feature deletes the documents of every non-system 
database but keeps the collections and their indexes, so a later feature in the 
same fork can inherit an index an earlier one created; a spec that creates an 
index has to drop it itself.
+  ```groovy
+  class DocumentMappingSpec extends 
GrailsDataTckSpec<GrailsDataMongoTckManager> {
+      void setupSpec() {
+          manager.registerDomainClasses(CustomMapping)
+      }
+      void "test custom document mapping"() { ... }
+  }
+  ```
+  Domain classes are top-level classes in the same spec file, registered via 
`manager.registerDomainClasses(...)` in `setupSpec()` — same convention as 
`HibernateGormDatastoreSpec`.
+- **`AutoStartedMongoSpec`** (`grails-testing-support-mongodb`) — a 
lighter-weight base used by a handful of specs; a Spock global extension 
auto-injects `@Shared MongoDBContainer dbContainer` and auto-constructs a 
`@Shared MongoDatastore` field if present.
+- **`grails.test.mongodb.MongoSpec`** — a separate, *app-facing* base class 
shipped via `testFixtures` in `grails-plugin/`, for Grails-application-level 
Mongo integration tests. Don't confuse it with the two internal patterns above 
— a spec being both a `MongoSpec` and an `AutoStartedMongoSpec` is explicitly 
forbidden.
+- The MongoDB image version comes from `-PmongodbContainerVersion`, which CI 
always passes; see `gradle/mongodb-forked-test-config.gradle`.
+- `core` applies `gradle/mongodb-forked-test-config.gradle` (`maxParallelForks 
= rootProject.ext.configuredTestParallel`, the forked, parallel layout); every 
other subproject (`bson`, `ext`, `embedded`, `spring-data`, `boot-plugin`, 
`grails-plugin`, `gson-templates`) applies `gradle/mongodb-test-config.gradle`, 
which runs serially (`maxParallelForks = 1`). Check which file a subproject 
applies before changing its parallelism.
+- `-PskipMongodbTests` / `-PonlyMongodbTests` gate these tests at the root, 
matching the `Container missing` row in root `AGENTS.md`'s Common Issues table 
— use `-PskipMongodbTests` when Docker isn't available.
+
+## Change Workflow
+
+1. Identify which layer owns the behavior: mapping 
(`MongoMappingContext`/`MongoCollection`/`MongoAttribute`) vs. codec/runtime 
(`BsonPersistentEntityCodec`/`PersistentEntityCodec`) vs. datastore-level 
(`MongoDatastore`, index/transaction handling).
+2. Check whether the change affects the general `bson/` codec machinery (used 
by any BSON-backed consumer) or is genuinely Mongo-specific (`core/`) — don't 
put Mongo-only logic in `bson/`.
+3. Update or add specs via `GrailsDataTckSpec<GrailsDataMongoTckManager>`, 
registering any new domain classes as top-level classes in the same spec file.
+4. Run the affected subproject's tests with Docker/Podman running; expect 
`core` tests to run serially.
+
+## Pitfalls to Avoid
+
+- Do not treat `shard "name"` as a functioning DSL keyword — it's a documented 
no-op (see above). Don't build new features assuming it works, and flag it if 
you're asked to "fix" sharding — the DSL surface exists but the implementation 
doesn't.
+- Do not change a subproject's test parallelism without reading the test 
config file it applies; the serial ones share one container.
+- TTL index changes go through `collMod`, not drop/rebuild — a single-field 
`expireAfterSeconds` change should reconcile in place. MongoDB silently ignores 
the TTL option on a compound index; don't declare one there.
+- The global `stringIds.defaultStoredAs` setting must be read by 
`MongoMappingContext` **before** `initialize(classes)` runs (`createIdentity` 
is invoked during entity registration and depends on it) — if you touch 
mapping-context initialization order, this dependency is easy to break silently.
+- Known unaddressed gaps (real `// TODO`s in the encode/decode path, not 
exhaustive but worth checking before assuming behavior): unprocessed 
`OneToMany` associations in `encodeUpdate` (`PersistentEntityCodec.groovy`), 
`Map` handling in the embedded-collection update path, and embedded-collection 
support in the base `BsonPersistentEntityCodec.encodeUpdate` (only the Mongo 
subclass handles it).
+
+## Known Status and Constraints
+
+- Multi-document transactions require positive cluster-topology detection 
(`REPLICA_SET`/`SHARDED`/`LOAD_BALANCED`); a `STANDALONE` cluster falls back to 
legacy client-side flush behavior with a one-time warning, not a hard failure.
+- `MongoDbGormAutoConfiguration` only closes a `MongoClient` it created 
itself, not one supplied as an external bean — preserve that ownership tracking 
if you touch auto-configuration shutdown logic.

Review Comment:
   Nit on where the ownership lives: the tracking is 
`MongoDatastore.ownsClient()` (line 2694; `close()` at line 2701 consults it). 
The auto-configuration's part is the pair of nested configurations, 
`ApplicationClientConfiguration` (`@ConditionalOnBean(MongoClient)`, the 
application's client is used as is) and `GormClientConfiguration` 
(`@ConditionalOnMissingBean`, whose `mongo` bean is declared with 
`destroyMethod = ''` so Spring does not close the datastore's client a second 
time). Saying that points an agent at the right class.



##########
grails-gradle/AGENTS.md:
##########
@@ -0,0 +1,55 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for grails-gradle
+
+> **IMPORTANT**: `grails-gradle` holds the Grails Gradle plugins that 
applications apply. It has its own
+> `settings.gradle` and its own CI jobs, but it shares the root's dependency 
management: `build.gradle` applies the
+> root's `dependencies.gradle`, so versions are managed there. It is build 
tooling, not Grails application code, so
+> two of the root rules do not apply here (see below). Root 
[`AGENTS.md`](../AGENTS.md) still governs PR, branch and
+> review conventions and repository-wide policy.
+
+## Quick Reference
+
+Run from inside `grails-gradle/`:
+
+```bash
+./gradlew build --continue
+./gradlew build -PskipTests -PskipCodeStyle
+./gradlew validateDependencyVersions --continue
+```
+
+## Rules That Differ From Root
+
+1. **Use plain `@CompileStatic`, not `@GrailsCompileStatic`.** The plugins are 
Gradle code, not Grails artefacts; the only `@GrailsCompileStatic` mentions in 
this build are documentation of what a plugin configures for an application.
+2. **`javax.inject.Inject` and `javax.xml.*` are correct here.** They are 
JSR-330 and JDK APIs, not Jakarta EE packages. The `jakarta.*` references in 
this build configure a downstream application's dependencies.
+3. **Versions are not pinned here.** `gradle.properties` holds daemon and 
cache settings only; `build.gradle` applies the root's `dependencies.gradle`. 
Bump versions in the root file.
+4. **Tests are Gradle TestKit tests.** Plugin specs extend 
`GradleSpecification` 
(`plugins/src/test/groovy/org/grails/gradle/plugin/core/GradleSpecification.groovy`)
 and run a real Gradle build against a generated project, not a mocked Grails 
application.
+
+## Project Structure
+
+| Directory | Gradle project | Role |
+|---|---|---|
+| `bom/` | `:grails-gradle-bom` | A `java-platform` constraining the sibling 
projects |
+| `common/` | `:grails-gradle-common` | Shared utilities |
+| `model/` | `:grails-gradle-model` | The subset of Grails runtime classes the 
plugins need at build time, before the framework is on the classpath |
+| `plugins/` | `:grails-gradle-plugins` | The `Plugin<Project>` 
implementations |
+| `tasks/` | `:grails-gradle-tasks` | The task classes |
+
+## CI
+
+The build-health, code-style, code-analysis, coverage and release workflows 
under `.github/workflows` each have a job

Review Comment:
   The list leaves out `gradle.yml`, which is where this build is actually 
built and tested: the `buildGradle` job runs `./gradlew build` in 
`grails-gradle` on JDK 21 and 25, with `--rerun-tasks` when the policy enables 
tests and `-PskipTests` otherwise (line 144 onward); `validateDependencies` 
runs `validateDependencyVersions` in `grails-gradle` (line 82) and 
`validateBomProperties` has a step there too (line 114); `publishGradle` 
publishes it (line 982). `end-to-end.yml` consumes it as an included build. 
Please put `gradle.yml` first, since it is the one an agent should look at when 
a plugin change breaks.



##########
grails-gradle/AGENTS.md:
##########
@@ -0,0 +1,55 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for grails-gradle
+
+> **IMPORTANT**: `grails-gradle` holds the Grails Gradle plugins that 
applications apply. It has its own
+> `settings.gradle` and its own CI jobs, but it shares the root's dependency 
management: `build.gradle` applies the
+> root's `dependencies.gradle`, so versions are managed there. It is build 
tooling, not Grails application code, so
+> two of the root rules do not apply here (see below). Root 
[`AGENTS.md`](../AGENTS.md) still governs PR, branch and
+> review conventions and repository-wide policy.
+
+## Quick Reference
+
+Run from inside `grails-gradle/`:
+
+```bash
+./gradlew build --continue
+./gradlew build -PskipTests -PskipCodeStyle
+./gradlew validateDependencyVersions --continue
+```
+
+## Rules That Differ From Root
+
+1. **Use plain `@CompileStatic`, not `@GrailsCompileStatic`.** The plugins are 
Gradle code, not Grails artefacts; the only `@GrailsCompileStatic` mentions in 
this build are documentation of what a plugin configures for an application.
+2. **`javax.inject.Inject` and `javax.xml.*` are correct here.** They are 
JSR-330 and JDK APIs, not Jakarta EE packages. The `jakarta.*` references in 
this build configure a downstream application's dependencies.
+3. **Versions are not pinned here.** `gradle.properties` holds daemon and 
cache settings only; `build.gradle` applies the root's `dependencies.gradle`. 
Bump versions in the root file.
+4. **Tests are Gradle TestKit tests.** Plugin specs extend 
`GradleSpecification` 
(`plugins/src/test/groovy/org/grails/gradle/plugin/core/GradleSpecification.groovy`)
 and run a real Gradle build against a generated project, not a mocked Grails 
application.

Review Comment:
   "Tests are Gradle TestKit tests" overstates it: 23 specs extend 
`GradleSpecification`, while 38 extend plain `Specification` (27 in `plugins`, 
9 in `model`, 2 in `common`). Suggest: the specs that need a real build extend 
`GradleSpecification` and run a generated project under TestKit; the rest are 
ordinary Spock unit specs.



##########
build-logic/AGENTS.md:
##########
@@ -0,0 +1,56 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Agent Guide for build-logic
+
+> **IMPORTANT**: `build-logic` is the Gradle convention-plugin layer that the 
root build, `grails-gradle` and
+> `grails-forge` consume through `includeBuild`. It is build tooling, not 
Grails application code, so two of the
+> root rules do not apply here (see below). Root [`AGENTS.md`](../AGENTS.md) 
still governs PR, branch and review
+> conventions and repository-wide policy.
+
+## Quick Reference
+
+Run from inside `build-logic/`:
+
+```bash
+./gradlew build                     # all three projects
+./gradlew :build-logic:test         # the convention plugins (Spock and 
TestKit specs)
+./gradlew :grails-docs-core:test    # the documentation engine
+```
+
+## Rules That Differ From Root
+
+1. **Use plain `@CompileStatic`, not `@GrailsCompileStatic`.** Nothing here is 
a Grails artefact; no source under this directory uses `@GrailsCompileStatic`.
+2. **`javax.inject.Inject` is correct here.** Gradle's constructor injection 
uses JSR-330's `javax.inject`, which is unrelated to the Jakarta EE migration. 
Do not change it to `jakarta.*`.
+3. **Versions are not pinned here.** `plugins/build.gradle` and 
`docs-core/build.gradle` apply the root's `dependencies.gradle`; do not 
hardcode a version in this build.
+4. **There is no dedicated CI job for this build.** Every other build includes 
it and exercises the plugins through its own CI runs, so a missing job is not a 
sign of neglect.

Review Comment:
   This is wrong. `gradle.yml` has a `buildLogic` job ("Build and test the 
build logic") that runs `./gradlew check --continue` with `working-directory: 
'build-logic'` whenever the policy enables tests (line 191 onward), and the 
`build` matrix runs `:build-logic-root:vulnerability-scan:check` through the 
root build on every entry (line 298). `build-health.yml` runs 
`:build-logic-root:buildHealth` as well (line 64). An agent told there is no 
job would either add a duplicate or ignore a failing one. Please replace the 
rule with those three.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to