name: tinker-review description: > Graph-based PR review for Apache TinkerPop. Builds a knowledge graph from PR source code, enriches it with semantic relationships guided by domain playbooks, runs structural analysis, and produces an HTML evidence package. Use when asked to review a TinkerPop PR by number. license: Apache-2.0 compatibility: Requires Docker, Node.js 20+, git. Network access for fetching PR refs. metadata: version: "0.1.0" project: Apache TinkerPop
Graph Review Skill
Prerequisites
- Docker running (for Gremlin Server)
upstreamremote pointing togit@github.com:apache/tinkerpop.git(fetch only)- Node.js 20+ with dependencies installed in
.skills/tinker-review/
References (load on demand)
- Read references/schema.md when you need to understand what vertices, edges, or properties exist in the knowledge graph (typically during enrichment or when writing raw Gremlin)
- Read references/interfaces.md when you need the exact function signatures or data type definitions for a module
Execution Sequence
When invoked with /review <pr-number>:
1. Setup + Phase 1 (deterministic)
Run the review script. This handles everything mechanical:
npm install --prefix .skills/tinker-review # only needed once
node .skills/tinker-review/scripts/review.js <pr-number> <repo-path>
This performs: fetch PR → create worktree → start Gremlin Server → extract structure via Tree-sitter → populate knowledge graph → discover discussions (JIRA, dev list, proposals, PR comments) → run pattern checks (completeness, coverage gaps, centrality, blast radius, cluster analysis) → write evidence JSON.
Output: /tmp/pr-review-<pr>/evidence.json
Server: remains running (the agent needs it for enrichment)
Worktree: available at /tmp/pr-review-<pr>/src/
If re-running, the script cleans up stale worktrees/branches automatically.
2. Classify and Load Playbooks
Always load playbooks/general.md — it applies to every PR.
Then determine which domain-specific playbooks apply from changed file paths:
gremlin-dart/,gremlin-go/,gremlin-python/,gremlin-dotnet/,gremlin-js/→playbooks/glv.mdgremlin-core/with new step patterns →playbooks/new-step.mdgremlin-driver/,gremlin-server/,gremlin-util/→playbooks/driver-server.md- Small change set with linked issue →
playbooks/bug-fix.md gremlin-language/or*.g4→playbooks/grammar.md
Load ALL matching playbooks. Execute enrichment for each in sequence.
3. Phase 2 — Enrichment (agent-driven)
The Gremlin Server is still running. Use scripts/enrichment/cli.js to
read from and write to the knowledge graph. Do NOT write your own connection
code or import gremlin-js directly — the CLI handles connections for you.
Usage:
node scripts/enrichment/cli.js <command> --workDir /tmp/pr-review-<pr> [--options...]
Read commands:
node scripts/enrichment/cli.js listFunctions --workDir /tmp/pr-review-<pr> --changed true --visibility public
node scripts/enrichment/cli.js listTypes --workDir /tmp/pr-review-<pr> --kind class
node scripts/enrichment/cli.js getCallsFrom --workDir /tmp/pr-review-<pr> --function <name> --file <path>
node scripts/enrichment/cli.js getCanonicalSteps --workDir /tmp/pr-review-<pr>
Write commands:
node scripts/enrichment/cli.js mapStep --workDir /tmp/pr-review-<pr> --function <name> --file <path> --step <canonicalName>
node scripts/enrichment/cli.js linkDiscussion --workDir /tmp/pr-review-<pr> --url <url> --source jira --title <title>
node scripts/enrichment/cli.js linkDoc --workDir /tmp/pr-review-<pr> --entity Step --name <name> --doc <path>
node scripts/enrichment/cli.js addGrammarRule --workDir /tmp/pr-review-<pr> --name <name>
node scripts/enrichment/cli.js annotate --workDir /tmp/pr-review-<pr> --label Function --name <name> --key <key> --value <value>
Each command connects, executes, prints JSON result to stdout, and disconnects.
The connection info is read from /tmp/pr-review-<pr>/session.json automatically.
Read source files: worktree at /tmp/pr-review-<pr>/src/
Follow the playbook's Enrich section. Check Escape conditions.
4. Functional Testing (subagent)
IMPORTANT: Functional testing is NOT running the project's unit tests.
DO NOT use mvn test. DO NOT run TreeTest, DO NOT run any existing test class.
The project's own tests are the author's responsibility — running them tells
the reviewer nothing new.
Functional testing means: test the feature AS A USER WOULD. Connect to a running Gremlin Server and submit traversals. Try to use the feature based only on what the documentation says. Try to break it with adversarial inputs.
Build the full project:
git worktree add /tmp/pr-review-<pr>/build pr-review/<pr>
mvn -f /tmp/pr-review-<pr>/build/pom.xml clean install -DskipTests
Start Gremlin Server from built artifacts on a random port (different from
the knowledge graph server). Use the built assembly at:
/tmp/pr-review-<pr>/build/gremlin-server/target/apache-tinkerpop-gremlin-server-*-standalone/
Test from the outside. Spawn a subagent that receives ONLY:
- PR title/description (what the change claims to do)
- Relevant documentation sections
- Relevant Gherkin test features (for expected behavior reference)
- The Gremlin Server URL
The subagent does NOT get: source code, the knowledge graph, code review findings, or access to the analysis worktree. It tests blind — like a user who read the docs.
The subagent tests by submitting Gremlin traversals via the Gremlin Console or a GLV client. It devises its own test plan from the docs, executes traversals, and attempts adversarial edge cases.
Layer decision:
- Layer 1 (embedded): Gremlin Console with TinkerGraph. For core logic changes.
- Layer 2 (per-GLV wire): Connect from each GLV to the server. For serialization/type changes. Skip if purely computational.
The subagent returns: test plan, results, adversarial findings, exact test code.
5. Produce Report
Write the narrative JSON, then render.
Step A: Read /tmp/pr-review-<pr>/evidence.json. Add narrative fields to
produce a complete evidence-with-narrative JSON file. Write it to
/tmp/pr-review-<pr>/report.json. The narrative fields you must provide:
summary— HTML paragraph describing the PRclusters.assessment— HTML prose about what the clusters meanguidedWalk— array of{ title, badge, badgeText, body }objectsfindings— array of{ title, snippet, body }objectsopenQuestions— array of{ title, body, meta }objectsfunctionalTest—{ plan, results: [{name, pass, output}], observations }(if testing was done)appendixFunctional—{ environment, testCode, fullOutput }(if testing was done)
All body fields are HTML. Use <code>, <strong>, <ul>, <p> as needed.
The renderer handles all layout, CSS, and structure.
Step B: Render the report:
node .skills/tinker-review/scripts/renderer/render.js /tmp/pr-review-<pr>/report.json /tmp/pr-review-<pr>/report.html
The renderer produces a complete HTML report with consistent structure. Every section is always present — if you didn't provide a field, it shows "Section not provided" in red. DO NOT write HTML yourself.
6. Teardown
node -e "import { teardown } from './scripts/review.js'; await teardown('/tmp/pr-review-<pr>');"
Or simply stop the Docker container and clean up manually:
docker stop $(cat /tmp/pr-review-<pr>/session.json | python3 -c "import json,sys; print(json.load(sys.stdin)['containerId'])")
rm -rf /tmp/pr-review-<pr>
git worktree prune
git branch -D pr-review/<pr>
This stops the knowledge graph server, removes worktrees, deletes the branch. Call this ONLY after all phases are complete.
Important Notes
- NEVER push to the
upstreamremote. It is fetch-only. - ALL output goes to
/tmp/pr-review-<pr>/— never write inside the git repo. - The Gremlin Server stays alive until teardown. Don't kill it early.
- If re-running, the script auto-cleans stale state.
- The agent populates JSON narrative fields; the renderer produces HTML. No agent writes raw HTML.