AGENTS.md
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/AGENTS.mdAGENTS.md
Quality
100/100
Scores the file, not the repository.Length
1,045 words
13 headings · 2 code blocksRepository
78k
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.1# ML contracts library (xpack-core/ml)23Guidance for coding agents working in the `org.elasticsearch.xpack.core.ml` package inside xpack-core. It holds the *contracts* (serializable config/state POJOs, transport action definitions, registries, cluster-state metadata, versioning), **not** runtime logic. The execution side (transport handlers, REST handlers, persistent-task executors, native processes) lives in `x-pack/plugin/ml` (see its own `AGENTS.md`). The repository-root `AGENTS.md` is authoritative for toolchain, formatting, logging, and transport-version rules — this file does not repeat them.45## Build & Test67This code is **not its own Gradle project** — it compiles and tests under `:x-pack:plugin:core` (esplugin `x-pack-core`). Run from the repository root.89```bash10# Unit tests for the whole core project (ML tests live under .../core/ml/)11./gradlew :x-pack:plugin:core:test1213# Single test class / method14./gradlew :x-pack:plugin:core:test --tests org.elasticsearch.xpack.core.ml.job.config.JobTests15./gradlew :x-pack:plugin:core:test --tests org.elasticsearch.xpack.core.ml.job.config.JobTests.testMethodName1617# Format / forbidden-API / style gate (run before claiming Java work done)18./gradlew :x-pack:plugin:core:spotlessApply19./gradlew :x-pack:plugin:core:precommit20```2122`x-pack-core` applies `internal-test-artifact`, so the ML plugin and other consumers reuse these test base classes and helpers via `testArtifact(xpackModule('core'))`. Changing a shared test base class here affects downstream test compilation.2324## What lives here vs. the ML plugin2526| Here (`core/ml`) | In `x-pack/plugin/ml` |27|---|---|28| `ActionType` definitions + nested `Request`/`Response` | `Transport*Action` handlers, `Rest*Action` handlers |29| Config/state POJOs (`Job`, `DatafeedConfig`, `DataFrameAnalyticsConfig`, `TrainedModelConfig`, state enums) | Managers, indexers, persistent-task executors, native process I/O |30| Registries, `MlMetadata`, `MlTasks`, system-index defs | Business logic that reads/writes them |3132Adding an API typically means: define the `ActionType` + `Request`/`Response` (and any config POJO) **here**, then implement the `Transport*Action` and `Rest*Action` in the plugin.3334## Serialization & registry mechanics3536Every contract type implements both `Writeable` (wire) and `ToXContent` (JSON), and ships a matching round-trip test (see Testing).3738**Action class pattern** (e.g. `action/PutJobAction.java`, `action/GetJobsStatsAction.java`):3940```java41public class FooAction extends ActionType<FooAction.Response> {42 public static final FooAction INSTANCE = new FooAction();43 public static final String NAME = "cluster:.../foo"; // scope-encoded name44 private FooAction() { super(NAME); }45 public static class Request extends ... { /* StreamInput ctor, writeTo, toXContent, validate, equals/hashCode */ }46 public static class Response extends ... { /* same contract */ }47}48```4950**Polymorphic types are registered in NamedXContent providers**, not ad hoc. When you add a new inference config, tokenization, data-frame analysis, evaluation metric, or inference result subtype, register it (NamedWriteable + NamedXContent) in the matching provider, or it will not deserialize:5152- `inference/MlInferenceNamedXContentProvider` — inference configs, preprocessors, trained-model/tokenization types, results53- `dataframe/analyses/MlDataFrameAnalysisNamedXContentProvider` — Classification / Regression / OutlierDetection54- `dataframe/evaluation/MlEvaluationNamedXContentProvider` — evaluation metrics55- `ltr/MlLTRNamedXContentProvider` — learning-to-rank configs5657## Parser duality (strict vs. lenient)5859Most configs expose two `ObjectParser`s, and picking the wrong one is a recurring bug source:6061- **`LENIENT_PARSER`** — used when reading **persisted documents or cluster state**. Ignores unknown fields (forward-compat) and parses internal/generated fields (`create_time`, version).62- **`STRICT_PARSER` / `REST_REQUEST_PARSER`** — used for **REST API input**. Rejects unknown fields (catches client typos) and excludes internal fields (clients cannot set them).6364Configs are immutable with a nested `Builder`; validation runs at `build()` time and throws `ActionRequestValidationException` / `ElasticsearchException`.6566## Versioning & backwards compatibility6768`MlConfigVersion` is a **config-format version, distinct from `TransportVersion`**: it is human-readable and persisted inside documents and cluster state, so it tracks the schema of stored ML configs rather than the wire protocol. Post-8.10 it uses detached incrementing integer ids (the latest is `MlConfigVersion.CURRENT`), and each constant carries a unique id string to avoid duplicate-id git merge collisions; `MlConfigVersionComponent` surfaces it in node info.6970For wire-format changes across mixed-version clusters, follow the root `AGENTS.md` "Backwards compatibility" section — do not restate that workflow here. Any change to a `Writeable`'s `writeTo`/`StreamInput` constructor needs a new named `TransportVersion` gate and a BWC round-trip test. Referable transport-version ids are global (`server/src/main/resources/transport/definitions/referable/*.csv`); after merging `main`, re-check the highest allocated id before keeping a pre-merge id on your branch (`./gradlew :server:generateClusterFeaturesMetadata` fails fast on a duplicate id at class-init).7172## Cluster-state, tasks, system indices7374- `MlMetadata` — `Metadata.ProjectCustom` cluster-state custom; holds `upgradeMode` and `resetMode` flags (parsed leniently for forward-compat).75- `MlTasks` — persistent-task name constants (`xpack/ml/job`, `xpack/ml/datafeed`, `xpack/ml/data_frame/analytics`, …), task-id prefix helpers, and task matchers/assignment constants.76- System indices: `MlConfigIndex` (`.ml-config`), `MlMetaIndex` (`.ml-meta`), `MlStatsIndex` (`.ml-stats-*` with the `.ml-stats-write` rollover alias). Bumping mappings means bumping the index mappings version.7778## Domain-model map (`core/ml/<subpackage>/`)7980- `job/` — anomaly-detection `Job`, `AnalysisConfig`, `Detector`, `DataDescription`, model-snapshot & state types.81- `datafeed/` — `DatafeedConfig`/`DatafeedUpdate`, chunking, delayed-data, cross-project routing, state.82- `dataframe/` — `DataFrameAnalyticsConfig`, source/dest; `analyses/` (Classification/Regression/OutlierDetection), `evaluation/` (metrics), `stats/`.83- `inference/` — `TrainedModelConfig`, model definitions; `trainedmodel/` (per-task InferenceConfig + tokenizations + ensemble/tree), `results/` (inference result types), `preprocessing/`.84- `calendars/` — `Calendar` + `ScheduledEvent` (maintenance windows that suppress anomalies).85- `annotations/` — `Annotation` + its system index definition.86- `autoscaling/` — ML node autoscaling policy/decision contracts.87- `ltr/` — learning-to-rank config contracts.88- `process/` — native-process result contracts (`DataCounts`, `ModelSizeStats`, `TimingStats`).89- `stats/` — aggregated usage stats (e.g. `ForecastStats`).90- `notifications/` — audit-message contracts.91- `packageloader/` — packaged-model (e.g. ELSER) loader contracts.92- `vectors/` — dense-vector/embedding metadata.93- `utils/` — shared validation/serialization helpers (`ExceptionsHelper`, `ToXContentParams`, `NamedXContentObjectHelper`, `RuntimeMappingsValidator`).9495Top-level: `MachineLearningField` (ML settings/constants, `machine-learning` feature family, PLATINUM license), `MachineLearningFeatureSetUsage`.9697## Gotchas9899- **Pick the right parser.** Use `STRICT_PARSER`/`REST_REQUEST_PARSER` for API input and `LENIENT_PARSER` for persisted docs / cluster state. The wrong one either rejects valid stored data or lets clients set internal fields.100- **Register new polymorphic subtypes.** A new inference config, tokenization, data-frame analysis, evaluation metric, or result type must be added to the matching `Ml*NamedXContentProvider` (NamedWriteable + NamedXContent) or it will not deserialize.101- **Gate wire changes.** Any change to a `Writeable`'s `writeTo`/`StreamInput` constructor needs a new named `TransportVersion` gate **and** a BWC round-trip test (`AbstractBWC*SerializationTestCase`). Follow the root `AGENTS.md` "Backwards compatibility" workflow.102- **`MlConfigVersion` ≠ `TransportVersion`.** They version different things (stored config schema vs. wire protocol); don't substitute one for the other, and don't reuse a version constant's unique id string.103104## Testing conventions105106ML contracts are tested almost entirely with serialization round-trip bases — pick by what you're verifying:107108- `AbstractXContentSerializingTestCase` — JSON/XContent round-trip (most common).109- `AbstractWireSerializingTestCase` — wire (`Writeable`) round-trip.110- `AbstractBWCSerializationTestCase` / `AbstractBWCWireSerializationTestCase` — backwards-compat across versions; use these when a type's wire/XContent format changed under a version gate.111- ML-local helpers: `org.elasticsearch.xpack.core.ml.AbstractBWCWireSerializationTestCase`, `AbstractChunkedBWCSerializationTestCase`.112113Every new serialized contract type (or new field on one) needs a round-trip test; format changes need the BWC variant. Tests live under `x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ml/`, mirroring the main-source subpackages.114
Also in elastic/elasticsearch
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| elastic/elasticsearchAGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+6 | 96/100 | 3 days ago | |
| elastic/elasticsearchbenchmarks/AGENTS.md · 78k | AGENTS.md | test | 54/100 | 3 days ago | |
| elastic/elasticsearchlibs/columnar/AGENTS.md · 78k | AGENTS.md | builddo-notagent-behaviour | 67/100 | 3 days ago | |
| elastic/elasticsearchx-pack/plugin/esql/compute/AGENTS.md · 78k | AGENTS.md | no sections | 25/100 | 3 days ago | |
| elastic/elasticsearchx-pack/plugin/inference/AGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+3 | 100/100 | 3 days ago |
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| SkeneTechnologies/skene-cookbookAGENTS.md · 51 | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 2 days ago | |
| code-yeongyu/oh-my-openagentpackages/web/AGENTS.md · 67k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 2 days ago | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | 3 days ago | |
| elastic/elasticsearchx-pack/plugin/inference/AGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+3 | 100/100 | 3 days ago | |
| bagisto/bagistoAGENTS.md · 28k | AGENTS.md | setupbuildteststyle+7 | 100/100 | 3 days ago |
