opentology 0.2.3 → 0.2.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.
- package/dist/commands/context.js +2 -1
- package/dist/index.js +1 -1
- package/dist/lib/codebase-scanner.js +2 -1
- package/dist/lib/deep-scan-triples.d.ts +3 -3
- package/dist/lib/deep-scan-triples.js +0 -2
- package/dist/lib/module-uri.d.ts +6 -0
- package/dist/lib/module-uri.js +11 -0
- package/dist/lib/reasoner.d.ts +0 -11
- package/dist/lib/reasoner.js +1 -1
- package/dist/lib/shacl.d.ts +3 -2
- package/dist/lib/sparql-utils.d.ts +0 -5
- package/dist/lib/sparql-utils.js +0 -36
- package/dist/lib/store-factory.d.ts +0 -1
- package/dist/lib/store-factory.js +0 -6
- package/dist/mcp/server.js +2 -1
- package/dist/templates/claude-md-context.d.ts +0 -2
- package/dist/templates/claude-md-context.js +2 -2
- package/dist/templates/otx-ontology.d.ts +0 -1
- package/dist/templates/otx-ontology.js +0 -3
- package/package.json +1 -1
package/dist/commands/context.js
CHANGED
|
@@ -11,6 +11,7 @@ import { generateContextSection, updateClaudeMd } from '../templates/claude-md-c
|
|
|
11
11
|
import { generateHookScript } from '../templates/session-start-hook.js';
|
|
12
12
|
import { generatePreEditHookScript } from '../templates/pre-edit-hook.js';
|
|
13
13
|
import { generateSlashCommands } from '../templates/slash-commands.js';
|
|
14
|
+
import { normalizeModuleUri } from '../lib/module-uri.js';
|
|
14
15
|
function ask(question) {
|
|
15
16
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
16
17
|
return new Promise((resolve) => {
|
|
@@ -454,7 +455,7 @@ export function registerContext(program) {
|
|
|
454
455
|
}
|
|
455
456
|
const contextUri = graphs['context'];
|
|
456
457
|
const OTX = 'https://opentology.dev/vocab#';
|
|
457
|
-
const moduleUriStr =
|
|
458
|
+
const moduleUriStr = normalizeModuleUri(opts.file);
|
|
458
459
|
try {
|
|
459
460
|
const adapter = await createReadyAdapter(config);
|
|
460
461
|
// Dependents (reverse deps)
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import { registerDoctor } from './commands/doctor.js';
|
|
|
20
20
|
const program = new Command();
|
|
21
21
|
program
|
|
22
22
|
.name('opentology')
|
|
23
|
-
.version('0.2.
|
|
23
|
+
.version('0.2.4')
|
|
24
24
|
.description('CLI-managed RDF/SPARQL infrastructure — Supabase for RDF');
|
|
25
25
|
registerInit(program);
|
|
26
26
|
registerValidate(program);
|
|
@@ -2,6 +2,7 @@ import { readFile, readdir } from 'node:fs/promises';
|
|
|
2
2
|
import { join, relative } from 'node:path';
|
|
3
3
|
import { execFile } from 'node:child_process';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
|
+
import { stripSourceExtension } from './module-uri.js';
|
|
5
6
|
const execFileAsync = promisify(execFile);
|
|
6
7
|
const DEFAULT_MAX_BYTES = 15360;
|
|
7
8
|
const HARDCODED_EXCLUDES = new Set(['.git', 'node_modules', 'dist', 'build', '.opentology', '.claude', '.omc']);
|
|
@@ -212,7 +213,7 @@ export async function extractDependencyGraph(rootDir, gitFiles) {
|
|
|
212
213
|
const moduleSet = new Set();
|
|
213
214
|
const edges = [];
|
|
214
215
|
for (const filePath of sourceFiles) {
|
|
215
|
-
const moduleName = filePath
|
|
216
|
+
const moduleName = stripSourceExtension(filePath);
|
|
216
217
|
moduleSet.add(moduleName);
|
|
217
218
|
let content;
|
|
218
219
|
try {
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
import type { DeepScanResult } from './deep-scanner.js';
|
|
6
6
|
export declare function generateSymbolTriples(result: DeepScanResult): string[];
|
|
7
7
|
export declare function batchTriples(triples: string[], batchSize?: number): string[][];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
8
|
+
import type { StoreAdapter as FullStoreAdapter } from './store-adapter.js';
|
|
9
|
+
type StoreAdapter = Pick<FullStoreAdapter, 'sparqlUpdate'>;
|
|
11
10
|
export declare function deleteExistingSymbols(adapter: StoreAdapter, graphUri: string, modulePaths: string[]): Promise<void>;
|
|
12
11
|
export declare function pushSymbolTriples(adapter: StoreAdapter, graphUri: string, result: DeepScanResult): Promise<{
|
|
13
12
|
triplesInserted: number;
|
|
14
13
|
batchCount: number;
|
|
15
14
|
}>;
|
|
15
|
+
export {};
|
|
@@ -75,8 +75,6 @@ export function generateSymbolTriples(result) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
for (const call of result.methodCalls) {
|
|
78
|
-
const callerParts = call.caller.split('.');
|
|
79
|
-
const calleeParts = call.callee.split('.');
|
|
80
78
|
// Method calls reference by class.method pattern — generate a simple triple
|
|
81
79
|
triples.push(`<urn:call:${encodeSegment(call.caller)}> <${OTX}calls> <urn:call:${encodeSegment(call.callee)}> .`);
|
|
82
80
|
// Store caller/callee names for queryability
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared module URI normalization — single source of truth for
|
|
3
|
+
* converting file paths to urn:module: URIs.
|
|
4
|
+
*/
|
|
5
|
+
const SOURCE_EXT_RE = /\.[tj]sx?$/;
|
|
6
|
+
export function stripSourceExtension(filePath) {
|
|
7
|
+
return filePath.replace(SOURCE_EXT_RE, '');
|
|
8
|
+
}
|
|
9
|
+
export function normalizeModuleUri(filePath) {
|
|
10
|
+
return `urn:module:${stripSourceExtension(filePath)}`;
|
|
11
|
+
}
|
package/dist/lib/reasoner.d.ts
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
import type { StoreAdapter } from './store-adapter.js';
|
|
2
|
-
interface Triple {
|
|
3
|
-
s: string;
|
|
4
|
-
p: string;
|
|
5
|
-
o: string;
|
|
6
|
-
isLiteral: boolean;
|
|
7
|
-
}
|
|
8
2
|
export interface InferenceResult {
|
|
9
3
|
assertedCount: number;
|
|
10
4
|
inferredCount: number;
|
|
11
5
|
rules: Record<string, number>;
|
|
12
6
|
}
|
|
13
|
-
export declare function computeInferences(triples: Triple[]): {
|
|
14
|
-
inferred: Triple[];
|
|
15
|
-
rules: Record<string, number>;
|
|
16
|
-
};
|
|
17
7
|
export declare function clearInferences(adapter: StoreAdapter, graphUri: string): Promise<void>;
|
|
18
8
|
export declare function materializeInferences(adapter: StoreAdapter, graphUri: string): Promise<InferenceResult>;
|
|
19
|
-
export {};
|
package/dist/lib/reasoner.js
CHANGED
|
@@ -68,7 +68,7 @@ function transitiveClosure(pairs) {
|
|
|
68
68
|
return result;
|
|
69
69
|
}
|
|
70
70
|
// ── Pure inference engine ──────────────────────────────────────────────
|
|
71
|
-
|
|
71
|
+
function computeInferences(triples) {
|
|
72
72
|
const assertedSet = new Set(triples.map(tripleKey));
|
|
73
73
|
const inferredMap = new Map(); // tripleKey → rule name
|
|
74
74
|
const rules = {};
|
package/dist/lib/shacl.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
interface ShaclViolation {
|
|
2
2
|
focusNode: string;
|
|
3
3
|
path: string | null;
|
|
4
4
|
message: string;
|
|
5
5
|
severity: string;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
interface ShaclReport {
|
|
8
8
|
conforms: boolean;
|
|
9
9
|
violations: ShaclViolation[];
|
|
10
10
|
}
|
|
@@ -20,3 +20,4 @@ export declare function hasShapes(shapesDir?: string): boolean;
|
|
|
20
20
|
* Validate a Turtle data string against the given SHACL shape files.
|
|
21
21
|
*/
|
|
22
22
|
export declare function validateWithShacl(dataTurtle: string, shapePaths: string[]): Promise<ShaclReport>;
|
|
23
|
+
export {};
|
|
@@ -20,9 +20,4 @@ export declare function hasGraphScope(sparql: string): boolean;
|
|
|
20
20
|
* Returns null if the outermost `{ ... }` block cannot be located safely.
|
|
21
21
|
*/
|
|
22
22
|
export declare function autoScopeQuery(sparql: string, graphUri: string): string | null;
|
|
23
|
-
/**
|
|
24
|
-
* Auto-scope a SPARQL query with UNION over asserted + inference graphs.
|
|
25
|
-
* Returns null if brace matching fails.
|
|
26
|
-
*/
|
|
27
|
-
export declare function autoScopeQueryWithInference(sparql: string, graphUri: string, inferenceGraphUri: string): string | null;
|
|
28
23
|
export declare function getInferenceGraphUri(graphUri: string): string;
|
package/dist/lib/sparql-utils.js
CHANGED
|
@@ -175,42 +175,6 @@ export function autoScopeQuery(sparql, graphUri) {
|
|
|
175
175
|
const after = sparql.slice(braceEnd); // from `}` onwards
|
|
176
176
|
return `${before} GRAPH <${graphUri}> {${inner}} ${after}`;
|
|
177
177
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Auto-scope a SPARQL query with UNION over asserted + inference graphs.
|
|
180
|
-
* Returns null if brace matching fails.
|
|
181
|
-
*/
|
|
182
|
-
export function autoScopeQueryWithInference(sparql, graphUri, inferenceGraphUri) {
|
|
183
|
-
const whereMatch = sparql.match(/\bWHERE\s*\{/i);
|
|
184
|
-
let braceStart;
|
|
185
|
-
if (whereMatch && whereMatch.index !== undefined) {
|
|
186
|
-
braceStart = whereMatch.index + whereMatch[0].length - 1;
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
const firstBrace = sparql.indexOf('{');
|
|
190
|
-
if (firstBrace === -1)
|
|
191
|
-
return null;
|
|
192
|
-
braceStart = firstBrace;
|
|
193
|
-
}
|
|
194
|
-
let depth = 0;
|
|
195
|
-
let braceEnd = -1;
|
|
196
|
-
for (let i = braceStart; i < sparql.length; i++) {
|
|
197
|
-
if (sparql[i] === '{')
|
|
198
|
-
depth++;
|
|
199
|
-
else if (sparql[i] === '}') {
|
|
200
|
-
depth--;
|
|
201
|
-
if (depth === 0) {
|
|
202
|
-
braceEnd = i;
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
if (braceEnd === -1)
|
|
208
|
-
return null;
|
|
209
|
-
const before = sparql.slice(0, braceStart + 1);
|
|
210
|
-
const inner = sparql.slice(braceStart + 1, braceEnd);
|
|
211
|
-
const after = sparql.slice(braceEnd);
|
|
212
|
-
return `${before} GRAPH ?__g {${inner}} FILTER(?__g = <${graphUri}> || ?__g = <${inferenceGraphUri}>) ${after}`;
|
|
213
|
-
}
|
|
214
178
|
// ── Inference graph URI ───────────────────────────────────────────────
|
|
215
179
|
export function getInferenceGraphUri(graphUri) {
|
|
216
180
|
return `${graphUri}/inferred`;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { StoreAdapter } from './store-adapter.js';
|
|
2
2
|
import type { OpenTologyConfig } from './config.js';
|
|
3
|
-
export declare function createAdapter(config: OpenTologyConfig): StoreAdapter;
|
|
4
3
|
/**
|
|
5
4
|
* Reset the cached embedded adapter. Useful for tests or after config-level
|
|
6
5
|
* changes that invalidate the entire store (e.g. project re-init).
|
|
@@ -7,12 +7,6 @@ import { materializeInferences } from './reasoner.js';
|
|
|
7
7
|
// Singleton cache for embedded mode — keeps data alive across MCP tool calls.
|
|
8
8
|
let cachedAdapter = null;
|
|
9
9
|
let loadedFileKeys = new Set();
|
|
10
|
-
export function createAdapter(config) {
|
|
11
|
-
if (config.mode === 'embedded') {
|
|
12
|
-
return new EmbeddedAdapter();
|
|
13
|
-
}
|
|
14
|
-
return new HttpAdapter(config.endpoint ?? 'http://localhost:7878');
|
|
15
|
-
}
|
|
16
10
|
/**
|
|
17
11
|
* Reset the cached embedded adapter. Useful for tests or after config-level
|
|
18
12
|
* changes that invalidate the entire store (e.g. project re-init).
|
package/dist/mcp/server.js
CHANGED
|
@@ -5,6 +5,7 @@ import { loadConfig, saveConfig, configExists, resolveGraphUri } from '../lib/co
|
|
|
5
5
|
import { deepScan } from '../lib/deep-scanner.js';
|
|
6
6
|
import { pushSymbolTriples } from '../lib/deep-scan-triples.js';
|
|
7
7
|
import { createReadyAdapter } from '../lib/store-factory.js';
|
|
8
|
+
import { normalizeModuleUri } from '../lib/module-uri.js';
|
|
8
9
|
import { hasGraphScope, autoScopeQuery, getInferenceGraphUri } from '../lib/sparql-utils.js';
|
|
9
10
|
import { validateTurtle } from '../lib/validator.js';
|
|
10
11
|
import { discoverShapes, validateWithShacl, hasShapes } from '../lib/shacl.js';
|
|
@@ -627,7 +628,7 @@ async function handleContextImpact(args) {
|
|
|
627
628
|
const contextUri = `${config.graphUri}/context`;
|
|
628
629
|
const adapter = await createReadyAdapter(config);
|
|
629
630
|
const OTX = 'https://opentology.dev/vocab#';
|
|
630
|
-
const moduleUriStr =
|
|
631
|
+
const moduleUriStr = normalizeModuleUri(filePath);
|
|
631
632
|
// 1. Modules that depend on this file (dependents / reverse deps)
|
|
632
633
|
const dependentsQuery = `
|
|
633
634
|
SELECT ?dependent WHERE {
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export declare const MARKER_BEGIN = "<!-- OPENTOLOGY:CONTEXT:BEGIN -->";
|
|
2
|
-
export declare const MARKER_END = "<!-- OPENTOLOGY:CONTEXT:END -->";
|
|
3
1
|
export declare function generateContextSection(projectId: string, graphUri: string): string;
|
|
4
2
|
export declare function updateClaudeMd(filePath: string, section: string): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const MARKER_BEGIN = '<!-- OPENTOLOGY:CONTEXT:BEGIN -->';
|
|
3
|
+
const MARKER_END = '<!-- OPENTOLOGY:CONTEXT:END -->';
|
|
4
4
|
export function generateContextSection(projectId, graphUri) {
|
|
5
5
|
const contextUri = `${graphUri}/context`;
|
|
6
6
|
const sessionsUri = `${graphUri}/sessions`;
|
|
@@ -1,2 +1 @@
|
|
|
1
1
|
export declare const OTX_BOOTSTRAP_TURTLE = "@prefix otx: <https://opentology.dev/vocab#> .\n@prefix owl: <http://www.w3.org/2002/07/owl#> .\n@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\notx:Project a owl:Class .\notx:Decision a owl:Class .\notx:Issue a owl:Class .\notx:Knowledge a owl:Class .\notx:Session a owl:Class .\notx:Pattern a owl:Class .\notx:Module a owl:Class .\n\notx:title a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:date a owl:DatatypeProperty ; rdfs:range xsd:date .\notx:body a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:status a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:reason a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:cause a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:solution a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:nextTodo a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:relatedTo a owl:ObjectProperty .\notx:project a owl:ObjectProperty .\notx:dependsOn a owl:ObjectProperty ; rdfs:domain otx:Module ; rdfs:range otx:Module .\notx:stack a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:alternative a owl:DatatypeProperty ; rdfs:range xsd:string .\n\notx:Class a owl:Class .\notx:Interface a owl:Class .\notx:Function a owl:Class .\notx:Method a owl:Class .\n\notx:definedIn a owl:ObjectProperty ; rdfs:range otx:Module .\notx:extends a owl:ObjectProperty ; rdfs:domain otx:Class ; rdfs:range otx:Class .\notx:implements a owl:ObjectProperty ; rdfs:domain otx:Class ; rdfs:range otx:Interface .\notx:hasMethod a owl:ObjectProperty ; rdfs:domain otx:Class ; rdfs:range otx:Method .\notx:calls a owl:ObjectProperty ; rdfs:domain otx:Method ; rdfs:range otx:Method .\notx:returns a owl:DatatypeProperty ; rdfs:range xsd:string .\notx:paramType a owl:DatatypeProperty ; rdfs:range xsd:string .\n";
|
|
2
|
-
export declare function buildAskQuery(contextGraphUri: string): string;
|
|
@@ -39,6 +39,3 @@ otx:calls a owl:ObjectProperty ; rdfs:domain otx:Method ; rdfs:range otx:Method
|
|
|
39
39
|
otx:returns a owl:DatatypeProperty ; rdfs:range xsd:string .
|
|
40
40
|
otx:paramType a owl:DatatypeProperty ; rdfs:range xsd:string .
|
|
41
41
|
`;
|
|
42
|
-
export function buildAskQuery(contextGraphUri) {
|
|
43
|
-
return `ASK { GRAPH <${contextGraphUri}> { <https://opentology.dev/vocab#Decision> a <http://www.w3.org/2002/07/owl#Class> } }`;
|
|
44
|
-
}
|