@elevasis/core 0.22.0 → 0.24.0

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 (244) hide show
  1. package/dist/index.d.ts +3214 -2501
  2. package/dist/index.js +3112 -1222
  3. package/dist/knowledge/index.d.ts +1108 -1264
  4. package/dist/knowledge/index.js +112 -9
  5. package/dist/organization-model/index.d.ts +3214 -2501
  6. package/dist/organization-model/index.js +3112 -1222
  7. package/dist/test-utils/index.d.ts +985 -1103
  8. package/dist/test-utils/index.js +2464 -1165
  9. package/package.json +5 -5
  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 -80
  13. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2389 -2121
  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 +1493 -1500
  37. package/src/business/acquisition/build-templates.test.ts +240 -240
  38. package/src/business/acquisition/build-templates.ts +83 -41
  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 -151
  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 -392
  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 +202 -202
  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 +33 -32
  123. package/src/knowledge/__tests__/queries.test.ts +633 -541
  124. package/src/knowledge/format.ts +100 -99
  125. package/src/knowledge/index.ts +5 -5
  126. package/src/knowledge/published.ts +5 -5
  127. package/src/knowledge/queries.ts +274 -222
  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 -109
  131. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  132. package/src/organization-model/__tests__/defaults.test.ts +168 -194
  133. package/src/organization-model/__tests__/domains/actions.test.ts +78 -0
  134. package/src/organization-model/__tests__/domains/customers.test.ts +48 -44
  135. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  136. package/src/organization-model/__tests__/domains/goals.test.ts +110 -96
  137. package/src/organization-model/__tests__/domains/identity.test.ts +4 -3
  138. package/src/organization-model/__tests__/domains/navigation.test.ts +222 -166
  139. package/src/organization-model/__tests__/domains/offerings.test.ts +83 -88
  140. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  141. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +30 -30
  142. package/src/organization-model/__tests__/domains/resources.test.ts +396 -175
  143. package/src/organization-model/__tests__/domains/roles.test.ts +463 -402
  144. package/src/organization-model/__tests__/domains/statuses.test.ts +13 -10
  145. package/src/organization-model/__tests__/domains/systems.test.ts +209 -193
  146. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +362 -0
  147. package/src/organization-model/__tests__/foundation.test.ts +47 -75
  148. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  149. package/src/organization-model/__tests__/graph.test.ts +1336 -149
  150. package/src/organization-model/__tests__/icons.test.ts +10 -1
  151. package/src/organization-model/__tests__/knowledge.test.ts +418 -61
  152. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  153. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  154. package/src/organization-model/__tests__/prospecting-ssot.test.ts +103 -94
  155. package/src/organization-model/__tests__/recursive-system-schema.test.ts +549 -0
  156. package/src/organization-model/__tests__/resolve.test.ts +303 -42
  157. package/src/organization-model/__tests__/schema.test.ts +863 -153
  158. package/src/organization-model/__tests__/surface-projection.test.ts +284 -174
  159. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  160. package/src/organization-model/content-kinds/config.ts +36 -0
  161. package/src/organization-model/content-kinds/index.ts +78 -0
  162. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  163. package/src/organization-model/content-kinds/registry.ts +44 -0
  164. package/src/organization-model/content-kinds/status.ts +71 -0
  165. package/src/organization-model/content-kinds/template.ts +83 -0
  166. package/src/organization-model/content-kinds/types.ts +117 -0
  167. package/src/organization-model/contracts.ts +27 -17
  168. package/src/organization-model/defaults.ts +489 -107
  169. package/src/organization-model/domains/actions.ts +333 -0
  170. package/src/organization-model/domains/customers.ts +10 -7
  171. package/src/organization-model/domains/entities.ts +144 -0
  172. package/src/organization-model/domains/goals.ts +9 -6
  173. package/src/organization-model/domains/knowledge.ts +128 -54
  174. package/src/organization-model/domains/navigation.ts +139 -416
  175. package/src/organization-model/domains/offerings.ts +15 -10
  176. package/src/organization-model/domains/policies.ts +102 -0
  177. package/src/organization-model/domains/projects.ts +6 -40
  178. package/src/organization-model/domains/prospecting.ts +395 -514
  179. package/src/organization-model/domains/resources.ts +173 -81
  180. package/src/organization-model/domains/roles.ts +96 -93
  181. package/src/organization-model/domains/sales.test.ts +218 -218
  182. package/src/organization-model/domains/sales.ts +380 -589
  183. package/src/organization-model/domains/shared.ts +8 -8
  184. package/src/organization-model/domains/statuses.ts +298 -89
  185. package/src/organization-model/domains/systems.ts +240 -38
  186. package/src/organization-model/foundation.ts +35 -48
  187. package/src/organization-model/graph/build.ts +1035 -279
  188. package/src/organization-model/graph/index.ts +4 -4
  189. package/src/organization-model/graph/link.ts +10 -10
  190. package/src/organization-model/graph/schema.ts +77 -56
  191. package/src/organization-model/graph/types.ts +75 -56
  192. package/src/organization-model/helpers.ts +312 -59
  193. package/src/organization-model/icons.ts +78 -66
  194. package/src/organization-model/index.ts +129 -16
  195. package/src/organization-model/migration-helpers.ts +252 -0
  196. package/src/organization-model/ontology.ts +661 -0
  197. package/src/organization-model/organization-graph.mdx +110 -89
  198. package/src/organization-model/organization-model.mdx +226 -171
  199. package/src/organization-model/published.ts +295 -139
  200. package/src/organization-model/resolve.ts +139 -21
  201. package/src/organization-model/schema.ts +841 -301
  202. package/src/organization-model/surface-projection.ts +212 -218
  203. package/src/organization-model/types.ts +181 -90
  204. package/src/platform/api/types.ts +38 -38
  205. package/src/platform/constants/versions.ts +3 -3
  206. package/src/platform/index.ts +23 -23
  207. package/src/platform/registry/__tests__/command-view.test.ts +5 -7
  208. package/src/platform/registry/__tests__/resource-link.test.ts +35 -30
  209. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +17 -32
  210. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  211. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2051
  212. package/src/platform/registry/__tests__/validation.test.ts +1347 -1343
  213. package/src/platform/registry/command-view.ts +10 -10
  214. package/src/platform/registry/index.ts +103 -103
  215. package/src/platform/registry/resource-link.ts +32 -32
  216. package/src/platform/registry/resource-registry.ts +890 -878
  217. package/src/platform/registry/serialization.ts +295 -295
  218. package/src/platform/registry/serialized-types.ts +166 -166
  219. package/src/platform/registry/stats-types.ts +68 -68
  220. package/src/platform/registry/types.ts +425 -425
  221. package/src/platform/registry/validation.ts +745 -743
  222. package/src/platform/utils/__tests__/validation.test.ts +1084 -1084
  223. package/src/platform/utils/validation.ts +425 -425
  224. package/src/projects/api-schemas.test.ts +39 -39
  225. package/src/projects/api-schemas.ts +291 -291
  226. package/src/reference/_generated/contracts.md +2389 -2121
  227. package/src/reference/glossary.md +76 -76
  228. package/src/scaffold-registry/__tests__/index.test.ts +206 -206
  229. package/src/scaffold-registry/__tests__/schema.test.ts +166 -166
  230. package/src/scaffold-registry/index.ts +392 -392
  231. package/src/scaffold-registry/schema.ts +243 -243
  232. package/src/server.ts +289 -289
  233. package/src/supabase/database.types.ts +3153 -3093
  234. package/src/test-utils/README.md +37 -37
  235. package/src/test-utils/entities.ts +108 -108
  236. package/src/test-utils/fixtures/memberships.ts +82 -82
  237. package/src/test-utils/index.ts +12 -12
  238. package/src/test-utils/organization-model.ts +65 -65
  239. package/src/test-utils/published.ts +6 -6
  240. package/src/test-utils/rls/RLSTestContext.ts +588 -588
  241. package/src/test-utils/test-utils.test.ts +44 -49
  242. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  243. package/src/organization-model/domains/features.ts +0 -31
  244. package/src/organization-model/domains/operations.ts +0 -85
