predicate-skill 1.6.0 → 2.0.1
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 +6 -5
- package/README.md +6 -4
- package/cli.bundle.mjs +28242 -26871
- package/dashboard/index.html +180 -0
- package/hooks/gemini-cli/README.md +10 -1
- package/hooks/gemini-cli/stop.sh +19 -4
- package/hooks/hooks.json +25 -22
- package/hooks/opencode/README.md +10 -1
- package/hooks/opencode/stop.sh +19 -3
- package/package.json +2 -1
- package/server.bundle.mjs +28371 -18709
- package/skills/predicate/SKILL.md +193 -1
|
@@ -16,6 +16,11 @@ Use Predicate when the user asks:
|
|
|
16
16
|
- **What breaks if** X changes ("blast radius of renaming `validateToken`?")
|
|
17
17
|
- **What's connected to** X transitively ("everything downstream of `JWT_SECRET`?")
|
|
18
18
|
- **Where the contradiction is** ("these two docs disagree — which holds?")
|
|
19
|
+
- **What was done previously** ("which files did I modify last session?",
|
|
20
|
+
"did `pnpm test` pass last time?", "what commands have failed most often?") —
|
|
21
|
+
the Stop-hook extractor records every prior session's tool calls into
|
|
22
|
+
`kg:abox` as `pred:Session` + `codebase:modifiedIn` / `succeededIn` /
|
|
23
|
+
`failedIn` triples. See worked example 4.
|
|
19
24
|
|
|
20
25
|
Do NOT use Predicate for:
|
|
21
26
|
- Fuzzy semantic recall ("find docs about login" — use vector search)
|
|
@@ -101,7 +106,99 @@ kg_ask(
|
|
|
101
106
|
)
|
|
102
107
|
```
|
|
103
108
|
|
|
104
|
-
## 4.
|
|
109
|
+
## 4. Session history — "which files did I touch last session?"
|
|
110
|
+
|
|
111
|
+
When the user references prior work, query the session-history slice that
|
|
112
|
+
the Stop-hook extractor maintains in `kg:abox`. The relevant predicates
|
|
113
|
+
are `pred:Session` (the session entity), `codebase:modifiedIn`,
|
|
114
|
+
`codebase:succeededIn`, `codebase:failedIn`, `codebase:commandText`.
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
kg_explore_schema("Session") # confirm the predicates
|
|
118
|
+
kg_ask(
|
|
119
|
+
question="Which files did I modify in the most recent session?",
|
|
120
|
+
sparql="""
|
|
121
|
+
PREFIX pred: <https://predicate.dev/meta#>
|
|
122
|
+
PREFIX cb: <https://predicate.dev/codebase#>
|
|
123
|
+
SELECT ?file ?session ?at WHERE {
|
|
124
|
+
GRAPH <kg:abox> {
|
|
125
|
+
?session a pred:Session ; pred:at ?at .
|
|
126
|
+
?file cb:modifiedIn ?session .
|
|
127
|
+
}
|
|
128
|
+
} ORDER BY DESC(?at) LIMIT 20
|
|
129
|
+
"""
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Other useful queries on this slice:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
# Commands that have failed most often (debug-cycle hotspots)
|
|
137
|
+
SELECT ?text (COUNT(?session) AS ?failures) WHERE {
|
|
138
|
+
GRAPH <kg:abox> {
|
|
139
|
+
?cmd a cb:Command ; cb:commandText ?text ; cb:failedIn ?session .
|
|
140
|
+
}
|
|
141
|
+
} GROUP BY ?text ORDER BY DESC(?failures)
|
|
142
|
+
|
|
143
|
+
# Files modified in this session that also failed a command (suspect debug targets)
|
|
144
|
+
SELECT DISTINCT ?file WHERE {
|
|
145
|
+
GRAPH <kg:abox> {
|
|
146
|
+
?file cb:modifiedIn ?session .
|
|
147
|
+
?cmd cb:failedIn ?session .
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Cite the session URI as provenance when the answer is "you last touched
|
|
153
|
+
auth.ts in session ses-X".
|
|
154
|
+
|
|
155
|
+
The reasoner derives additional classes on top of the raw action data
|
|
156
|
+
(refreshed by every `predicate maintain` run):
|
|
157
|
+
|
|
158
|
+
| Derived class | Means |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `codebase:Hotspot` | File modified in >= 3 sessions — likely active work-in-progress |
|
|
161
|
+
| `codebase:FlakyCommand` | Command that has failed in >= 2 sessions — suspect debug target |
|
|
162
|
+
| `codebase:ActiveFile` | File modified in the single most-recent session |
|
|
163
|
+
|
|
164
|
+
Query them directly via `kg:inferred`:
|
|
165
|
+
|
|
166
|
+
```sparql
|
|
167
|
+
PREFIX cb: <https://predicate.dev/codebase#>
|
|
168
|
+
SELECT ?file WHERE { GRAPH <kg:inferred> { ?file a cb:Hotspot } }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## 5. Memory recall — "what did I do with X recently?"
|
|
172
|
+
|
|
173
|
+
For substring-match recall over session history, call `predicate recall`
|
|
174
|
+
(or `kg_ask` with the equivalent SPARQL). Useful when the user asks
|
|
175
|
+
"what did I work on related to X?" or "did I ever run command Y?"
|
|
176
|
+
|
|
177
|
+
```sparql
|
|
178
|
+
PREFIX cb: <https://predicate.dev/codebase#>
|
|
179
|
+
PREFIX pred: <https://predicate.dev/meta#>
|
|
180
|
+
SELECT ?file (COUNT(DISTINCT ?session) AS ?n) (MAX(?at) AS ?lastAt)
|
|
181
|
+
WHERE {
|
|
182
|
+
GRAPH <kg:abox> {
|
|
183
|
+
?file cb:modifiedIn ?session .
|
|
184
|
+
?session pred:at ?at .
|
|
185
|
+
FILTER (CONTAINS(LCASE(STR(?file)), LCASE("auth")))
|
|
186
|
+
}
|
|
187
|
+
} GROUP BY ?file ORDER BY DESC(?lastAt)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Combine with the `cb:Hotspot` / `cb:FlakyCommand` / `cb:ActiveFile` derived
|
|
191
|
+
classes from `kg:inferred` for richer answers ("is auth.ts a hotspot?").
|
|
192
|
+
|
|
193
|
+
Shell shortcut:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
predicate recall auth # files + commands matching "auth"
|
|
197
|
+
predicate recall "pnpm test" # commands matching exact substring
|
|
198
|
+
predicate recall auth --json # machine-readable output
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 6. Schema gap → propose
|
|
105
202
|
|
|
106
203
|
```
|
|
107
204
|
# User asks: "which services own these endpoints?"
|
|
@@ -117,3 +214,98 @@ kg_propose_schema(
|
|
|
117
214
|
)
|
|
118
215
|
# This goes to kg:tbox-staging. The promotion gate requires 3 successful uses in 7 days.
|
|
119
216
|
```
|
|
217
|
+
|
|
218
|
+
## Federation
|
|
219
|
+
|
|
220
|
+
If teammates also use Predicate, they can share session-history:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# On Alice's machine:
|
|
224
|
+
predicate export-sessions --user alice > alice.trig
|
|
225
|
+
# Send to Bob (Slack, scp, etc.)
|
|
226
|
+
|
|
227
|
+
# On Bob's machine:
|
|
228
|
+
predicate import-sessions alice.trig
|
|
229
|
+
predicate peer add alice http://alice.local:3030/predicate/query # optional, for live queries
|
|
230
|
+
|
|
231
|
+
# Then kg_ask can union local + remote:
|
|
232
|
+
kg_ask --include-remote ...
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
This MVP is offline-friendly: no realtime sync, no auth. Each user's data
|
|
236
|
+
lives in a separate named graph so there are no merge conflicts. Same-IRI
|
|
237
|
+
collisions (e.g. `file:///work/auth.ts` from two users) are treated as
|
|
238
|
+
the same resource by RDF — use `owl:sameAs` if you want them merged, or
|
|
239
|
+
namespace your files per-user if you want them separate.
|
|
240
|
+
|
|
241
|
+
## External Linked Data
|
|
242
|
+
|
|
243
|
+
For canonical public knowledge (Wikidata, DBpedia), call `predicate ld
|
|
244
|
+
ask` instead of trying to recall from training data. Examples:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
predicate ld init # one-time
|
|
248
|
+
|
|
249
|
+
predicate ld ask 'SELECT ?label WHERE {
|
|
250
|
+
<http://dbpedia.org/resource/JSON> rdfs:label ?label .
|
|
251
|
+
FILTER (LANG(?label) = "en")
|
|
252
|
+
} LIMIT 1'
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Use cases:
|
|
256
|
+
- "Is library X deprecated?" → check Wikidata for last-release metadata
|
|
257
|
+
- "Who maintains project Y?" → DBpedia abstract
|
|
258
|
+
- "What's the canonical URI for concept Z?" → both
|
|
259
|
+
|
|
260
|
+
`predicate ld init` registers `dbpedia` and `wikidata` as peers in
|
|
261
|
+
`kg:peers` with `pred:peerKind "external-ld"`. The marker keeps them
|
|
262
|
+
distinct from team peers — `predicate peer list` shows everything
|
|
263
|
+
side-by-side with a `kind` column; `predicate ld list` filters to just
|
|
264
|
+
the LD endpoints. Results from `ld ask` are NOT written back to local
|
|
265
|
+
`kg:abox` — each call re-fetches, so don't run this in tight loops.
|
|
266
|
+
|
|
267
|
+
## Goal decomposition
|
|
268
|
+
|
|
269
|
+
The default `kg_research_goal` uses a pattern-based decomposer
|
|
270
|
+
(deterministic, fast, predictable). For questions that don't match any
|
|
271
|
+
pattern, you can opt-in to LLM-augmented decomposition by passing
|
|
272
|
+
`useLlmDecomposer: true`. The LLM (Claude Haiku) is constrained to
|
|
273
|
+
emit only the known intent kinds — invented kinds are filtered out.
|
|
274
|
+
If no `ANTHROPIC_API_KEY` is set, it transparently falls back to the
|
|
275
|
+
deterministic decomposer's 'unknown' result. The response includes a
|
|
276
|
+
`decomposerKind` field (`"deterministic"` or `"semantic"`) so you know
|
|
277
|
+
which path produced the sub-questions. Pattern-matched questions like
|
|
278
|
+
"what calls X" skip the LLM entirely.
|
|
279
|
+
|
|
280
|
+
## Schema-learning toggle (v2.0)
|
|
281
|
+
|
|
282
|
+
The autonomous proposer (Generalizer) runs by default — when the agent
|
|
283
|
+
asserts a triple using a not-yet-declared pattern that appears in >= K
|
|
284
|
+
instances, it auto-stages a `kg_propose_schema` candidate. The sweeper
|
|
285
|
+
promotes after 3 successful uses.
|
|
286
|
+
|
|
287
|
+
To pause that loop (e.g., the user says "stop adding new predicates"):
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
kg_config_set({ key: "schema-learning", value: false })
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
When off:
|
|
294
|
+
- The Generalizer skips proposal generation.
|
|
295
|
+
- `kg_propose_schema` (explicit MCP calls) STILL works.
|
|
296
|
+
- The PromotionSweeper STILL promotes existing staged proposals.
|
|
297
|
+
|
|
298
|
+
Re-enable with `kg_config_set({ key: "schema-learning", value: true })`.
|
|
299
|
+
Read current state with `kg_config_get({ key: "schema-learning" })`.
|
|
300
|
+
|
|
301
|
+
## Init / bootstrap (v2.0)
|
|
302
|
+
|
|
303
|
+
Predicate v2.0 boots empty. On first `predicate up`, the user picks one
|
|
304
|
+
of three modes via `predicate init` (interactive prompt or flags):
|
|
305
|
+
|
|
306
|
+
- **community**: bundled ontology (codebase, foaf, schema-org-lite, fhir-core)
|
|
307
|
+
- **upload**: user-supplied .ttl
|
|
308
|
+
- **empty**: meta + minimal top vocab; agent grows it via propose -> 3-use -> promote
|
|
309
|
+
|
|
310
|
+
The chosen mode is stored at `<urn:predicate:config>` in kg:meta and the
|
|
311
|
+
SessionStart banner reflects it.
|