Review documentation files for grammar, factual accuracy, and query correctness. Use when the user asks to review docs, validate documentation, or check YQL examples. Accepts a path to a file or directory as argument.
Review documentation files for grammar, factual accuracy, and query correctness.
The user will provide a path to a single document or a folder containing documents.
Use $ARGUMENTS as the target path. If no argument is provided, ask the user for the path.
This command reviews Markdown documentation files (.md) covering:
$ARGUMENTS points to a single .md file, review that file.$ARGUMENTS points to a directory, discover all .md files in it recursively using Glob.For each document, check for:
YouTrackDB, YQL, class names, etc.```sql, ```java, etc. are present and correct.Produce a table of findings per file: line number, issue, suggested fix.
[text](target) and anchor links [text](#anchor).YQL-Where.md), check if the referenced file exists relative to the document using Glob. Report missing files but do not block the review — flag them as warnings.SQL-Syntax.md and YQL-Syntax.md when only one exists).Read through each document and extract all verifiable factual claims about YouTrackDB / YQL behavior. Examples:
For each claim, note the file, line number, and the exact claim text.
Extract all YQL/SQL code examples from fenced code blocks (```sql sections). For each query, note:
Add new test methods to the persistent DocValidationTest class (core/src/test/java/com/jetbrains/youtrackdb/internal/core/sql/DocValidationTest.java) that validate extracted queries and factual claims against a real in-memory YouTrackDB instance using the Gremlin API with yql() methods. If the test class does not exist yet, create it with the following pattern:
package com.jetbrains.youtrackdb.internal.core.sql;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import com.jetbrains.youtrackdb.api.DatabaseType;
import com.jetbrains.youtrackdb.api.YouTrackDB;
import com.jetbrains.youtrackdb.api.YourTracks;
import com.jetbrains.youtrackdb.api.gremlin.YTDBGraphTraversalSource;
import java.nio.file.Path;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class DocValidationTest {
private static YouTrackDB youTrackDB;
private static Path dbPath;
private YTDBGraphTraversalSource g;
@BeforeClass
public static void setUpClass() throws Exception {
dbPath = Path.of(System.getProperty("java.io.tmpdir"), "doc-validation-test");
youTrackDB = YourTracks.instance(dbPath.toString());
youTrackDB.create("test", DatabaseType.MEMORY, "admin", "admin", "admin");
}
@AfterClass
public static void tearDownClass() {
youTrackDB.close();
}
@Before
public void setUp() {
g = youTrackDB.openTraversal("test", "admin", "admin");
}
@After
public void tearDown() {
g.close();
}
}
CRITICAL: Only use the public Gremlin API. The test class lives in com.jetbrains.youtrackdb.internal.core.sql for organizational reasons (it is in the core module's test tree), but it must only import from com.jetbrains.youtrackdb.api.* and standard TinkerPop packages (org.apache.tinkerpop.gremlin.*). Never import internal classes like DatabaseSessionEmbedded, YouTrackDBImpl, DbTestBase, or anything else under com.jetbrains.youtrackdb.internal.
Key patterns for writing tests:
g.command(): g.command("CREATE CLASS Foo EXTENDS V") — always use EXTENDS V (vertex) or EXTENDS E (edge) so results are compatible with the Gremlin result mapper.CREATE VERTEX (not INSERT INTO) inside transactions:
g.executeInTx(tx -> {
tx.yql("CREATE VERTEX Foo SET name = 'bar'").iterate();
});
UPDATE inside transactions via yql().iterate():
g.executeInTx(tx -> {
tx.yql("UPDATE Foo SET name = 'baz' WHERE name = 'bar'").iterate();
});
SELECT inside transactions via g.computeInTx():
var results = g.computeInTx(tx -> tx.yql("SELECT FROM Foo").toList());
assertThat(results).isNotEmpty();
Results from SELECT on vertex classes are Vertex objects — cast and use .value("prop"):
Vertex v = (Vertex) results.get(0);
assertThat((String) v.value("name")).isEqualTo("baz");
assertThatThrownBy:
assertThatThrownBy(() -> g.executeInTx(tx -> {
tx.yql("BAD QUERY").iterate();
}));
yql() method returns a lazy YTDBGraphTraversal — always call .iterate() or .toList() to execute it.command() method executes eagerly — no need to call .iterate(). However, command() internally iterates results through the Gremlin result mapper, which only supports vertices and stateful edges. Therefore, (CREATE CLASS, CREATE PROPERTY, CREATE INDEX) — never for INSERT, UPDATE, or DELETE.These limitations affect what can be validated through the public API:
GremlinResultMapper) only supports vertices and stateful edges. SELECT on a plain class (not extending V/E) will throw IllegalStateException: Only vertices and stateful edges are supported in Gremlin results. If a document example uses a plain class, create it with EXTENDS V for testing purposes.yql().iterate() for UPDATE/INSERT — never use command() for data mutation commands, as it will fail when the result mapper tries to process the non-vertex result.RETURN AFTER on UPDATE — use tx.yql("UPDATE ... RETURN AFTER @this").toList() to collect results. The results are vertex objects when the target class extends V.Group tests by document section. Each test method should have a comment referencing the document claim it validates.
./mvnw -pl core clean test -Dtest=DocValidationTest
./mvnw -pl core spotless:apply
After all checks complete, present a consolidated report to the user:
## Documentation Review: <path>
### Grammar & Style
| File | Line | Issue | Suggested Fix |
|------|------|-------|---------------|
| ... | ... | ... | ... |
### Link Validation
| File | Line | Link Target | Status |
|------|------|-------------|--------|
| ... | ... | ... | Missing / OK |
### Factual Claims
| File | Line | Claim | Verified | Notes |
|------|------|-------|----------|-------|
| ... | ... | ... | Yes/No | ... |
### Query Validation
| File | Line | Query | Expected | Result | Notes |
|------|------|-------|----------|--------|-------|
| ... | ... | ... | Success/Fail | Pass/Fail | ... |
### Summary
- Total files reviewed: N
- Grammar issues found: N
- Broken links: N
- Factual claims verified: N/N
- Queries validated: N/N
Ask the user whether to:
After the review is complete:
DocValidationTest class — it serves as a living validation of documentation examples../mvnw -pl core clean test -Dtest=DocValidationTest./mvnw -pl core spotless:applyDocValidationTest.core module uses JUnit 4 (not JUnit 5). Use @Test, @Before, @After, @BeforeClass, @AfterClass from org.junit.spotless:apply before running tests if the test class is new.CityDistinct, EmpSalary).yql() for YQL queries — the yql() method on YTDBGraphTraversalSourceDSL returns a lazy traversal; always terminate with .iterate() or .toList().command() for schema DDL — command() executes eagerly and is appropriate for CREATE CLASS, CREATE PROPERTY, CREATE INDEX, etc.g.executeInTx() for side-effecting operations, g.computeInTx() when you need a return value, and g.autoExecuteInTx() when returning a traversal that should be auto-iterated.command() for DDLtx.yql("SELECT FROM Foo WHERE name = :name", "name", "bar")