@@ -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
- * featureId (graph node ID: `feature:<featureId>`).
39
- *
40
- * @param graph - The built OrganizationGraph.
41
- * @param featureId - The dotted feature id (e.g. `sales.crm`).
42
- */
43
- export function byFeature(
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
+ */
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
- featureId: string,
93
+ ontologyId: string,
46
94
  knowledgeNodes: OrgKnowledgeNode[]
47
95
  ): OrgKnowledgeNode[] {
48
- const targetGraphNodeId = `feature:${featureId}`
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 byFeature(
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,190 +111,198 @@ export function byFeature(
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. `['feature: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. `feature:sales.crm`) or a
130
- * bare feature id (e.g. `sales.crm` will be prefixed with `feature:`).
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 `feature:sales.crm` and bare `sales.crm`
135
- const targetId =
136
- nodeId.startsWith('feature:') || nodeId.startsWith('knowledge:') || nodeId.startsWith('resource:')
137
- ? nodeId
138
- : `feature:${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
- }
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:
203
+ * - `by-system`: `[systemId]` (e.g. `['sales.crm']`)
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:
219
+ * `/by-system/<systemId>` -> `{ mount: 'by-system', args: ['<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>
252
+ if (first === 'by-system') {
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('/')] }
145
257
  }
146
- return results
147
- }
148
258
 
149
- // ---------------------------------------------------------------------------
150
- // Path parser
151
- // ---------------------------------------------------------------------------
152
-
153
- /** The recognized mount axes for Knowledge Map paths. */
154
- export type KnowledgeMount = 'by-feature' | '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:
162
- * - `by-feature`: `[featureId]` (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:
177
- * `/by-feature/<featureId>` → `{ mount: 'by-feature', args: ['<featureId>'] }`
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-feature/<featureId>
209
- if (first === 'by-feature') {
210
- if (rest.length === 0) {
211
- throw new Error(`parsePath: /by-feature requires a featureId argument, got: "${pathString}"`)
212
- }
213
- return { mount: 'by-feature', args: [rest.join('/')] }
214
- }
215
-
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}"`)
220
- }
221
- return { mount: 'by-kind', args: [rest[0]] }
222
- }
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}"`)
262
+ throw new Error(`parsePath: /by-ontology requires an ontologyId argument, got: "${pathString}"`)
236
263
  }
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] }
264
+ return { mount: 'by-ontology', args: [rest.join('/')] }
245
265
  }
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-feature/<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
+ }
308
+