@elevasis/core 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/dist/index.d.ts +4343 -2690
  2. package/dist/index.js +1101 -156
  3. package/dist/knowledge/index.d.ts +574 -210
  4. package/dist/knowledge/index.js +104 -1
  5. package/dist/organization-model/index.d.ts +4343 -2690
  6. package/dist/organization-model/index.js +1101 -156
  7. package/dist/test-utils/index.d.ts +483 -109
  8. package/dist/test-utils/index.js +904 -144
  9. package/package.json +3 -3
  10. package/src/README.md +14 -14
  11. package/src/__tests__/publish.test.ts +24 -24
  12. package/src/__tests__/template-core-compatibility.test.ts +9 -12
  13. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2137 -2093
  14. package/src/_gen/__tests__/scaffold-contracts.test.ts +30 -30
  15. package/src/auth/multi-tenancy/credentials/__tests__/encryption.test.ts +217 -217
  16. package/src/auth/multi-tenancy/credentials/server/encryption.ts +69 -69
  17. package/src/auth/multi-tenancy/credentials/server/kek-loader.ts +37 -37
  18. package/src/auth/multi-tenancy/index.ts +26 -26
  19. package/src/auth/multi-tenancy/invitations/api-schemas.ts +104 -104
  20. package/src/auth/multi-tenancy/memberships/api-schemas.ts +143 -143
  21. package/src/auth/multi-tenancy/memberships/index.ts +26 -26
  22. package/src/auth/multi-tenancy/memberships/membership.ts +130 -130
  23. package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -194
  24. package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -136
  25. package/src/auth/multi-tenancy/permissions.test.ts +42 -42
  26. package/src/auth/multi-tenancy/permissions.ts +123 -123
  27. package/src/auth/multi-tenancy/role-management/api-schemas.ts +78 -78
  28. package/src/auth/multi-tenancy/role-management/index.ts +16 -16
  29. package/src/auth/multi-tenancy/theme-presets.ts +45 -45
  30. package/src/auth/multi-tenancy/types.ts +57 -57
  31. package/src/auth/multi-tenancy/users/api-schemas.ts +165 -165
  32. package/src/business/README.md +2 -2
  33. package/src/business/acquisition/activity-events.test.ts +250 -250
  34. package/src/business/acquisition/activity-events.ts +93 -93
  35. package/src/business/acquisition/api-schemas.test.ts +1883 -1843
  36. package/src/business/acquisition/api-schemas.ts +1492 -1497
  37. package/src/business/acquisition/build-templates.test.ts +240 -240
  38. package/src/business/acquisition/build-templates.ts +98 -98
  39. package/src/business/acquisition/crm-next-action.test.ts +262 -262
  40. package/src/business/acquisition/crm-next-action.ts +220 -220
  41. package/src/business/acquisition/crm-priority.test.ts +216 -216
  42. package/src/business/acquisition/crm-priority.ts +349 -349
  43. package/src/business/acquisition/crm-state-actions.test.ts +153 -153
  44. package/src/business/acquisition/deal-ownership.test.ts +351 -351
  45. package/src/business/acquisition/deal-ownership.ts +120 -120
  46. package/src/business/acquisition/derive-actions.test.ts +129 -104
  47. package/src/business/acquisition/derive-actions.ts +74 -84
  48. package/src/business/acquisition/index.ts +171 -170
  49. package/src/business/acquisition/ontology-validation.ts +309 -0
  50. package/src/business/acquisition/stateful.ts +30 -30
  51. package/src/business/acquisition/types.ts +396 -396
  52. package/src/business/clients/api-schemas.test.ts +115 -115
  53. package/src/business/clients/api-schemas.ts +158 -158
  54. package/src/business/clients/index.ts +1 -1
  55. package/src/business/crm/api-schemas.ts +40 -40
  56. package/src/business/crm/index.ts +1 -1
  57. package/src/business/deals/api-schemas.ts +87 -87
  58. package/src/business/deals/index.ts +1 -1
  59. package/src/business/index.ts +5 -5
  60. package/src/business/projects/types.ts +144 -144
  61. package/src/commands/queue/types/task.ts +15 -15
  62. package/src/execution/core/runner-types.ts +61 -61
  63. package/src/execution/core/sse-executions.ts +7 -7
  64. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -10
  65. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -16
  66. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -4
  67. package/src/execution/engine/agent/core/types.ts +25 -25
  68. package/src/execution/engine/agent/index.ts +6 -6
  69. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -24
  70. package/src/execution/engine/index.ts +443 -443
  71. package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +298 -298
  72. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -55
  73. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -107
  74. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -48
  75. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -99
  76. package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -1
  77. package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +363 -363
  78. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +162 -162
  79. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +316 -316
  80. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -18
  81. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -194
  82. package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -7
  83. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +204 -204
  84. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +105 -105
  85. package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -428
  86. package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -2
  87. package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
  88. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1474 -1474
  89. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +103 -103
  90. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.test.ts +88 -88
  91. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +141 -141
  92. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +76 -76
  93. package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +182 -182
  94. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +310 -310
  95. package/src/execution/engine/tools/integration/service.test.ts +239 -239
  96. package/src/execution/engine/tools/integration/service.ts +172 -172
  97. package/src/execution/engine/tools/integration/tool.ts +255 -255
  98. package/src/execution/engine/tools/lead-service-types.ts +1005 -1005
  99. package/src/execution/engine/tools/messages.ts +43 -43
  100. package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -7
  101. package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -6
  102. package/src/execution/engine/tools/platform/acquisition/list-tools.ts +6 -6
  103. package/src/execution/engine/tools/platform/acquisition/types.ts +280 -280
  104. package/src/execution/engine/tools/platform/email/types.ts +97 -97
  105. package/src/execution/engine/tools/registry.ts +704 -704
  106. package/src/execution/engine/tools/tool-maps.ts +831 -831
  107. package/src/execution/engine/tools/types.ts +234 -234
  108. package/src/execution/engine/workflow/types.ts +195 -197
  109. package/src/execution/external/__tests__/api-schemas.test.ts +127 -127
  110. package/src/execution/external/api-schemas.ts +40 -40
  111. package/src/execution/external/index.ts +1 -1
  112. package/src/index.ts +18 -18
  113. package/src/integrations/credentials/__tests__/api-schemas.test.ts +420 -420
  114. package/src/integrations/credentials/api-schemas.ts +146 -146
  115. package/src/integrations/credentials/schemas.ts +200 -200
  116. package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -7
  117. package/src/integrations/oauth/provider-registry.ts +74 -74
  118. package/src/integrations/oauth/server/credentials.ts +43 -43
  119. package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +327 -327
  120. package/src/integrations/webhook-endpoints/api-schemas.ts +103 -103
  121. package/src/integrations/webhook-endpoints/types.ts +58 -58
  122. package/src/knowledge/README.md +32 -32
  123. package/src/knowledge/__tests__/queries.test.ts +626 -535
  124. package/src/knowledge/format.ts +99 -99
  125. package/src/knowledge/index.ts +5 -5
  126. package/src/knowledge/published.ts +5 -5
  127. package/src/knowledge/queries.ts +269 -218
  128. package/src/operations/activities/api-schemas.ts +80 -80
  129. package/src/operations/activities/types.ts +64 -64
  130. package/src/organization-model/README.md +149 -149
  131. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -210
  132. package/src/organization-model/__tests__/defaults.test.ts +168 -168
  133. package/src/organization-model/__tests__/domains/actions.test.ts +78 -56
  134. package/src/organization-model/__tests__/domains/customers.test.ts +299 -299
  135. package/src/organization-model/__tests__/domains/entities.test.ts +56 -56
  136. package/src/organization-model/__tests__/domains/goals.test.ts +493 -493
  137. package/src/organization-model/__tests__/domains/identity.test.ts +280 -280
  138. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -268
  139. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -414
  140. package/src/organization-model/__tests__/domains/policies.test.ts +323 -323
  141. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +293 -293
  142. package/src/organization-model/__tests__/domains/resources.test.ts +387 -277
  143. package/src/organization-model/__tests__/domains/roles.test.ts +463 -463
  144. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -246
  145. package/src/organization-model/__tests__/domains/systems.test.ts +209 -209
  146. package/src/organization-model/__tests__/domains/topology.test.ts +188 -0
  147. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +362 -361
  148. package/src/organization-model/__tests__/foundation.test.ts +77 -77
  149. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -144
  150. package/src/organization-model/__tests__/graph.test.ts +1312 -862
  151. package/src/organization-model/__tests__/icons.test.ts +10 -1
  152. package/src/organization-model/__tests__/knowledge.test.ts +251 -15
  153. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -438
  154. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -591
  155. package/src/organization-model/__tests__/prospecting-ssot.test.ts +103 -103
  156. package/src/organization-model/__tests__/recursive-system-schema.test.ts +535 -506
  157. package/src/organization-model/__tests__/resolve.test.ts +274 -164
  158. package/src/organization-model/__tests__/schema.test.ts +844 -301
  159. package/src/organization-model/__tests__/surface-projection.test.ts +284 -284
  160. package/src/organization-model/catalogs/lead-gen.ts +144 -144
  161. package/src/organization-model/content-kinds/config.ts +36 -36
  162. package/src/organization-model/content-kinds/index.ts +76 -72
  163. package/src/organization-model/content-kinds/pipeline.ts +68 -68
  164. package/src/organization-model/content-kinds/registry.ts +44 -44
  165. package/src/organization-model/content-kinds/status.ts +71 -71
  166. package/src/organization-model/content-kinds/template.ts +83 -83
  167. package/src/organization-model/content-kinds/types.ts +117 -117
  168. package/src/organization-model/contracts.ts +27 -27
  169. package/src/organization-model/defaults.ts +42 -50
  170. package/src/organization-model/domains/actions.ts +333 -239
  171. package/src/organization-model/domains/customers.ts +78 -78
  172. package/src/organization-model/domains/entities.ts +144 -144
  173. package/src/organization-model/domains/goals.ts +83 -83
  174. package/src/organization-model/domains/knowledge.ts +117 -101
  175. package/src/organization-model/domains/navigation.ts +139 -139
  176. package/src/organization-model/domains/offerings.ts +71 -71
  177. package/src/organization-model/domains/policies.ts +102 -102
  178. package/src/organization-model/domains/projects.ts +14 -14
  179. package/src/organization-model/domains/prospecting.ts +395 -395
  180. package/src/organization-model/domains/resources.ts +202 -124
  181. package/src/organization-model/domains/roles.ts +96 -96
  182. package/src/organization-model/domains/sales.test.ts +218 -218
  183. package/src/organization-model/domains/sales.ts +380 -380
  184. package/src/organization-model/domains/shared.ts +63 -63
  185. package/src/organization-model/domains/statuses.ts +339 -339
  186. package/src/organization-model/domains/systems.ts +217 -172
  187. package/src/organization-model/domains/topology.ts +261 -0
  188. package/src/organization-model/foundation.ts +75 -75
  189. package/src/organization-model/graph/build.ts +1043 -867
  190. package/src/organization-model/graph/index.ts +4 -4
  191. package/src/organization-model/graph/link.ts +10 -10
  192. package/src/organization-model/graph/schema.ts +75 -68
  193. package/src/organization-model/graph/types.ts +71 -64
  194. package/src/organization-model/helpers.ts +289 -241
  195. package/src/organization-model/icons.ts +78 -66
  196. package/src/organization-model/index.ts +128 -125
  197. package/src/organization-model/migration-helpers.ts +247 -244
  198. package/src/organization-model/ontology.ts +658 -0
  199. package/src/organization-model/organization-graph.mdx +110 -90
  200. package/src/organization-model/organization-model.mdx +225 -213
  201. package/src/organization-model/published.ts +299 -222
  202. package/src/organization-model/resolve.ts +146 -91
  203. package/src/organization-model/schema.ts +818 -659
  204. package/src/organization-model/surface-projection.ts +212 -212
  205. package/src/organization-model/types.ts +179 -155
  206. package/src/platform/api/types.ts +38 -38
  207. package/src/platform/constants/versions.ts +3 -3
  208. package/src/platform/index.ts +23 -23
  209. package/src/platform/registry/__tests__/command-view.test.ts +10 -10
  210. package/src/platform/registry/__tests__/resource-link.test.ts +35 -35
  211. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +20 -20
  212. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -245
  213. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2053
  214. package/src/platform/registry/__tests__/validation.test.ts +1444 -1259
  215. package/src/platform/registry/command-view.ts +10 -10
  216. package/src/platform/registry/index.ts +103 -103
  217. package/src/platform/registry/resource-link.ts +32 -32
  218. package/src/platform/registry/resource-registry.ts +886 -886
  219. package/src/platform/registry/serialization.ts +295 -295
  220. package/src/platform/registry/serialized-types.ts +166 -166
  221. package/src/platform/registry/stats-types.ts +68 -68
  222. package/src/platform/registry/types.ts +425 -425
  223. package/src/platform/registry/validation.ts +876 -684
  224. package/src/platform/utils/__tests__/validation.test.ts +1084 -1084
  225. package/src/platform/utils/validation.ts +425 -425
  226. package/src/projects/api-schemas.test.ts +39 -39
  227. package/src/projects/api-schemas.ts +291 -291
  228. package/src/reference/_generated/contracts.md +2136 -2093
  229. package/src/reference/glossary.md +76 -76
  230. package/src/scaffold-registry/__tests__/index.test.ts +206 -206
  231. package/src/scaffold-registry/__tests__/schema.test.ts +166 -166
  232. package/src/scaffold-registry/index.ts +392 -392
  233. package/src/scaffold-registry/schema.ts +243 -243
  234. package/src/server.ts +289 -289
  235. package/src/supabase/database.types.ts +3 -0
  236. package/src/test-utils/README.md +37 -37
  237. package/src/test-utils/entities.ts +108 -108
  238. package/src/test-utils/fixtures/memberships.ts +82 -82
  239. package/src/test-utils/index.ts +12 -12
  240. package/src/test-utils/organization-model.ts +65 -65
  241. package/src/test-utils/published.ts +6 -6
  242. package/src/test-utils/rls/RLSTestContext.ts +588 -588
  243. package/src/test-utils/test-utils.test.ts +44 -44
