This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit e5e2c9384fa29311af30924cc7137f877f17af0d
Merge: b7a1affcec ceb0404b88
Author: Stephen Mallette <[email protected]>
AuthorDate: Wed Jul 29 15:15:09 2026 -0400

    Merge branch '3.8-dev'

 bin/process-docs.sh                                |  64 ++-
 bin/publish-docs.sh                                |  32 ++
 bin/validate-llms-txt.sh                           | 177 +++++++
 docs/src/dev/developer/contributing.asciidoc       |   4 +
 .../dev/developer/development-environment.asciidoc |  70 ++-
 docs/src/dev/developer/for-committers.asciidoc     |   2 +
 docs/src/dev/developer/index.asciidoc              |   1 +
 docs/src/dev/developer/release.asciidoc            |   1 +
 docs/src/dev/future/index.asciidoc                 |   1 +
 docs/src/dev/io/index.asciidoc                     |   1 +
 docs/src/dev/provider/gremlin-semantics.asciidoc   |  36 ++
 docs/src/dev/provider/index.asciidoc               |   6 +
 docs/src/docinfo-footer.html                       |  19 +
 docs/src/recipes/between-vertices.asciidoc         |   1 +
 docs/src/recipes/centrality.asciidoc               |   1 +
 docs/src/recipes/collections.asciidoc              |   1 +
 docs/src/recipes/connected-components.asciidoc     |   1 +
 docs/src/recipes/cycle-detection.asciidoc          |   1 +
 docs/src/recipes/duplicate-edge.asciidoc           |   1 +
 docs/src/recipes/duplicate-vertex.asciidoc         |   1 +
 docs/src/recipes/edge-move.asciidoc                |   1 +
 docs/src/recipes/element-existence.asciidoc        |   1 +
 docs/src/recipes/if-then-based-grouping.asciidoc   |   1 +
 docs/src/recipes/index.asciidoc                    |   3 +
 docs/src/recipes/looping.asciidoc                  |   1 +
 docs/src/recipes/olap-spark-yarn.asciidoc          |   1 +
 .../recipes/operating-on-dropped-elements.asciidoc |   1 +
 docs/src/recipes/pagination.asciidoc               |   1 +
 docs/src/recipes/recommendation.asciidoc           |   1 +
 docs/src/recipes/shortest-path.asciidoc            |   1 +
 docs/src/recipes/traversal-induced-values.asciidoc |   1 +
 docs/src/recipes/tree.asciidoc                     |   1 +
 docs/src/reference/gremlin-applications.asciidoc   |   6 +
 docs/src/reference/gremlin-variants.asciidoc       |   7 +
 .../implementations-hadoop-start.asciidoc          |   1 +
 docs/src/reference/implementations-intro.asciidoc  |   1 +
 docs/src/reference/intro.asciidoc                  |   1 +
 docs/src/reference/preface.asciidoc                |   1 +
 docs/src/reference/the-graph.asciidoc              |   1 +
 docs/src/reference/the-graphcomputer.asciidoc      |   1 +
 docs/src/reference/the-traversal.asciidoc          | 130 +++++
 docs/src/tutorials/getting-started/index.asciidoc  |   1 +
 .../gremlin-language-variants/index.asciidoc       |   3 +
 docs/src/tutorials/gremlins-anatomy/index.asciidoc |   1 +
 .../tutorials/the-gremlin-console/index.asciidoc   |   1 +
 docs/src/upgrade/index.asciidoc                    |   1 +
 docs/src/upgrade/release-3.0.x-incubating.asciidoc |   1 +
 docs/src/upgrade/release-3.1.x-incubating.asciidoc |   1 +
 docs/src/upgrade/release-3.2.x-incubating.asciidoc |   3 +
 docs/src/upgrade/release-3.3.x.asciidoc            |   2 +
 docs/src/upgrade/release-3.4.x.asciidoc            |   2 +
 docs/src/upgrade/release-3.5.x.asciidoc            |   3 +
 docs/src/upgrade/release-3.6.x.asciidoc            |   1 +
 docs/src/upgrade/release-3.7.x.asciidoc            |   2 +
 docs/tinkeradoc-extension/README.md                |  14 +
 .../tinkeradoc/GremlinDocsConverterRegistry.java   |  36 ++
 .../tinkeradoc/GremlinExecutionCache.java          |  94 ++++
 .../tinkerpop/tinkeradoc/GremlinHighlighter.java   | 117 +++++
 .../tinkerpop/tinkeradoc/GremlinPostprocessor.java |  37 +-
 .../tinkerpop/tinkeradoc/GremlinTreeprocessor.java | 213 +++++----
 .../tinkerpop/tinkeradoc/HtmlTabRenderer.java      |  67 +++
 .../tinkerpop/tinkeradoc/LlmsTxtGenerator.java     | 288 ++++++++++++
 .../tinkerpop/tinkeradoc/MarkdownConverter.java    | 501 ++++++++++++++++++++
 .../tinkerpop/tinkeradoc/MarkdownSplitter.java     | 521 +++++++++++++++++++++
 .../tinkerpop/tinkeradoc/MarkdownTabRenderer.java  | 103 ++++
 .../apache/tinkerpop/tinkeradoc/NeutralTab.java    |  84 ++++
 .../tinkerpop/tinkeradoc/NeutralTabCodec.java      | 221 +++++++++
 ...ciidoctor.jruby.converter.spi.ConverterRegistry |   1 +
 .../tinkeradoc/DualBackendIntegrationTest.java     | 118 +++++
 .../tinkeradoc/GremlinExecutionCacheTest.java      | 124 +++++
 .../tinkeradoc/GremlinHighlighterTest.java         |  72 +++
 .../tinkerpop/tinkeradoc/HtmlTabRendererTest.java  | 104 ++++
 .../tinkerpop/tinkeradoc/LlmsTxtGeneratorTest.java | 137 ++++++
 .../tinkeradoc/MarkdownConverterProbeTest.java     | 241 ++++++++++
 .../tinkerpop/tinkeradoc/MarkdownSplitterTest.java | 227 +++++++++
 .../tinkeradoc/MarkdownTabRendererTest.java        | 113 +++++
 .../tinkerpop/tinkeradoc/NeutralTabCodecTest.java  | 113 +++++
 .../tinkeradoc/PostprocessorBackendTest.java       |  79 ++++
 pom.xml                                            | 275 +++++++++++
 79 files changed, 4383 insertions(+), 123 deletions(-)

diff --cc docs/src/dev/developer/development-environment.asciidoc
index f8625eec8f,4f14941012..f7c9acd30c
--- a/docs/src/dev/developer/development-environment.asciidoc
+++ b/docs/src/dev/developer/development-environment.asciidoc
@@@ -125,12 -129,22 +126,22 @@@ The core of the documentation generatio
  Gremlin Console subprocess, and renders the console output as tabbed HTML. 
The orchestration script
  `bin/process-docs.sh` wraps this and acts as the entrypoint: it validates the 
Gremlin Console and Gremlin Server
  distributions, installs the required plugins into the console, starts a 
Gremlin Server (for the `:remote` examples) and
 -a Gephi mock, then invokes Maven to run the extension. Javadocs should be 
built using Java 11.
 +a Gephi mock, then invokes Maven to run the extension. Javadocs should be 
built using Java 17.
  
- Before generating documentation, build all the dependencies that the process 
consumes:
+ The `docs/tinkeradoc-extension` project is a standalone Maven project rather 
than a module of the root reactor, so a
+ `mvn clean install` from the project root does not build it. It must be built 
and installed into the local repository
+ before generating documentation -- both because the 
`asciidoctor-maven-plugin` consumes it as a plugin dependency and
+ because `bin/process-docs.sh` runs its compiled classes to produce the 
Markdown mirror and `llms.txt` (see
+ <<agent-friendly-documentation>>). If the extension has not been built, the 
Markdown and `llms.txt` step is silently
+ skipped with a `skipping Markdown split` warning. Build it with:
+ 
+ [source,text]
+ mvn clean install -f docs/tinkeradoc-extension/pom.xml
+ 
+ Next, build all of the dependencies that the documentation process consumes:
  
  [source,text]
 -mvn clean install -pl 
:gremlin-console,:gremlin-server:spark-gremlin,:neo4j-gremlin -am -DskipTests 
-DincludeNeo4j
 +mvn clean install -pl :gremlin-console,:gremlin-server,:spark-gremlin -am 
-DskipTests
  
  Documentation can then be generated locally with:
  
@@@ -393,39 -473,48 +455,39 @@@ be done automatically on `mvn deploy` o
  == Using AI Coding Agents
  
  TinkerPop does not endorse or require any particular AI Coding Agents or 
tool. As a result, tool-specific project
 -guidelines are not included with the code base. TinkerPop does, however, 
provide for a generic, agent-agnostic `AGENTS.md`
 -file at the root of the project. Developers should make use of this file's 
instructions by pointing their specific
 -AI-based tool to it. While tools may vary in how they are set up, the 
approach is to treat tool-specific files, such as
 -`.junie/guidelines.md`, `.claude/CLAUDE.md` etc., as thin shims that just 
point to TinkerPop's `AGENTS.md` instead of
 -relying on individual rules. The content of those tool-specific files should:
 -
 -* Explain that AGENTS.md is the canonical source.
 -* Tell the assistant to read and follow it, and not to diverge from it.
 -* Optionally include one or two tool‑specific behaviors (like “prefer smaller 
edits”) if you want.
 +guidelines are not included with the code base. In general, TinkerPop 
attempts to stay agnostic to coding agents
- while also supporting 
++while also supporting
  
 -The following is a basic example of such a setup:
 +=== Agent Skills
  
 -[source,text]
 -----
 -# Apache TinkerPop – Guidelines
 +TinkerPop provides development guidance as an 
link:https://agentskills.io[Agent Skill] in `.skills/tinker-dev/`.
 +The skill follows the open Agent Skills standard and includes:
  
 -This project uses `AGENTS.md` in the repository root as the canonical guide 
for AI/IDE assistants and automated tools.
 +* Project conventions, coding standards, and agent guardrails (in `SKILL.md`)
 +* Build and test recipes for each Gremlin Language Variant (in `references/`)
 +* Development environment setup instructions and a verification script (in 
`scripts/`)
 +* Gremlin MCP server usage guidance for query translation, formatting, and 
graph querying
  
 -You should:
 +Tools that support Agent Skills (Claude Code, GitHub Copilot, Cursor, OpenAI 
Codex, JetBrains Junie, Kiro, and others)
 +will discover and activate the skill automatically when it is placed in the 
tool's expected directory. A setup script
 +is provided to create the necessary symlinks or copies:
  
 -1. Read and follow the instructions in `AGENTS.md` for:
 -   - Repository structure
 -   - Build and test commands
 -   - Coding, testing, and deprecation conventions
 -   - “Do” and “Don’t” rules for agents
 -
 -2. Treat `AGENTS.md`, `CONTRIBUTING.*`, and the developer docs under 
`docs/src/dev/**` as higher priority than any generic or built‑in behavior.
 -
 -3. Prefer small, focused edits that:
 -   - Match the existing code style and patterns in the files being changed
 -   - Include or update tests when behavior changes
 -   - Update documentation and `CHANGELOG.asciidoc` when public behavior or 
APIs change
 -
 -You must **not**:
 +[source,bash]
 +----
 +# Set up for a specific tool
 +bin/agent-setup.sh claude
 +bin/agent-setup.sh kiro
  
 -- Introduce new dependencies, modules, or large refactors without an explicit 
human request
 -- Change public APIs, protocols, or configuration formats without a clearly 
documented issue and human approval
 -- Rewrite AsciiDoc documentation into other formats
 +# Set up for all supported tools
 +bin/agent-setup.sh --all
  
 -If you are uncertain how to proceed based on this file, `AGENTS.md`, or the 
local AsciiDoc documentation, you should stop and ask for clarification instead 
of guessing.
 +# List supported tools and their discovery paths
 +bin/agent-setup.sh --list
  ----
  
 +The script supports: `claude`, `copilot`, `cursor`, `codex`, `junie`, and 
