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, only use command() for DDL (CREATE CLASS, CREATE PROPERTY, CREATE INDEX) — never for INSERT, UPDATE, or DELETE.tx.yql("SELECT FROM Foo WHERE name = :name", "name", "bar")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.