@@ -20,7 +20,16 @@ describe('OrganizationModelIconTokenSchema', () => {
20
20
  })
21
21
 
22
22
  it('rejects random strings outside the built-in and custom namespaces', () => {
23
- for (const token of ['crm', 'lead-gen', 'settings', 'random.icon', 'custom.', 'custom.Bad']) {
23
+ for (const token of [
24
+ 'nav.crm',
25
+ 'feature.sales',
26
+ 'surface.dashboard',
27
+ 'action.approve',
28
+ 'status.success',
29
+ 'random.icon',
30
+ 'custom.',
31
+ 'custom.Bad'
32
+ ]) {
24
33
  expect(OrganizationModelIconTokenSchema.safeParse(token).success).toBe(false)
25
34
  }
26
35
  })
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from 'vitest'
1
+ import { describe, expect, it } from 'vitest'
2
2
  import {
3
3
  OrgKnowledgeNodeSchema,
4
4
  OrgKnowledgeKindSchema,
@@ -11,10 +11,12 @@ import { OrganizationGraphEdgeKindSchema } from '../graph/schema'
11
11
  import { buildOrganizationGraph } from '../graph/build'
12
12
  import { DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE } from '../defaults'
13
13
  import { resolveOrganizationModel } from '../resolve'
14
+ import { compileOrganizationOntology } from '../ontology'
15
+ import { byOntology, governedBy, parsePath } from '../../knowledge/queries'
14
16
  import type { OrganizationModel } from '../types'
15
17
 
16
18
  // ---------------------------------------------------------------------------
17
- // OrgKnowledgeNodeSchema shape and validation
19
+ // OrgKnowledgeNodeSchema — shape and validation
18
20
  // ---------------------------------------------------------------------------
19
21
 
20
22
  describe('OrgKnowledgeNodeSchema', () => {
@@ -89,10 +91,10 @@ describe('OrgKnowledgeNodeSchema', () => {
89
91
  it('accepts an optional semantic icon token', () => {
90
92
  const node = OrgKnowledgeNodeSchema.parse({
91
93
  ...makeNode('playbook'),
92
- icon: 'knowledge.playbook'
94
+ icon: 'playbook'
93
95
  })
94
96
 
95
- expect(node.icon).toBe('knowledge.playbook')
97
+ expect(node.icon).toBe('playbook')
96
98
  })
97
99
 
98
100
  it('rejects an unknown icon token', () => {
@@ -121,6 +123,15 @@ describe('OrgKnowledgeNodeSchema', () => {
121
123
 
122
124
  expect(result.success).toBe(false)
123
125
  })
126
+
127
+ it('accepts an optional generated sourceFilePath', () => {
128
+ const node = OrgKnowledgeNodeSchema.parse({
129
+ ...makeNode('reference'),
130
+ sourceFilePath: 'packages/elevasis-core/src/knowledge/nodes/platform/reference.mdx'
131
+ })
132
+
133
+ expect(node.sourceFilePath).toBe('packages/elevasis-core/src/knowledge/nodes/platform/reference.mdx')
134
+ })
124
135
  })
125
136
 
126
137
  describe('resolveOrganizationModel with knowledge owner roles', () => {
@@ -153,8 +164,117 @@ describe('resolveOrganizationModel with knowledge owner roles', () => {
153
164
  })
154
165
  })
155
166
 
167
+ describe('resolveOrganizationModel with ontology knowledge targets', () => {
168
+ it('accepts knowledge links that directly target compiled ontology records', () => {
169
+ expect(() =>
170
+ resolveOrganizationModel({
171
+ systems: {
172
+ 'sales.crm': {
173
+ id: 'sales.crm',
174
+ order: 10,
175
+ label: 'CRM',
176
+ enabled: true,
177
+ ontology: {
178
+ objectTypes: {
179
+ 'sales.crm:object/deal': {
180
+ id: 'sales.crm:object/deal',
181
+ label: 'Deal'
182
+ }
183
+ }
184
+ }
185
+ }
186
+ },
187
+ knowledge: {
188
+ 'knowledge.deal-policy': {
189
+ id: 'knowledge.deal-policy',
190
+ kind: 'reference',
191
+ title: 'Deal Policy',
192
+ summary: 'How deal records are governed.',
193
+ body: 'Deal policy.',
194
+ links: [{ target: { kind: 'ontology', id: 'sales.crm:object/deal' } }],
195
+ updatedAt: '2026-05-14'
196
+ }
197
+ }
198
+ })
199
+ ).not.toThrow()
200
+ })
201
+
202
+ it('rejects knowledge links to unknown ontology records', () => {
203
+ expect(() =>
204
+ resolveOrganizationModel({
205
+ knowledge: {
206
+ 'knowledge.missing-ontology': {
207
+ id: 'knowledge.missing-ontology',
208
+ kind: 'reference',
209
+ title: 'Missing Ontology',
210
+ summary: 'References a missing ontology record.',
211
+ body: 'Missing.',
212
+ links: [{ target: { kind: 'ontology', id: 'sales.crm:object/missing' } }],
213
+ updatedAt: '2026-05-14'
214
+ }
215
+ }
216
+ })
217
+ ).toThrow(/unknown ontology target/)
218
+ })
219
+
220
+ it('compiles authored ontology targets without requiring legacy provenance fields', () => {
221
+ const model = resolveOrganizationModel({
222
+ systems: {
223
+ 'sales.crm': {
224
+ id: 'sales.crm',
225
+ order: 10,
226
+ label: 'CRM',
227
+ enabled: true,
228
+ ontology: {
229
+ objectTypes: {
230
+ 'sales.crm:object/deal': {
231
+ id: 'sales.crm:object/deal',
232
+ label: 'Deal'
233
+ }
234
+ },
235
+ actionTypes: {
236
+ 'sales.crm:action/update-deal': {
237
+ id: 'sales.crm:action/update-deal',
238
+ label: 'Update Deal',
239
+ actsOn: ['sales.crm:object/deal']
240
+ }
241
+ },
242
+ catalogTypes: {
243
+ 'sales.crm:catalog/pipeline': {
244
+ id: 'sales.crm:catalog/pipeline',
245
+ label: 'Pipeline',
246
+ appliesTo: 'sales.crm:object/deal'
247
+ }
248
+ }
249
+ }
250
+ }
251
+ },
252
+ knowledge: {
253
+ 'knowledge.pipeline-policy': {
254
+ id: 'knowledge.pipeline-policy',
255
+ kind: 'reference',
256
+ title: 'Pipeline Policy',
257
+ summary: 'How pipeline ontology is governed.',
258
+ body: 'Pipeline policy.',
259
+ links: [{ target: { kind: 'ontology', id: 'sales.crm:catalog/pipeline' } }],
260
+ updatedAt: '2026-05-14'
261
+ }
262
+ }
263
+ })
264
+ const compiled = compileOrganizationOntology(model)
265
+
266
+ expect(compiled.diagnostics).toEqual([])
267
+ expect(compiled.ontology.objectTypes['sales.crm:object/deal']).not.toHaveProperty('legacyEntityId')
268
+ expect(compiled.ontology.actionTypes['sales.crm:action/update-deal']).not.toHaveProperty('legacyActionId')
269
+ expect(compiled.ontology.catalogTypes['sales.crm:catalog/pipeline']).not.toHaveProperty('legacyContentId')
270
+ expect(model.knowledge['knowledge.pipeline-policy']?.links[0]?.nodeId).toBe(
271
+ 'ontology:sales.crm:catalog/pipeline'
272
+ )
273
+ })
274
+ })
275
+
156
276
  // ---------------------------------------------------------------------------
157
- // OrgKnowledgeKindSchema enum shape
277
+ // OrgKnowledgeKindSchema — enum shape
158
278
  // ---------------------------------------------------------------------------
159
279
 
160
280
  describe('OrgKnowledgeKindSchema', () => {
@@ -171,7 +291,7 @@ describe('OrgKnowledgeKindSchema', () => {
171
291
  })
172
292
 
173
293
  // ---------------------------------------------------------------------------
174
- // OrganizationGraphEdgeKindSchema governs edge is present
294
+ // OrganizationGraphEdgeKindSchema — governs edge is present
175
295
  // ---------------------------------------------------------------------------
176
296
 
177
297
  describe('OrganizationGraphEdgeKindSchema', () => {
@@ -181,7 +301,7 @@ describe('OrganizationGraphEdgeKindSchema', () => {
181
301
  })
182
302
 
183
303
  // ---------------------------------------------------------------------------
184
- // DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE Phase 4: flat Record<id, OrgKnowledgeNode> (D3).
304
+ // DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE — Phase 4: flat Record<id, OrgKnowledgeNode> (D3).
185
305
  // The wrapper shape { version, lastModified, nodes[] } was removed; versioning
186
306
  // is in domainMetadata.knowledge. The default is an empty map {}.
187
307
  // ---------------------------------------------------------------------------
@@ -205,11 +325,11 @@ describe('DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE', () => {
205
325
  })
206
326
 
207
327
  // ---------------------------------------------------------------------------
208
- // buildOrganizationGraph knowledge nodes + governs edges
328
+ // buildOrganizationGraph — knowledge nodes + governs edges
209
329
  // Synthetic OM authored via flat Record<id, OrgKnowledgeNode> per Phase 4 schema.
210
330
  // ---------------------------------------------------------------------------
211
331
 
212
- // Phase 4: knowledge is a flat Record<id, OrgKnowledgeNode> no .nodes array wrapper.
332
+ // Phase 4: knowledge is a flat Record<id, OrgKnowledgeNode> — no .nodes array wrapper.
213
333
  const SYNTHETIC_OM: OrganizationModel = {
214
334
  ...DEFAULT_ORGANIZATION_MODEL,
215
335
  systems: Object.fromEntries(
@@ -295,10 +415,97 @@ describe('buildOrganizationGraph with knowledge', () => {
295
415
  const defaultKnowledgeNodes = defaultGraph.nodes.filter((n) => n.kind === 'knowledge')
296
416
  expect(defaultKnowledgeNodes).toHaveLength(0)
297
417
  })
418
+
419
+ it('emits governs edges from knowledge directly to ontology graph nodes', () => {
420
+ const model = resolveOrganizationModel({
421
+ systems: {
422
+ 'sales.crm': {
423
+ id: 'sales.crm',
424
+ order: 10,
425
+ label: 'CRM',
426
+ enabled: true,
427
+ ontology: {
428
+ objectTypes: {
429
+ 'sales.crm:object/deal': {
430
+ id: 'sales.crm:object/deal',
431
+ label: 'Deal'
432
+ }
433
+ }
434
+ }
435
+ }
436
+ },
437
+ knowledge: {
438
+ 'knowledge.deal-policy': {
439
+ id: 'knowledge.deal-policy',
440
+ kind: 'reference',
441
+ title: 'Deal Policy',
442
+ summary: 'How deal records are governed.',
443
+ body: 'Deal policy.',
444
+ links: [{ target: { kind: 'ontology', id: 'sales.crm:object/deal' } }],
445
+ ownerIds: [],
446
+ updatedAt: '2026-05-14'
447
+ }
448
+ }
449
+ })
450
+ const ontologyGraph = buildOrganizationGraph({ organizationModel: model })
451
+
452
+ expect(
453
+ ontologyGraph.edges.find(
454
+ (edge) =>
455
+ edge.kind === 'governs' &&
456
+ edge.sourceId === 'knowledge:knowledge.deal-policy' &&
457
+ edge.targetId === 'ontology:sales.crm:object/deal'
458
+ )
459
+ ).toBeDefined()
460
+ })
461
+
462
+ it('knowledge query helpers traverse ontology graph node IDs', () => {
463
+ const model = resolveOrganizationModel({
464
+ systems: {
465
+ 'sales.crm': {
466
+ id: 'sales.crm',
467
+ order: 10,
468
+ label: 'CRM',
469
+ enabled: true,
470
+ ontology: {
471
+ objectTypes: {
472
+ 'sales.crm:object/deal': {
473
+ id: 'sales.crm:object/deal',
474
+ label: 'Deal'
475
+ }
476
+ }
477
+ }
478
+ }
479
+ },
480
+ knowledge: {
481
+ 'knowledge.deal-policy': {
482
+ id: 'knowledge.deal-policy',
483
+ kind: 'reference',
484
+ title: 'Deal Policy',
485
+ summary: 'How deal records are governed.',
486
+ body: 'Deal policy.',
487
+ links: [{ target: { kind: 'ontology', id: 'sales.crm:object/deal' } }],
488
+ ownerIds: [],
489
+ updatedAt: '2026-05-14'
490
+ }
491
+ }
492
+ })
493
+ const ontologyGraph = buildOrganizationGraph({ organizationModel: model })
494
+ const nodes = Object.values(model.knowledge)
495
+
496
+ expect(byOntology(ontologyGraph, 'sales.crm:object/deal', nodes).map((node) => node.id)).toEqual([
497
+ 'knowledge.deal-policy'
498
+ ])
499
+ expect(governedBy(ontologyGraph, 'ontology:sales.crm:object/deal')).toEqual(['knowledge:knowledge.deal-policy'])
500
+ expect(parsePath('/by-ontology/sales.crm:object/deal')).toEqual({
501
+ mount: 'by-ontology',
502
+ args: ['sales.crm:object/deal']
503
+ })
504
+ })
298
505
  })
299
506
 
300
507
  // ---------------------------------------------------------------------------
301
- // KnowledgeLinkSchema nodeId format validation
508
+ // KnowledgeLinkSchema — nodeId format validation
302
509
  // ---------------------------------------------------------------------------
303
510
 
304
511
  describe('KnowledgeLinkSchema', () => {
@@ -325,10 +532,19 @@ describe('KnowledgeLinkSchema', () => {
325
532
  expect(() => KnowledgeLinkSchema.parse({ nodeId: 'knowledge:knowledge.test-doc' })).not.toThrow()
326
533
  })
327
534
 
328
- it('accepts content-node: prefixed node IDs (D4 KnowledgeTargetKindSchema includes content-node)', () => {
535
+ it('accepts content-node: prefixed node IDs (D4 — KnowledgeTargetKindSchema includes content-node)', () => {
329
536
  expect(() => KnowledgeLinkSchema.parse({ nodeId: 'content-node:sales.crm:default-pipeline' })).not.toThrow()
330
537
  })
331
538
 
539
+ it('accepts and normalizes ontology graph node IDs', () => {
540
+ const link = KnowledgeLinkSchema.parse({ nodeId: 'ontology:sales.crm:object/deal' })
541
+
542
+ expect(link).toEqual({
543
+ target: { kind: 'ontology', id: 'sales.crm:object/deal' },
544
+ nodeId: 'ontology:sales.crm:object/deal'
545
+ })
546
+ })
547
+
332
548
  it('rejects a bare dotted ID with no kind: prefix', () => {
333
549
  expect(KnowledgeLinkSchema.safeParse({ nodeId: 'sales.crm' }).success).toBe(false)
334
550
  })
@@ -365,6 +581,26 @@ describe('KnowledgeTargetRefSchema', () => {
365
581
  )
366
582
  })
367
583
 
584
+ it('keeps content-node targets as compatibility pass-through links', () => {
585
+ const link = KnowledgeLinkSchema.parse({
586
+ target: { kind: 'content-node', id: 'sales.crm:default-pipeline' }
587
+ })
588
+
589
+ expect(link).toEqual({
590
+ target: { kind: 'content-node', id: 'sales.crm:default-pipeline' },
591
+ nodeId: 'content-node:sales.crm:default-pipeline'
592
+ })
593
+ })
594
+
595
+ it('accepts ontology as a target kind when the id is a valid ontology id', () => {
596
+ expect(KnowledgeTargetKindSchema.safeParse('ontology').success).toBe(true)
597
+ expect(KnowledgeTargetRefSchema.safeParse({ kind: 'ontology', id: 'sales.crm:object/deal' }).success).toBe(true)
598
+ })
599
+
600
+ it('rejects ontology targets with malformed ontology ids', () => {
601
+ expect(KnowledgeTargetRefSchema.safeParse({ kind: 'ontology', id: 'sales.crm.deal' }).success).toBe(false)
602
+ })
603
+
368
604
  it('rejects unknown target kinds', () => {
369
605
  expect(KnowledgeTargetKindSchema.safeParse('integration').success).toBe(false)
370
606
  expect(KnowledgeTargetRefSchema.safeParse({ kind: 'integration', id: 'hubspot' }).success).toBe(false)
@@ -372,10 +608,10 @@ describe('KnowledgeTargetRefSchema', () => {
372
608
  })
373
609
 
374
610
  // ---------------------------------------------------------------------------
375
- // KnowledgeDomainSchema flat Record shape (Phase 4 D3)
611
+ // KnowledgeDomainSchema — flat Record shape (Phase 4 D3)
376
612
  // ---------------------------------------------------------------------------
377
613
 
378
- describe('KnowledgeDomainSchema flat Record<id, OrgKnowledgeNode>', () => {
614
+ describe('KnowledgeDomainSchema — flat Record<id, OrgKnowledgeNode>', () => {
379
615
  it('accepts an empty map', () => {
380
616
  expect(KnowledgeDomainSchema.safeParse({}).success).toBe(true)
381
617
  })
@@ -412,13 +648,13 @@ describe('KnowledgeDomainSchema — flat Record<id, OrgKnowledgeNode>', () => {
412
648
  nodes: []
413
649
  })
414
650
  // Each key ('version', 'lastModified', 'nodes') would be parsed as a knowledge node id,
415
- // and the values are not valid OrgKnowledgeNodeSchema so this should fail
651
+ // and the values are not valid OrgKnowledgeNodeSchema — so this should fail
416
652
  expect(result.success).toBe(false)
417
653
  })
418
654
  })
419
655
 
420
656
  // ---------------------------------------------------------------------------
421
- // OrgKnowledgeNodeSchema field length constraints
657
+ // OrgKnowledgeNodeSchema — field length constraints
422
658
  // ---------------------------------------------------------------------------
423
659
 
424
660
  describe('OrgKnowledgeNodeSchema length constraints', () => {