predicate-skill 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +24 -0
- package/LICENSE +202 -0
- package/README.md +47 -0
- package/cli.bundle.mjs +324 -0
- package/commands/ask.md +18 -0
- package/commands/doctor.md +14 -0
- package/commands/down.md +11 -0
- package/commands/stats.md +22 -0
- package/commands/up.md +13 -0
- package/compose/docker-compose.yml +25 -0
- package/compose/fuseki/config.ttl +18 -0
- package/hooks/hooks.json +9 -0
- package/hooks/session-start.sh +25 -0
- package/package.json +47 -0
- package/server.bundle.mjs +38038 -0
- package/skills/predicate/SKILL.md +119 -0
- package/skills/predicate-doctor/SKILL.md +28 -0
- package/skills/predicate-stats/SKILL.md +29 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: predicate
|
|
3
|
+
description: Local reasoning knowledge graph for "why", "what breaks if", and "what's connected to" questions. OWL-backed, provenance-tracked, schema-versioned. Use instead of RAG when the question is structural rather than fuzzy-semantic.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<EXTREMELY-IMPORTANT>
|
|
7
|
+
Do NOT invent predicates. ALWAYS call `kg_explore_schema` before drafting SPARQL.
|
|
8
|
+
If a predicate you need does not exist, call `kg_propose_schema` — never use
|
|
9
|
+
`kg_assert` with a fabricated property name.
|
|
10
|
+
</EXTREMELY-IMPORTANT>
|
|
11
|
+
|
|
12
|
+
# When to use this skill
|
|
13
|
+
|
|
14
|
+
Use Predicate when the user asks:
|
|
15
|
+
- **Why** something happened ("why did login break?")
|
|
16
|
+
- **What breaks if** X changes ("blast radius of renaming `validateToken`?")
|
|
17
|
+
- **What's connected to** X transitively ("everything downstream of `JWT_SECRET`?")
|
|
18
|
+
- **Where the contradiction is** ("these two docs disagree — which holds?")
|
|
19
|
+
|
|
20
|
+
Do NOT use Predicate for:
|
|
21
|
+
- Fuzzy semantic recall ("find docs about login" — use vector search)
|
|
22
|
+
- One-shot Q&A with no entities/relations
|
|
23
|
+
|
|
24
|
+
# Workflow
|
|
25
|
+
|
|
26
|
+
Follow this sequence. Each step has a hard gate.
|
|
27
|
+
|
|
28
|
+
1. **Explore the schema first.** Call `kg_explore_schema(concept)` to learn the
|
|
29
|
+
predicates available. Do not draft SPARQL without doing this.
|
|
30
|
+
2. **Draft fresh SPARQL.** Compose a query against `kg:abox` and `kg:inferred`.
|
|
31
|
+
Pre-baked templates are forbidden. The query should be specific to the
|
|
32
|
+
concept slice you just read.
|
|
33
|
+
3. **Execute via `kg_ask`.** Pass the question and SPARQL. Inspect rows. If
|
|
34
|
+
empty or odd, refine — narrow filters, broaden graphs, check for typos.
|
|
35
|
+
4. **Cite provenance.** For every claim the user might act on, call
|
|
36
|
+
`kg_explain` to surface the inference path. Show the user the SOURCE,
|
|
37
|
+
CONFIDENCE, and METHOD for the load-bearing triples.
|
|
38
|
+
5. **Assert only after research.** If you learned something new in the session,
|
|
39
|
+
call `kg_assert(triple, source, confidence, method)`. Confidence must be
|
|
40
|
+
honest (parsed code: 0.95+; extracted from prose: 0.6–0.8).
|
|
41
|
+
6. **Propose schema only when ABox cannot represent the fact.** If the gap is
|
|
42
|
+
structural (no class or property exists), call `kg_propose_schema(delta,
|
|
43
|
+
justification)`. The promotion gate requires the proposed concept be used
|
|
44
|
+
in N ≥ 3 successful queries within 7 days before it joins the live TBox.
|
|
45
|
+
|
|
46
|
+
# HARD-GATE anti-patterns
|
|
47
|
+
|
|
48
|
+
- ❌ Dumping raw text into `kg_assert` — assertions are triples, not prose.
|
|
49
|
+
- ❌ Querying `kg:inferred` to write back into `kg:abox`.
|
|
50
|
+
- ❌ Bypassing SHACL by writing to graphs that skip validation.
|
|
51
|
+
- ❌ Inventing predicates — always check the TBox first.
|
|
52
|
+
|
|
53
|
+
# Worked examples
|
|
54
|
+
|
|
55
|
+
## 1. Why did login break?
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
kg_explore_schema("Function") # learn :calls, :declaredIn, :reads
|
|
59
|
+
kg_ask(
|
|
60
|
+
question="What does login depend on?",
|
|
61
|
+
sparql="""
|
|
62
|
+
PREFIX c: <https://predicate.dev/codebase#>
|
|
63
|
+
SELECT ?dep WHERE {
|
|
64
|
+
{ GRAPH <kg:abox> { <https://predicate.dev/codebase/auth.ts#login> c:reads|c:calls ?dep } }
|
|
65
|
+
UNION
|
|
66
|
+
{ GRAPH <kg:inferred> { <https://predicate.dev/codebase/auth.ts#login> c:dependsOn ?dep } }
|
|
67
|
+
}
|
|
68
|
+
"""
|
|
69
|
+
)
|
|
70
|
+
kg_explain("auth.ts#login depends on JWT_SECRET")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 2. Blast radius of renaming `validateToken`
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
kg_explore_schema("calls")
|
|
77
|
+
kg_ask(
|
|
78
|
+
question="What calls validateToken transitively?",
|
|
79
|
+
sparql="""
|
|
80
|
+
PREFIX c: <https://predicate.dev/codebase#>
|
|
81
|
+
SELECT ?caller WHERE {
|
|
82
|
+
GRAPH <kg:inferred> { ?caller c:calls* <...#validateToken> }
|
|
83
|
+
}
|
|
84
|
+
"""
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 3. Contradiction detection
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
kg_ask(
|
|
92
|
+
question="Any disjoint-class violations?",
|
|
93
|
+
sparql="""
|
|
94
|
+
PREFIX c: <https://predicate.dev/codebase#>
|
|
95
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
96
|
+
SELECT ?x ?a ?b WHERE {
|
|
97
|
+
GRAPH <kg:inferred> { ?x a ?a, ?b }
|
|
98
|
+
GRAPH <kg:tbox> { ?a owl:disjointWith ?b }
|
|
99
|
+
}
|
|
100
|
+
"""
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 4. Schema gap → propose
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
# User asks: "which services own these endpoints?"
|
|
108
|
+
# kg_explore_schema reveals: no :owns property exists
|
|
109
|
+
kg_propose_schema(
|
|
110
|
+
delta="""
|
|
111
|
+
@prefix c: <https://predicate.dev/codebase#> .
|
|
112
|
+
c:Service a owl:Class .
|
|
113
|
+
c:owns a owl:ObjectProperty ;
|
|
114
|
+
rdfs:domain c:Service ; rdfs:range c:Endpoint .
|
|
115
|
+
""",
|
|
116
|
+
justification="Goal G-123 asks 'which service owns /login'; no current property captures service-to-endpoint ownership."
|
|
117
|
+
)
|
|
118
|
+
# This goes to kg:tbox-staging. The promotion gate requires 3 successful uses in 7 days.
|
|
119
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: predicate-doctor
|
|
3
|
+
description: Run a health check on the Predicate stack — Fuseki reachability, TBox loaded, all 8 kg_* tools responsive. Use when the user asks "is predicate working", "what's the status", or any kg_* tool just returned an unexpected error.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# When to use
|
|
7
|
+
|
|
8
|
+
- The user asks "is predicate up", "check predicate", "what's wrong with the kg".
|
|
9
|
+
- A `kg_*` MCP tool just returned a connection or auth error.
|
|
10
|
+
- After bringing Fuseki up for the first time, to confirm the seed TBox loaded.
|
|
11
|
+
|
|
12
|
+
# Workflow
|
|
13
|
+
|
|
14
|
+
1. Call `kg_stats`. If it errors with a connection refused or 401, **Fuseki is not reachable** — tell the user to run `predicate up` (or `pnpm fuseki:up` from a dev clone) and stop here.
|
|
15
|
+
2. If `kg_stats` succeeds, report:
|
|
16
|
+
- `s.tbox > 0` → TBox is loaded.
|
|
17
|
+
- `s.classes` → number of declared classes (should be ≥ 10 for the seed codebase TBox).
|
|
18
|
+
- `s.triples`, `s.abox`, `s.inferred` → graph sizes.
|
|
19
|
+
3. Optionally call `kg_explore_schema("File")` to confirm the seed TBox is the codebase domain.
|
|
20
|
+
|
|
21
|
+
# Report format
|
|
22
|
+
|
|
23
|
+
A short summary in this shape:
|
|
24
|
+
|
|
25
|
+
> Predicate is **up**. TBox: N classes. ABox: M triples. Inferred: K. Last
|
|
26
|
+
> materialization p95: X ms. (or: "no materialization events yet")
|
|
27
|
+
|
|
28
|
+
If anything is off, lead with what's broken and the one-liner fix.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: predicate-stats
|
|
3
|
+
description: Show current graph metrics — triple counts, inferred ratio, unused-concept ratio. Use when the user asks "how big is the graph", "what's the inferred ratio", "show stats", or wants to track v1 success metrics from the PRD.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# When to use
|
|
7
|
+
|
|
8
|
+
- The user asks "how many triples", "graph size", "stats", "metrics".
|
|
9
|
+
- The user wants to track the bounded-growth metric (`unusedConceptRatio < 0.15`).
|
|
10
|
+
- Before/after a `kg_maintain` run to see what changed.
|
|
11
|
+
|
|
12
|
+
# Workflow
|
|
13
|
+
|
|
14
|
+
1. Call `kg_stats`.
|
|
15
|
+
2. Render the result as a compact table:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
triples 123
|
|
19
|
+
abox 45
|
|
20
|
+
inferred 8
|
|
21
|
+
tbox 70
|
|
22
|
+
classes 12
|
|
23
|
+
inferredRatio 0.151
|
|
24
|
+
unusedConceptRatio 0.500
|
|
25
|
+
materializationLatencyMsP95 0
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
3. If `unusedConceptRatio > 0.15`, note that the bounded-growth metric is currently failing the PRD §16 target and the next `kg_maintain` run should help.
|
|
29
|
+
4. If `materializationLatencyMsP95 == 0`, note that no materialization events have been recorded yet (this is normal until the reasoner runs).
|