@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
@@ -1,53 +1,100 @@
1
- import type { OrganizationGraph } from '../organization-model/graph/types'
1
+ import type { OrganizationGraph } from '../organization-model/graph/types'
2
2
  import type { OrgKnowledgeKind, OrgKnowledgeNode } from '../organization-model/domains/knowledge'
3
-
4
- // ---------------------------------------------------------------------------
5
- // Internal helpers
6
- // ---------------------------------------------------------------------------
7
-
8
- /**
9
- * Graph node ID prefix for knowledge nodes.
10
- * Graph node IDs follow the convention: `knowledge:<om-node-id>`
11
- * e.g. `knowledge:knowledge.outreach-playbook`
12
- */
3
+ import { OntologyIdSchema, ontologyGraphNodeId } from '../organization-model/ontology'
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Internal helpers
7
+ // ---------------------------------------------------------------------------
8
+
9
+ /**
10
+ * Graph node ID prefix for knowledge nodes.
11
+ * Graph node IDs follow the convention: `knowledge:<om-node-id>`
12
+ * e.g. `knowledge:knowledge.outreach-playbook`
13
+ */
13
14
  function toGraphNodeId(omNodeId: string): string {
14
15
  return `knowledge:${omNodeId}`
15
16
  }
16
17
 
17
- /**
18
- * Resolve the sourceId of every knowledge node in the graph, keyed by graph
19
- * node ID. The `sourceId` on a knowledge graph node is the OM node id
20
- * (e.g. `knowledge.outreach-playbook`).
21
- */
22
- function buildKnowledgeSourceIdMap(graph: OrganizationGraph): Map<string, string> {
23
- const map = new Map<string, string>()
24
- for (const node of graph.nodes) {
25
- if (node.kind === 'knowledge' && node.sourceId) {
26
- map.set(node.id, node.sourceId)
27
- }
18
+ function toTargetGraphNodeId(nodeId: string): string {
19
+ if (
20
+ nodeId.startsWith('system:') ||
21
+ nodeId.startsWith('knowledge:') ||
22
+ nodeId.startsWith('resource:') ||
23
+ nodeId.startsWith('content-node:') ||
24
+ nodeId.startsWith('ontology:')
25
+ ) {
26
+ return nodeId
28
27
  }
29
- return map
30
- }
31
28
 
32
- // ---------------------------------------------------------------------------
33
- // Query functions
34
- // ---------------------------------------------------------------------------
29
+ const ontologyId = OntologyIdSchema.safeParse(nodeId)
30
+ if (ontologyId.success) {
31
+ return ontologyGraphNodeId(ontologyId.data)
32
+ }
35
33
 
36
- /**
37
- * Returns all knowledge nodes whose `governs` edges point to the given
38
- * systemId (graph node ID: `system:<systemId>`).
39
- *
40
- * @param graph - The built OrganizationGraph.
41
- * @param systemId - The dotted system id (e.g. `sales.crm`).
42
- */
34
+ return `system:${nodeId}`
35
+ }
36
+
37
+ /**
38
+ * Resolve the sourceId of every knowledge node in the graph, keyed by graph
39
+ * node ID. The `sourceId` on a knowledge graph node is the OM node id
40
+ * (e.g. `knowledge.outreach-playbook`).
41
+ */
42
+ function buildKnowledgeSourceIdMap(graph: OrganizationGraph): Map<string, string> {
43
+ const map = new Map<string, string>()
44
+ for (const node of graph.nodes) {
45
+ if (node.kind === 'knowledge' && node.sourceId) {
46
+ map.set(node.id, node.sourceId)
47
+ }
48
+ }
49
+ return map
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Query functions
54
+ // ---------------------------------------------------------------------------
55
+
56
+ /**
57
+ * Returns all knowledge nodes whose `governs` edges point to the given
58
+ * systemId (graph node ID: `system:<systemId>`).
59
+ *
60
+ * @param graph - The built OrganizationGraph.
61
+ * @param systemId - The dotted system id (e.g. `sales.crm`).
62
+ */
43
63
  export function bySystem(
64
+ graph: OrganizationGraph,
65
+ systemId: string,
66
+ knowledgeNodes: OrgKnowledgeNode[]
67
+ ): OrgKnowledgeNode[] {
68
+ const targetGraphNodeId = `system:${systemId}`
69
+
70
+ // Find all knowledge graph node IDs that have a `governs` edge to the target
71
+ const governingKnowledgeNodeIds = new Set<string>()
72
+ for (const edge of graph.edges) {
73
+ if (edge.kind === 'governs' && edge.targetId === targetGraphNodeId && edge.sourceId.startsWith('knowledge:')) {
74
+ governingKnowledgeNodeIds.add(edge.sourceId)
75
+ }
76
+ }
77
+
78
+ // Build a lookup from graph-node-id -> OM sourceId
79
+ const sourceIdMap = buildKnowledgeSourceIdMap(graph)
80
+
81
+ // Collect the OM node ids that correspond to those graph nodes
82
+ const matchingOmIds = new Set<string>()
83
+ for (const graphNodeId of governingKnowledgeNodeIds) {
84
+ const omId = sourceIdMap.get(graphNodeId)
85
+ if (omId) matchingOmIds.add(omId)
86
+ }
87
+
88
+ return knowledgeNodes.filter((n) => matchingOmIds.has(n.id))
89
+ }
90
+
91
+ export function byOntology(
44
92
  graph: OrganizationGraph,
45
- systemId: string,
93
+ ontologyId: string,
46
94
  knowledgeNodes: OrgKnowledgeNode[]
47
95
  ): OrgKnowledgeNode[] {
48
- const targetGraphNodeId = `system:${systemId}`
96
+ const targetGraphNodeId = toTargetGraphNodeId(ontologyId)
49
97
 
50
- // Find all knowledge graph node IDs that have a `governs` edge to the target
51
98
  const governingKnowledgeNodeIds = new Set<string>()
52
99
  for (const edge of graph.edges) {
53
100
  if (edge.kind === 'governs' && edge.targetId === targetGraphNodeId && edge.sourceId.startsWith('knowledge:')) {
@@ -55,10 +102,7 @@ export function bySystem(
55
102
  }
56
103
  }
57
104
 
58
- // Build a lookup from graph-node-id -> OM sourceId
59
105
  const sourceIdMap = buildKnowledgeSourceIdMap(graph)
60
-
61
- // Collect the OM node ids that correspond to those graph nodes
62
106
  const matchingOmIds = new Set<string>()
63
107
  for (const graphNodeId of governingKnowledgeNodeIds) {
64
108
  const omId = sourceIdMap.get(graphNodeId)
@@ -67,191 +111,198 @@ export function bySystem(
67
111
 
68
112
  return knowledgeNodes.filter((n) => matchingOmIds.has(n.id))
69
113
  }
70
-
71
- /**
72
- * Returns all knowledge nodes whose `kind` matches the given kind.
73
- *
74
- * @param graph - The built OrganizationGraph (unused structurally; kept for API symmetry).
75
- * @param kind - The knowledge kind (`'playbook' | 'strategy' | 'reference'`).
76
- * @param knowledgeNodes - Flat array of OrgKnowledgeNode from the OrganizationModel.
77
- */
78
- export function byKind(
79
- _graph: OrganizationGraph,
80
- kind: OrgKnowledgeKind,
81
- knowledgeNodes: OrgKnowledgeNode[]
82
- ): OrgKnowledgeNode[] {
83
- return knowledgeNodes.filter((n) => n.kind === kind)
84
- }
85
-
86
- /**
87
- * Returns all knowledge nodes where `ownerIds` includes the given `ownerId`.
88
- *
89
- * @param _graph - The built OrganizationGraph (unused; kept for API symmetry).
90
- * @param ownerId - The owner id string (matches values in `node.ownerIds`).
91
- * @param knowledgeNodes - Flat array of OrgKnowledgeNode from the OrganizationModel.
92
- */
93
- export function byOwner(
94
- _graph: OrganizationGraph,
95
- ownerId: string,
96
- knowledgeNodes: OrgKnowledgeNode[]
97
- ): OrgKnowledgeNode[] {
98
- return knowledgeNodes.filter((n) => n.ownerIds.includes(ownerId))
99
- }
100
-
101
- /**
102
- * Returns the IDs of the graph nodes that the given knowledge node governs
103
- * (outgoing `governs` edges from the knowledge graph node).
104
- *
105
- * The graph node ID for a knowledge OM node with id `X` is `knowledge:X`.
106
- *
107
- * @param graph - The built OrganizationGraph.
108
- * @param nodeId - The OM knowledge node id (e.g. `knowledge.outreach-playbook`).
109
- * Also accepts the graph node ID format (`knowledge:knowledge.outreach-playbook`).
110
- * @returns Array of target graph node IDs (e.g. `['system:sales.crm', ...]`).
111
- */
112
- export function governs(graph: OrganizationGraph, nodeId: string): string[] {
113
- const graphNodeId = nodeId.startsWith('knowledge:') ? nodeId : toGraphNodeId(nodeId)
114
-
115
- const results: string[] = []
116
- for (const edge of graph.edges) {
117
- if (edge.kind === 'governs' && edge.sourceId === graphNodeId) {
118
- results.push(edge.targetId)
119
- }
120
- }
121
- return results
122
- }
123
-
124
- /**
125
- * Returns the IDs of the knowledge graph nodes that govern the given node
126
- * (incoming `governs` edges pointing to `nodeId`).
127
- *
128
- * @param graph - The built OrganizationGraph.
129
- * @param nodeId - The target graph node ID (e.g. `system:sales.crm`) or a
130
- * bare system id (e.g. `sales.crm` — will be prefixed with `system:`).
131
- * @returns Array of source graph node IDs (e.g. `['knowledge:knowledge.outreach-playbook', ...]`).
132
- */
114
+
115
+ /**
116
+ * Returns all knowledge nodes whose `kind` matches the given kind.
117
+ *
118
+ * @param graph - The built OrganizationGraph (unused structurally; kept for API symmetry).
119
+ * @param kind - The knowledge kind (`'playbook' | 'strategy' | 'reference'`).
120
+ * @param knowledgeNodes - Flat array of OrgKnowledgeNode from the OrganizationModel.
121
+ */
122
+ export function byKind(
123
+ _graph: OrganizationGraph,
124
+ kind: OrgKnowledgeKind,
125
+ knowledgeNodes: OrgKnowledgeNode[]
126
+ ): OrgKnowledgeNode[] {
127
+ return knowledgeNodes.filter((n) => n.kind === kind)
128
+ }
129
+
130
+ /**
131
+ * Returns all knowledge nodes where `ownerIds` includes the given `ownerId`.
132
+ *
133
+ * @param _graph - The built OrganizationGraph (unused; kept for API symmetry).
134
+ * @param ownerId - The owner id string (matches values in `node.ownerIds`).
135
+ * @param knowledgeNodes - Flat array of OrgKnowledgeNode from the OrganizationModel.
136
+ */
137
+ export function byOwner(
138
+ _graph: OrganizationGraph,
139
+ ownerId: string,
140
+ knowledgeNodes: OrgKnowledgeNode[]
141
+ ): OrgKnowledgeNode[] {
142
+ return knowledgeNodes.filter((n) => n.ownerIds.includes(ownerId))
143
+ }
144
+
145
+ /**
146
+ * Returns the IDs of the graph nodes that the given knowledge node governs
147
+ * (outgoing `governs` edges from the knowledge graph node).
148
+ *
149
+ * The graph node ID for a knowledge OM node with id `X` is `knowledge:X`.
150
+ *
151
+ * @param graph - The built OrganizationGraph.
152
+ * @param nodeId - The OM knowledge node id (e.g. `knowledge.outreach-playbook`).
153
+ * Also accepts the graph node ID format (`knowledge:knowledge.outreach-playbook`).
154
+ * @returns Array of target graph node IDs (e.g. `['system:sales.crm', ...]`).
155
+ */
156
+ export function governs(graph: OrganizationGraph, nodeId: string): string[] {
157
+ const graphNodeId = nodeId.startsWith('knowledge:') ? nodeId : toGraphNodeId(nodeId)
158
+
159
+ const results: string[] = []
160
+ for (const edge of graph.edges) {
161
+ if (edge.kind === 'governs' && edge.sourceId === graphNodeId) {
162
+ results.push(edge.targetId)
163
+ }
164
+ }
165
+ return results
166
+ }
167
+
168
+ /**
169
+ * Returns the IDs of the knowledge graph nodes that govern the given node
170
+ * (incoming `governs` edges pointing to `nodeId`).
171
+ *
172
+ * @param graph - The built OrganizationGraph.
173
+ * @param nodeId - The target graph node ID (e.g. `system:sales.crm`) or a
174
+ * bare system id (e.g. `sales.crm` — will be prefixed with `system:`).
175
+ * @returns Array of source graph node IDs (e.g. `['knowledge:knowledge.outreach-playbook', ...]`).
176
+ */
133
177
  export function governedBy(graph: OrganizationGraph, nodeId: string): string[] {
134
- // Accept both `system:sales.crm` and bare `sales.crm`
135
- const targetId =
136
- nodeId.startsWith('system:') || nodeId.startsWith('knowledge:') || nodeId.startsWith('resource:')
137
- ? nodeId
138
- : `system:${nodeId}`
139
-
140
- const results: string[] = []
141
- for (const edge of graph.edges) {
142
- if (edge.kind === 'governs' && edge.targetId === targetId) {
143
- results.push(edge.sourceId)
144
- }
145
- }
146
- return results
147
- }
148
-
149
- // ---------------------------------------------------------------------------
150
- // Path parser
151
- // ---------------------------------------------------------------------------
152
-
153
- /** The recognized mount axes for Knowledge Map paths. */
154
- export type KnowledgeMount = 'by-system' | 'by-kind' | 'by-owner' | 'graph' | 'node'
155
-
156
- /**
157
- * The result of parsing a Knowledge Map path string.
158
- *
159
- * Shape: `{ mount: KnowledgeMount, args: string[] }`
160
- *
161
- * Per-mount arg arrays:
178
+ // Accept prefixed graph IDs, bare system IDs, and bare ontology IDs.
179
+ const targetId = toTargetGraphNodeId(nodeId)
180
+
181
+ const results: string[] = []
182
+ for (const edge of graph.edges) {
183
+ if (edge.kind === 'governs' && edge.targetId === targetId) {
184
+ results.push(edge.sourceId)
185
+ }
186
+ }
187
+ return results
188
+ }
189
+
190
+ // ---------------------------------------------------------------------------
191
+ // Path parser
192
+ // ---------------------------------------------------------------------------
193
+
194
+ /** The recognized mount axes for Knowledge Map paths. */
195
+ export type KnowledgeMount = 'by-system' | 'by-ontology' | 'by-kind' | 'by-owner' | 'graph' | 'node'
196
+
197
+ /**
198
+ * The result of parsing a Knowledge Map path string.
199
+ *
200
+ * Shape: `{ mount: KnowledgeMount, args: string[] }`
201
+ *
202
+ * Per-mount arg arrays:
162
203
  * - `by-system`: `[systemId]` (e.g. `['sales.crm']`)
163
- * - `by-kind`: `[kind]` (e.g. `['playbook']`)
164
- * - `by-owner`: `[ownerId]` (e.g. `['role.ops-lead']`)
165
- * - `graph`: `[nodeId, verb]` where verb is `'governs'` or `'governed-by'`
166
- * - `node`: `[nodeId]` (single node lookup, no sub-path)
167
- */
168
- export interface ParsedKnowledgePath {
169
- mount: KnowledgeMount
170
- args: string[]
171
- }
172
-
173
- /**
174
- * Parses a Knowledge Map path string into a `{ mount, args }` descriptor.
175
- *
176
- * Supported path patterns:
204
+ * - `by-ontology`:`[ontologyId]` (e.g. `['sales.crm:object/deal']`)
205
+ * - `by-kind`: `[kind]` (e.g. `['playbook']`)
206
+ * - `by-owner`: `[ownerId]` (e.g. `['role.ops-lead']`)
207
+ * - `graph`: `[nodeId, verb]` where verb is `'governs'` or `'governed-by'`
208
+ * - `node`: `[nodeId]` (single node lookup, no sub-path)
209
+ */
210
+ export interface ParsedKnowledgePath {
211
+ mount: KnowledgeMount
212
+ args: string[]
213
+ }
214
+
215
+ /**
216
+ * Parses a Knowledge Map path string into a `{ mount, args }` descriptor.
217
+ *
218
+ * Supported path patterns:
177
219
  * `/by-system/<systemId>` -> `{ mount: 'by-system', args: ['<systemId>'] }`
178
- * `/by-kind/<kind>` → `{ mount: 'by-kind', args: ['<kind>'] }`
179
- * `/by-owner/<ownerId>` → `{ mount: 'by-owner', args: ['<ownerId>'] }`
180
- * `/graph/<nodeId>/governs` → `{ mount: 'graph', args: ['<nodeId>', 'governs'] }`
181
- * `/graph/<nodeId>/governed-by` → `{ mount: 'graph', args: ['<nodeId>', 'governed-by'] }`
182
- * `/<nodeId>` → `{ mount: 'node', args: ['<nodeId>'] }`
183
- *
184
- * The path MUST start with `/`. Trailing slashes are stripped before parsing.
185
- *
186
- * @throws {Error} If the path is empty, missing a leading slash, or does not
187
- * match any supported mount pattern.
188
- */
189
- export function parsePath(pathString: string): ParsedKnowledgePath {
190
- if (!pathString || typeof pathString !== 'string') {
191
- throw new Error('parsePath: path must be a non-empty string')
192
- }
193
-
194
- if (!pathString.startsWith('/')) {
195
- throw new Error(`parsePath: path must start with "/", got: "${pathString}"`)
196
- }
197
-
198
- // Strip trailing slashes then split
199
- const normalized = pathString.replace(/\/+$/, '')
200
- const segments = normalized.split('/').filter((s) => s.length > 0)
201
-
202
- if (segments.length === 0) {
203
- throw new Error(`parsePath: path resolves to root with no mount: "${pathString}"`)
204
- }
205
-
206
- const [first, ...rest] = segments
207
-
208
- // /by-system/<systemId>
220
+ * `/by-ontology/<ontologyId>` -> `{ mount: 'by-ontology', args: ['<ontologyId>'] }`
221
+ * `/by-kind/<kind>` → `{ mount: 'by-kind', args: ['<kind>'] }`
222
+ * `/by-owner/<ownerId>` → `{ mount: 'by-owner', args: ['<ownerId>'] }`
223
+ * `/graph/<nodeId>/governs` → `{ mount: 'graph', args: ['<nodeId>', 'governs'] }`
224
+ * `/graph/<nodeId>/governed-by` → `{ mount: 'graph', args: ['<nodeId>', 'governed-by'] }`
225
+ * `/<nodeId>` → `{ mount: 'node', args: ['<nodeId>'] }`
226
+ *
227
+ * The path MUST start with `/`. Trailing slashes are stripped before parsing.
228
+ *
229
+ * @throws {Error} If the path is empty, missing a leading slash, or does not
230
+ * match any supported mount pattern.
231
+ */
232
+ export function parsePath(pathString: string): ParsedKnowledgePath {
233
+ if (!pathString || typeof pathString !== 'string') {
234
+ throw new Error('parsePath: path must be a non-empty string')
235
+ }
236
+
237
+ if (!pathString.startsWith('/')) {
238
+ throw new Error(`parsePath: path must start with "/", got: "${pathString}"`)
239
+ }
240
+
241
+ // Strip trailing slashes then split
242
+ const normalized = pathString.replace(/\/+$/, '')
243
+ const segments = normalized.split('/').filter((s) => s.length > 0)
244
+
245
+ if (segments.length === 0) {
246
+ throw new Error(`parsePath: path resolves to root with no mount: "${pathString}"`)
247
+ }
248
+
249
+ const [first, ...rest] = segments
250
+
251
+ // /by-system/<systemId>
209
252
  if (first === 'by-system') {
210
- if (rest.length === 0) {
211
- throw new Error(`parsePath: /by-system requires a systemId argument, got: "${pathString}"`)
212
- }
213
- return { mount: 'by-system', args: [rest.join('/')] }
253
+ if (rest.length === 0) {
254
+ throw new Error(`parsePath: /by-system requires a systemId argument, got: "${pathString}"`)
255
+ }
256
+ return { mount: 'by-system', args: [rest.join('/')] }
214
257
  }
215
258
 
216
- // /by-kind/<kind>
217
- if (first === 'by-kind') {
259
+ // /by-ontology/<ontologyId>
260
+ if (first === 'by-ontology') {
218
261
  if (rest.length === 0) {
219
- throw new Error(`parsePath: /by-kind requires a kind argument, got: "${pathString}"`)
262
+ throw new Error(`parsePath: /by-ontology requires an ontologyId argument, got: "${pathString}"`)
220
263
  }
221
- return { mount: 'by-kind', args: [rest[0]] }
264
+ return { mount: 'by-ontology', args: [rest.join('/')] }
222
265
  }
223
-
224
- // /by-owner/<ownerId>
225
- if (first === 'by-owner') {
226
- if (rest.length === 0) {
227
- throw new Error(`parsePath: /by-owner requires an ownerId argument, got: "${pathString}"`)
228
- }
229
- return { mount: 'by-owner', args: [rest.join('/')] }
230
- }
231
-
232
- // /graph/<nodeId>/governs or /graph/<nodeId>/governed-by
233
- if (first === 'graph') {
234
- if (rest.length < 2) {
235
- throw new Error(`parsePath: /graph requires <nodeId>/<verb> (governs|governed-by), got: "${pathString}"`)
236
- }
237
- const graphNodeId = rest.slice(0, -1).join('/')
238
- const verb = rest[rest.length - 1]
239
- if (verb !== 'governs' && verb !== 'governed-by') {
240
- throw new Error(
241
- `parsePath: /graph/<nodeId> verb must be "governs" or "governed-by", got: "${verb}" in "${pathString}"`
242
- )
243
- }
244
- return { mount: 'graph', args: [graphNodeId, verb] }
245
- }
246
-
247
- // /<nodeId> (single node)
248
- // first must not be a recognized mount prefix
249
- if (segments.length === 1) {
250
- return { mount: 'node', args: [first] }
251
- }
252
-
253
- throw new Error(
254
- `parsePath: unrecognized path pattern "${pathString}". Supported: /by-system/<id>, /by-kind/<kind>, /by-owner/<id>, /graph/<nodeId>/governs, /graph/<nodeId>/governed-by, /<nodeId>`
255
- )
256
- }
266
+
267
+ // /by-kind/<kind>
268
+ if (first === 'by-kind') {
269
+ if (rest.length === 0) {
270
+ throw new Error(`parsePath: /by-kind requires a kind argument, got: "${pathString}"`)
271
+ }
272
+ return { mount: 'by-kind', args: [rest[0]] }
273
+ }
274
+
275
+ // /by-owner/<ownerId>
276
+ if (first === 'by-owner') {
277
+ if (rest.length === 0) {
278
+ throw new Error(`parsePath: /by-owner requires an ownerId argument, got: "${pathString}"`)
279
+ }
280
+ return { mount: 'by-owner', args: [rest.join('/')] }
281
+ }
282
+
283
+ // /graph/<nodeId>/governs or /graph/<nodeId>/governed-by
284
+ if (first === 'graph') {
285
+ if (rest.length < 2) {
286
+ throw new Error(`parsePath: /graph requires <nodeId>/<verb> (governs|governed-by), got: "${pathString}"`)
287
+ }
288
+ const graphNodeId = rest.slice(0, -1).join('/')
289
+ const verb = rest[rest.length - 1]
290
+ if (verb !== 'governs' && verb !== 'governed-by') {
291
+ throw new Error(
292
+ `parsePath: /graph/<nodeId> verb must be "governs" or "governed-by", got: "${verb}" in "${pathString}"`
293
+ )
294
+ }
295
+ return { mount: 'graph', args: [graphNodeId, verb] }
296
+ }
297
+
298
+ // /<nodeId> (single node)
299
+ // first must not be a recognized mount prefix
300
+ if (segments.length === 1) {
301
+ return { mount: 'node', args: [first] }
302
+ }
303
+
304
+ throw new Error(
305
+ `parsePath: unrecognized path pattern "${pathString}". Supported: /by-system/<id>, /by-kind/<kind>, /by-owner/<id>, /graph/<nodeId>/governs, /graph/<nodeId>/governed-by, /<nodeId>`
306
+ )
307
+ }
257
308