`kiro`. The generated symlinks and copies
 +are gitignored and local to each developer's environment.
 +
  [[building-testing]]
  == Building and Testing
  
diff --cc docs/src/dev/provider/gremlin-semantics.asciidoc
index 86ff317f30,bced422437..f5b58d847e
--- a/docs/src/dev/provider/gremlin-semantics.asciidoc
+++ b/docs/src/dev/provider/gremlin-semantics.asciidoc
@@@ -598,82 -589,7 +600,83 @@@ See: link:https://github.com/apache/tin
  
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AddVertexStartStep.java[source
 (start)],
  
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#addvertex-step[reference]
  
 +=== addLabel()
 +
 +*Description:* Adds one or more labels to an element.
 +
 +*Syntax:* `addLabel(label: STRING, moreLabels: STRING...)` | 
`addLabel(labelTraversal: Traversal<any, STRING>, moreLabelTraversals: 
Traversal<any, STRING>...)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`Element` |`Element`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `label` - The label to add.
 +* `moreLabels` - Additional labels to add.
 +* `labelTraversal` - The first (or only) traversal that produces a label to 
add.
 +* `moreLabelTraversals` - Additional label-producing traversals (may be empty 
for single-traversal behavior).
 +
 +*Considerations:*
 +
 +Label add and remove operations require a graph that permits the set of 
labels on an element to change. Where a graph
 +fixes a single immutable label per vertex, that label is assigned at creation 
and can be neither added to nor removed.
 +Adding a label that already exists on the element is a no-op. The step 
returns the element (sideEffect semantics).
 +Each traversal argument is iterated for a single result only. If exactly one 
traversal is provided and it produces
 +a `LIST` or `SET` of `STRING`, the collection will be automatically unfolded 
into the set of labels added. If more
 +than one traversal is provided, each must resolve to a single `STRING` label.
 +
 +*Exceptions*
 +
 +* If the graph does not permit label modification, a `State Error` is raised.
 +* If any label argument is null or empty, an `Argument Error` is raised.
 +* If more than one traversal is provided and any of them produces a `LIST` or 
`SET`, an `Argument Error` is raised.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddLabelStep.java[source],
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#addlabel-step[reference]
 +
 +=== dropLabel()
 +
 +*Description:* Removes one or more specific labels from an element, or 
removes all labels.
 +
 +*Syntax:* `dropLabel(label: STRING, moreLabels: STRING...)` | 
`dropLabel(labelTraversal: Traversal<any, STRING>, moreLabelTraversals: 
Traversal<any, STRING>...)` | `dropLabels()`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`Element` |`Element`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `label` - The label to remove.
 +* `moreLabels` - Additional labels to remove.
 +* `labelTraversal` - The first (or only) traversal that produces a label to 
remove.
 +* `moreLabelTraversals` - Additional label-producing traversals (may be empty 
for single-traversal behavior).
 +
 +*Considerations:*
 +
 +Label add and remove operations require a graph that permits the set of 
labels on an element to change. Dropping a
 +label that does not exist on the element is a no-op. `dropLabels()` removes 
all labels and is only valid on a graph
 +that allows an element to carry no labels at all. The step returns the
 +element (sideEffect semantics).
 +Each traversal argument is iterated for a single result only. If exactly one 
traversal is provided and it produces
 +a `LIST` or `SET` of `STRING`, the collection will be automatically unfolded 
into the set of labels removed. If more
 +than one traversal is provided, each must resolve to a single `STRING` label.
 +
 +*Exceptions*
 +
 +* If the graph does not permit label modification, a `State Error` is raised.
 +* If `dropLabel()` or `dropLabels()` would leave the element with fewer 
labels than the graph requires, a `State Error`
 +is raised.
 +* If more than one traversal is provided and any of them produces a `LIST` or 
`SET`, an `Argument Error` is raised.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/DropLabelsStep.java[source],
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#droplabel-step[reference]
 +
+ [llms-summary="The formal semantics of the all() step: filters array data 
from the Traversal Stream if all of the array's items match the supplied 
predicate."]
  [[all-step]]
  === all()
  
@@@ -1671,27 -1540,13 +1686,31 @@@ Non
  
  None
  
 +*Considerations:*
 +
 +The `element()` step traverses from a `Property` to the `Element` that owns 
it. A `VertexProperty`
 +yields its `Vertex`, an edge `Property` yields its `Edge`, and a meta 
`Property` (a property on a
 +`VertexProperty`) yields the `VertexProperty`. The step is a pure navigation 
step and does not
 +consult the underlying graph.
 +
+ [llms-summary="The formal semantics of the format() step: a mid-traversal 
step which will handle result formatting to string values."]
+ [[format-step]]
+ === format()
+ 
 -*Description:* a mid-traversal step which will handle result formatting to 
string values.
 +*Exceptions:*
  
 -*Syntax:* `format(String formatString)`
 +None
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ElementStep.java[source],
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#element-step[reference]
 +
 +[[elementmap-step]]
 +=== elementMap()
 +
 +*Description:* Converts elements to a `Map` representation containing the 
element's `id`, `label`, and properties.
 +For an `Edge`, the map also includes the `IN` and `OUT` vertex structures 
(each a nested map of `id` and `label`).
 +
 +*Syntax:* `elementMap(String... propertyKeys)`
  
  [width="100%",options="header"]
  |=========================================================
@@@ -2029,283 -1774,21 +2048,287 @@@ Non
  
  *Considerations:*
  
 -Every element in the list (except `null`) is converted to a String. Null 
values are ignored. The delimiter is inserted
 -between neighboring elements to form the final result. This step only applies 
to list types which means that
 -non-iterable types (including `null`) will cause exceptions to be thrown.
 +* Equivalent to `has(T.label, ...)`.
 +* Child traversals must be read-only; mutating steps are rejected with an 
`Argument Error`.
  
 -*Exceptions*
 +The label test is applied to each label the element carries and the element 
is retained when at least one label
 +satisfies it. For single-label elements this is equivalent to testing the 
label directly. For multi-label vertices a
 +negation predicate therefore retains any vertex carrying at least one other 
label, so a vertex labelled both "person"
 +and "employee" satisfies `hasLabel(neq("person"))`. Excluding every element 
that carries a given label requires
 +`not(hasLabel("person"))`. The same rule makes `hasLabel("a", "b")` a 
disjunction, matching when either label is
 +present, while chained `hasLabel("a").hasLabel("b")` is a conjunction.
  
 -* If the incoming traverser isn't a list (array or Iterable) then an 
`IllegalArgumentException` will be thrown.
 -* If the argument doesn't resolve to a list (array or Iterable) then an 
`IllegalArgumentException` will be thrown.
 +*Exceptions:*
  
 -See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java[source],
 
-link:https://tinkerpop.apache.org/docs/x.y.z/reference/#conjoin-step[reference]
 +* An `Argument Error` is raised if a child traversal contains mutating steps.
  
 -[llms-summary="The formal semantics of the lTrim() step: returns a string 
with leading whitespace removed."]
 -[[lTrim-step]]
 -=== lTrim()
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference]
 +
 +[[hasvalue-step]]
 +=== hasValue()
 +
 +*Description:* Filters properties by their value.
 +
 +*Syntax:* `hasValue(value: any, otherValues: any...)` | `hasValue(predicate: 
P)` | `hasValue(traversal: Traversal)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`Property` / `VertexProperty` |`Property` / `VertexProperty`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `value` - One or more values to match against.
 +* `predicate` - A `P` predicate for value comparison. The predicate value may 
contain a `Traversal`.
 +* `traversal` - A child traversal whose first result is used as the value 
(implicitly wrapped in `P.eq()`).
 +  Must be read-only.
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +* Equivalent to `has(T.value, ...)`.
 +* Operates on `Property` or `VertexProperty` traversers (typically reached 
via `properties()`).
 +* Child traversals must be read-only; mutating steps are rejected with an 
`Argument Error`.
 +
 +*Exceptions:*
 +
 +* An `Argument Error` is raised if a child traversal contains mutating steps.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/HasStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#has-step[reference]
 +
 +[[label-step]]
 +=== label()
 +
 +*Description:* Maps an element to its label as a single string value.
 +
 +*Syntax:* `label()`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`Element` |`String`
 +|=========================================================
 +
 +*Considerations:*
 +
 +The `label()` step returns exactly one label string per element. For graphs 
that support multiple labels per vertex,
 +`label()` returns only one of the vertex's labels and the choice is 
non-deterministic (implementation-dependent
 +ordering). Use `labels()` to retrieve all labels reliably.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#label-step[reference]
 +
 +[[labels-step]]
 +=== labels()
 +
 +*Description:* Maps an element to its labels, emitting one traverser per 
label.
 +
 +*Syntax:* `labels()`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`Element` |`String`
 +|=========================================================
 +
 +*Considerations:*
 +
 +For vertices with a single label, `labels()` emits one traverser (equivalent 
to `label()`). For multi-label vertices,
 +it emits one traverser per label. For vertices that carry no labels, no 
traversers are emitted.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LabelsStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#labels-step[reference]
 +
