trellis 2.0.8 → 2.0.13

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.
Files changed (42) hide show
  1. package/README.md +279 -116
  2. package/dist/cli/index.js +655 -4
  3. package/dist/core/index.js +471 -2
  4. package/dist/embeddings/index.js +5 -1
  5. package/dist/{index-s603ev6w.js → index-5b01h414.js} +1 -1
  6. package/dist/index-5m0g9r0y.js +1100 -0
  7. package/dist/{index-zf6htvnm.js → index-7gvjxt27.js} +166 -2
  8. package/dist/index-hybgxe40.js +1174 -0
  9. package/dist/index.js +7 -2
  10. package/dist/transformers.node-bx3q9d7k.js +33130 -0
  11. package/package.json +9 -4
  12. package/src/cli/index.ts +939 -0
  13. package/src/core/agents/harness.ts +380 -0
  14. package/src/core/agents/index.ts +18 -0
  15. package/src/core/agents/types.ts +90 -0
  16. package/src/core/index.ts +85 -2
  17. package/src/core/kernel/trellis-kernel.ts +593 -0
  18. package/src/core/ontology/builtins.ts +248 -0
  19. package/src/core/ontology/index.ts +34 -0
  20. package/src/core/ontology/registry.ts +209 -0
  21. package/src/core/ontology/types.ts +124 -0
  22. package/src/core/ontology/validator.ts +382 -0
  23. package/src/core/persist/backend.ts +10 -0
  24. package/src/core/persist/sqlite-backend.ts +298 -0
  25. package/src/core/plugins/index.ts +17 -0
  26. package/src/core/plugins/registry.ts +322 -0
  27. package/src/core/plugins/types.ts +126 -0
  28. package/src/core/query/datalog.ts +188 -0
  29. package/src/core/query/engine.ts +370 -0
  30. package/src/core/query/index.ts +34 -0
  31. package/src/core/query/parser.ts +481 -0
  32. package/src/core/query/types.ts +200 -0
  33. package/src/embeddings/auto-embed.ts +248 -0
  34. package/src/embeddings/index.ts +7 -0
  35. package/src/embeddings/model.ts +21 -4
  36. package/src/embeddings/types.ts +8 -1
  37. package/src/index.ts +9 -0
  38. package/src/sync/http-transport.ts +144 -0
  39. package/src/sync/index.ts +11 -0
  40. package/src/sync/multi-repo.ts +200 -0
  41. package/src/sync/ws-transport.ts +145 -0
  42. package/dist/index-5bhe57y9.js +0 -326
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Built-in Ontology Definitions
3
+ *
4
+ * Pre-defined ontologies for common domain models:
5
+ * - Project: software project management entities
6
+ * - Team: team/developer organizational entities
7
+ * - Agent: AI agent entities for the agent harness
8
+ *
9
+ * @module trellis/core/ontology
10
+ */
11
+
12
+ import type { OntologySchema } from './types.js';
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Project Ontology
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export const projectOntology: OntologySchema = {
19
+ id: 'trellis:project',
20
+ name: 'Project Ontology',
21
+ version: '1.0.0',
22
+ description: 'Entity types for software project management.',
23
+ entities: [
24
+ {
25
+ name: 'Project',
26
+ description: 'A software project or repository.',
27
+ attributes: [
28
+ { name: 'name', type: 'string', required: true, description: 'Project name' },
29
+ { name: 'description', type: 'string', description: 'Project description' },
30
+ { name: 'status', type: 'string', enum: ['active', 'archived', 'draft', 'deprecated'], default: 'active' },
31
+ { name: 'url', type: 'string', description: 'Project URL or repository link' },
32
+ { name: 'language', type: 'string', description: 'Primary programming language' },
33
+ { name: 'createdAt', type: 'date', description: 'Creation timestamp' },
34
+ { name: 'updatedAt', type: 'date', description: 'Last update timestamp' },
35
+ ],
36
+ },
37
+ {
38
+ name: 'Module',
39
+ description: 'A logical module or package within a project.',
40
+ attributes: [
41
+ { name: 'name', type: 'string', required: true },
42
+ { name: 'path', type: 'string', description: 'Filesystem path relative to project root' },
43
+ { name: 'description', type: 'string' },
44
+ ],
45
+ },
46
+ {
47
+ name: 'Feature',
48
+ description: 'A product feature or capability.',
49
+ attributes: [
50
+ { name: 'name', type: 'string', required: true },
51
+ { name: 'description', type: 'string' },
52
+ { name: 'status', type: 'string', enum: ['planned', 'in-progress', 'shipped', 'cut'], default: 'planned' },
53
+ { name: 'priority', type: 'string', enum: ['critical', 'high', 'medium', 'low'], default: 'medium' },
54
+ ],
55
+ },
56
+ {
57
+ name: 'Dependency',
58
+ description: 'An external dependency or library.',
59
+ attributes: [
60
+ { name: 'name', type: 'string', required: true },
61
+ { name: 'version', type: 'string' },
62
+ { name: 'registry', type: 'string', description: 'Package registry (npm, pypi, etc.)' },
63
+ { name: 'scope', type: 'string', enum: ['runtime', 'dev', 'optional'], default: 'runtime' },
64
+ ],
65
+ },
66
+ {
67
+ name: 'Config',
68
+ description: 'A configuration entry or setting.',
69
+ attributes: [
70
+ { name: 'key', type: 'string', required: true },
71
+ { name: 'value', type: 'any', required: true },
72
+ { name: 'description', type: 'string' },
73
+ { name: 'scope', type: 'string', enum: ['project', 'user', 'system'], default: 'project' },
74
+ ],
75
+ },
76
+ {
77
+ name: 'Artifact',
78
+ description: 'A build artifact, release asset, or output file.',
79
+ attributes: [
80
+ { name: 'name', type: 'string', required: true },
81
+ { name: 'path', type: 'string' },
82
+ { name: 'size', type: 'number' },
83
+ { name: 'hash', type: 'string' },
84
+ { name: 'format', type: 'string' },
85
+ ],
86
+ },
87
+ {
88
+ name: 'Release',
89
+ description: 'A versioned release of a project.',
90
+ attributes: [
91
+ { name: 'version', type: 'string', required: true },
92
+ { name: 'tag', type: 'string' },
93
+ { name: 'date', type: 'date' },
94
+ { name: 'notes', type: 'string' },
95
+ { name: 'status', type: 'string', enum: ['draft', 'published', 'yanked'], default: 'draft' },
96
+ ],
97
+ },
98
+ ],
99
+ relations: [
100
+ { name: 'contains', sourceTypes: ['Project'], targetTypes: ['Module', 'Feature', 'Config'], cardinality: 'many', description: 'Project contains modules/features/configs' },
101
+ { name: 'dependsOn', sourceTypes: ['Project', 'Module'], targetTypes: ['Dependency', 'Module', 'Project'], cardinality: 'many', description: 'Depends on another entity' },
102
+ { name: 'implementedBy', sourceTypes: ['Feature'], targetTypes: ['Module'], cardinality: 'many', description: 'Feature is implemented by modules' },
103
+ { name: 'produces', sourceTypes: ['Project', 'Release'], targetTypes: ['Artifact'], cardinality: 'many', description: 'Produces artifacts' },
104
+ { name: 'releases', sourceTypes: ['Project'], targetTypes: ['Release'], cardinality: 'many', description: 'Project has releases' },
105
+ ],
106
+ };
107
+
108
+ // ---------------------------------------------------------------------------
109
+ // Team / Developer Ontology
110
+ // ---------------------------------------------------------------------------
111
+
112
+ export const teamOntology: OntologySchema = {
113
+ id: 'trellis:team',
114
+ name: 'Team Ontology',
115
+ version: '1.0.0',
116
+ description: 'Entity types for team and developer organization.',
117
+ entities: [
118
+ {
119
+ name: 'Team',
120
+ description: 'A team or organizational group.',
121
+ attributes: [
122
+ { name: 'name', type: 'string', required: true },
123
+ { name: 'description', type: 'string' },
124
+ { name: 'slug', type: 'string', description: 'URL-safe identifier' },
125
+ ],
126
+ },
127
+ {
128
+ name: 'Developer',
129
+ description: 'A developer or contributor.',
130
+ attributes: [
131
+ { name: 'name', type: 'string', required: true },
132
+ { name: 'email', type: 'string' },
133
+ { name: 'handle', type: 'string', description: 'Username or handle' },
134
+ { name: 'role', type: 'string', enum: ['admin', 'maintainer', 'contributor', 'reviewer'] },
135
+ ],
136
+ },
137
+ {
138
+ name: 'Role',
139
+ description: 'A named role with specific permissions.',
140
+ attributes: [
141
+ { name: 'name', type: 'string', required: true },
142
+ { name: 'description', type: 'string' },
143
+ { name: 'permissions', type: 'string', unique: false, description: 'Permission strings (multi-valued)' },
144
+ ],
145
+ },
146
+ {
147
+ name: 'Capability',
148
+ description: 'A skill or capability.',
149
+ attributes: [
150
+ { name: 'name', type: 'string', required: true },
151
+ { name: 'category', type: 'string' },
152
+ { name: 'level', type: 'string', enum: ['beginner', 'intermediate', 'advanced', 'expert'] },
153
+ ],
154
+ },
155
+ ],
156
+ relations: [
157
+ { name: 'hasMember', sourceTypes: ['Team'], targetTypes: ['Developer'], cardinality: 'many', inverse: 'memberOf', description: 'Team has member' },
158
+ { name: 'memberOf', sourceTypes: ['Developer'], targetTypes: ['Team'], cardinality: 'many', inverse: 'hasMember', description: 'Developer is member of team' },
159
+ { name: 'owns', sourceTypes: ['Developer'], targetTypes: ['Project', 'Module'], cardinality: 'many', description: 'Developer owns/maintains' },
160
+ { name: 'reviewsFor', sourceTypes: ['Developer'], targetTypes: ['Project', 'Module'], cardinality: 'many', description: 'Developer reviews for' },
161
+ { name: 'hasCapability', sourceTypes: ['Developer'], targetTypes: ['Capability'], cardinality: 'many', description: 'Developer has capability' },
162
+ { name: 'hasRole', sourceTypes: ['Developer'], targetTypes: ['Role'], cardinality: 'many', description: 'Developer has role' },
163
+ { name: 'assignedTo', sourceTypes: ['Developer'], targetTypes: ['Feature'], cardinality: 'many', description: 'Developer is assigned to feature' },
164
+ ],
165
+ };
166
+
167
+ // ---------------------------------------------------------------------------
168
+ // Agent Ontology
169
+ // ---------------------------------------------------------------------------
170
+
171
+ export const agentOntology: OntologySchema = {
172
+ id: 'trellis:agent',
173
+ name: 'Agent Ontology',
174
+ version: '1.0.0',
175
+ description: 'Entity types for AI agents, runs, plans, and tools.',
176
+ entities: [
177
+ {
178
+ name: 'Agent',
179
+ description: 'An AI agent definition.',
180
+ attributes: [
181
+ { name: 'name', type: 'string', required: true },
182
+ { name: 'description', type: 'string' },
183
+ { name: 'model', type: 'string', description: 'LLM model identifier' },
184
+ { name: 'provider', type: 'string', description: 'LLM provider (openai, anthropic, local, etc.)' },
185
+ { name: 'systemPrompt', type: 'string' },
186
+ { name: 'status', type: 'string', enum: ['active', 'inactive', 'deprecated'], default: 'active' },
187
+ ],
188
+ },
189
+ {
190
+ name: 'AgentCapability',
191
+ description: 'A capability or skill an agent possesses.',
192
+ attributes: [
193
+ { name: 'name', type: 'string', required: true },
194
+ { name: 'description', type: 'string' },
195
+ { name: 'category', type: 'string' },
196
+ ],
197
+ },
198
+ {
199
+ name: 'AgentRun',
200
+ description: 'A single execution run of an agent.',
201
+ attributes: [
202
+ { name: 'startedAt', type: 'date', required: true },
203
+ { name: 'completedAt', type: 'date' },
204
+ { name: 'status', type: 'string', enum: ['running', 'completed', 'failed', 'cancelled'], default: 'running' },
205
+ { name: 'input', type: 'string' },
206
+ { name: 'output', type: 'string' },
207
+ { name: 'tokenCount', type: 'number' },
208
+ ],
209
+ },
210
+ {
211
+ name: 'AgentPlan',
212
+ description: 'A plan or strategy created by an agent.',
213
+ attributes: [
214
+ { name: 'title', type: 'string', required: true },
215
+ { name: 'description', type: 'string' },
216
+ { name: 'status', type: 'string', enum: ['draft', 'active', 'completed', 'abandoned'], default: 'draft' },
217
+ ],
218
+ },
219
+ {
220
+ name: 'Tool',
221
+ description: 'A tool available to agents.',
222
+ attributes: [
223
+ { name: 'name', type: 'string', required: true },
224
+ { name: 'description', type: 'string' },
225
+ { name: 'schema', type: 'string', description: 'JSON schema for tool parameters' },
226
+ { name: 'endpoint', type: 'string' },
227
+ ],
228
+ },
229
+ ],
230
+ relations: [
231
+ { name: 'hasCapability', sourceTypes: ['Agent'], targetTypes: ['AgentCapability'], cardinality: 'many' },
232
+ { name: 'hasTool', sourceTypes: ['Agent'], targetTypes: ['Tool'], cardinality: 'many' },
233
+ { name: 'executedBy', sourceTypes: ['AgentRun'], targetTypes: ['Agent'], cardinality: 'one' },
234
+ { name: 'hasPlan', sourceTypes: ['AgentRun'], targetTypes: ['AgentPlan'], cardinality: 'many' },
235
+ { name: 'usedTool', sourceTypes: ['AgentRun'], targetTypes: ['Tool'], cardinality: 'many' },
236
+ { name: 'createdBy', sourceTypes: ['AgentPlan'], targetTypes: ['Agent'], cardinality: 'one' },
237
+ ],
238
+ };
239
+
240
+ // ---------------------------------------------------------------------------
241
+ // All built-in ontologies
242
+ // ---------------------------------------------------------------------------
243
+
244
+ export const builtinOntologies: OntologySchema[] = [
245
+ projectOntology,
246
+ teamOntology,
247
+ agentOntology,
248
+ ];
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Ontology Module — Public API Surface
3
+ *
4
+ * @module trellis/core/ontology
5
+ */
6
+
7
+ // Types
8
+ export type {
9
+ AttrType,
10
+ AttributeDef,
11
+ RelationDef,
12
+ EntityDef,
13
+ OntologySchema,
14
+ ValidationError,
15
+ ValidationResult,
16
+ } from './types.js';
17
+
18
+ // Registry
19
+ export { OntologyRegistry } from './registry.js';
20
+
21
+ // Built-in ontologies
22
+ export {
23
+ projectOntology,
24
+ teamOntology,
25
+ agentOntology,
26
+ builtinOntologies,
27
+ } from './builtins.js';
28
+
29
+ // Validation
30
+ export {
31
+ validateEntity,
32
+ validateStore,
33
+ createValidationMiddleware,
34
+ } from './validator.js';
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Ontology Registry — Manages loaded ontology schemas.
3
+ *
4
+ * Provides registration, lookup, inheritance resolution, and
5
+ * entity-type-to-schema mapping.
6
+ *
7
+ * @module trellis/core/ontology
8
+ */
9
+
10
+ import type {
11
+ OntologySchema,
12
+ EntityDef,
13
+ RelationDef,
14
+ AttributeDef,
15
+ } from './types.js';
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Registry
19
+ // ---------------------------------------------------------------------------
20
+
21
+ export class OntologyRegistry {
22
+ private schemas: Map<string, OntologySchema> = new Map();
23
+ /** Resolved entity defs (with inherited attributes merged). */
24
+ private resolvedEntities: Map<string, { def: EntityDef; ontologyId: string }> = new Map();
25
+ /** Resolved relation defs. */
26
+ private resolvedRelations: Map<string, { def: RelationDef; ontologyId: string }[]> = new Map();
27
+
28
+ /**
29
+ * Register an ontology schema.
30
+ * Throws if an ontology with the same ID is already registered at the same version.
31
+ */
32
+ register(schema: OntologySchema): void {
33
+ const existing = this.schemas.get(schema.id);
34
+ if (existing && existing.version === schema.version) {
35
+ throw new Error(
36
+ `Ontology "${schema.id}" v${schema.version} is already registered.`,
37
+ );
38
+ }
39
+ this.schemas.set(schema.id, schema);
40
+ this._resolve(schema);
41
+ }
42
+
43
+ /**
44
+ * Unregister an ontology by ID.
45
+ */
46
+ unregister(id: string): void {
47
+ const schema = this.schemas.get(id);
48
+ if (!schema) return;
49
+
50
+ // Remove entities belonging to this ontology
51
+ for (const [name, entry] of this.resolvedEntities) {
52
+ if (entry.ontologyId === id) {
53
+ this.resolvedEntities.delete(name);
54
+ }
55
+ }
56
+
57
+ // Remove relations belonging to this ontology
58
+ for (const [name, entries] of this.resolvedRelations) {
59
+ const filtered = entries.filter((e) => e.ontologyId !== id);
60
+ if (filtered.length === 0) {
61
+ this.resolvedRelations.delete(name);
62
+ } else {
63
+ this.resolvedRelations.set(name, filtered);
64
+ }
65
+ }
66
+
67
+ this.schemas.delete(id);
68
+ }
69
+
70
+ /**
71
+ * Get a registered ontology schema by ID.
72
+ */
73
+ get(id: string): OntologySchema | undefined {
74
+ return this.schemas.get(id);
75
+ }
76
+
77
+ /**
78
+ * List all registered ontology schemas.
79
+ */
80
+ list(): OntologySchema[] {
81
+ return [...this.schemas.values()];
82
+ }
83
+
84
+ /**
85
+ * Get the resolved entity definition for an entity type name.
86
+ * Returns the entity def with inherited attributes merged in.
87
+ */
88
+ getEntityDef(typeName: string): EntityDef | undefined {
89
+ return this.resolvedEntities.get(typeName)?.def;
90
+ }
91
+
92
+ /**
93
+ * Get the ontology ID that defines a given entity type.
94
+ */
95
+ getEntityOntology(typeName: string): string | undefined {
96
+ return this.resolvedEntities.get(typeName)?.ontologyId;
97
+ }
98
+
99
+ /**
100
+ * List all known entity type names.
101
+ */
102
+ listEntityTypes(): string[] {
103
+ return [...this.resolvedEntities.keys()];
104
+ }
105
+
106
+ /**
107
+ * Get all relation definitions involving a given entity type
108
+ * (either as source or target).
109
+ */
110
+ getRelationsForType(typeName: string): RelationDef[] {
111
+ const results: RelationDef[] = [];
112
+ for (const [, entries] of this.resolvedRelations) {
113
+ for (const entry of entries) {
114
+ if (
115
+ entry.def.sourceTypes.includes(typeName) ||
116
+ entry.def.targetTypes.includes(typeName)
117
+ ) {
118
+ results.push(entry.def);
119
+ }
120
+ }
121
+ }
122
+ return results;
123
+ }
124
+
125
+ /**
126
+ * Get a specific relation definition by name.
127
+ */
128
+ getRelationDef(name: string): RelationDef | undefined {
129
+ const entries = this.resolvedRelations.get(name);
130
+ return entries?.[0]?.def;
131
+ }
132
+
133
+ /**
134
+ * List all known relation names.
135
+ */
136
+ listRelationNames(): string[] {
137
+ return [...this.resolvedRelations.keys()];
138
+ }
139
+
140
+ /**
141
+ * Check if an entity type is known to any registered ontology.
142
+ */
143
+ hasEntityType(typeName: string): boolean {
144
+ return this.resolvedEntities.has(typeName);
145
+ }
146
+
147
+ /**
148
+ * Get the required attributes for an entity type.
149
+ */
150
+ getRequiredAttributes(typeName: string): AttributeDef[] {
151
+ const def = this.getEntityDef(typeName);
152
+ if (!def) return [];
153
+ return def.attributes.filter((a) => a.required);
154
+ }
155
+
156
+ // -------------------------------------------------------------------------
157
+ // Resolution (inheritance)
158
+ // -------------------------------------------------------------------------
159
+
160
+ private _resolve(schema: OntologySchema): void {
161
+ // Register entities
162
+ for (const entity of schema.entities) {
163
+ const resolved = this._resolveEntity(entity, schema);
164
+ this.resolvedEntities.set(entity.name, {
165
+ def: resolved,
166
+ ontologyId: schema.id,
167
+ });
168
+ }
169
+
170
+ // Register relations
171
+ for (const relation of schema.relations) {
172
+ const existing = this.resolvedRelations.get(relation.name) ?? [];
173
+ existing.push({ def: relation, ontologyId: schema.id });
174
+ this.resolvedRelations.set(relation.name, existing);
175
+ }
176
+ }
177
+
178
+ private _resolveEntity(entity: EntityDef, schema: OntologySchema): EntityDef {
179
+ if (!entity.extends) return entity;
180
+
181
+ // Find parent — check current schema first, then all registered
182
+ let parent = schema.entities.find((e) => e.name === entity.extends);
183
+ if (!parent) {
184
+ const resolved = this.resolvedEntities.get(entity.extends!);
185
+ parent = resolved?.def;
186
+ }
187
+
188
+ if (!parent) {
189
+ throw new Error(
190
+ `Entity "${entity.name}" extends "${entity.extends}" which is not defined.`,
191
+ );
192
+ }
193
+
194
+ // Resolve parent first (recursive)
195
+ const resolvedParent = this._resolveEntity(parent, schema);
196
+
197
+ // Merge: child attributes override parent attributes with same name
198
+ const childAttrNames = new Set(entity.attributes.map((a) => a.name));
199
+ const mergedAttrs = [
200
+ ...resolvedParent.attributes.filter((a) => !childAttrNames.has(a.name)),
201
+ ...entity.attributes,
202
+ ];
203
+
204
+ return {
205
+ ...entity,
206
+ attributes: mergedAttrs,
207
+ };
208
+ }
209
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Ontology Type System — Declarative schemas for entity types, attributes,
3
+ * constraints, and relationships.
4
+ *
5
+ * Ontologies define the "shape" of entities in the graph. They are used for:
6
+ * - Schema validation (reject mutations that violate constraints)
7
+ * - Documentation (describe what entity types exist and their attributes)
8
+ * - Code generation and tooling (auto-complete, type checking)
9
+ *
10
+ * @module trellis/core/ontology
11
+ */
12
+
13
+ import type { Atom } from '../store/eav-store.js';
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Attribute types
17
+ // ---------------------------------------------------------------------------
18
+
19
+ export type AttrType = 'string' | 'number' | 'boolean' | 'date' | 'ref' | 'any';
20
+
21
+ export interface AttributeDef {
22
+ /** Attribute name (fact key). */
23
+ name: string;
24
+ /** Expected value type. */
25
+ type: AttrType;
26
+ /** Human-readable description. */
27
+ description?: string;
28
+ /** Whether this attribute is required on entity creation. */
29
+ required?: boolean;
30
+ /** Whether only one value is allowed (default: true). */
31
+ unique?: boolean;
32
+ /** Default value if not provided. */
33
+ default?: Atom;
34
+ /** Allowed values (enum constraint). */
35
+ enum?: Atom[];
36
+ /** Regex pattern for string values. */
37
+ pattern?: string;
38
+ /** Minimum value (for numbers) or min length (for strings). */
39
+ min?: number;
40
+ /** Maximum value (for numbers) or max length (for strings). */
41
+ max?: number;
42
+ /** If type is 'ref', the target entity type(s) this can reference. */
43
+ refTypes?: string[];
44
+ }
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // Relation types
48
+ // ---------------------------------------------------------------------------
49
+
50
+ export interface RelationDef {
51
+ /** Relation attribute name (link key). */
52
+ name: string;
53
+ /** Human-readable description. */
54
+ description?: string;
55
+ /** Source entity type(s) that can have this relation. */
56
+ sourceTypes: string[];
57
+ /** Target entity type(s) this relation can point to. */
58
+ targetTypes: string[];
59
+ /** Cardinality: 'one' = at most one target, 'many' = unlimited. */
60
+ cardinality?: 'one' | 'many';
61
+ /** Whether this relation is required. */
62
+ required?: boolean;
63
+ /** Inverse relation name (auto-created on the target). */
64
+ inverse?: string;
65
+ }
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Entity type definitions
69
+ // ---------------------------------------------------------------------------
70
+
71
+ export interface EntityDef {
72
+ /** Entity type name (e.g. "Project", "User", "Agent"). */
73
+ name: string;
74
+ /** Human-readable description. */
75
+ description?: string;
76
+ /** Attribute definitions for this entity type. */
77
+ attributes: AttributeDef[];
78
+ /** Whether this entity type is abstract (cannot be instantiated directly). */
79
+ abstract?: boolean;
80
+ /** Parent entity type (for inheritance). */
81
+ extends?: string;
82
+ }
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // Ontology Schema
86
+ // ---------------------------------------------------------------------------
87
+
88
+ export interface OntologySchema {
89
+ /** Unique ontology identifier (e.g. "trellis:project", "trellis:team"). */
90
+ id: string;
91
+ /** Human-readable name. */
92
+ name: string;
93
+ /** Semantic version. */
94
+ version: string;
95
+ /** Human-readable description. */
96
+ description?: string;
97
+ /** Entity type definitions. */
98
+ entities: EntityDef[];
99
+ /** Relation definitions. */
100
+ relations: RelationDef[];
101
+ }
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // Validation result
105
+ // ---------------------------------------------------------------------------
106
+
107
+ export interface ValidationError {
108
+ /** Entity ID that failed validation. */
109
+ entityId: string;
110
+ /** Entity type. */
111
+ entityType: string;
112
+ /** Which attribute or relation failed. */
113
+ field: string;
114
+ /** Error message. */
115
+ message: string;
116
+ /** Severity: 'error' = hard failure, 'warning' = advisory. */
117
+ severity: 'error' | 'warning';
118
+ }
119
+
120
+ export interface ValidationResult {
121
+ valid: boolean;
122
+ errors: ValidationError[];
123
+ warnings: ValidationError[];
124
+ }