predicate-skill 2.0.2 → 2.0.4

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "predicate",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Local reasoning knowledge graph (RDF/OWL) for AI agents — 9 kg_* MCP tools + cross-platform Stop-hook turn extraction (Claude Code + Gemini CLI + OpenCode) + reasoning bridge for action data.",
5
5
  "author": {
6
6
  "name": "Nordic Agents Research",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "homepage": "https://github.com/NordicAgents/predicate#readme",
10
10
  "repository": "https://github.com/NordicAgents/predicate",
11
- "license": "Apache-2.0",
11
+ "license": "Elastic-2.0",
12
12
  "keywords": ["mcp", "knowledge-graph", "rdf", "owl", "sparql", "reasoning"],
13
13
  "mcpServers": {
14
14
  "predicate": {
package/LICENSE CHANGED
@@ -1,202 +1,93 @@
1
+ Elastic License 2.0 (ELv2)
1
2
 
2
- Apache License
3
- Version 2.0, January 2004
4
- http://www.apache.org/licenses/
5
-
6
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
-
8
- 1. Definitions.
9
-
10
- "License" shall mean the terms and conditions for use, reproduction,
11
- and distribution as defined by Sections 1 through 9 of this document.
12
-
13
- "Licensor" shall mean the copyright owner or entity authorized by
14
- the copyright owner that is granting the License.
15
-
16
- "Legal Entity" shall mean the union of the acting entity and all
17
- other entities that control, are controlled by, or are under common
18
- control with that entity. For the purposes of this definition,
19
- "control" means (i) the power, direct or indirect, to cause the
20
- direction or management of such entity, whether by contract or
21
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
- outstanding shares, or (iii) beneficial ownership of such entity.
23
-
24
- "You" (or "Your") shall mean an individual or Legal Entity
25
- exercising permissions granted by this License.
26
-
27
- "Source" form shall mean the preferred form for making modifications,
28
- including but not limited to software source code, documentation
29
- source, and configuration files.
30
-
31
- "Object" form shall mean any form resulting from mechanical
32
- transformation or translation of a Source form, including but
33
- not limited to compiled object code, generated documentation,
34
- and conversions to other media types.
35
-
36
- "Work" shall mean the work of authorship, whether in Source or
37
- Object form, made available under the License, as indicated by a
38
- copyright notice that is included in or attached to the work
39
- (an example is provided in the Appendix below).
40
-
41
- "Derivative Works" shall mean any work, whether in Source or Object
42
- form, that is based on (or derived from) the Work and for which the
43
- editorial revisions, annotations, elaborations, or other modifications
44
- represent, as a whole, an original work of authorship. For the purposes
45
- of this License, Derivative Works shall not include works that remain
46
- separable from, or merely link (or bind by name) to the interfaces of,
47
- the Work and Derivative Works thereof.
48
-
49
- "Contribution" shall mean any work of authorship, including
50
- the original version of the Work and any modifications or additions
51
- to that Work or Derivative Works thereof, that is intentionally
52
- submitted to Licensor for inclusion in the Work by the copyright owner
53
- or by an individual or Legal Entity authorized to submit on behalf of
54
- the copyright owner. For the purposes of this definition, "submitted"
55
- means any form of electronic, verbal, or written communication sent
56
- to the Licensor or its representatives, including but not limited to
57
- communication on electronic mailing lists, source code control systems,
58
- and issue tracking systems that are managed by, or on behalf of, the
59
- Licensor for the purpose of discussing and improving the Work, but
60
- excluding communication that is conspicuously marked or otherwise
61
- designated in writing by the copyright owner as "Not a Contribution."
62
-
63
- "Contributor" shall mean Licensor and any individual or Legal Entity
64
- on behalf of whom a Contribution has been received by Licensor and
65
- subsequently incorporated within the Work.
66
-
67
- 2. Grant of Copyright License. Subject to the terms and conditions of
68
- this License, each Contributor hereby grants to You a perpetual,
69
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
- copyright license to reproduce, prepare Derivative Works of,
71
- publicly display, publicly perform, sublicense, and distribute the
72
- Work and such Derivative Works in Source or Object form.
73
-
74
- 3. Grant of Patent License. Subject to the terms and conditions of
75
- this License, each Contributor hereby grants to You a perpetual,
76
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
- (except as stated in this section) patent license to make, have made,
78
- use, offer to sell, sell, import, and otherwise transfer the Work,
79
- where such license applies only to those patent claims licensable
80
- by such Contributor that are necessarily infringed by their
81
- Contribution(s) alone or by combination of their Contribution(s)
82
- with the Work to which such Contribution(s) was submitted. If You
83
- institute patent litigation against any entity (including a
84
- cross-claim or counterclaim in a lawsuit) alleging that the Work
85
- or a Contribution incorporated within the Work constitutes direct
86
- or contributory patent infringement, then any patent licenses
87
- granted to You under this License for that Work shall terminate
88
- as of the date such litigation is filed.
89
-
90
- 4. Redistribution. You may reproduce and distribute copies of the
91
- Work or Derivative Works thereof in any medium, with or without
92
- modifications, and in Source or Object form, provided that You
93
- meet the following conditions:
94
-
95
- (a) You must give any other recipients of the Work or
96
- Derivative Works a copy of this License; and
97
-
98
- (b) You must cause any modified files to carry prominent notices
99
- stating that You changed the files; and
100
-
101
- (c) You must retain, in the Source form of any Derivative Works
102
- that You distribute, all copyright, patent, trademark, and
103
- attribution notices from the Source form of the Work,
104
- excluding those notices that do not pertain to any part of
105
- the Derivative Works; and
106
-
107
- (d) If the Work includes a "NOTICE" text file as part of its
108
- distribution, then any Derivative Works that You distribute must
109
- include a readable copy of the attribution notices contained
110
- within such NOTICE file, excluding those notices that do not
111
- pertain to any part of the Derivative Works, in at least one
112
- of the following places: within a NOTICE text file distributed
113
- as part of the Derivative Works; within the Source form or
114
- documentation, if provided along with the Derivative Works; or,
115
- within a display generated by the Derivative Works, if and
116
- wherever such third-party notices normally appear. The contents
117
- of the NOTICE file are for informational purposes only and
118
- do not modify the License. You may add Your own attribution
119
- notices within Derivative Works that You distribute, alongside
120
- or as an addendum to the NOTICE text from the Work, provided
121
- that such additional attribution notices cannot be construed
122
- as modifying the License.
123
-
124
- You may add Your own copyright statement to Your modifications and
125
- may provide additional or different license terms and conditions
126
- for use, reproduction, or distribution of Your modifications, or
127
- for any such Derivative Works as a whole, provided Your use,
128
- reproduction, and distribution of the Work otherwise complies with
129
- the conditions stated in this License.
130
-
131
- 5. Submission of Contributions. Unless You explicitly state otherwise,
132
- any Contribution intentionally submitted for inclusion in the Work
133
- by You to the Licensor shall be under the terms and conditions of
134
- this License, without any additional terms or conditions.
135
- Notwithstanding the above, nothing herein shall supersede or modify
136
- the terms of any separate license agreement you may have executed
137
- with Licensor regarding such Contributions.
138
-
139
- 6. Trademarks. This License does not grant permission to use the trade
140
- names, trademarks, service marks, or product names of the Licensor,
141
- except as required for reasonable and customary use in describing the
142
- origin of the Work and reproducing the content of the NOTICE file.
143
-
144
- 7. Disclaimer of Warranty. Unless required by applicable law or
145
- agreed to in writing, Licensor provides the Work (and each
146
- Contributor provides its Contributions) on an "AS IS" BASIS,
147
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
- implied, including, without limitation, any warranties or conditions
149
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
- PARTICULAR PURPOSE. You are solely responsible for determining the
151
- appropriateness of using or redistributing the Work and assume any
152
- risks associated with Your exercise of permissions under this License.
153
-
154
- 8. Limitation of Liability. In no event and under no legal theory,
155
- whether in tort (including negligence), contract, or otherwise,
156
- unless required by applicable law (such as deliberate and grossly
157
- negligent acts) or agreed to in writing, shall any Contributor be
158
- liable to You for damages, including any direct, indirect, special,
159
- incidental, or consequential damages of any character arising as a
160
- result of this License or out of the use or inability to use the
161
- Work (including but not limited to damages for loss of goodwill,
162
- work stoppage, computer failure or malfunction, or any and all
163
- other commercial damages or losses), even if such Contributor
164
- has been advised of the possibility of such damages.
165
-
166
- 9. Accepting Warranty or Additional Liability. While redistributing
167
- the Work or Derivative Works thereof, You may choose to offer,
168
- and charge a fee for, acceptance of support, warranty, indemnity,
169
- or other liability obligations and/or rights consistent with this
170
- License. However, in accepting such obligations, You may act only
171
- on Your own behalf and on Your sole responsibility, not on behalf
172
- of any other Contributor, and only if You agree to indemnify,
173
- defend, and hold each Contributor harmless for any liability
174
- incurred by, or claims asserted against, such Contributor by reason
175
- of your accepting any such warranty or additional liability.
176
-
177
- END OF TERMS AND CONDITIONS
178
-
179
- APPENDIX: How to apply the Apache License to your work.
180
-
181
- To apply the Apache License to your work, attach the following
182
- boilerplate notice, with the fields enclosed by brackets "[]"
183
- replaced with your own identifying information. (Don't include
184
- the brackets!) The text should be enclosed in the appropriate
185
- comment syntax for the file format. We also recommend that a
186
- file or class name and description of purpose be included on the
187
- same "printed page" as the copyright notice for easier
188
- identification within third-party archives.
189
-
190
- Copyright [yyyy] [name of copyright owner]
191
-
192
- Licensed under the Apache License, Version 2.0 (the "License");
193
- you may not use this file except in compliance with the License.
194
- You may obtain a copy of the License at
195
-
196
- http://www.apache.org/licenses/LICENSE-2.0
197
-
198
- Unless required by applicable law or agreed to in writing, software
199
- distributed under the License is distributed on an "AS IS" BASIS,
200
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
- See the License for the specific language governing permissions and
202
- limitations under the License.
3
+ URL: https://www.elastic.co/licensing/elastic-license
4
+
5
+ ## Acceptance
6
+
7
+ By using the software, you agree to all of the terms and conditions below.
8
+
9
+ ## Copyright License
10
+
11
+ The licensor grants you a non-exclusive, royalty-free, worldwide,
12
+ non-sublicensable, non-transferable license to use, copy, distribute, make
13
+ available, and prepare derivative works of the software, in each case subject
14
+ to the limitations and conditions below.
15
+
16
+ ## Limitations
17
+
18
+ You may not provide the software to third parties as a hosted or managed
19
+ service, where the service provides users with access to any substantial set of
20
+ the features or functionality of the software.
21
+
22
+ You may not move, change, disable, or circumvent the license key functionality
23
+ in the software, and you may not remove or obscure any functionality in the
24
+ software that is protected by the license key.
25
+
26
+ You may not alter, remove, or obscure any licensing, copyright, or other notices
27
+ of the licensor in the software. Any use of the licensor's trademarks is subject
28
+ to applicable law.
29
+
30
+ ## Patents
31
+
32
+ The licensor grants you a license, under any patent claims the licensor can
33
+ license, or becomes able to license, to make, have made, use, sell, offer for
34
+ sale, import and have imported the software, in each case subject to the
35
+ limitations and conditions in this license. This license does not cover any
36
+ patent claims that you cause to be infringed by modifications or additions to
37
+ the software. If you or your company make any written claim that the software
38
+ infringes or contributes to infringement of any patent, your patent license for
39
+ the software granted under these terms ends immediately. If your company makes
40
+ such a claim, your patent license ends immediately for work on behalf of your
41
+ company.
42
+
43
+ ## Notices
44
+
45
+ You must ensure that anyone who gets a copy of any part of the software from you
46
+ also gets a copy of these terms.
47
+
48
+ If you modify the software, you must include in any modified copies of the
49
+ software prominent notices stating that you have modified the software.
50
+
51
+ ## No Other Rights
52
+
53
+ These terms do not imply any licenses other than those expressly granted in
54
+ these terms.
55
+
56
+ ## Termination
57
+
58
+ If you use the software in violation of these terms, such use is not licensed,
59
+ and your licenses will automatically terminate. If the licensor provides you
60
+ with a notice of your violation, and you cease all violation of this license no
61
+ later than 30 days after you receive that notice, your licenses will be
62
+ reinstated retroactively. However, if you violate these terms after such
63
+ reinstatement, any additional violation of these terms will cause your licenses
64
+ to terminate automatically and permanently.
65
+
66
+ ## No Liability
67
+
68
+ *As far as the law allows, the software comes as is, without any warranty or
69
+ condition, and the licensor will not be liable to you for any damages arising
70
+ out of these terms or the use or nature of the software, under any kind of
71
+ legal claim.*
72
+
73
+ ## Definitions
74
+
75
+ The **licensor** is the entity offering these terms, and the **software** is the
76
+ software the licensor makes available under these terms, including any portion
77
+ of it.
78
+
79
+ **you** refers to the individual or entity agreeing to these terms.
80
+
81
+ **your company** is any legal entity, sole proprietorship, or other kind of
82
+ organization that you work for, plus all organizations that have control over,
83
+ are under the control of, or are under common control with that organization.
84
+ **control** means ownership of substantially all the assets of an entity, or
85
+ the power to direct its management and policies by vote, contract, or
86
+ otherwise. Control can be direct or indirect.
87
+
88
+ **your licenses** are all the licenses granted to you for the software under
89
+ these terms.
90
+
91
+ **use** means anything you do with the software requiring one of your licenses.
92
+
93
+ **trademark** means trademarks, service marks, and similar rights.
package/README.md CHANGED
@@ -1,97 +1,375 @@
1
- # predicate-skill
1
+ # Predicate
2
2
 
3
- Distributable Predicate package: bundled MCP server + `predicate` CLI +
4
- Claude Code plugin (SKILL.md + hooks + slash commands) + per-platform
5
- hook adapters for Cursor, Gemini CLI, VS Code Copilot, OpenCode, and
6
- Codex CLI. This is the install target for both the Claude Code
7
- marketplace and the npm path.
3
+ **Reasoning memory for AI agents a knowledge graph that compounds with use.**
8
4
 
9
- Current version: **2.0.0** (`v2.0.0-domain-agnostic-bootstrap`).
5
+ [![npm](https://img.shields.io/npm/v/predicate-skill?label=npm&color=blue)](https://www.npmjs.com/package/predicate-skill)
6
+ [![marketplace](https://img.shields.io/badge/Claude%20Code-Marketplace-blue)](https://github.com/NordicAgents/predicate)
7
+ [![License: ELv2](https://img.shields.io/badge/License-ELv2-blue.svg)](LICENSE)
8
+ [![GitHub stars](https://img.shields.io/github/stars/NordicAgents/predicate?style=flat&color=yellow)](https://github.com/NordicAgents/predicate/stargazers)
9
+ [![Last commit](https://img.shields.io/github/last-commit/NordicAgents/predicate?color=green)](https://github.com/NordicAgents/predicate/commits)
10
+
11
+ ## The Problem
12
+
13
+ An AI coding or research agent loses most of its value to two failures: it
14
+ forgets across sessions, and it can only answer single-hop lookups. Ask
15
+ *"why did login break?"* and a RAG system returns documents containing the
16
+ word *login*. It cannot traverse
17
+ `auth.ts → validateToken → jwt.verify → JWT_SECRET → .env.production`,
18
+ cannot tell you the blast radius of a rename, and cannot say which of two
19
+ documents contradicts the other. The "agent memory" category mostly stores
20
+ text or vectors with light graph structure on top — it does not separate
21
+ schema from data, does not run a reasoner, does not track provenance per
22
+ fact, and grows without bound until the operator cleans up by hand.
23
+
24
+ ### How Predicate solves it
25
+
26
+ Predicate is an MCP skill that gives the agent a real reasoning graph,
27
+ not a search index.
28
+
29
+ 1. **RDF/OWL, not retrieval.** Facts are stored as triples in Apache Jena
30
+ Fuseki. A curated OWL 2 RL ruleset materializes entailments through
31
+ SPARQL `CONSTRUCT` rules; SHACL covers closed-world validation. The
32
+ model formulates SPARQL against a freshly read schema — pre-baked
33
+ queries are forbidden — and reads logically entailed answers, never
34
+ hand-derived ones.
35
+ 2. **Provenance per triple.** Every fact carries source, time, confidence,
36
+ and extraction method via RDF-star. Low-confidence triples stay visible
37
+ to queries but are excluded from the inference closure so they cannot
38
+ poison entailment. `kg_explain` returns the backward-chained derivation
39
+ for any claim with citations.
40
+ 3. **Schema as code, with a use-gated promotion loop.** The TBox lives in
41
+ git as Turtle. The agent never edits it directly — it proposes deltas
42
+ to `kg:tbox-staging`. The reasoner validates each proposal; only after
43
+ N successful queries inside a TTL is a delta promoted into `kg:tbox`.
44
+ Unused proposals expire quietly. The graph cannot thrash because the
45
+ gate, not the goal source, is the safety mechanism.
46
+ 4. **Goal-conditioned growth.** Concepts enter because a goal needed
47
+ them, not because a document mentioned them. `kg_research_goal`
48
+ decomposes a goal, detects schema or data gaps, and runs research only
49
+ where the existing graph cannot answer. Periodic generalization and a
50
+ reaper sweep keep size bounded.
51
+ 5. **Cross-session continuity.** A Stop hook on each platform extracts
52
+ typed triples from the turn — files modified, commands that succeeded
53
+ or failed, decisions reached — and asserts them into `kg:abox`. The
54
+ reasoner derives `Hotspot`, `FlakyCommand`, and `ActiveFile` from
55
+ action data so `kg_ask` can answer "what is unstable here?" without
56
+ re-reading the repo next session.
10
57
 
11
58
  ## Install
12
59
 
13
60
  Prerequisites everywhere: **Docker** (for Fuseki) and **Node 20+**.
14
61
 
15
- ### Claude Code marketplace
62
+ <details open>
63
+ <summary><strong>Claude Code</strong> — plugin marketplace, fully automatic</summary>
16
64
 
17
- ```
65
+ **Install:**
66
+
67
+ ```bash
18
68
  /plugin marketplace add NordicAgents/predicate
19
69
  /plugin install predicate@predicate
20
70
  ```
21
71
 
22
- ### npm (any MCP-capable host)
72
+ Restart Claude Code (or `/reload-plugins`). Then start the graph:
23
73
 
24
74
  ```bash
25
- npm install -g predicate-skill
26
75
  predicate up
76
+ ```
77
+
78
+ **Verify:**
79
+
80
+ ```bash
27
81
  predicate doctor
28
82
  ```
29
83
 
30
- Or one-shot without a global install:
84
+ All checks should show OK. The doctor validates Docker, Fuseki, the named
85
+ graphs, the reasoner, and plugin registration.
86
+
87
+ **Slash commands:**
88
+
89
+ | Command | What it does |
90
+ |---|---|
91
+ | `/predicate:up` | Start Fuseki and bootstrap the 9 named graphs. |
92
+ | `/predicate:down` | Stop Fuseki, keep the volume. |
93
+ | `/predicate:doctor` | Health check across Docker, Fuseki, TBox, tools. |
94
+ | `/predicate:stats` | Triples, ABox, inferred, TBox counts; inferred ratio; unused-concept ratio. |
95
+ | `/predicate:ask <question>` | Free-form question routed through `kg_ask`. |
96
+
97
+ **Routing:** Automatic. The SessionStart hook injects a one-line KG
98
+ status banner. PreToolUse, PostToolUse, and Stop hooks capture tool
99
+ calls and extract typed session triples — no file is written to your
100
+ project.
101
+
102
+ <details>
103
+ <summary>Alternative — MCP-only install (no hooks or slash commands)</summary>
31
104
 
32
105
  ```bash
33
106
  claude mcp add predicate -- npx -y predicate-skill
34
107
  ```
35
108
 
36
- ### Other platforms
109
+ This gives you all `kg_*` tools without lifecycle hooks. Good for a quick
110
+ trial before installing the full plugin.
37
111
 
38
- See the platform-specific config templates and READMEs under `hooks/`:
112
+ </details>
39
113
 
40
- | Platform | Subdirectory | Hook events wired |
41
- |---|---|---|
42
- | Claude Code | `hooks/` (root) | SessionStart, PreToolUse, PostToolUse, Stop |
43
- | Gemini CLI | `hooks/gemini-cli/` | sessionStart, preCompress, stop |
44
- | Cursor | `hooks/cursor/` | manual / cron only (no native events) |
45
- | VS Code Copilot | `hooks/vscode-copilot/` | manual / VS Code tasks |
46
- | OpenCode | `hooks/opencode/` | session.started, session.compacted, session.stopped |
47
- | Codex CLI | `hooks/codex-cli/` | manual / shell alias / cron |
114
+ </details>
48
115
 
49
- ## CLI
116
+ <details>
117
+ <summary><strong>Any MCP-capable client</strong> — npm install</summary>
50
118
 
119
+ ```bash
120
+ npm install -g predicate-skill
121
+ predicate up
122
+ predicate doctor
51
123
  ```
52
- predicate up # docker compose up + bootstrap graphs (then init on first run)
53
- predicate init # initialize kg:tbox (community ontology / upload / empty)
54
- predicate down # stop fuseki, keep the volume
55
- predicate doctor # health checks (docker, fuseki, tbox)
56
- predicate stats # current kg_stats output
57
- predicate sessionstart # one-line KG status banner (used by hook scripts)
58
- predicate maintain # reaper + generalizer + promotion sweeper
59
- predicate capture # record a tool invocation in kg:usage (opt-in: PREDICATE_RAW_CAPTURE=1)
60
- predicate extract # read a Stop-hook payload and assert typed triples to kg:abox
61
- predicate --version
62
- predicate --help
124
+
125
+ The bundled MCP server lives at the package's `bin` entry. Point any
126
+ MCP-over-stdio client at `predicate-skill` (or
127
+ `node /path/to/predicate-skill/server.bundle.mjs`) with env
128
+ `FUSEKI_URL=http://localhost:3030` and `PREDICATE_DATASET=predicate`.
129
+
130
+ </details>
131
+
132
+ <details>
133
+ <summary><strong>Cursor</strong> — MCP + maintenance scripts</summary>
134
+
135
+ **Install:**
136
+
137
+ 1. Install context-mode globally and start Fuseki:
138
+
139
+ ```bash
140
+ npm install -g predicate-skill
141
+ predicate up
142
+ ```
143
+
144
+ 2. Copy the MCP config template to `~/.cursor/mcp.json` and replace
145
+ `__PLUGIN_DIR__` with the absolute path to the installed
146
+ `predicate-skill` directory:
147
+
148
+ ```bash
149
+ cp $(npm root -g)/predicate-skill/hooks/cursor/mcp.json.template ~/.cursor/mcp.json
150
+ ```
151
+
152
+ 3. Reload MCP servers (Cmd-Shift-P → "Reload MCP servers").
153
+
154
+ **Verify:** Open Cursor Settings → MCP and confirm "predicate" is
155
+ connected. In agent chat, type `predicate stats`.
156
+
157
+ **Routing:** Cursor has no native SessionStart / Stop events. The
158
+ SessionStart, PreCompact, and Stop maintenance scripts under
159
+ `hooks/cursor/` can be wired via cron or a shell alias — see
160
+ `hooks/cursor/README.md`.
161
+
162
+ </details>
163
+
164
+ <details>
165
+ <summary><strong>Gemini CLI</strong> — MCP + sessionStart + preCompress + stop hooks</summary>
166
+
167
+ **Install:**
168
+
169
+ 1. Install and start Fuseki:
170
+
171
+ ```bash
172
+ npm install -g predicate-skill
173
+ predicate up
174
+ ```
175
+
176
+ 2. Merge the template into `~/.gemini/settings.json`, replacing
177
+ `__PLUGIN_DIR__` with the absolute path to the installed
178
+ `predicate-skill` directory:
179
+
180
+ ```bash
181
+ cat $(npm root -g)/predicate-skill/hooks/gemini-cli/settings.json.template
182
+ ```
183
+
184
+ 3. Restart Gemini CLI.
185
+
186
+ **Verify:** `/mcp list` should show `predicate: ... Connected`.
187
+
188
+ **Routing:** Automatic via the three hook events. The Stop hook pipes
189
+ the transcript through `predicate extract --from-stdin --platform gemini`
190
+ so session triples land in `kg:abox` after every turn.
191
+
192
+ </details>
193
+
194
+ <details>
195
+ <summary><strong>VS Code Copilot</strong> — MCP via settings.json</summary>
196
+
197
+ **Install:**
198
+
199
+ 1. Install and start Fuseki:
200
+
201
+ ```bash
202
+ npm install -g predicate-skill
203
+ predicate up
204
+ ```
205
+
206
+ 2. Merge `hooks/vscode-copilot/settings.json.template` into your VS Code
207
+ `settings.json`, replacing `__PLUGIN_DIR__`. Restart VS Code.
208
+
209
+ **Verify:** Open Copilot Chat and type `predicate stats`.
210
+
211
+ **Routing:** VS Code Copilot does not yet expose SessionStart / PreCompact
212
+ / Stop events. See `hooks/vscode-copilot/README.md` for manual and
213
+ VS Code-task wiring of the maintenance scripts.
214
+
215
+ </details>
216
+
217
+ <details>
218
+ <summary><strong>OpenCode</strong> — MCP + session.started + session.compacted + session.stopped hooks</summary>
219
+
220
+ **Install:**
221
+
222
+ 1. Install and start Fuseki:
223
+
224
+ ```bash
225
+ npm install -g predicate-skill
226
+ predicate up
227
+ ```
228
+
229
+ 2. Merge `hooks/opencode/opencode.json.template` into
230
+ `~/.config/opencode/opencode.json`, replacing `__PLUGIN_DIR__`.
231
+
232
+ 3. Restart OpenCode.
233
+
234
+ **Verify:** In the OpenCode session, type `predicate stats`.
235
+
236
+ **Routing:** Automatic via the three lifecycle events. The
237
+ session.stopped hook pipes the transcript through
238
+ `predicate extract --from-stdin --platform opencode`.
239
+
240
+ </details>
241
+
242
+ <details>
243
+ <summary><strong>Codex CLI</strong> — MCP via config.toml</summary>
244
+
245
+ **Install:**
246
+
247
+ 1. Install and start Fuseki:
248
+
249
+ ```bash
250
+ npm install -g predicate-skill
251
+ predicate up
252
+ ```
253
+
254
+ 2. Merge `hooks/codex-cli/config.toml.template` into
255
+ `~/.codex/config.toml`, replacing `__PLUGIN_DIR__`.
256
+
257
+ **Verify:** Launch `codex` and type `predicate stats`.
258
+
259
+ **Routing:** Codex CLI has no lifecycle events yet. See
260
+ `hooks/codex-cli/README.md` for shell-alias wiring of the maintenance
261
+ scripts.
262
+
263
+ </details>
264
+
265
+ <details>
266
+ <summary><strong>Continue.dev</strong> — MCP via config.yaml</summary>
267
+
268
+ In `~/.continue/config.yaml`:
269
+
270
+ ```yaml
271
+ mcpServers:
272
+ - name: predicate
273
+ command: predicate-skill
274
+ env:
275
+ FUSEKI_URL: http://localhost:3030
276
+ PREDICATE_DATASET: predicate
63
277
  ```
64
278
 
279
+ Then `predicate up` and restart Continue.
280
+
281
+ </details>
282
+
283
+ ## Bootstrap modes
284
+
285
+ On first `predicate up`, choose how to seed the schema:
286
+
287
+ - **Community ontology** — install a bundled vocabulary (`top`,
288
+ `codebase`, `foaf`, `schema-org-lite`, `fhir-core`) from the catalog
289
+ in `packages/predicate-ontology/catalog/`.
290
+ - **Bring your own** — upload a Turtle file as the initial TBox.
291
+ - **Empty** — start with no schema; let the agent grow vocabulary through
292
+ the propose → validate → 3-uses-in-7-days promotion gate.
293
+
294
+ Schema-learning is toggleable at runtime via `kg_config_set` /
295
+ `kg_config_get`.
296
+
65
297
  ## MCP tools
66
298
 
67
- The bundled server exposes 11 tools over stdio: `kg_explore_schema`,
68
- `kg_ask`, `kg_assert`, `kg_explain`, `kg_propose_schema`,
69
- `kg_research_goal`, `kg_stats`, `kg_maintain`, `kg_capture`,
70
- `kg_config_get`, `kg_config_set`.
299
+ The bundled server exposes 11 tools over stdio:
71
300
 
72
- Env vars consumed at runtime:
301
+ | Tool | What it does |
302
+ |---|---|
303
+ | `kg_explore_schema` | Returns the TBox slice for a concept so the model uses real predicates. |
304
+ | `kg_ask` | Executes a caller-drafted SPARQL query against asserted + inferred graphs. Logs to `kg:usage`, truncates results, supports `includeRemote: true` for peer-federated queries. |
305
+ | `kg_assert` | Writes a triple to `kg:abox` with RDF-star provenance. Rejects undeclared predicates. |
306
+ | `kg_explain` | Returns the backward-chained derivation for a claim, with cited provenance. |
307
+ | `kg_propose_schema` | Stages a `SchemaDelta` proposal in `kg:tbox-staging`. |
308
+ | `kg_research_goal` | Decompose a goal → gap-detect → optionally execute research → return a plan. |
309
+ | `kg_stats` | Triples, ABox, inferred, TBox counts; inferred ratio; unused-concept ratio. |
310
+ | `kg_maintain` | Runs reaper, generalizer, and promotion sweeper, then re-materializes inferred. |
311
+ | `kg_capture` | Records a tool invocation (toolName, input, output, sessionId, phase) into `kg:usage`. Used by PreToolUse / PostToolUse hooks. |
312
+ | `kg_config_get` / `kg_config_set` | Read or update runtime config (e.g. schema-learning toggle). |
73
313
 
74
- - `FUSEKI_URL` (default `http://localhost:3030`)
75
- - `PREDICATE_DATASET` (default `predicate`)
76
- - `PREDICATE_CAPTURE_SKIP` (comma list of tool names to suppress in `kg_capture`, default empty)
77
- - `PREDICATE_CAPTURE_TRUNCATE` (max chars per captured input/output field, default `500`)
314
+ ## CLI
315
+
316
+ ```
317
+ predicate up # docker compose up + bootstrap the 9 named graphs
318
+ predicate init # initialize kg:tbox (community / upload / empty)
319
+ predicate down # stop Fuseki, keep the volume
320
+ predicate doctor # health checks (docker, fuseki, tbox, tools)
321
+ predicate stats # current kg_stats output
322
+ predicate sessionstart # one-line KG status banner (used by hook scripts)
323
+ predicate maintain # reaper + generalizer + promotion sweeper
324
+ predicate capture # record a tool call in kg:usage (opt-in: PREDICATE_RAW_CAPTURE=1)
325
+ predicate extract # read a Stop-hook payload and assert typed triples to kg:abox
326
+ predicate sessions # list recent extracted sessions (modifiedFiles / ok / fail)
327
+ predicate captures # list raw kg:usage ToolCall captures
328
+ predicate recall <query> # substring search over session history (files + commands)
329
+ predicate dashboard # serve a localhost web view of session history + reasoning output
330
+
331
+ predicate peer add <name> <sparql-endpoint> # register a teammate's Fuseki
332
+ predicate peer list | peer remove
333
+ predicate export-sessions [--since DATE] [--user NAME]
334
+ predicate import-sessions <file.trig>
335
+
336
+ predicate ld init # register DBpedia + Wikidata as external LD peers
337
+ predicate ld list
338
+ predicate ld ask <query> # one-shot SPARQL across all registered LD endpoints
339
+
340
+ predicate --version
341
+ predicate --help
342
+ ```
343
+
344
+ ## Environment
345
+
346
+ | Var | Default | What it controls |
347
+ |---|---|---|
348
+ | `FUSEKI_URL` | `http://localhost:3030` | Where the MCP server reaches Fuseki. |
349
+ | `PREDICATE_DATASET` | `predicate` | Fuseki dataset name. |
350
+ | `PREDICATE_CAPTURE_SKIP` | *(empty)* | Comma-separated tool names suppressed by `kg_capture`. |
351
+ | `PREDICATE_CAPTURE_TRUNCATE` | `500` | Max chars per captured input/output field. |
352
+ | `PREDICATE_RAW_CAPTURE` | unset | When `1`, raw PreToolUse/PostToolUse captures are persisted to `kg:usage`. |
353
+ | `ANTHROPIC_API_KEY` | unset | Enables the LLM-augmented decomposer fallback in `kg_research_goal`. |
78
354
 
79
355
  ## What's in this directory
80
356
 
81
- - `.claude-plugin/plugin.json` MCP server + skills + hooks registration for the Claude Code marketplace path.
82
- - `server.bundle.mjs` — bundled MCP server (no `node_modules` required at runtime).
83
- - `cli.bundle.mjs` bundled `predicate` CLI, surfaced via this package's `bin` entry.
84
- - `skills/predicate/SKILL.md` host-agent contract: triggers, workflow, HARD-GATE anti-patterns, worked examples.
85
- - `skills/predicate-doctor/SKILL.md`, `skills/predicate-stats/SKILL.md` operator skills.
86
- - `commands/{up,down,doctor,stats,ask}.md` slash-command definitions for `/predicate:*`.
87
- - `hooks/hooks.json` Claude Code hook registration (SessionStart, PreToolUse, PostToolUse).
88
- - `hooks/session-start.sh`, `hooks/pre-tool-use.sh`, `hooks/post-tool-use.sh` Claude Code lifecycle hooks; each delegates to a `predicate` CLI subcommand.
89
- - `hooks/{cursor,gemini-cli,vscode-copilot,opencode,codex-cli}/` per-platform hook scripts + config templates + per-platform README.
90
- - `compose/docker-compose.yml`, `compose/fuseki/config.ttl`Fuseki + TDB2 config that `predicate up` launches.
357
+ | Path | Purpose |
358
+ |---|---|
359
+ | `.claude-plugin/plugin.json` | MCP + skills + hooks registration for the Claude Code marketplace. |
360
+ | `server.bundle.mjs` | Bundled MCP server runs without `node_modules` at runtime. |
361
+ | `cli.bundle.mjs` | Bundled `predicate` CLI, surfaced via this package's `bin` entry. |
362
+ | `skills/predicate/SKILL.md` | Host-agent contract: triggers, workflow, HARD-GATE anti-patterns, worked examples. |
363
+ | `skills/predicate-doctor/`, `skills/predicate-stats/` | Operator skills. |
364
+ | `commands/{up,down,doctor,stats,ask}.md` | Slash-command definitions for `/predicate:*`. |
365
+ | `hooks/hooks.json` | Claude Code hook registration (SessionStart, PreToolUse, PostToolUse, Stop). |
366
+ | `hooks/{session-start,pre-tool-use,post-tool-use,stop}.sh` | Claude Code lifecycle hooks each delegates to a `predicate` CLI subcommand. |
367
+ | `hooks/{cursor,gemini-cli,vscode-copilot,opencode,codex-cli}/` | Per-platform hook scripts + config templates + per-platform README. |
368
+ | `compose/docker-compose.yml`, `compose/fuseki/config.ttl` | Fuseki + TDB2 config launched by `predicate up`. |
91
369
 
92
370
  ## Rebuilding the bundles
93
371
 
94
- Bundles are committed so the marketplace install path works without
372
+ The bundles are committed so the marketplace install path works without
95
373
  `pnpm install`. To rebuild after a source change:
96
374
 
97
375
  ```bash
@@ -110,9 +388,9 @@ The full workspace test suite runs against a live Fuseki:
110
388
 
111
389
  ```bash
112
390
  predicate up
113
- pnpm test # 160 tests across 5 packages
391
+ pnpm test
114
392
  ```
115
393
 
116
394
  ## License
117
395
 
118
- Apache-2.0. See `LICENSE`.
396
+ Elastic License 2.0 (ELv2) — source-available. See [`LICENSE`](LICENSE).
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "ontologies": [
4
+ {
5
+ "name": "top",
6
+ "description": "Minimal upper ontology — Thing, dependsOn, relatedTo",
7
+ "license": "CC0",
8
+ "files": ["top.ttl"]
9
+ },
10
+ {
11
+ "name": "codebase",
12
+ "description": "Software code structure (files, symbols, calls, modifications)",
13
+ "license": "Elastic-2.0",
14
+ "files": ["codebase.ttl"],
15
+ "shapes": "codebase.shacl.ttl"
16
+ },
17
+ {
18
+ "name": "foaf",
19
+ "description": "Friend-of-a-friend — faithful subset of xmlns.com/foaf/0.1",
20
+ "license": "CC0",
21
+ "files": ["foaf.ttl"]
22
+ },
23
+ {
24
+ "name": "schema-org-lite",
25
+ "description": "Web entities — faithful subset of schema.org core (soft-typed)",
26
+ "license": "CC-BY-4.0",
27
+ "files": ["schema-org-lite.ttl"]
28
+ },
29
+ {
30
+ "name": "fhir-core",
31
+ "description": "HL7 FHIR R4 resource class vocabulary (class hierarchy only; load fhir.ttl for full data modeling)",
32
+ "license": "HL7",
33
+ "files": ["fhir-core.ttl"]
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,24 @@
1
+ @prefix sh: <http://www.w3.org/ns/shacl#> .
2
+ @prefix : <https://predicate.dev/codebase#> .
3
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
4
+
5
+ :FileShape a sh:NodeShape ;
6
+ sh:targetClass :File ;
7
+ sh:property [
8
+ sh:path :path ; sh:datatype xsd:string ;
9
+ sh:minCount 1 ; sh:maxCount 1
10
+ ] .
11
+
12
+ :SymbolShape a sh:NodeShape ;
13
+ sh:targetClass :Symbol ;
14
+ sh:property [
15
+ sh:path :declaredIn ; sh:class :File ;
16
+ sh:minCount 1 ; sh:maxCount 1
17
+ ] .
18
+
19
+ :CommitShape a sh:NodeShape ;
20
+ sh:targetClass :Commit ;
21
+ sh:property [
22
+ sh:path :sha ; sh:datatype xsd:string ;
23
+ sh:minCount 1 ; sh:maxCount 1
24
+ ] .
@@ -0,0 +1,92 @@
1
+ @prefix : <https://predicate.dev/codebase#> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
6
+
7
+ # --- Classes -------------------------------------------------------
8
+
9
+ :Artifact a owl:Class ; rdfs:label "Artifact" .
10
+ :File a owl:Class ; rdfs:subClassOf :Artifact ; rdfs:label "File" .
11
+ :Symbol a owl:Class ; rdfs:subClassOf :Artifact ; rdfs:label "Symbol" .
12
+ :Function a owl:Class ; rdfs:subClassOf :Symbol ; rdfs:label "Function" .
13
+ :Class a owl:Class ; rdfs:subClassOf :Symbol ; rdfs:label "Class" .
14
+ :Module a owl:Class ; rdfs:subClassOf :Artifact ; rdfs:label "Module" .
15
+ :Package a owl:Class ; rdfs:subClassOf :Artifact ; rdfs:label "Package" .
16
+ :EnvVar a owl:Class ; rdfs:subClassOf :Artifact ; rdfs:label "EnvVar" .
17
+ :Commit a owl:Class ; rdfs:label "Commit" .
18
+ :Test a owl:Class ; rdfs:subClassOf :Artifact ; rdfs:label "Test" .
19
+ :Command a owl:Class ; rdfs:label "Shell command invocation" .
20
+
21
+ :Hotspot a owl:Class ; rdfs:subClassOf :File ; rdfs:label "File modified in many sessions" .
22
+ :FlakyCommand a owl:Class ; rdfs:subClassOf :Command ; rdfs:label "Command that has failed in multiple sessions" .
23
+ :ActiveFile a owl:Class ; rdfs:subClassOf :File ; rdfs:label "File modified in the most recent session" .
24
+
25
+ :Function owl:disjointWith :Class .
26
+ :File owl:disjointWith :Symbol .
27
+
28
+ # --- Properties ----------------------------------------------------
29
+
30
+ :declaredIn a owl:ObjectProperty ;
31
+ rdfs:domain :Symbol ; rdfs:range :File ;
32
+ rdfs:label "declared in" .
33
+
34
+ :imports a owl:ObjectProperty , owl:TransitiveProperty ;
35
+ rdfs:domain :Artifact ; rdfs:range :Artifact ;
36
+ rdfs:label "imports" .
37
+
38
+ :calls a owl:ObjectProperty , owl:TransitiveProperty ;
39
+ rdfs:domain :Function ; rdfs:range :Function ;
40
+ rdfs:label "calls" .
41
+
42
+ :reads a owl:ObjectProperty ;
43
+ rdfs:domain :Function ; rdfs:range :EnvVar ;
44
+ rdfs:label "reads env var" .
45
+
46
+ :dependsOn a owl:ObjectProperty , owl:TransitiveProperty ;
47
+ rdfs:label "depends on" .
48
+
49
+ # Property chain: f calls g ∧ g declaredIn h → f dependsOn h
50
+ :dependsOn owl:propertyChainAxiom ( :calls :declaredIn ) .
51
+
52
+ # Imports implies dependsOn
53
+ :imports rdfs:subPropertyOf :dependsOn .
54
+
55
+ :testedBy a owl:ObjectProperty ;
56
+ owl:inverseOf :tests ;
57
+ rdfs:label "tested by" .
58
+
59
+ :tests a owl:ObjectProperty ;
60
+ rdfs:domain :Test ; rdfs:range :Symbol ;
61
+ rdfs:label "tests" .
62
+
63
+ :lastModifiedIn a owl:ObjectProperty , owl:FunctionalProperty ;
64
+ rdfs:domain :Artifact ; rdfs:range :Commit ;
65
+ rdfs:label "last modified in" .
66
+
67
+ :path a owl:DatatypeProperty , owl:FunctionalProperty ;
68
+ rdfs:domain :File ; rdfs:range xsd:string ;
69
+ rdfs:label "path" .
70
+
71
+ :sha a owl:DatatypeProperty , owl:FunctionalProperty ;
72
+ rdfs:domain :Commit ; rdfs:range xsd:string ;
73
+ rdfs:label "sha" .
74
+
75
+ # --- Action predicates (used by the Stop-hook deterministic extractor) ---
76
+
77
+ :commandText a owl:DatatypeProperty ;
78
+ rdfs:domain :Command ; rdfs:range xsd:string ;
79
+ rdfs:label "The literal command string." .
80
+
81
+ :modifiedIn a owl:ObjectProperty ;
82
+ rdfs:domain :File ; rdfs:range <https://predicate.dev/meta#Session> ;
83
+ rdfs:label "File was modified during this session." .
84
+ :createdIn a owl:ObjectProperty ;
85
+ rdfs:domain :File ; rdfs:range <https://predicate.dev/meta#Session> ;
86
+ rdfs:label "File was newly created in this session." .
87
+ :succeededIn a owl:ObjectProperty ;
88
+ rdfs:domain :Command ; rdfs:range <https://predicate.dev/meta#Session> ;
89
+ rdfs:label "Command exited 0 in this session." .
90
+ :failedIn a owl:ObjectProperty ;
91
+ rdfs:domain :Command ; rdfs:range <https://predicate.dev/meta#Session> ;
92
+ rdfs:label "Command exited non-zero in this session." .
@@ -0,0 +1,32 @@
1
+ @prefix fhir: <http://hl7.org/fhir/> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+
6
+ # FHIR core — TRUE subset of HL7 FHIR R4 resource-type vocabulary.
7
+ # Upstream: http://hl7.org/fhir/R4/ License: see HL7 terms
8
+ #
9
+ # This file ships ONLY the resource class hierarchy. The published
10
+ # HL7 FHIR RDF ontology (http://hl7.org/fhir/fhir.ttl) uses a rich
11
+ # value-type metamodel (fhir:link, fhir:CodeableConcept, fhir:Reference,
12
+ # wrapped scalar values, etc.) — flattening Patient.subject, Observation.code
13
+ # etc. into bare OWL properties with rdfs:range xsd:string would NOT be a
14
+ # subset of FHIR-RDF; it would contradict it. So we omit those axioms.
15
+ #
16
+ # If you need full FHIR data modeling, load HL7's published RDF ontology
17
+ # directly (predicate init --mode upload --file fhir.ttl).
18
+
19
+ fhir:Resource a owl:Class ; rdfs:label "Resource" .
20
+
21
+ fhir:Patient a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Patient" .
22
+ fhir:Practitioner a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Practitioner" .
23
+ fhir:Organization a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Organization" .
24
+ fhir:Encounter a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Encounter" .
25
+ fhir:Observation a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Observation" .
26
+ fhir:Condition a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Condition" .
27
+ fhir:Medication a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Medication" .
28
+ fhir:MedicationRequest a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Medication Request" .
29
+ fhir:Procedure a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Procedure" .
30
+ fhir:DiagnosticReport a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Diagnostic Report" .
31
+ fhir:AllergyIntolerance a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Allergy Intolerance" .
32
+ fhir:Immunization a owl:Class ; rdfs:subClassOf fhir:Resource ; rdfs:label "Immunization" .
@@ -0,0 +1,55 @@
1
+ @prefix foaf: <http://xmlns.com/foaf/0.1/> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+
6
+ # FOAF (Friend Of A Friend) — true subset of the upstream vocabulary.
7
+ # Upstream: http://xmlns.com/foaf/spec/ License: CC0
8
+ # Every axiom below is also asserted (or is strictly entailed) by the
9
+ # published FOAF ontology. We add nothing FOAF does not say.
10
+
11
+ # --- Classes -------------------------------------------------------
12
+
13
+ foaf:Agent a owl:Class ; rdfs:label "Agent" .
14
+ foaf:Person a owl:Class ; rdfs:subClassOf foaf:Agent ; rdfs:label "Person" .
15
+ foaf:Organization a owl:Class ; rdfs:subClassOf foaf:Agent ; rdfs:label "Organization" .
16
+ foaf:Group a owl:Class ; rdfs:subClassOf foaf:Agent ; rdfs:label "Group" .
17
+ foaf:Document a owl:Class ; rdfs:label "Document" .
18
+ foaf:Image a owl:Class ; rdfs:subClassOf foaf:Document ; rdfs:label "Image" .
19
+ foaf:OnlineAccount a owl:Class ; rdfs:label "Online Account" .
20
+
21
+ # --- Object properties --------------------------------------------
22
+
23
+ foaf:knows a owl:ObjectProperty ;
24
+ rdfs:domain foaf:Person ; rdfs:range foaf:Person ;
25
+ rdfs:label "knows" .
26
+
27
+ foaf:member a owl:ObjectProperty ;
28
+ rdfs:domain foaf:Group ; rdfs:range foaf:Agent ;
29
+ rdfs:label "member" .
30
+
31
+ foaf:made a owl:ObjectProperty ;
32
+ rdfs:domain foaf:Agent ;
33
+ rdfs:label "made" .
34
+
35
+ foaf:maker a owl:ObjectProperty ;
36
+ rdfs:range foaf:Agent ;
37
+ owl:inverseOf foaf:made ;
38
+ rdfs:label "maker" .
39
+
40
+ # --- Datatype properties ------------------------------------------
41
+
42
+ # Domains left unconstrained where the FOAF spec does so — over-tightening
43
+ # (e.g. domain foaf:Person on foaf:name) would be a non-subset extension.
44
+
45
+ foaf:name a owl:DatatypeProperty ; rdfs:label "name" .
46
+ foaf:firstName a owl:DatatypeProperty ; rdfs:domain foaf:Person ; rdfs:label "first name" .
47
+ foaf:lastName a owl:DatatypeProperty ; rdfs:domain foaf:Person ; rdfs:label "last name" .
48
+ foaf:age a owl:DatatypeProperty ; rdfs:domain foaf:Agent ; rdfs:label "age" .
49
+ foaf:homepage a owl:DatatypeProperty ; rdfs:label "homepage" .
50
+
51
+ # foaf:mbox is the canonical FOAF identity property — InverseFunctional
52
+ # is core to its meaning. Domain is Agent, not Person.
53
+ foaf:mbox a owl:DatatypeProperty , owl:InverseFunctionalProperty ;
54
+ rdfs:domain foaf:Agent ;
55
+ rdfs:label "email" .
@@ -0,0 +1,63 @@
1
+ @prefix schema: <https://schema.org/> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+
6
+ # Schema.org-lite — true subset of schema.org's published vocabulary.
7
+ # Upstream: https://schema.org/ License: CC-BY-4.0
8
+ #
9
+ # Schema.org deliberately does NOT use rdfs:domain / rdfs:range on its
10
+ # properties — it uses its own schema:domainIncludes / schema:rangeIncludes,
11
+ # which are "soft" expected-type hints, not OWL-style strict constraints.
12
+ # We follow that convention so anything we publish is a faithful subset.
13
+
14
+ schema:domainIncludes a rdf:Property ; rdfs:label "domain includes" .
15
+ schema:rangeIncludes a rdf:Property ; rdfs:label "range includes" .
16
+
17
+ # --- Classes (real schema.org hierarchy) --------------------------
18
+
19
+ schema:Thing a owl:Class ; rdfs:label "Thing" .
20
+ schema:Person a owl:Class ; rdfs:subClassOf schema:Thing ; rdfs:label "Person" .
21
+ schema:Organization a owl:Class ; rdfs:subClassOf schema:Thing ; rdfs:label "Organization" .
22
+ schema:Place a owl:Class ; rdfs:subClassOf schema:Thing ; rdfs:label "Place" .
23
+ schema:Event a owl:Class ; rdfs:subClassOf schema:Thing ; rdfs:label "Event" .
24
+ schema:Product a owl:Class ; rdfs:subClassOf schema:Thing ; rdfs:label "Product" .
25
+
26
+ schema:CreativeWork a owl:Class ; rdfs:subClassOf schema:Thing ; rdfs:label "Creative Work" .
27
+ schema:Article a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Article" .
28
+ schema:Book a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Book" .
29
+ schema:Movie a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Movie" .
30
+ schema:Recipe a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Recipe" .
31
+ schema:Review a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Review" .
32
+ schema:WebPage a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Web Page" .
33
+ schema:SoftwareApplication a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Software Application" .
34
+ schema:Dataset a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Dataset" .
35
+ schema:ImageObject a owl:Class ; rdfs:subClassOf schema:CreativeWork ; rdfs:label "Image Object" .
36
+
37
+ # --- Datatype-ish properties --------------------------------------
38
+
39
+ schema:name a rdf:Property ; rdfs:label "name" .
40
+ schema:description a rdf:Property ; rdfs:label "description" .
41
+ schema:url a rdf:Property ; rdfs:label "url" .
42
+ schema:identifier a rdf:Property ; rdfs:label "identifier" .
43
+ schema:datePublished a rdf:Property ; rdfs:label "date published" .
44
+ schema:dateCreated a rdf:Property ; rdfs:label "date created" .
45
+ schema:dateModified a rdf:Property ; rdfs:label "date modified" .
46
+
47
+ # --- Object-ish properties (schema-style soft typing) -------------
48
+
49
+ schema:author a rdf:Property ;
50
+ schema:rangeIncludes schema:Person , schema:Organization ;
51
+ rdfs:label "author" .
52
+ schema:publisher a rdf:Property ;
53
+ schema:rangeIncludes schema:Organization , schema:Person ;
54
+ rdfs:label "publisher" .
55
+ schema:image a rdf:Property ;
56
+ schema:rangeIncludes schema:ImageObject , schema:URL ;
57
+ rdfs:label "image" .
58
+ schema:about a rdf:Property ;
59
+ schema:rangeIncludes schema:Thing ;
60
+ rdfs:label "about" .
61
+ schema:location a rdf:Property ;
62
+ schema:rangeIncludes schema:Place , schema:Organization ;
63
+ rdfs:label "location" .
@@ -0,0 +1,20 @@
1
+ @prefix : <https://predicate.dev/top#> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+
6
+ # Minimal upper ontology (Predicate v2.0 "start-empty" mode seed)
7
+
8
+ :Thing a owl:Class ;
9
+ rdfs:label "Thing" ;
10
+ rdfs:comment "The universal class. Everything is a Thing." .
11
+
12
+ :dependsOn a owl:ObjectProperty , owl:TransitiveProperty ;
13
+ rdfs:domain :Thing ; rdfs:range :Thing ;
14
+ rdfs:label "depends on" ;
15
+ rdfs:comment "Asymmetric directional dependency. Transitive: A→B and B→C implies A→C." .
16
+
17
+ :relatedTo a owl:ObjectProperty , owl:SymmetricProperty ;
18
+ rdfs:domain :Thing ; rdfs:range :Thing ;
19
+ rdfs:label "related to" ;
20
+ rdfs:comment "Generic symmetric association." .
package/cli.bundle.mjs CHANGED
@@ -17302,6 +17302,9 @@ function hasFlag(args, name) {
17302
17302
  function findCatalogDir() {
17303
17303
  const here = dirname2(fileURLToPath2(import.meta.url));
17304
17304
  const candidates = [
17305
+ // Bundled-alongside-CLI layout (predicate-skill global install).
17306
+ join2(here, "catalog"),
17307
+ // Monorepo / source-tree layouts.
17305
17308
  join2(here, "..", "..", "..", "predicate-ontology", "catalog"),
17306
17309
  join2(here, "..", "predicate-ontology", "catalog"),
17307
17310
  join2(here, "..", "..", "predicate-ontology", "catalog"),
@@ -0,0 +1,99 @@
1
+ @prefix pred: <https://predicate.dev/meta#> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
6
+
7
+ # --- Event class hierarchy ---------------------------------------
8
+
9
+ pred:Event a owl:Class ; rdfs:label "Predicate lifecycle event" .
10
+
11
+ pred:SchemaProposed a owl:Class ; rdfs:subClassOf pred:Event .
12
+ pred:SchemaValidationPassed a owl:Class ; rdfs:subClassOf pred:Event .
13
+ pred:SchemaValidationFailed a owl:Class ; rdfs:subClassOf pred:Event .
14
+ pred:SchemaPromoted a owl:Class ; rdfs:subClassOf pred:Event .
15
+ pred:SchemaRejected a owl:Class ; rdfs:subClassOf pred:Event .
16
+ pred:SchemaRolledBack a owl:Class ; rdfs:subClassOf pred:Event .
17
+ pred:TBoxVersionAdvanced a owl:Class ; rdfs:subClassOf pred:Event .
18
+
19
+ pred:GoalCreated a owl:Class ; rdfs:subClassOf pred:Event .
20
+ pred:GoalStatusChanged a owl:Class ; rdfs:subClassOf pred:Event .
21
+
22
+ pred:InconsistencyDetected a owl:Class ; rdfs:subClassOf pred:Event .
23
+ pred:MaintenanceRun a owl:Class ; rdfs:subClassOf pred:Event .
24
+
25
+ # --- Common event properties -------------------------------------
26
+
27
+ pred:at a owl:DatatypeProperty , owl:FunctionalProperty ;
28
+ rdfs:domain pred:Event ; rdfs:range xsd:dateTime .
29
+ pred:actor a owl:DatatypeProperty ;
30
+ rdfs:domain pred:Event ; rdfs:range xsd:string .
31
+ pred:goal a owl:ObjectProperty ; rdfs:domain pred:Event .
32
+ pred:payload a owl:DatatypeProperty ;
33
+ rdfs:domain pred:Event ; rdfs:range xsd:string .
34
+
35
+ # --- Provenance properties (already used by kg_assert RDF-star) --
36
+
37
+ pred:source a owl:DatatypeProperty ; rdfs:range xsd:string .
38
+ pred:confidence a owl:DatatypeProperty ; rdfs:range xsd:decimal .
39
+ pred:method a owl:DatatypeProperty ; rdfs:range xsd:string .
40
+ pred:timestamp a owl:DatatypeProperty ; rdfs:range xsd:dateTime .
41
+
42
+ # --- Query/usage event class (already used by kg_ask) ------------
43
+
44
+ pred:Query a owl:Class ; rdfs:label "Query execution record" .
45
+ pred:question a owl:DatatypeProperty ; rdfs:domain pred:Query ; rdfs:range xsd:string .
46
+ pred:sparql a owl:DatatypeProperty ; rdfs:domain pred:Query ; rdfs:range xsd:string .
47
+ pred:rowCount a owl:DatatypeProperty ; rdfs:domain pred:Query ; rdfs:range xsd:integer .
48
+ pred:elapsedMs a owl:DatatypeProperty ; rdfs:domain pred:Query ; rdfs:range xsd:integer .
49
+
50
+ # --- Tool-call capture event class (used by kg_capture) ----------
51
+
52
+ pred:ToolCall a owl:Class ; rdfs:label "Captured tool invocation" .
53
+
54
+ pred:toolName a owl:DatatypeProperty ;
55
+ rdfs:domain pred:ToolCall ; rdfs:range xsd:string .
56
+ pred:toolInput a owl:DatatypeProperty ;
57
+ rdfs:domain pred:ToolCall ; rdfs:range xsd:string .
58
+ pred:toolOutput a owl:DatatypeProperty ;
59
+ rdfs:domain pred:ToolCall ; rdfs:range xsd:string .
60
+ pred:sessionId a owl:DatatypeProperty ;
61
+ rdfs:domain pred:ToolCall ; rdfs:range xsd:string .
62
+ pred:phase a owl:DatatypeProperty ;
63
+ rdfs:domain pred:ToolCall ; rdfs:range xsd:string .
64
+
65
+ # --- Session class (used by the Stop-hook extractor) -------------
66
+
67
+ pred:Session a owl:Class ; rdfs:label "Development session" .
68
+ pred:startedAt a owl:DatatypeProperty ;
69
+ rdfs:domain pred:Session ; rdfs:range xsd:dateTime .
70
+ pred:endedAt a owl:DatatypeProperty ;
71
+ rdfs:domain pred:Session ; rdfs:range xsd:dateTime .
72
+
73
+ # --- Peer registry (federation) ----------------------------------
74
+
75
+ pred:Peer a owl:Class ; rdfs:label "Registered federation peer" .
76
+ pred:peerName a owl:DatatypeProperty ;
77
+ rdfs:domain pred:Peer ; rdfs:range xsd:string .
78
+ pred:peerEndpoint a owl:DatatypeProperty ;
79
+ rdfs:domain pred:Peer ; rdfs:range xsd:anyURI .
80
+ pred:peerAddedAt a owl:DatatypeProperty ;
81
+ rdfs:domain pred:Peer ; rdfs:range xsd:dateTime .
82
+ pred:peerKind a owl:DatatypeProperty ;
83
+ rdfs:domain pred:Peer ; rdfs:range xsd:string ;
84
+ rdfs:label "Peer kind tag: 'team' (default) or 'external-ld'" .
85
+
86
+ # --- Bootstrap/init config (v2.0) --------------------------------
87
+
88
+ pred:Config a owl:Class ; rdfs:label "Predicate runtime config singleton" .
89
+ pred:initMode a owl:DatatypeProperty , owl:FunctionalProperty ;
90
+ rdfs:domain pred:Config ; rdfs:range xsd:string ;
91
+ rdfs:comment "One of: community | upload | empty" .
92
+ pred:initOntology a owl:DatatypeProperty , owl:FunctionalProperty ;
93
+ rdfs:domain pred:Config ; rdfs:range xsd:string ;
94
+ rdfs:comment "Catalog name (e.g. codebase, foaf), or 'user' for upload, or 'top' for empty" .
95
+ pred:schemaLearningEnabled a owl:DatatypeProperty , owl:FunctionalProperty ;
96
+ rdfs:domain pred:Config ; rdfs:range xsd:boolean ;
97
+ rdfs:comment "When false, Generalizer skips auto-proposal generation (Sweeper still promotes existing staging)" .
98
+ pred:initializedAt a owl:DatatypeProperty , owl:FunctionalProperty ;
99
+ rdfs:domain pred:Config ; rdfs:range xsd:dateTime .
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "0.8.0",
3
+ "tbox_files": ["tbox/codebase.ttl", "meta/predicate-meta.ttl"],
4
+ "shape_files": ["shapes/codebase.shacl.ttl"],
5
+ "domain": "codebase"
6
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "predicate-skill",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Local reasoning knowledge graph (RDF/OWL) for AI agents — Claude Code plugin + MCP server + predicate CLI.",
5
5
  "author": {
6
6
  "name": "Nordic Agents Research",
7
7
  "email": "midhunxavier@outlook.com"
8
8
  },
9
- "license": "Apache-2.0",
9
+ "license": "SEE LICENSE IN LICENSE",
10
10
  "homepage": "https://github.com/NordicAgents/predicate#readme",
11
11
  "repository": {
12
12
  "type": "git",
@@ -30,13 +30,15 @@
30
30
  "commands",
31
31
  "hooks",
32
32
  "compose",
33
+ "catalog",
34
+ "meta",
33
35
  "dashboard",
34
36
  "LICENSE",
35
37
  "README.md"
36
38
  ],
37
39
  "scripts": {
38
40
  "bundle": "node scripts/bundle.mjs",
39
- "prepublishOnly": "node scripts/bundle.mjs && node -e \"const fs=require('fs');for(const f of ['server.bundle.mjs','cli.bundle.mjs']){if(!fs.existsSync(f)){console.error('missing '+f);process.exit(1)}}\""
41
+ "prepublishOnly": "node scripts/bundle.mjs && node -e \"const fs=require('fs');for(const f of ['server.bundle.mjs','cli.bundle.mjs','catalog/catalog.json','meta/predicate-meta.ttl']){if(!fs.existsSync(f)){console.error('missing '+f);process.exit(1)}}\""
40
42
  },
41
43
  "engines": {
42
44
  "node": ">=20"