++[llms-summary="The formal semantics of the length() step: returns the length 
of the incoming string or list, if Scope.local is specified, returns the length 
of each string elements inside incoming list traverser."]
 +[[length-step]]
 +=== length()
 +
 +*Description:* Returns the length of the incoming string or list, if 
`Scope.local` is specified, returns
 +the length of each string element inside incoming list traverser.
 +
 +*Syntax:* `length()` | `length(scope: Scope)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`STRING`/`LIST` |`INT`/`LIST`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `scope` - Determines the type of traverser it operates on. Both scopes will 
operate on the level of individual traversers.
 +The `global` scope will operate on individual string traverser. The `local` 
scope will operate on list traverser with string elements inside.
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +Null values from the incoming traverser are not processed and remain as null 
when returned.
 +
 +*Exceptions:*
 +
 +* For `Scope.global` or parameterless function calls, if the incoming 
traverser is a non-`STRING` value then an `Argument Error` is raised.
 +* For `Scope.local`, if the incoming traverser is not a string or a list of 
strings then an `Argument Error` is raised.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthGlobalStep.java[source],
 
+link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LengthLocalStep.java[source
 (local)],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#length-step[reference]
 +
 +[[local-step]]
 +=== local()
 +
 +*Description:* Executes the provided traversal in an object-local manner.
 +
 +*Syntax:* `local(localTraversal: Traversal)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`any` |`any`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `localTraversal` - The traversal that processes each single-object 
traverser individually.
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +The `local()` step enforces object-local execution. As a branching step with 
local children, it implements strict lazy
 +evaluation by passing a single traverser at a time to the local traversal 
(bulk of exactly one, if bulking is supported)
 +and resetting the traversal to clean state between executions.
 +
 +*Exceptions:*
 +
 +None
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LocalStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#local-step[reference]
 +
++[llms-summary="The formal semantics of the intersect() step: adds the 
intersection to the Traversal Stream."]
 +[[intersect-step]]
 +=== intersect()
 +
 +*Description:* Adds the intersection to the Traversal Stream.
 +
 +*Syntax:* `intersect(values: any)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`LIST` |`SET`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `values` - A list of items or a `Traversal` that will produce a list of 
items.
 +
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +A set is returned after the intersect operation is applied so there won't be 
duplicates. This step only applies to list
 +types which means that non-iterable types (including null) will cause 
exceptions to be thrown.
 +
 +*Exceptions:*
 +
 +* If the incoming traverser isn't a list then an `Argument Error` is raised.
 +* If the argument doesn't resolve to a list then an `Argument Error` is 
raised.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/IntersectStep.java[source],
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#intersect-step[reference]
 +
 +[[is-step]]
 +=== is()
 +
 +*Description:* Filters scalar values by testing them against a predicate or 
value.
 +
 +*Syntax:* `is(value: any)` | `is(predicate: P)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`any` |`any`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `value` - A literal value or a `Traversal` to test equality against. 
`value` is implicitly wrapped
 +  in `P.eq(value)`.
 +* `predicate` - A `P` predicate for comparison. The predicate value may be a 
literal or a `Traversal`.
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +* When a `Traversal` is supplied as a value or inside a `P`, it is resolved 
per-traverser: the current traverser seeds
 +  the child traversal and its first result is used for comparison.
 +* If the child traversal produces no result, the comparison is aborted and 
the traverser is filtered out.
 +* Child traversals must be read-only; mutating steps are rejected with an 
`Argument Error`.
 +* Type mismatches during comparison (e.g., comparing a number to a string) 
result in the traverser being filtered.
 +
 +*Exceptions:*
 +
 +* An `Argument Error` is raised if a child traversal contains mutating steps.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/IsStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#is-step[reference]
 +
++[llms-summary="The formal semantics of the conjoin() step: joins every 
element in a list together into a String."]
 +[[conjoin-step]]
 +=== conjoin()
 +
 +*Description:* Joins every element in a list together into a String. 
 +
 +*Syntax:* `conjoin(delimiter: STRING)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`LIST` |`STRING`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `delimiter` - A delimiter to use to join the elements together. Can't be 
null.
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +Every element in the list (except `null`) is converted to a String. Null 
values are ignored. The delimiter is inserted
 +between neighboring elements to form the final result. This step only applies 
to list types which means that
 +non-iterable types (including `null`) will cause exceptions to be thrown.
 +
 +*Exceptions:*
 +
 +* If the incoming traverser isn't a list then an `Argument Error` is raised.
 +* If the argument doesn't resolve to a list then an `Argument Error` is 
raised.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ConjoinStep.java[source],
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#conjoin-step[reference]
 +
++[llms-summary="The formal semantics of the lTrim() step: returns a string 
with leading whitespace removed."]
 +[[lTrim-step]]
 +=== lTrim()
  
  *Description:* Returns a string with leading whitespace removed.
  
@@@ -2339,59 -1816,7 +2362,60 @@@ See: link:https://github.com/apache/tin
  
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/LTrimLocalStep.java[source
 (local)],
  link:https://tinkerpop.apache.org/docs/x.y.z/reference/#lTrim-step[reference]
  
 +[[match-step]]
 +=== match()
 +
 +*Description:* Executes a declarative pattern match query against the graph 
using a provider-supported query
 +string. The query string format is provider-specific; providers may use 
TinkerPop's optional `gql-gremlin` module
 +(which implements the <<tinkergql,TinkerGQL>> dialect) or supply their own 
engine. Users should consult their
 +graph system's documentation to determine what format is supported. The 
second argument, when provided, supplies
 +bound parameters to the query; how (and whether) these are used is left to 
the provider.
 +
 +*Syntax:*
 +
 +* `match(matchQuery: STRING)` +
 +* `match(matchQuery: STRING, params: MAP<STRING, any>)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|Y |Y |Y (via `with()`) |`any` |`MAP<STRING, any>`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `matchQuery` - An opaque query string evaluated by the graph provider. For 
example, a GQL MATCH expression:
 +  `"MATCH (a:person)-[:knows]->(b:person)"`.
 +* `params` - Optional bound parameters passed to the provider alongside the 
query string. May be `null` or empty.
 +
 +*Modulation:*
 +
 +`with("queryLanguage", value)` - specifies which query language the provider 
should use to evaluate the string.
 +When omitted, the provider uses its native or default language.
 +
 +*Considerations:*
 +
 +* The step is a provider-delegation point. `gremlin-core` supplies only the 
placeholder `DeclarativeMatchStep`;
 +graph providers replace it with their own implementation via a 
`TraversalStrategy`.
 +* The traverser value emitted by the step is a `MAP<STRING, any>` containing 
one entry per named variable in
 +the matched pattern, keyed by variable name. Providers must set this map as 
the traverser value for each result
 +row.
 +* Each named variable is also recorded as a labeled entry in the traverser's 
path, so results remain retrievable
 +by name via `select()` when downstream steps require individual values.
 +* Anonymous elements in the pattern (those without a variable name) are not 
exposed in the map or path and cannot be
 +referenced by `select()`.
 +* When used as a spawn step on `GraphTraversalSource`, no upstream traversers 
are consumed; the provider
 +executes the query once and emits one traverser per result row.
 +
 +*Exceptions:*
 +
 +* If the step is reached and no supporting strategy has replaced the 
placeholder, an `Unsupported Operation` is
 +raised.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DeclarativeMatchStep.java[source],
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#match-step[reference]
 +
+ [llms-summary="The formal semantics of the merge() step: adds the union of 
two sets (or two maps) to the Traversal Stream."]
  [[merge-step]]
  === merge()
  
@@@ -2607,6 -2034,8 +2633,7 @@@ will be filtered out of the traversal s
  See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NoneStep.java[source],
  link:https://tinkerpop.apache.org/docs/x.y.z/reference/#none-step[reference]
  
 -
+ [llms-summary="The formal semantics of the product() step: adds the cartesian 
product to the Traversal Stream."]
  [[product-step]]
  === product()
  
@@@ -2678,53 -2107,7 +2705,54 @@@ from the resulting `MAP`
  See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java[source],
  
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#project-step[reference]
  
 +[[property-step]]
 +=== property()
 +
 +*Description:* Adds or sets properties on elements. This is a sideEffect 
step: it returns the element, not the
 +property it created.
 +
 +*Syntax:* `property(key: any, value: any, keyValues: any...)` | 
`property(cardinality: Cardinality, key: any, value: any, keyValues: any...)` | 
`property(keyValues: MAP)` | `property(cardinality: Cardinality, keyValues: 
MAP)` | `property(mapTraversal: Traversal)`
 +
 +[width="100%",options="header"]
 +|=========================================================
 +|Start Step |Mid Step |Modulated |Domain |Range
 +|N |Y |N |`Element` |`Element`
 +|=========================================================
 +
 +*Arguments:*
 +
 +* `key` - The property key. May be a literal or a `Traversal` whose first 
result is used as the key.
 +* `value` - The property value. May be a literal or a `Traversal` whose first 
result is used as the value.
 +* `keyValues` - Additional key/value pairs for meta-properties on vertex 
properties.
 +* `cardinality` - The vertex property cardinality (`single`, `list`, `set`). 
If `null`, uses the graph's default.
 +* `keyValues` (`MAP`) - A map of property key-value pairs to set. Values may 
use `CardinalityValue` to override
 +  the cardinality on a per-entry basis.
 +* `mapTraversal` - A child traversal that must produce a `MAP`. Each entry 
becomes a property on the element.
 +  Must be read-only.
 +
 +*Modulation:*
 +
 +None
 +
 +*Considerations:*
 +
 +* When following `addV()` or `addE()`, the step may be folded into the 
creation operation (only when cardinality is
 +  not specified and meta-properties are not included).
 +* Key and value arguments may be traversals; their first result is used 
per-traverser.
 +* A `MAP` argument (literal or from a traversal) sets multiple properties in 
one step.
 +* `property(null)` and `property(Cardinality, null)` are no-ops that return 
the input unchanged.
 +* Child traversals must be read-only; mutating steps are rejected with an 
`Argument Error`.
 +* If a map traversal does not produce a `MAP`, a `State Error` is raised.
 +
 +*Exceptions:*
 +
 +* An `Argument Error` is raised if a child traversal contains mutating steps.
 +* A `State Error` is raised if a map traversal does not produce a `MAP`.
 +
 +See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AddPropertyStep.java[source],
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#property-step[reference]
 +
+ [llms-summary="The formal semantics of the repeat() step: iteratively applies 
a traversal (the \"loop body\") to each incoming traverser until a stopping 
condition is met."]
  [[repeat-step]]
  === repeat()
  
@@@ -2798,8 -2181,10 +2826,9 @@@ message containing: `The repeat()-trave
    when the step is initialized during iteration with the message containing: 
`The repeat()-traversal was not defined`.
  
  See: 
link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/RepeatStep.java[source],
 
-link:https://tinkerpop.apache.org/docs/x.y.z/reference/#repeat-step[reference],
 
-link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/branch/Repeat.feature[tests]
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#repeat-step[reference]
  
+ [llms-summary="The formal semantics of the replace() step: returns a string 
with the specified characters in the original string replaced with the new 
characters."]
  [[replace-step]]
  === replace()
  
diff --cc docs/src/dev/provider/index.asciidoc
index 3ef6ff585c,864ecaa780..0a53f03023
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@@ -629,201 -627,8 +632,202 @@@ from TinkerPop using the link:https://t
  Simply provide a `InputFormat` and `OutputFormat` that can be referenced by a 
`HadoopGraph` instance as discussed
  in the 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#clonevertexprogram[Reference
 Documentation].
  
 +[[tinkerpop-providers-tinkergql]]
 +==== Supporting Declarative Pattern Matching (TinkerGQL)
 +
 +Graph providers can offer declarative pattern matching via the 
`match(String)` step by integrating the
 +link:https://tinkerpop.apache.org/docs/x.y.z/reference/#tinkergql[TinkerGQL] 
engine shipped in the optional
 +`gql-gremlin` module. TinkerGQL handles GQL `MATCH` parsing, query planning, 
and execution against any `Graph`
 +implementation through a thin set of default interface methods, so most 
providers can get working `match()` support
 +with only a few lines of wiring code.
 +
 +===== Maven Dependency
 +
 +Add `gql-gremlin` alongside your provider's existing TinkerPop dependencies:
 +
 +[source,xml]
 +----
 +<dependency>
 +    <groupId>org.apache.tinkerpop</groupId>
 +    <artifactId>gql-gremlin</artifactId>
 +    <version>x.y.z</version>
 +</dependency>
 +----
 +
 +===== Registering the Strategy
 +
 +Register `GqlDeclarativeMatchStrategy.instance()` in the global strategy 
cache from a static initializer on your
 +graph class. This is exactly how TinkerGraph registers TinkerGQL support:
 +
 +[source,java]
 +----
 +import org.apache.tinkerpop.gremlin.gql.GqlDeclarativeMatchStrategy;
 +import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 +import org.apache.tinkerpop.gremlin.structure.Graph;
 +
 +public class AcmeGraph implements Graph {
 +
 +    static {
 +        TraversalStrategies.GlobalCache.registerStrategies(
 +                AcmeGraph.class,
 +                
TraversalStrategies.GlobalCache.getStrategies(Graph.class).clone()
 +                        
.addStrategies(GqlDeclarativeMatchStrategy.instance()));  // <1>
 +    }
 +    // ...
 +}
 +----
 +
 +<1> `instance()` is a singleton. On first use against a given graph it lazily 
creates one `DefaultGqlPlanner`
 +    and one `DefaultGqlExecutor` for that graph instance and caches them. All 
traversals on the same graph
 +    reuse that pair, so the planner's query parse cache is shared 
automatically.
 +
 +Providers should also evict the cached pair when the graph is closed to avoid 
retaining it in memory:
 +
 +[source,java]
 +----
 +@Override
 +public void close() {
 +    GqlDeclarativeMatchStrategy.evict(this);  // <1>
 +    // ... other cleanup
 +}
 +----
 +
 +<1> Removes the per-graph `DefaultGqlPlanner` / `DefaultGqlExecutor` pair 
from the singleton cache.
 +    `AbstractTinkerGraph.close()` does this automatically for 
TinkerGraph-based implementations.
 +
 +===== Performance Hints (Optional, but strongly recommended)
 +
 +Without these overrides the TinkerGQL planner has no cardinality information. 
It treats every label count as
 +unknown (`Long.MAX_VALUE`), which causes it to pick the seed vertex 
arbitrarily and order extension steps without
 +regard to label density. On any graph of meaningful size this produces 
unnecessarily large intermediate result
 +sets and slow query execution. The fix is two method overrides.
 +
 +The most common customization — and the one that requires the least code — is 
telling the planner about your
 +graph's label cardinalities. Overriding these two methods on your `Graph` 
implementation is all that is needed
 +for the planner to make better join-ordering decisions:
 +
 +[source,java]
 +----
 +@Override
 +public long countVerticesByLabel(final String label) {
 +    return myLabelIndex.getCount(label);  // <1>
 +}
 +
 +@Override
 +public long countEdgesByLabel(final String label) {
 +    return myEdgeLabelIndex.getCount(label);
 +}
 +----
 +
 +<1> Return `Long.MAX_VALUE` if the count is unknown. The planner uses these 
values only for relative comparison
 +    when choosing a seed vertex and ordering extension steps — approximate 
counts are fine.
 +
 +These hooks feed directly into `DefaultGqlPlanner`'s seed-selection and 
step-ordering logic, so no planner
 +replacement is needed to benefit from them.
 +
 +===== Property Index Integration (Optional, but strongly recommended)
 +
 +Without this override every `MATCH` query performs a full scan of all 
vertices regardless of any inline property
 +filters in the pattern. A query like `MATCH (p:Person {name: $n})` will 
iterate every vertex in the graph and
 +test each one against the predicate, even if your graph has a `name` index 
that could satisfy it in a single
 +lookup. The planner is also unable to use index cardinalities to refine seed 
selection, so join ordering
 +degrades to label-count-only heuristics.
 +
 +If your graph maintains property indexes, expose them by returning a custom 
`Graph.Index` from `Graph.index()`.
 +When a `MATCH` pattern includes an inline property filter and the executor 
finds an index for that key, it
 +replaces the full vertex scan with a targeted index lookup. The planner also 
uses index cardinalities to
 +refine seed selection:
 +
 +[source,java]
 +----
 +@Override
 +public Graph.Index index() {
 +    return new Graph.Index() {
 +
 +        @Override
 +        public Iterator<Vertex> queryVertexIndex(final String key, final 
Object value) {
 +            return myVertexIndex.lookup(key, value);  // <1>
 +        }
 +
 +        @Override
 +        public long countVertexIndex(final String key, final Object value) {
 +            return myVertexIndex.isIndexed(key)
 +                    ? myVertexIndex.count(key, value)
 +                    : Long.MAX_VALUE;  // <2>
 +        }
 +    };
 +}
 +----
 +
 +<1> Return an empty iterator (not `null`) when the key is not indexed or no 
match exists.
 +<2> Returning `Long.MAX_VALUE` for an un-indexed key signals both the planner 
and executor to fall back to a
 +    full vertex scan. Any value less than `Long.MAX_VALUE` — including `0` — 
means "the index was consulted
 +    and returned this count."
 +
 +===== Custom Executor (Native Engine Integration, Optional)
 +
 +For providers whose graph has a native traversal API, the most practical 
advanced customization is replacing
 +only the *executor* while keeping `DefaultGqlPlanner`. This lets a provider 
get free GQL parsing and
 +cardinality-guided join ordering from the default planner, then translate the 
resulting `GqlMatchPlan` into
 +native queries rather than running `DefaultGqlExecutor`'s DFS over 
`Graph.vertices()`.
 +
 +[source,java]
 +----
 +public class AcmeGraph implements Graph {
 +
 +    private final GqlPlanner gqlPlanner = new DefaultGqlPlanner(this);  // <1>
 +    private final GqlExecutor gqlExecutor = new AcmeGqlExecutor(this);  // <2>
 +
 +    @Override
 +    public GraphTraversalSource traversal() {
 +        return super.traversal()
 +                
.withStrategies(GqlDeclarativeMatchStrategy.create(gqlPlanner, gqlExecutor));  
// <3>
 +    }
 +    // ...
 +}
 +----
 +
 +<1> The default planner is reused: it handles GQL MATCH parsing, BFS join 
ordering, and seed selection using
 +    the `countVerticesByLabel`, `countEdgesByLabel`, and `Graph.index()` 
overrides already in place.
 +<2> `AcmeGqlExecutor` receives a `GqlMatchPlan` and translates each 
`ExtensionStep` to a native traversal
 +    or query rather than calling `Graph.vertices()`.
 +<3> Instances are held as fields and reused so the parse cache is shared 
across traversals.
 +
 +The contract for a `GqlExecutor` implementation is: for each seed vertex 
matching the plan's seed label and
 +predicates, extend through each `ExtensionStep` in an order that keeps every 
step's anchor variable bound
 +before that step executes, and emit one `Element[]` per complete match. Each 
array's indices must match
 +`GqlMatchPlan.getVariables()`, with the seed variable at index 0. See 
`DefaultGqlExecutor` for a reference
 +implementation.
 +
 +NOTE: Replacing only the *planner* is rarely worthwhile. Producing a valid 
`GqlMatchPlan` requires
 +      constructing `ExtensionStep` objects, assigning variable index maps, 
and satisfying all other
 +      invariants of that concrete class — effort comparable to writing a full 
executor anyway. The
 +      `Graph` method hooks described above (`countVerticesByLabel`, 
`countEdgesByLabel`, `Graph.index()`)
 +      are the right way to improve plan quality because `DefaultGqlPlanner` 
already consults them when
 +      selecting the seed and ordering steps. A custom planner is only 
warranted when a provider needs a
 +      fundamentally different join strategy (such as a cost-based optimizer 
backed by richer statistics
 +      than label counts). At that level of investment, consider whether 
replacing both planner and
 +      executor — or bypassing `gql-gremlin` entirely via the 
`DeclarativeMatchStep` pattern described
 +      below — is the cleaner path.
 +
 +===== Implementing a Different Declarative Language
 +
 +The `GqlDeclarativeMatchStrategy` pattern is not TinkerGQL-specific. 
Providers that want to support a different
 +declarative language over the `match(String)` step, for example openCypher, 
SPARQL, or a proprietary query language,
 +can follow the same pattern:
 +
 +. Implement `TraversalStrategy.ProviderOptimizationStrategy` and in its 
`apply()` method locate all
 +  `DeclarativeMatchStep` instances in the traversal using 
`TraversalHelper.getStepsOfClass()`.
 +. Replace each `DeclarativeMatchStep` with a custom step that parses the 
query string and executes it
 +  against the graph, emitting binding maps in the same form as `GqlMatchStep`.
 +. Register the strategy in the global cache from a static initializer, 
exactly as shown above for TinkerGQL.
 +
 +`DeclarativeMatchStep` is the placeholder step inserted by the 
`match(String)` overload. The first registered
 +`ProviderOptimizationStrategy` to claim all `DeclarativeMatchStep` instances 
in a traversal wins; providers do not
 +need to interact with `gql-gremlin` at all if they supply their own 
end-to-end implementation.
 +
  [[validating-with-gremlin-test]]
+ [llms-summary="Using the gremlin-test suite to validate a graph 
implementation: the structure and process test standards and how to opt in or 
out of feature-gated tests."]
  === Validating with Gremlin-Test
  
  image:gremlin-edumacated.png[width=225]
@@@ -1541,384 -1363,9 +1546,385 @@@ link:https://tinkerpop.apache.org/docs/
  NOTE: While Gremlin Server supports this authorization feature it is not a 
feature that TinkerPop requires of graph
  providers as part of the agreement between client and server.
  
 +[[serializers]]
 +=== Serializers
 +
 +In order to serialize and deserialize the requests and responses, your graph 
driver will need to implement
 
+link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphbinary[GraphBinary]. 
The Gremlin Server is capable of
 +returning both GraphBinary and GraphSON, however, GraphBinary is a more 
compact format which can lead to increased
 +performance as fewer bytes need to be sent through the wire. For this reason, 
drivers only need to support GraphBinary.
 +link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphson[GraphSON] can 
be used by applications that only support JSON serialization.
 +
 +The following table lists the serializers supported by the Gremlin Server and 
their MIME types. These MIME types should
 +be used in the `Content-Type` and `Accept` HTTP headers.
 +
 +[width="100%",cols="3,5,5",options="header"]
 +|=========================================================
 +|Name |Description |MIME type
 +|Untyped GraphSON 4.0 |A JSON-based graph format 
|application/vnd.gremlin-v4.0+json;types=false
 +|Typed GraphSON 4.0 |A JSON-based graph format with embedded type information 
used for serialization |application/vnd.gremlin-v4.0+json;types=true
 +|GraphBinary 4.0 |A binary graph format |application/vnd.graphbinary-v4.0
 +|=========================================================
 +
 +==== IO Tests
 +
 +The IO test suite is a collection of files that contain the expected outcome 
of serialization of certain types. These
 +tests can be used to determine if a particular serializer has been correctly 
implemented. In general, a driver should
 +be able to "round trip" each of these types. That is, it should be able to 
both read from and write to those exact same
 +bytes. Not all programming languages provide library types that will match 
the specification of the corresponding type
 +defined by the serializer. In this case, it is not possible to completely 
round trip that type and you may skip that
 +test. The GraphBinary test files can be found
 
+link:https://github.com/apache/tinkerpop/tree/x.y.z/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary[here].
 +The 
link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java:[Java
 implementation]
 +can be used as a reference on how these files can be used and its
 
+link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/Model.java[model]
 +shows the Java representation of those files.
 +
 +[[provider-defined-types]]
 +=== Provider Defined Types (PDT)
 +
 +Provider Defined Types let graph providers expose custom types that drivers 
serialize and deserialize automatically,
 +without manual client-side configuration. PDT comes in two forms. A 
*Composite PDT* represents a type as a map of
 +named fields and suits a type with structure, such as multiple properties or 
nested types. A *Primitive PDT*
 +represents a type as a single opaque stringified value and suits a type 
better expressed as one value, such as an
 +unsigned 32-bit integer or a provider-specific identifier.
 +
 +Both forms follow the same workflow. A provider makes a type available for 
dehydration, and optionally hydration,
 +either by annotating the class directly or by registering an adapter for it. 
Clients configure a `PDTRegistry` to
 +enable automatic round-tripping.
 +
 +[[composite-pdt]]
 +==== Composite PDT
 +
 +A Composite PDT serializes a type as a map of named fields. This is the right 
choice whenever a type has more than
 +one meaningful property, or where nested provider-defined types need to be 
represented.
 +
 +===== Basic Usage
 +
 +Annotate a class with `@ProviderDefined` from the 
`org.apache.tinkerpop.gremlin.structure.io.pdt` package:
 +
 +[source,java]
 +----
 +import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefined;
 +
 +@ProviderDefined(name = "mygraph:Point")
 +public class Point {
 +    public double x;
 +    public double y;
 +
 +    public Point(double x, double y) {
 +        this.x = x;
 +        this.y = y;
 +    }
 +}
 +----
 +
 +The `name` attribute is a unique identifier for the type. It must not be null 
or empty. All GLVs reject an
 +empty name when a type is defined or a `CompositePDT` is constructed. It is 
strongly recommended to namespace
 +type names using the graph's identifier as a prefix (e.g. `"mygraph:Point"`). 
This avoids collisions when clients
 +interact with multiple providers and makes the origin of a type immediately 
clear. By default, all fields are included.
 +Use `includedFields` or `excludedFields` to control which fields are 
serialized:
 +
 +[source,java]
 +----
 +@ProviderDefined(name = "mygraph:Point", includedFields = {"x", "y"})
 +public class Point { ... }
 +
 +// or exclude specific fields
 +@ProviderDefined(name = "mygraph:Person", excludedFields = {"internalId"})
 +public class Person { ... }
 +----
 +
 +NOTE: For annotation-based round-trip hydration (see <<round-trip-support>>), 
an annotated class must expose a no-arg
 +constructor, and the mapped fields must be directly settable (e.g. public 
fields). A class that cannot meet these
 +requirements, for example one with immutable `final` fields or no default 
constructor, should instead use a
 +`CompositePDTAdapter` (see <<adapter-for-types-you-dont-own>>), which gives 
full control over construction.
 +
 +The serialized field set becomes a map whose keys are always strings. In 
statically typed GLVs (Java, .NET,
 +Go, and TypeScript) this is enforced by the type system. In Python the keys 
are validated at runtime, and a
 +`TypeError` is raised for any non-string key.
 +
 +===== Nested Types
 +
 +PDT supports nested custom types. Each nested type must also be annotated:
 +
 +[source,java]
 +----
 +@ProviderDefined(name = "mygraph:Address")
 +public class Address {
 +    public String street;
 +    public String city;
 +}
 +
 +@ProviderDefined(name = "mygraph:Person")
 +public class Person {
 +    public String name;
 +    public Address address;
 +}
 +----
 +
 +When serialized, the `address` field is itself encoded as a PDT value.
 +
 +[[primitive-provider-defined-types]]
 +==== Primitive PDT
 +
 +A Primitive PDT represents a type as a single opaque stringified value rather 
than a map of fields. It suits a type
 +that is best expressed as one value, for example an unsigned 32-bit integer 
or a provider-specific identifier. A
 +Primitive PDT carries only a type name and a string value, and TinkerPop 
never parses or interprets the value.
 +
 +A type may be registered as composite or primitive, not both. Attempting to 
register a type for both forms throws an
 +error. Unlike Composite PDT, there is no annotation form for Primitive PDT. 
Because there is only a single value to
 +extract, providers must always supply an adapter (see 
<<adapter-for-types-you-dont-own>>) rather than annotating fields.
 +
 +[[adapter-for-types-you-dont-own]]
 +==== Adapters for Types You Don't Own
 +
 +For a class that cannot be annotated, either because the provider does not 
own the class (e.g. `java.awt.Color`) or
 +because the type is a Primitive PDT, register an adapter instead. Composite 
PDT uses `CompositePDTAdapter<T>`,
 +and Primitive PDT uses `PrimitivePDTAdapter<T>`.
 +
 +NOTE: A registered adapter always takes precedence over annotation-based 
handling on dehydration. This is consistent
 +across all GLVs. If an adapter is registered for a type, it controls 
serialization regardless of whether the class is
 +also annotated.
 +
 +===== Composite Adapter
 +
 +Implement `CompositePDTAdapter<T>`:
 +
 +[source,java]
 +----
 +import org.apache.tinkerpop.gremlin.structure.io.pdt.CompositePDTAdapter;
 +
 +public class ColorAdapter implements CompositePDTAdapter<java.awt.Color> {
 +
 +    @Override
 +    public String typeName() { return "mygraph:Color"; }
 +
 +    @Override
 +    public Class<java.awt.Color> targetClass() { return java.awt.Color.class; 
}
 +
 +    @Override
 +    public Map<String, Object> toFields(java.awt.Color color) {
 +        return Map.of("r", color.getRed(), "g", color.getGreen(),
 +                      "b", color.getBlue(), "a", color.getAlpha());
 +    }
 +
 +    @Override
 +    public java.awt.Color fromFields(Map<String, Object> fields) {
 +        return new java.awt.Color((int) fields.get("r"), (int) 
fields.get("g"),
 +                                  (int) fields.get("b"), (int) 
fields.get("a"));
 +    }
 +}
 +----
 +
 +===== Primitive Adapter
 +
 +Implement `PrimitivePDTAdapter<T>`:
 +
 +[source,java]
 +----
 +public class Uint32Adapter implements PrimitivePDTAdapter<Uint32> {
 +    @Override public String typeName() { return "mygraph:Uint32"; }
 +    @Override public Class<Uint32> targetClass() { return Uint32.class; }
 +    @Override public String toValue(Uint32 obj) { return 
Long.toUnsignedString(obj.getValue()); }
 +    @Override public Uint32 fromValue(String value) { return new 
Uint32(Integer.parseUnsignedInt(value)); }
 +}
 +----
 +
 +Both adapter kinds are registered the same way. See <<round-trip-support>> 
below.
 +
 +[[round-trip-support]]
 +==== Round-Trip Support (Dehydration and Hydration)
 +
 +There is an important distinction between *dehydration*, serializing a type 
for sending, and *hydration*,
 +deserializing a received PDT back into a language-native type. This 
distinction, and the registration mechanism used
 +to enable it, applies the same way to both Composite and Primitive PDT.
 +
 +*Dehydration* is handled automatically for `@ProviderDefined`-annotated 
classes and for adapter-registered types,
 +composite or primitive. When an annotated or adapter-backed object is passed 
into a Gremlin traversal or script,
 +TinkerPop converts it to a PDT on the wire without any extra configuration.
 +
 +*Hydration*, reconstructing an incoming PDT back into the original typed 
object, requires the driver to know which
 +class corresponds to a given PDT name. Without this mapping, the driver 
returns a generic `CompositePDT` or
 +`PrimitivePDT` object (see <<pdt-unregistered-values>>). To enable automatic 
round-trip hydration, providers must
 +expose a pre-configured `PDTRegistry` to users. How that registry is 
populated differs by language, but each language
 +follows the same pattern. Composite types register through annotation-derived 
or `CompositePDTAdapter`
 +mappings, and primitive types register through `PrimitivePDTAdapter` or an 
equivalent, alongside them.
 +
 +===== Java
 +
 +Register annotated composite classes explicitly with the registry. 
`register(Class<?>...)` inspects the
 +`@ProviderDefined` annotation to derive the type name and field mapping 
automatically:
 +
 +[source,java]
 +----
 +PDTRegistry registry = PDTRegistry.create();
 +registry.register(Point.class, Address.class, Person.class);
 +----
 +
 +Composite and primitive adapter types (for classes the provider does not own) 
are both discovered automatically via
 +`ServiceLoader` when using `PDTRegistry.create()`, since 
`CompositePDTAdapter` and `PrimitivePDTAdapter` both extend
 +the common `ProviderDefinedTypeAdapter` interface. Register an adapter of 
either kind by adding its fully qualified
 +class name to a single file at:
 +
 +----
 
+META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter
 +----
 +
 +for example:
 +
 +----
 +com.example.graph.ColorAdapter
 +----
 +
 +NOTE: Annotation-based hydration reflectively constructs and populates the 
annotated class
 +(`Constructor.setAccessible(true)` and `Field.set()` in 
`AnnotatedTypeAdapter`). Under JPMS, the provider's module
 +must therefore `opens` its PDT package to `org.apache.tinkerpop.gremlin.core` 
(e.g.
 +`opens com.example.graph.types to org.apache.tinkerpop.gremlin.core;` in 
`module-info.java`, or the equivalent
 +`--add-opens` JVM flag). Otherwise the JVM throws 
`InaccessibleObjectException` at hydration time. A provider using a
 +`CompositePDTAdapter` or `PrimitivePDTAdapter` with explicit 
`fromFields`/`fromValue` logic does not rely on
 +reflection and is unaffected.
 +
 +===== Python
 +
 +Hydration is fully automatic for `@provider_defined`-decorated composite 
classes. The decorator registers the class at
 +definition time (import time), so any annotated type round-trips without any 
additional setup.
 +
 +For primitive types, use `register_primitive` on the registry:
 +
 +[source,python]
 +----
 +from gremlin_python.structure.graph import PDTRegistry
 +
 +registry = PDTRegistry()
 +registry.register_primitive('mygraph:Uint32',
 +    from_value=lambda s: Uint32(int(s)),
 +    to_value=lambda obj: str(obj.value),
 +    target_class=Uint32)
 +----
 +
 +===== .NET
 +
 +`[ProviderDefined]`-annotated composite types are discovered automatically. 
Calling `PDTRegistry.Create()`
 +scans all loaded assemblies for `[ProviderDefined]`-annotated types and 
registers them for hydration. No extra
 +configuration is needed. Providers simply annotate their types, and users 
call `Create()` to create the registry.
 +
 +For primitive types, implement `IPrimitivePdtAdapter<T>` and register it on 
the `PDTRegistry` in the same way as
 +composite adapters:
 +
 +[source,csharp]
 +----
 +public class Uint32Adapter : IPrimitivePdtAdapter<Uint32>
 +{
 +    public string TypeName => "mygraph:Uint32";
 +    public Uint32 FromString(string value) => new Uint32(uint.Parse(value));
 +    public string ToString(Uint32 obj) => obj.Value.ToString();
 +}
 +----
 +
 +===== JavaScript
 +
 +Register composite hydration adapters explicitly on a `PDTRegistry` instance, 
then pass it to the connection:
 +
 +[source,javascript]
 +----
 +const registry = new PDTRegistry();
 +registry.register('mygraph:Point', {
 +    serialize: (obj) => ({ x: obj.x, y: obj.y }),
 +    deserialize: (fields) => new Point(fields.x, fields.y)
 +}, Point);
 +----
 +
 +For primitive types, use `registerPrimitive` with a `PrimitivePdtAdapter`:
 +
 +[source,javascript]
 +----
 +const { PDTRegistry, PrimitivePdtAdapter } = require('gremlin');
 +
 +const registry = new PDTRegistry();
 +registry.registerPrimitive('mygraph:Uint32', new PrimitivePdtAdapter(
 +    (str) => new Uint32(parseInt(str)),   // fromValue
 +    (obj) => obj.value.toString()          // toValue
 +), Uint32);
 +----
 +
 +===== Go
 +
 +Register composite types on a `PDTRegistry` instance. Go supports either 
reflection-based registration (using `pdt`
 +struct tags) or explicit function registration:
 +
 +[source,go]
 +----
 +registry := NewPDTRegistry()
 +registry.RegisterType("mygraph:Point", reflect.TypeOf(Point{}))
 +----
 +
 +For primitive types, use `RegisterPrimitiveFuncs` or 
`RegisterPrimitiveFuncsWithType`:
 +
 +[source,go]
 +----
 +registry := gremlingo.NewPDTRegistry()
 +registry.RegisterPrimitiveFuncsWithType("mygraph:Uint32", 
reflect.TypeOf(Uint32{}),
 +    // hydrate: string -> Go type
 +    func(value string) (interface{}, error) {
 +        v, err := strconv.ParseUint(value, 10, 32)
 +        return Uint32{Value: uint32(v)}, err
 +    },
 +    // dehydrate: Go type -> string
 +    func(obj interface{}) (string, error) {
 +        return strconv.FormatUint(uint64(obj.(Uint32).Value), 10), nil
 +    },
 +)
 +----
 +
 +===== Provider Factory Pattern
 +
 +Regardless of language, the recommended pattern is for providers to expose a 
factory method that returns a
 +pre-configured `PDTRegistry` with both composite and primitive types 
registered. This shields end users from needing
 +to know which types exist or how the registry is populated:
 +
 +[source,java]
 +----
 +// In the provider's client library
 +public class MyGraphTypeRegistry {
 +    public static PDTRegistry create() {
 +        PDTRegistry registry = PDTRegistry.create(); // discovers 
ServiceLoader composite and primitive adapters
 +        registry.register(Point.class, Address.class, Person.class); // 
registers annotated composite types
 +        return registry;
 +    }
 +}
 +----
 +
 +End users configure their connection in one line:
 +
 +[source,java]
 +----
 +DriverRemoteConnection conn = DriverRemoteConnection.using(cluster);
 +conn.setPdtRegistry(MyGraphTypeRegistry.create());
 +GraphTraversalSource g = traversal().with(conn);
 +----
 +
 +With this in place, `Point` objects round-trip transparently in both 
directions. The annotation handles outbound
 +serialization, and the registry handles inbound reconstruction. The same 
applies to any primitive type backed by a
 +registered `PrimitivePDTAdapter`.
 +
 +For driver users consuming PDTs, see the
 
+link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[Gremlin
 Drivers and Variants]
 +reference documentation for each language driver.
 +
 +[[pdt-unregistered-values]]
 +==== Unregistered PDT Values
 +
 +When a driver receives a PDT for which no matching registration exists in the 
`PDTRegistry`, it falls back to a
 +generic value object rather than failing:
 +
 +* An unregistered *Composite PDT* is returned as a `CompositePDT` object.
 +* An unregistered *Primitive PDT* is returned as a `PrimitivePDT` object.
 +
 +This behavior is consistent across all GLVs.
  
  [[gremlin-plugins]]
+ [llms-summary="How to author Gremlin Console/Server plugins as a provider: 
the plugin interface, dependency management, and registering custom bindings 
and DSLs."]
  == Gremlin Plugins
  
  image:gremlin-plugin.png[width=125]
diff --cc docs/src/reference/gremlin-applications.asciidoc
index e2ebb0e3dd,77e71d3917..d900c54af1
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@@ -860,11 -947,18 +862,12 @@@ Finally, as Gremlin Server can host mul
  possible to define the language to utilize to process the request:
  
  [source,text]
 -curl -X POST -d "{\"gremlin\":\"100-x\", \"language\":\"gremlin-groovy\", 
\"bindings\":{\"x\":1}}" "http://localhost:8182";
 +curl -X POST -d "{\"gremlin\":\"100-x\", \"language\":\"gremlin-groovy\", 
\"parameters\":\"[x:1]\"}" "http://localhost:8182";
  
 -By default this value is set to `gremlin-groovy`.  If using a `GET` 
operation, this value can be set as a query
 -string argument with by setting the `language` key.
 -
 -WARNING: Consider the size of the result of a submitted script being returned 
from the HTTP endpoint.  A script
 -that iterates thousands of results will serialize each of those in memory 
into a single JSON result set.  It is
 -quite possible that such a script will generate `OutOfMemoryError` exceptions 
on the server.  Consider the default
 -WebSocket configuration, which supports streaming, if that type of use case 
is required.
 +By default this value is set to `gremlin-lang`. The value is set in the 
request body with the `language` key.
  
  [[server-configuring]]
+ [llms-summary="Reference for Gremlin Server's YAML configuration options: 
graphs, serializers, channelizers, thread pools, SSL, and metrics."]
  === Configuring
  
  The `gremlin-server.sh` file serves multiple purposes.  It can be used to 
"install" dependencies to the Gremlin
diff --cc docs/src/reference/gremlin-variants.asciidoc
index 0b88c144ca,48cea9c558..8d34d3ce7c
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@@ -18,10 -18,12 +18,11 @@@ under the License
  ////
  
  anchor:gremlin-variants[]
 -// This book exercises only remote driver connections, but its predecessors 
leave Neo4j/Spark/Hadoop
 -// plugins active. Exclude all three to restart the console with a clean 
classpath and avoid the
 -// Scala 2.11/2.12 (and related) conflicts those plugins introduce.
 -[gremlin-docs-plugins-exclude="neo4j-gremlin,spark-gremlin,hadoop-gremlin"]
 +// This book exercises only remote driver connections, but its predecessors 
leave Spark/Hadoop
 +// plugins active. Exclude both to restart the console with a clean classpath.
 +[gremlin-docs-plugins-exclude="spark-gremlin,hadoop-gremlin"]
  [[gremlin-drivers-variants]]
+ [llms-summary="How Gremlin is embedded in host programming languages (Java, 
Groovy, Python, JavaScript, .NET, Go) and how language variants and drivers 
connect to a remote server."]
  = Gremlin Drivers and Variants
  
  image::gremlin-house-of-mirrors.png[width=1024]
@@@ -802,48 -607,7 +804,49 @@@ go run basic_gremlin.g
  go run modern_traversals.go
  ----
  
 +[[gremlin-go-pdt]]
 +=== Provider Defined Types
 +
 +Provider Defined Types (PDTs) allow graph providers to expose custom types 
through the driver. PDT values arrive as
 +`*CompositePDT` structs containing a `Name` and `Fields` map without any 
configuration.
 +Consult your graph provider's documentation for the list of PDTs they support.
 +
 +[source,go]
 +----
 +results, err := g.V().Has("location").Values("location").ToList()
 +pdt := results[0].GetInterface().(*gremlingo.CompositePDT)
 +fmt.Println(pdt.Name)   // "x:Point"
 +fmt.Println(pdt.Fields) // map[x:1.0 y:2.0]
 +----
 +
 +Working with raw `*CompositePDT` values is always available. Using a 
`PDTRegistry` is an optional
 +convenience that automates conversion between PDT values and application 
types on both the request and response paths.
 +
 +Using a `PDTRegistry` for hydration and dehydration:
 +
 +[source,go]
 +----
 +registry := gremlingo.NewPDTRegistry()
 +registry.RegisterFuncsWithType("x:Point", reflect.TypeOf(Point{}),
 +    // hydrate: convert incoming PDT fields map to a Go type
 +    func(fields map[string]interface{}) (interface{}, error) {
 +        return &Point{X: fields["x"].(float64), Y: fields["y"].(float64)}, nil
 +    },
 +    // dehydrate: convert a Go type to a PDT fields map for sending
 +    func(obj interface{}) (map[string]interface{}, error) {
 +        p := obj.(*Point)
 +        return map[string]interface{}{"x": p.X, "y": p.Y}, nil
 +    },
 +)
 +
 +remote, _ := 
gremlingo.NewDriverRemoteConnection("http://localhost:8182/gremlin";,
 +    func(settings *gremlingo.DriverRemoteConnectionSettings) {
 +        settings.PDTRegistry = registry
 +    })
 +g := gremlingo.Traversal_().With(remote)
 +----
 +
+ [llms-summary="Using Gremlin from Groovy: the JVM-based Gremlin-Groovy 
variant backed by Gremlin-Java, its role as the language of the Gremlin Console 
and Server, and its syntax differences."]
  [[gremlin-groovy]]
  == Gremlin-Groovy
  
@@@ -1799,73 -1558,8 +1803,74 @@@ java -cp target/run-examples-shaded.ja
  java -cp target/run-examples-shaded.jar examples.ModernTraversals
  ----
  
 +[[gremlin-java-pdt]]
 +=== Provider Defined Types
 +
 +Provider Defined Types (PDTs) allow graph providers to expose custom types 
through the driver. PDT values arrive as
 +`CompositePDT` objects containing a name and fields map without any 
configuration.
 +Consult your graph provider's documentation for the list of PDTs they support.
 +
 +Receiving a raw PDT:
 +
 +[source,java]
 +----
 +CompositePDT pdt = (CompositePDT) 
g.V().has("location").values("location").next();
 +String typeName = pdt.getName();                   // "x:Point"
 +Map<String, Object> fields = pdt.getFields();      // {x: 1.0, y: 2.0}
 +----
 +
 +Working with raw `CompositePDT` objects is always available. The following 
two approaches are optional
 +conveniences that automate conversion between PDT values and application 
types on both the request and response paths.
 +
 +Using a `PDTRegistry` for hydration and dehydration:
 +----
 +public class PointAdapter implements ProviderDefinedTypeAdapter<Point> {
 +    @Override public String typeName() { return "x:Point"; }
 +    @Override public Class<Point> targetClass() { return Point.class; }
 +    @Override public Map<String, Object> toFields(Point p) { return 
Map.of("x", p.getX(), "y", p.getY()); }
 +    @Override public Point fromFields(Map<String, Object> m) { return new 
Point((double) m.get("x"), (double) m.get("y")); }
 +}
 +----
 +
 +Register adapters via ServiceLoader by adding the fully qualified class name 
to
 
+`META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter`.
 The driver discovers
 +adapters on the classpath and automatically hydrates/dehydrates.
 +
 +For simpler cases where you own the type, annotate it directly to avoid 
writing an adapter:
 +
 +Annotation-based conversion with `@ProviderDefined`:
 +
 +[source,java]
 +----
 +// includedFields: only serialize the listed fields
 +@ProviderDefined(name = "x:Point", includedFields = {"x", "y"})
 +public class Point {
 +    private final double x;
 +    private final double y;
 +    private final String internalId; // not serialized
 +    // constructor, getters...
 +}
 +
 +// excludedFields: serialize all fields except those listed
 +@ProviderDefined(name = "x:Timestamped", excludedFields = {"createdAt"})
 +public class Timestamped {
 +    private final String value;
 +    private final long createdAt; // not serialized
 +    // constructor, getters...
 +}
 +
 +// send: Point is automatically dehydrated
 +g.inject(new Point(1.0, 2.0, "internal")).iterate();
 +
 +// receive: PDT is automatically hydrated back to Point
 +Point p = (Point) g.V().has("location").values("location").next();
 +----
 +
 +Classes annotated with `@ProviderDefined` are automatically dehydrated when 
passed as traversal arguments and
 +hydrated on deserialization without explicit registry configuration.
 +
  [[gremlin-javascript]]
+ [llms-summary="Using Gremlin from JavaScript/Node.js: installing the gremlin 
package, building traversals, and connecting to a remote Gremlin Server."]
  == Gremlin-JavaScript
  
  image:gremlin-js.png[width=130,float=right] Apache TinkerPop's 
Gremlin-JavaScript implements Gremlin within the
@@@ -2607,42 -2118,7 +2612,43 @@@ node basic-gremlin.j
  node modern-traversals.js
  ----
  
 +[[gremlin-javascript-pdt]]
 +=== Provider Defined Types
 +
 +Provider Defined Types (PDTs) allow graph providers to expose custom types 
through the driver. PDT values arrive as
 +`CompositePDT` objects containing a `name` and `fields` map without any 
configuration.
 +Consult your graph provider's documentation for the list of PDTs they support.
 +
 +Receiving a raw PDT:
 +
 +[source,javascript]
 +----
 +const results = await g.V().has('location').values('location').toList();
 +const pdt = results[0];
 +console.log(pdt.name);   // "x:Point"
 +console.log(pdt.fields); // { x: 1.0, y: 2.0 }
 +----
 +
 +Working with raw `CompositePDT` objects is always available. Using a 
`PDTRegistry` is an
 +optional convenience that automates conversion between PDT values and 
application types on both the request and
 +response paths.
 +
 +[source,javascript]
 +----
 +const { PDTRegistry } = require('gremlin');
 +
 +const registry = new PDTRegistry();
 +registry.register('x:Point', {
 +    serialize: (point) => ({ x: point.x, y: point.y }),
 +    deserialize: (fields) => new Point(fields.x, fields.y)
 +}, Point);
 +
 +const g = traversal().with_(new 
DriverRemoteConnection('http://localhost:8182/gremlin', {
 +    pdtRegistry: registry
 +}));
 +----
 +
+ [llms-summary="Using Gremlin from .NET: installing the Gremlin.Net package, 
its C# API with PascalCase step names, and connecting to a remote Gremlin 
Server."]
  anchor:gremlin-DotNet[]
  [[gremlin-dotnet]]
  == Gremlin.Net
@@@ -3255,83 -2552,8 +3261,84 @@@ dotnet run --project Connection
  dotnet run --project ModernTraversals
  ----
  
 +[[gremlin-dotnet-pdt]]
 +=== Provider Defined Types
 +
 +Provider Defined Types (PDTs) allow graph providers to expose custom types 
through the driver. PDT values arrive as
 +`CompositePDT` objects containing a `Name` and `Fields` dictionary without 
any configuration.
 +Consult your graph provider's documentation for the list of PDTs they support.
 +
 +Receiving a raw PDT:
 +
 +[source,csharp]
 +----
 +var pdt = (CompositePDT) 
g.V().Has("location").Values<object>("location").Next();
 +Console.WriteLine(pdt.Name);   // "x:Point"
 +Console.WriteLine(pdt.Fields); // { x: 1.0, y: 2.0 }
 +----
 +
 +Working with raw `CompositePDT` objects is always available. The following 
two approaches are optional
 +conveniences that automate conversion between PDT values and application 
types on both the request and response paths.
 +
 +Using a `PDTRegistry` for hydration and dehydration:
 +
 +[source,csharp]
 +----
 +public class PointAdapter : IProviderDefinedTypeAdapter<Point>
 +{
 +    public string TypeName => "x:Point";
 +
 +    public Point FromFields(IReadOnlyDictionary<string, object?> fields) =>
 +        new Point((double)fields["x"], (double)fields["y"]);
 +
 +    public IReadOnlyDictionary<string, object?> ToFields(Point value) =>
 +        new Dictionary<string, object?> { ["x"] = value.X, ["y"] = value.Y };
 +}
 +
 +var registry = new PDTRegistry();
 +registry.Register(new PointAdapter());
 +
 +using var client = new GremlinClient(new GremlinServer("localhost", 8182), 
pdtRegistry: registry);
 +----
 +
 +The `PDTRegistry.Create()` method scans loaded assemblies for 
`IProviderDefinedTypeAdapter<T>`
 +implementations and registers them automatically.
 +
 +For simpler cases where you own the type, annotate it directly to avoid 
writing an adapter:
 +
 +Attribute-based conversion with `[ProviderDefined]`:
 +
 +[source,csharp]
 +----
 +// IncludedFields: only serialize the listed fields
 +[ProviderDefined(Name = "x:Point", IncludedFields = new[] { "X", "Y" })]
 +public class Point
 +{
 +    public double X { get; set; }
 +    public double Y { get; set; }
 +    public string InternalId { get; set; } // not serialized
 +}
 +
 +// ExcludedFields: serialize all fields except those listed
 +[ProviderDefined(Name = "x:Timestamped", ExcludedFields = new[] { "CreatedAt" 
})]
 +public class Timestamped
 +{
 +    public string Value { get; set; }
 +    public long CreatedAt { get; set; } // not serialized
 +}
 +
 +// send: Point is automatically dehydrated
 +await g.Inject(new Point { X = 1.0, Y = 2.0 }).Promise(t => t.Iterate());
 +
 +// receive: PDT is automatically hydrated back to Point
 +var p = (Point) await 
g.V().Has("location").Values<object>("location").Promise(t => t.Next());
 +----
 +
 +Classes annotated with `[ProviderDefined]` are automatically dehydrated when 
passed as traversal arguments and
 +hydrated on deserialization without explicit registry configuration.
 +
  [[gremlin-python]]
+ [llms-summary="Using Gremlin from Python: installing gremlinpython, building 
traversals, Pythonic syntax differences, and connecting to a remote Gremlin 
Server."]
  == Gremlin-Python
  
  image:gremlin-python-drawing.png[width=130,float=right] Apache TinkerPop's 
Gremlin-Python implements Gremlin within
diff --cc docs/src/reference/implementations-hadoop-start.asciidoc
index 09dfe41934,bca8eb9f8c..88d483bb41
--- a/docs/src/reference/implementations-hadoop-start.asciidoc
+++ b/docs/src/reference/implementations-hadoop-start.asciidoc
@@@ -16,10 -16,11 +16,11 @@@ KIND, either express or implied.  See t
  specific language governing permissions and limitations
  under the License.
  ////
 -// Spark requires Scala 2.12 while Neo4j 3.4 requires Scala 2.11; they cannot 
share the console's
 -// flat classpath, so exclude neo4j-gremlin to restart the console without 
Neo4j's jars.
 -[gremlin-docs-plugins-exclude="neo4j-gremlin"]
 +// Re-includes spark-gremlin and hadoop-gremlin, which 
gremlin-variants.asciidoc excluded for its
 +// driver-only examples: an empty exclude list resets the console to every 
plugin enabled.
 +[gremlin-docs-plugins-exclude=""]
  [[hadoop-gremlin]]
+ [llms-summary="Running Gremlin OLAP over Hadoop: HadoopGraph, graph 
input/output formats, and executing traversals with SparkGraphComputer."]
  == Hadoop-Gremlin
  
  [source,xml]
diff --cc docs/src/reference/the-traversal.asciidoc
index 7f005c1687,6b979c286d..69a789de79
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@@ -679,49 -598,9 +685,50 @@@ throws, since a vertex may carry only 
  
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#addV()++[`addV()`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#addV(java.lang.String)++[`addV(String)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#addV(java.lang.String,java.lang.String...)++[`addV(String,
 String...)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#addV(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`addV(Traversal)`]
  
 +[[addlabel-step]]
 +=== AddLabel Step
 +
 +The `addLabel()`-step (*sideEffect*) adds one or more labels to an element. 
Because it mutates the set of labels on
 +an element, `addLabel()` can only be used on a graph configured with a 
`LabelCardinality` that allows more than one
 +label, namely `ZERO_OR_MORE` or `ONE_OR_MORE`.
 +
 +[gremlin-groovy]
 +----
 +conf = new BaseConfiguration()
 +conf.setProperty("gremlin.tinkergraph.vertexLabelCardinality", "ZERO_OR_MORE")
 +graph = TinkerGraph.open(conf)
 +g = traversal().with(graph)
 +g.addV('person').property('name','marko').addLabel('employee').labels()
 +g.V().has('name','marko').hasLabel('person')
 +g.V().has('name','marko').hasLabel('employee')
 +g.V().has('name','marko').addLabel('employee').labels() <1>
 +----
 +
 +<1> marko already carries the "employee" label, so adding it again leaves the 
set of labels unchanged.
 +
 +By contrast, calling `addLabel()` against a vertex whose graph is configured 
with `LabelCardinality.ONE`, which
 +fixes a single, immutable label for every vertex, results in an exception 
since there is no set of labels to
 +mutate:
 +
 +[source,groovy]
 +----
 +conf = new BaseConfiguration()
 +conf.setProperty("gremlin.tinkergraph.vertexLabelCardinality", "ONE")
 +graph = TinkerGraph.open(conf)
 +g = traversal().with(graph)
 +// results in: Label mutation is not supported with cardinality ONE. Labels 
are immutable once assigned.
 +g.addV('person').property('name','marko').addLabel('employee')
 +----
 +
 +*Additional References*
 +
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#addLabel(java.lang.String,java.lang.String...)++[`addLabel(String,
 String...)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#addLabel(org.apache.tinkerpop.gremlin.process.traversal.Traversal,org.apache.tinkerpop.gremlin.process.traversal.Traversal...)++[`addLabel(Traversal,
 Traversal...)`]
 +
+ [llms-summary="The aggregate()-step (sideEffect) is used to aggregate all the 
objects at a particular point of traversal into a Collection."]
  [[aggregate-step]]
  === [[store-step]]Aggregate Step
  
@@@ -1080,8 -965,9 +1095,9 @@@ robust steps like <<choose-step, choose
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#branch(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`branch(Traversal)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#branch(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`map(Traversal)`]
  
+ [llms-summary="The by()-step is not an actual step, but instead is a 
\"step-modulator\" similar to as() and option()."]
  [[by-step]]
  === By Step
  
@@@ -1524,9 -1381,10 +1547,10 @@@ desired strings between arguments
  *Additional References*
  
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#concat(java.lang.String)++[`concat(String...)`]
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#concat(org.apache.tinkerpop.gremlin.process.traversal.Traversal,org.apache.tinkerpop.gremlin.process.traversal.Traversal...)++[`concat(Taversal,
 Traversal...)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#concat(org.apache.tinkerpop.gremlin.process.traversal.Traversal,org.apache.tinkerpop.gremlin.process.traversal.Traversal...)++[`concat(Traversal,
 Traversal...)`]
  
link:++https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#concat-step++[`Semantics`]
  
+ [llms-summary="The conjoin()-step (map) joins together the elements in the 
incoming list traverser together with the provided argument as a delimiter."]
  [[conjoin-step]]
  === Conjoin Step
  
@@@ -1717,9 -1580,12 +1747,10 @@@ g.inject("2023-08-02T00:00:00Z").asDate
  *Additional References*
  
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(java.util.Date)++[`dateDiff(Date)`],
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(java.time.OffsetDateTime)++[`dateDiff(OffsetDateTime)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(java.util.Date)++[`dateDiff(OffsetDateTime)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`dateDiff(Traversal)`]
  
+ [llms-summary="With dedup()-step (filter), repeatedly seen objects are 
removed from the traversal stream."]
  [[dedup-step]]
  === Dedup Step
  
@@@ -1886,44 -1754,7 +1920,45 @@@ g.V(
  
  * 
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#drop()++[`drop()`]
  
 +[[droplabel-step]]
 +=== DropLabel Step
 +
 +The `dropLabel()`-step (*sideEffect*) removes one or more specific labels 
from an element and `dropLabels()`
 +removes all of them. Like `addLabel()`, both require a `LabelCardinality` of 
`ZERO_OR_MORE` or `ONE_OR_MORE`.
 +
 +[gremlin-groovy]
 +----
 +conf = new BaseConfiguration()
 +conf.setProperty("gremlin.tinkergraph.vertexLabelCardinality", "ZERO_OR_MORE")
 +graph = TinkerGraph.open(conf)
 +g = traversal().with(graph)
 +v = 
g.addV('person').property('name','marko').addLabel('employee').addLabel('manager').next()
 +g.V(v).labels()
 +g.V(v).dropLabel('manager').labels() <1>
 +g.V(v).dropLabel('manager').labels() <2>
 +g.V(v).dropLabels().labels() <3>
 +g.V(v).labels().count() <4>
 +----
 +
 +<1> Removes the "manager" label.
 +<2> Dropping a label that is not present has no effect.
 +<3> Removes all remaining labels.
 +<4> Confirms zero labels remain.
 +
 +NOTE: With `LabelCardinality.ONE_OR_MORE`, `dropLabels()` always throws and 
`dropLabel()` throws if it would
 +leave the element with zero labels.
 +
 +IMPORTANT: Do not confuse `dropLabel()` with `labels().drop()`. The 
standalone `drop()` step either drops an
 +`Element` from the `Graph`, or a `Property` from it's `Element`. Since a 
label is simply a `String` object,
 +the `drop()` step cannot operate on it.
 +
 +*Additional References*
 +
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dropLabel(java.lang.String,java.lang.String...)++[`dropLabel(String,
 String...)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dropLabel(org.apache.tinkerpop.gremlin.process.traversal.Traversal,org.apache.tinkerpop.gremlin.process.traversal.Traversal...)++[`dropLabel(Traversal,
 Traversal...)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dropLabels()++[`dropLabels()`]
 +
+ [llms-summary="The E()-step is meant to read edges from the graph and is 
usually used to start a GraphTraversal, but can also be used mid-traversal."]
  [[e-step]]
  === E Step
  
@@@ -1944,9 -1773,9 +1979,10 @@@ g.inject(1).coalesce(E().hasLabel("know
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#E(java.lang.Object...)++[`E(Object...)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#E(java.lang.Object...)++[`E(Object...)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#E(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`E(Traversal)`]
  
+ [llms-summary="The element() step is a no-argument step that traverses from a 
Property to the Element that owns it."]
  [[element-step]]
  === Element Step
  
@@@ -2129,8 -1928,9 +2170,9 @@@ information
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#filter(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`filter(Traversal)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#filter(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`map(Traversal)`]
  
+ [llms-summary="The flatMap() step maps the traverser from the current object 
to an Iterator of objects for the next step in the process."]
  [[flatmap-step]]
  === FlatMap Step
  
@@@ -2152,8 -1952,9 +2194,9 @@@ gremlin> g.withSack(1.0f).V(1).barrier(
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#flatMap(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`flatMap(Traversal)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#flatMap(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`map(Traversal)`]
  
+ [llms-summary="The format()-step (map) builds a string from a template with 
placeholders filled by traverser values and properties."]
  [[format-step]]
  === Format Step
  
@@@ -2437,8 -2191,10 +2485,9 @@@ link:++https://tinkerpop.apache.org/jav
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#hasValue(org.apache.tinkerpop.gremlin.process.traversal.P)++[`hasValue(P)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/P.html++[`P`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/TextP.html++[`TextP`],
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/structure/T.html++[`T`],
 
-link:++https://tinkerpop.apache.org/docs/x.y.z/recipes/#has-traversal++[Recipes
 - Anti-pattern]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/structure/T.html++[`T`]
  
+ [llms-summary="The id()-step (map) takes an Element and extracts its 
identifier from it."]
  [[id-step]]
  === Id Step
  
@@@ -2831,23 -2571,7 +2889,24 @@@ chosen non-deterministically
  
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#label()++[`label()`]
  
 +[[labels-step]]
 +=== Labels Step
 +
 +The `labels()`-step (*flatMap*) takes an `Element` and emits each of its 
labels as a separate traverser. For elements
 +with a single label this behaves identically to `label()`. For multi-label 
elements, it emits one traverser per label.
 +A vertex with no labels (possible only under `LabelCardinality.ZERO_OR_MORE`) 
emits nothing.
 +
 +[gremlin-groovy,theZoo]
 +----
 +g.V().labels()
 +g.V().labels().count()
 +----
 +
 +*Additional References*
 +
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#labels()++[`labels()`]
 +
+ [llms-summary="The length()-step (map) returns the length incoming string or 
list of string traverser."]
  [[length-step]]
  === Length Step
  
@@@ -3000,28 -2717,25 +3064,29 @@@ The `map()` step maps the traverser fro
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#map(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`map(Traversal)`]
  
  [[match-step]]
+ [llms-summary="The match() step (map) provides declarative, pattern-matching 
graph querying by combining traversal fragments bound to shared variables."]
  === Match Step
  
 -The `match()`-step (*map*) provides a more 
link:http://en.wikipedia.org/wiki/Declarative_programming[declarative]
 -form of graph querying based on the notion of 
link:http://en.wikipedia.org/wiki/Pattern_matching[pattern matching].
 -With `match()`, the user provides a collection of "traversal fragments," 
called patterns, that have variables defined
 -that must hold true throughout the duration of the `match()`. When a 
traverser is in `match()`, a registered
 -`MatchAlgorithm` analyzes the current state of the traverser (i.e. its 
history based on its
 -<<path-data-structure,path data>>), the runtime statistics of the traversal 
patterns, and returns a traversal-pattern
 -that the traverser should try next. The default `MatchAlgorithm` provided is 
called `CountMatchAlgorithm` and it
 -dynamically revises the pattern execution plan by sorting the patterns 
according to their filtering capabilities
 -(i.e. largest set reduction patterns execute first). For very large graphs, 
where the developer is uncertain of the
 -statistics of the graph (e.g. how many `knows`-edges vs. `worksFor`-edges 
exist in the graph), it is advantageous to
 -use `match()`, as an optimal plan will be determined automatically. 
Furthermore, some queries are much easier to
 -express via `match()` than with single-path traversals.
 +Gremlin is a mostly imperative-style query language, but it also supports a 
means for defining a query declaratively,
 +where users get a high degree of flexibility in deciding what parts of their 
query might be better written in one
 +fashion or the other. Having this choice helps promote better query 
readability and query ergonomics and offers graph
 +databases an opportunity to expose multi-language features and optimizations. 
This feature is provided by way of the
 +`match()`-step.
  
 -    "Who created a project named 'lop' that was also created by someone who 
is 29 years old? Return the two creators."
 +The `match()`-step (*map*) accepts a declarative query string, like 
link:https://www.iso.org/standard/76120.html[GQL],
 +and executes it against the graph. TinkerPop ships an optional module, 
`gql-gremlin`, that provides the
 +<<tinkergql,TinkerGQL>> dialect — a deliberate subset of ISO GQL `MATCH` 
syntax — which any graph system provider
 +may adopt. Providers may also implement their own declarative query engine 
with a completely different language.
 +*Whether `match()` is supported at all depends on the graph system being 
used.* Consult the documentation for your
 +graph system to determine what query languages and syntax are accepted.
  
 -image::match-step.png[width=500]
 +Since `match()` is a provider-specific feature, a traversal that uses 
`match()` against a graph system that has not
 +implemented support for it will throw an exception when the step is reached. 
The examples below are executed against
 +TinkerGraph, which ships TinkerGQL support out of the box (see 
<<tinkergraph-gql>>), demonstrating how the step
 +works in practice. What your graph system accepts may be entirely different.
 +
 +The step can be used in two ways. As a spawn step directly on a 
`GraphTraversalSource`, the pattern query is
 +evaluated once and each result becomes a traverser:
  
  [gremlin-groovy,modern]
  ----
@@@ -3343,9 -2941,9 +3408,10 @@@ Equivalent behaviour for `WHERE` and `R
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#match(org.apache.tinkerpop.gremlin.process.traversal.Traversal...)++[`match(Traversal...)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#match(java.lang.String)++[`match(String)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#match(java.lang.String,java.util.Map)++[`match(String,
 Map)`]
  
+ [llms-summary="The math()-step (math) enables scientific calculator 
functionality within Gremlin."]
  [[math-step]]
  === Math Step
  
@@@ -3621,8 -3223,9 +3691,9 @@@ link:++https://tinkerpop.apache.org/jav
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#mergeE(java.util.Map)++[`mergeE(Map)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#mergeE(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`mergeE(Traversal)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/Merge.html++[`Merge`],
 
-link:++https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#_mergee++[Semantics]
 
+link:++https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#merge-e-step++[`Semantics`]
  
+ [llms-summary="The mergeV() -step is used to add vertices and their 
properties to a graph in a \"create if not exist\" fashion."]
  [[mergevertex-step]]
  === MergeVertex Step
  
@@@ -3854,8 -3425,9 +3925,9 @@@ link:++https://tinkerpop.apache.org/jav
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#mergeV(java.util.Map)++[`mergeV(Map)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#mergeV(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`mergeV(Traversal)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/Merge.html++[`Merge`],
 
-link:++https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#_mergee++[Semantics]
 
+link:++https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#merge-v-step++[`Semantics`]
  
+ [llms-summary="The min()-step (map) operates on a stream of comparable 
objects and determines which is the first object according to its natural order 
in the stream."]
  [[min-step]]
  === Min Step
  
@@@ -3915,7 -3487,9 +3988,8 @@@ g.V().values('age').fold().none(gt(25)
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#none(org.apache.tinkerpop.gremlin.process.traversal.P)++[`none(P)`],
  
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/P.html++[`P`]
  
 -
  [[not-step]]
+ [llms-summary="The not() step (filter) removes traversers for which the 
provided sub-traversal returns a result, negating a pattern."]
  === Not Step
  
  The `not()`-step (*filter*) removes objects from the traversal stream when 
the traversal provided as an argument
@@@ -5128,8 -4720,9 +5227,9 @@@ see the <<general-steps, General Steps>
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#sideEffect(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`sideEffect(Traversal)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#sideEffect(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`map(Traversal)`]
  
+ [llms-summary="When it is important that a traverser not repeat its path 
through the graph, simplePath()-step should be used (filter)."]
  [[simplepath-step]]
  === SimplePath Step
  
@@@ -5729,9 -5325,9 +5846,10 @@@ g.V().has('name', within('marko', 'vada
  
  *Additional References*
  
 
-link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#V(java.lang.Object...)++[`V(Object...)`]
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#V(java.lang.Object...)++[`V(Object...)`],
 
+link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#V(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`V(Traversal)`]
  
+ [llms-summary="The value()-step (map) takes a Property and extracts the value 
from it."]
  [[value-step]]
  === Value Step
  
@@@ -6230,46 -5790,7 +6355,47 @@@ By default, `GType` enumerations are re
  g.V().values('age','name').is(P.typeOf('Integer'))
  ----
  
 +[[canonical-gremlin-literal-types]]
 +=== Canonical Gremlin Literal Types
 +
 +Canonical Gremlin represents typed values as text so that scripts and GLV 
requests can be expressed in the
 +`gremlin-lang` language and parsed by the `gremlin-lang` script engine. The 
authoritative definition of this syntax is
 +the 
link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-language/src/main/antlr4/Gremlin.g4[Gremlin.g4
 ANTLR grammar].
 +This section summarizes the commonly used literal forms for convenience when 
reading canonical Gremlin or writing direct
 +script requests.
 +
 +[width="100%",cols="2,3,6",options="header"]
 +|=========================================================
 +|Type |Canonical form |Expected input
 +|null |`null` |The literal keyword `null`.
 +|Boolean |`true`, `false` |The literal keywords `true` and `false`.
 +|String |`"marko"`, `'marko'`, `"M"s` |A single-quoted or double-quoted 
string. The optional `s` suffix still produces a `String`.
 +|Character |`"M"c`, `'M'c` |A single-quoted or double-quoted value that is 
one character.
 +|Byte |`1B` |An integer with a `B` suffix and a value within the bounds of 
`Byte`.
 +|Short |`1S` |An integer with an `S` suffix and a value within the bounds of 
`Short`.
 +|Integer |`1`, `1I` |An integer within the bounds of `Integer`. The `I` 
suffix forces `Integer`.
 +|Long |`1L` |An integer with an `L` suffix and a value within the bounds of 
`Long`.
 +|BigInteger |`1N` |An integer with an `N` suffix.
 +|Float |`1.0F` |A floating-point number with an `F` suffix and a value within 
the bounds of `Float`.
 +|Double |`1.0`, `1.0D` |A floating-point number with an optional `D` suffix.
 +|BigDecimal |`1.0M` |A floating-point number with an `M` suffix.
 +|DateTime |`DateTime("2018-03-22T00:35:44Z")`, `DateTime()` |An ISO-8601 date 
or date-time string. `DateTime()` evaluates to the current time.
 +|UUID |`UUID("f47af10b-58cc-4372-a567-0f02b2f3d479")`, `UUID()` |A UUID 
string in the textual form written as 8-4-4-4-12 hexadecimal digit groups. 
`UUID()` generates a random UUID.
 +|Duration |`Duration(3600,0)`, `Duration(30,0,false)` |The first argument is 
non-negative seconds. The second is nanoseconds from `0` to `999999999`. The 
optional third argument is a boolean sign flag with `false` negating the 
duration.
 +|Binary |`Binary("AQID")` |A Base64-encoded string.
 +|Enum |`T.id`, `Cardinality.single`, `Direction.OUT` |A Gremlin enum token 
from `T`, `Cardinality`, `Direction`, `Merge`, `Pick`, `DT`, or `GType`.
 +|List |`[1,"two",null]` |A comma-separated sequence of generic literals 
inside square brackets.
 +|Set |`{1,"two"}` |A comma-separated sequence of generic literals inside 
braces.
 +|Map |`[:]`, `["name":"marko", "age":29]` |An empty map is `[:]`. A populated 
map is a comma-separated sequence of `key:value` entries inside square brackets.
 +|Provider Defined Type |`PDT("Point",["x":1,"y":2])`, `PDT("Uint32","42")` 
|The first argument is the provider-defined type name. The composite form 
expects a map literal with string keys. The primitive form expects an opaque 
string value.
 +|=========================================================
 +
 +NOTE: Numeric values may be signed, and integer values may use decimal, 
hexadecimal (`0x`), or octal (`0`) notation.
 +Underscores may appear between digits. Numeric type suffixes are accepted in 
either uppercase or lowercase form, though
 +the examples above use uppercase suffixes. Special floating-point values are 
expressed as `NaN`, `Infinity`,
 +`+Infinity`, or `-Infinity`.
 +
+ [llms-summary="A note on maps in Gremlin, including differences in behavior 
between embedded and remote contexts."]
  [[a-note-on-maps]]
  == A Note on Maps
  
diff --cc docs/src/upgrade/release-3.2.x-incubating.asciidoc
index 18ef7d7448,820620712e..ab546bb583
--- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
@@@ -1456,9 -1459,10 +1458,10 @@@ See: link:https://issues.apache.org/jir
  The method signatures of `get_g_VXlistXv1_v2_v3XX_name` and 
`get_g_VXlistX1_2_3XX_name` of `VertexTest` were changed
  to take arguments for the `Traversal` to be constructed by extending classes.
  
+ [llms-summary="Upgrade notes specific to the TinkerPop 3.2.0 release: its 
breaking changes, new features, and changelog."]
  == TinkerPop 3.2.0
  
 -*Release Date: Release Date: April 8, 2016*
 +*Release Date: April 8, 2016*
  
  Please see the 
link:https://github.com/apache/tinkerpop/blob/3.2.0-incubating/CHANGELOG.asciidoc#tinkerpop-320-release-date-april-8-2016[changelog]
 for a complete list of all the modifications that are part of this release.
  

Reply via email to