---
name: devkg-sparql
version: 1.0.0
category: 生活与工具
trigger_words:
tags:
  - ai
platform: coze
source: DeepseekModel
source_url: https://deepseekmodel.com/skill?id=robertoshimizu-session-graph-claude-skills-devkg-sparql-skill-md
---

name devkg-sparql description Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files. Use this when asked about technologies, relationships between tools, session history, where a topic was discussed, or cross-platform knowledge. Prefer provenance-first SPARQL (message + session) over label-only CONTAINS or grep. user-invocable true allowed-tools ["Bash(curl:*)","Bash(jq:*)"] DevKG SPARQL Query Skill CRITICAL CONTEXT-SAFETY RULE NEVER READ LARGE SPARQL RESULTS, SESSION FILES, JSONL, LOGS, OR GENERATED ARTIFACTS ALL AT ONCE. Always add LIMIT , select only needed variables, inspect counts first, and summarize. Never dump huge result sets, ID lists, raw JSON, or transcript content into chat. Query the developer knowledge graph at http://localhost:3030/devkg/sparql via SPARQL. This graph contains extracted knowledge triples, entities, Wikidata links, and session metadata from Claude Code, pi, Codex, Cursor, ChatGPT, DeepSeek, Grok, and Warp sessions. Content limit: sioc:content on messages is capped at ~2000 characters at ingest. SPARQL is enough to locate sessions and reason lightly from triples + snippets. For full quotes or deep thread reconstruction, normalize hasSourceFile and read the JSONL only when needed. Retrieval Strategy (read this first) User intent Do this first Do NOT start with "Where / which sessions discussed X?" Template 5 (topic + intent + provenance) Label-only Template 6, or grep "What do we know about technology X?" Template 1 (entity + provenance) Grep "How does X relate to Y?" Template 2 Grep "Find the exact message wording" Template 5 or 9 → then JSONL only if snippet truncated Grepping all projects Default for session-discovery questions: multi-signal filter (topic and intent terms) on both triple labels and sioc:content , always joining extractedFrom / extractedInSession , ordered by DESC(?created) , with LIMIT . When Fuseki returns provenance hits, do not fall back to grep. Grep only if Fuseki is down or returns 0 rows after a provenance query. Execution Pattern Always use this pattern (POST, URL-encoded query, JSON output). Include Fuseki auth when required: curl -s -X POST 'http://localhost:3030/devkg/sparql' \ -u admin:admin \ -H 'Accept: application/sparql-results+json' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode "query=YOUR_SPARQL_HERE" \ | jq -r '.results.bindings[] | [.var1.value, .var2.value] | @tsv' Adjust the jq expression to match your SELECT variables. Use @tsv for compact tabular output. Always LIMIT results. For multi-line queries, use double quotes around the --data-urlencode value and escape inner quotes: curl -s -X POST 'http://localhost:3030/devkg/sparql' \ -u admin:admin \ -H 'Accept: application/sparql-results+json' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode "query=PREFIX devkg: <http://devkg.local/ontology#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> SELECT DISTINCT ?label WHERE { ?e a devkg:Entity ; rdfs:label ?label . FILTER(LANG(?label) = \"\") } LIMIT 10" \ | jq -r '.results.bindings[] | .label.value' Fallback Rule If Fuseki is unreachable (curl fails or times out) or a provenance query (Template 5/8) returns 0 results, then fall back to grep-based session search: grep -rli "keyword" ~/.claude/projects ~/.pi/agent/sessions ~/.cursor/projects 2>/dev/null | head -20 Then read matching JSONL files with bounded Python extraction. Only use this as a last resort. Resolving hasSourceFile to Disk (and Pruned Sources) hasSourceFile is NOT always a real absolute path. Normalize before any Read : hasSourceFile prefix Real on-disk location /Users/... absolute path — use as-is /claude-sessions/<munged>/<file> ~/.claude/projects/<munged>/<file> /pi-sessions/<munged>/<file> ~/.pi/agent/sessions/<munged>/<file> /codex-sessions/<path> ~/.codex/sessions/<path> /cursor-sessions/projects/<slug>/... ~/.cursor/projects/<slug>/... resolve_session_path () { local sf= " $1 " p= "" case " $sf " in /Users/*) p= " $sf " ;; /claude-sessions/*) p= " $HOME /.claude/projects/ ${sf#/claude-sessions/} " ;; /pi-sessions/*) p= " $HOME /.pi/agent/sessions/ ${sf#/pi-sessions/} " ;; /codex-sessions/*) p= " $HOME /.codex/sessions/ ${sf#/codex-sessions/} " ;; /cursor-sessions/projects/*) p= " $HOME /.cursor/projects/ ${sf#/cursor-sessions/projects/} " ;; *) p= " $sf " ;; esac local stem= " ${p%.jsonl} " if [ -f " $p " ]; then echo "FILE: $p " ; return ; fi if [ -f " $stem " ]; then echo "FILE: $stem " ; return ; fi if [ -d " $stem /subagents" ]; then echo "SUBAGENTS: $stem /subagents" ; return ; fi if [ -d " $p /subagents" ]; then echo "SUBAGENTS: $p /subagents" ; return ; fi echo "PRUNED: $p " } If the path is PRUNED , do NOT grep the filesystem. Re-query KnowledgeTriples for that session via extractedInSession and reconstruct from labels + any remaining sioc:content . Result Formatting Present SPARQL results as markdown tables. Never dump raw JSON to the user. Prefixes (copy into every query) PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX prov: <http://www.w3.org/ns/prov#> PREFIX sioc: <http://rdfs.org/sioc/ns#> PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX dcterms: <http://purl.org/dc/terms/> PREFIX devkg: <http://devkg.local/ontology#> PREFIX data: <http://devkg.local/data/> PREFIX wd: <http://www.wikidata.org/entity/> Ontology Cheat Sheet Classes Class Parent Description devkg:Session prov:Activity , sioc:Forum A working session (conversation) devkg:Message sioc:Post , prov:Entity A message in a session devkg:UserMessage devkg:Message Human message devkg:AssistantMessage devkg:Message AI message devkg:ToolCall prov:Activity Legacy tool invocation nodes (may be absent in new ingests — do not rely on them) devkg:ToolResult prov:Entity Legacy tool output (may be absent in new ingests) devkg:CodeArtifact prov:Entity , schema:SoftwareSourceCode Code file/snippet devkg:Entity prov:Entity Extracted technical concept devkg:KnowledgeTriple — Reified triple (subject→predicate→object) with provenance devkg:Project prov:Entity A development project devkg:Developer prov:Agent Human developer devkg:AIModel prov:Agent AI model (Claude, GPT, etc.) devkg:Topic skos:Concept Knowledge topic Structural Predicates (Session/Message graph) Predicate Domain → Range Notes devkg:usedInSession Message/ToolCall → Session Links content to its session devkg:hasParentMessage Message → Message Thread structure devkg:mentionsTopic Message → Topic Topic tagging devkg:invokedTool AssistantMessage → ToolCall Tool usage devkg:hasToolResult ToolCall → ToolResult Tool output devkg:producedArtifact Activity → CodeArtifact Code generation devkg:belongsToProject Session → Project Project membership devkg:extractedFrom KnowledgeTriple → Message Triple provenance devkg:extractedInSession KnowledgeTriple → Session Triple provenance devkg:tripleSubject KnowledgeTriple → Entity Reified subject devkg:tripleObject KnowledgeTriple → Entity Reified object devkg:triplePredicateLabel KnowledgeTriple → xsd:string Predicate name Key Datatype Properties Property On Value sioc:content Message Message text (truncated ~2000 chars at ingest) rdfs:label Entity/Session/Project Display name dcterms:created Session/Message ISO datetime devkg:hasSourcePlatform Session claude-code , pi-coding-agent , codex , cursor , chatgpt , deepseek , grok , warp devkg:hasSourceFile Session Logical path to raw source — normalize before Read (see "Resolving hasSourceFile to Disk") devkg:hasToolName ToolCall Legacy — prefer KnowledgeTriples + message content for discovery devkg:hasWorkingDirectory Session Project directory path owl:sameAs Entity Wikidata URI (e.g., wd:Q28865 ) Knowledge Predicates (24 total) These connect devkg:Entity to devkg:Entity via direct edges AND are stored as devkg:triplePredicateLabel strings on reified devkg:KnowledgeTriple nodes: uses , dependsOn , enables , isPartOf , hasPart , implements , extends , alternativeTo , solves , produces , configures , composesWith , provides , requires , isTypeOf , builtWith , deployedOn , storesIn , queriedWith , integratesWith , broader , narrower , relatedTo , servesAs Query Templates 1. Entity Lookup — "What do we know about X?" Returns all relationships (outbound + inbound) for an entity, with source file and content snippet for provenance. Use CONTAINS for fuzzy matching. SELECT DISTINCT ?direction ?predicate ?otherLabel ?sourceFile ?platform (SUBSTR(?content, 1, 150) AS ?snippet) WHERE { { ?triple a devkg:KnowledgeTriple ; devkg:tripleSubject ?s ; devkg:triplePredicateLabel ?predicate ; devkg:tripleObject ?o ; devkg:extractedFrom ?msg ; devkg:extractedInSession ?session . ?s rdfs:label ?sLabel . ?o rdfs:label ?otherLabel . FILTER(CONTAINS(LCASE(STR(?sLabel)), "ENTITY_LOWER")) BIND("outbound" AS ?direction) } UNION { ?triple a devkg:KnowledgeTriple ; devkg:tripleSubject ?o ; devkg:triplePredicateLabel ?predicate ; devkg:tripleObject ?obj ; devkg:extractedFrom ?msg ; devkg:extractedInSession ?session . ?obj rdfs:label ?oLabel . ?o rdfs:label ?otherLabel . FILTER(CONTAINS(LCASE(STR(?oLabel)), "ENTITY_LOWER")) BIND("inbound" AS ?direction) } OPTIONAL { ?session devkg:hasSourceFile ?sourceFile } OPTIONAL { ?session devkg:hasSourcePlatform ?platform } OPTIONAL { ?msg sioc:content ?content } } ORDER BY ?direction ?predicate Replace ENTITY_LOWER with the lowercase entity name (e.g., neo4j , opentelemetry ). The sourceFile column is a logical path to the original JSONL/JSON file — normalize it with resolve_session_path (see "Resolving hasSourceFile to Disk") before Read ; if it resolves to PRUNED , reconstruct from the triples instead. 2. Entity-to-Entity — "How does X relate to Y?" SELECT DISTINCT ?predicate ?sourceSnippet WHERE { ?triple a devkg:KnowledgeTriple ; devkg:tripleSubject ?s ; devkg:triplePredicateLabel ?predicate ; devkg:tripleObject ?o ; devkg:extractedFrom ?msg . ?s rdfs:label ?sLabel . ?o rdfs:label ?oLabel . OPTIONAL { ?msg sioc:content ?c . BIND(SUBSTR(?c, 1, 150) AS ?sourceSnippet) } FILTER( CONTAINS(LCASE(STR(?sLabel)), "ENTITY_X") && CONTAINS(LCASE(STR(?oLabel)), "ENTITY_Y") ) } 3. Predicate Search — "What uses/enables/solves X?" SELECT DISTINCT ?subjectLabel ?objectLabel WHERE { ?triple a devkg:KnowledgeTriple ; devkg:tripleSubject ?s ; devkg:triplePredicateLabel "PREDICATE" ;