@elevasis/core 0.23.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 (241) hide show
  1. package/dist/index.d.ts +1326 -552
  2. package/dist/index.js +869 -154
  3. package/dist/knowledge/index.d.ts +487 -209
  4. package/dist/knowledge/index.js +104 -1
  5. package/dist/organization-model/index.d.ts +1326 -552
  6. package/dist/organization-model/index.js +869 -154
  7. package/dist/test-utils/index.d.ts +357 -72
  8. package/dist/test-utils/index.js +795 -142
  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 -12
  13. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2102 -2096
  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 +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 +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 +382 -283
  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__/flatten-additive-merge.test.ts +362 -361
  147. package/src/organization-model/__tests__/foundation.test.ts +77 -77
  148. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -144
  149. package/src/organization-model/__tests__/graph.test.ts +1246 -887
  150. package/src/organization-model/__tests__/icons.test.ts +10 -1
  151. package/src/organization-model/__tests__/knowledge.test.ts +251 -15
  152. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -438
  153. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -591
  154. package/src/organization-model/__tests__/prospecting-ssot.test.ts +103 -103
  155. package/src/organization-model/__tests__/recursive-system-schema.test.ts +535 -506
  156. package/src/organization-model/__tests__/resolve.test.ts +274 -164
  157. package/src/organization-model/__tests__/schema.test.ts +834 -301
  158. package/src/organization-model/__tests__/surface-projection.test.ts +284 -284
  159. package/src/organization-model/catalogs/lead-gen.ts +144 -144
  160. package/src/organization-model/content-kinds/config.ts +36 -36
  161. package/src/organization-model/content-kinds/index.ts +76 -72
  162. package/src/organization-model/content-kinds/pipeline.ts +68 -68
  163. package/src/organization-model/content-kinds/registry.ts +44 -44
  164. package/src/organization-model/content-kinds/status.ts +71 -71
  165. package/src/organization-model/content-kinds/template.ts +83 -83
  166. package/src/organization-model/content-kinds/types.ts +117 -117
  167. package/src/organization-model/contracts.ts +27 -27
  168. package/src/organization-model/defaults.ts +40 -50
  169. package/src/organization-model/domains/actions.ts +333 -239
  170. package/src/organization-model/domains/customers.ts +78 -78
  171. package/src/organization-model/domains/entities.ts +144 -144
  172. package/src/organization-model/domains/goals.ts +83 -83
  173. package/src/organization-model/domains/knowledge.ts +117 -101
  174. package/src/organization-model/domains/navigation.ts +139 -139
  175. package/src/organization-model/domains/offerings.ts +71 -71
  176. package/src/organization-model/domains/policies.ts +102 -102
  177. package/src/organization-model/domains/projects.ts +14 -14
  178. package/src/organization-model/domains/prospecting.ts +395 -395
  179. package/src/organization-model/domains/resources.ts +167 -132
  180. package/src/organization-model/domains/roles.ts +96 -96
  181. package/src/organization-model/domains/sales.test.ts +218 -218
  182. package/src/organization-model/domains/sales.ts +380 -380
  183. package/src/organization-model/domains/shared.ts +63 -63
  184. package/src/organization-model/domains/statuses.ts +339 -339
  185. package/src/organization-model/domains/systems.ts +217 -172
  186. package/src/organization-model/foundation.ts +75 -75
  187. package/src/organization-model/graph/build.ts +1016 -888
  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 +76 -70
  191. package/src/organization-model/graph/types.ts +73 -67
  192. package/src/organization-model/helpers.ts +289 -241
  193. package/src/organization-model/icons.ts +78 -66
  194. package/src/organization-model/index.ts +130 -128
  195. package/src/organization-model/migration-helpers.ts +247 -244
  196. package/src/organization-model/ontology.ts +661 -0
  197. package/src/organization-model/organization-graph.mdx +110 -90
  198. package/src/organization-model/organization-model.mdx +226 -219
  199. package/src/organization-model/published.ts +289 -235
  200. package/src/organization-model/resolve.ts +146 -91
  201. package/src/organization-model/schema.ts +790 -671
  202. package/src/organization-model/surface-projection.ts +212 -212
  203. package/src/organization-model/types.ts +177 -167
  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 +10 -10
  208. package/src/platform/registry/__tests__/resource-link.test.ts +35 -35
  209. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +20 -20
  210. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -245
  211. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2053
  212. package/src/platform/registry/__tests__/validation.test.ts +1347 -1347
  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 -890
  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 -745
  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 +2101 -2096
  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 -3153
  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 -44
@@ -1,249 +1,252 @@
1
- /**
2
- * Migration helpers — Phase 4 internals swap
3
- *
4
- * External signatures are UNCHANGED from the pre-Phase-4 era so callers remain
5
- * mechanical. Internally, all compound-domain reads (model.sales.pipelines,
6
- * model.prospecting.*, model.projects.*) are replaced by walking system.content
7
- * via listAllSystems() and filtering by (kind, type).
8
- *
9
- * Registry entries used:
10
- * 'schema:pipeline' one pipeline per owning system
11
- * 'schema:stage' stage within a pipeline; parentContentId = pipeline local id
12
- * 'schema:template' prospecting build template
13
- * 'schema:template-step' step within a template; parentContentId = template local id
14
- * 'schema:status-flow' — status set for a project/milestone/task scope
15
- * 'schema:status' — single status within a flow; parentContentId = status-flow local id
16
- */
17
-
1
+ /**
2
+ * Migration helpers — Phase 4 internals swap
3
+ *
4
+ * External signatures are UNCHANGED from the pre-Phase-4 era so callers remain
5
+ * mechanical. Internally, compatibility reads for old compound-domain data
6
+ * walk System.content via listAllSystems() and filter by (kind, type).
7
+ *
8
+ * Compatibility registry entries read:
9
+ * 'schema:pipeline' — one pipeline per owning system
10
+ * 'schema:stage' stage within a pipeline; parentContentId = pipeline local id
11
+ * 'schema:template' prospecting build template
12
+ * 'schema:template-step' step within a template; parentContentId = template local id
13
+ * 'schema:status-flow' status set for a project/milestone/task scope
14
+ * 'schema:status' single status within a flow; parentContentId = status-flow local id
15
+ */
16
+
18
17
  import type { OrganizationModel } from './types'
19
18
  import type { z } from 'zod'
20
19
  import type { SalesPipelineSchema, SalesStageSchema } from './domains/sales'
21
- import type { ProspectingBuildTemplateSchema, ProspectingLifecycleStageSchema } from './domains/prospecting'
22
- import type { ProjectsDomainStateSchema } from './domains/projects'
20
+ import type { ProspectingBuildTemplateSchema, ProspectingLifecycleStageSchema } from './domains/prospecting'
21
+ import type { ProjectsDomainStateSchema } from './domains/projects'
23
22
  import { listAllSystems } from './helpers'
24
23
 
25
- // ---------------------------------------------------------------------------
26
- // Locally-scoped inferred types external signatures use these shapes.
27
- // ---------------------------------------------------------------------------
28
- type Pipeline = z.infer<typeof SalesPipelineSchema>
29
- type Stage = z.infer<typeof SalesStageSchema>
30
- type BuildTemplate = z.infer<typeof ProspectingBuildTemplateSchema>
31
- type ProspectingStage = z.infer<typeof ProspectingLifecycleStageSchema>
32
- type ProjectStatus = z.infer<typeof ProjectsDomainStateSchema>
33
-
34
- // ---------------------------------------------------------------------------
35
- // Sales Pipelines + Stages
36
- // ---------------------------------------------------------------------------
37
-
38
- /**
39
- * Return all sales pipelines defined in the model, each tagged with the
40
- * system path of the owning system.
41
- *
42
- * Phase 4: walks every system via listAllSystems(), finds content nodes where
43
- * (kind, type) === ('schema', 'pipeline'), and reconstructs the Pipeline shape
44
- * by pulling sibling stage content nodes (parentContentId === pipeline local id).
45
- */
46
- export function getAllPipelines(model: OrganizationModel): Array<{ systemPath: string; pipeline: Pipeline }> {
47
- const results: Array<{ systemPath: string; pipeline: Pipeline }> = []
48
-
49
- for (const { path: systemPath, system } of listAllSystems(model)) {
50
- const content = system.content ?? {}
51
-
52
- for (const [localId, node] of Object.entries(content)) {
53
- if (node.kind !== 'schema' || node.type !== 'pipeline') continue
54
-
55
- const data = (node.data ?? {}) as Record<string, unknown>
56
- const stages: Stage[] = Object.entries(content)
57
- .filter(([, s]) => s.kind === 'schema' && s.type === 'stage' && s.parentContentId === localId)
58
- .map(([stageLocalId, s]) => {
59
- const sd = (s.data ?? {}) as Record<string, unknown>
60
- return {
61
- id: stageLocalId,
62
- label: s.label ?? stageLocalId,
63
- order: typeof sd.order === 'number' ? sd.order : 0,
64
- semanticClass: (sd.semanticClass as Stage['semanticClass']) ?? 'open',
65
- surfaceIds: Array.isArray(sd.surfaceIds) ? (sd.surfaceIds as string[]) : [],
66
- resourceIds: Array.isArray(sd.resourceIds) ? (sd.resourceIds as string[]) : [],
67
- color: typeof sd.color === 'string' ? sd.color : undefined
68
- } satisfies Stage
69
- })
70
- .sort((a, b) => a.order - b.order)
71
-
72
- const pipeline: Pipeline = {
73
- id: localId,
74
- label: node.label ?? localId,
75
- entityId: typeof data.entityId === 'string' ? data.entityId : '',
76
- stages,
77
- ...(typeof node.description === 'string' ? { description: node.description } : {})
78
- }
79
-
80
- results.push({ systemPath, pipeline })
81
- }
82
- }
83
-
84
- return results
85
- }
86
-
87
- /**
88
- * Return the stages belonging to a given pipeline, identified by systemPath + pipelineLocalId.
89
- *
90
- * Phase 4: resolves the system at systemPath, filters its content for stage nodes
91
- * where parentContentId === pipelineLocalId.
92
- *
93
- * @param model - The resolved organization model.
94
- * @param systemPath - Dot-separated path to the owning system (e.g. 'sales.crm').
95
- * @param pipelineLocalId - The local content id of the target pipeline node.
96
- */
97
- export function getStagesInPipeline(model: OrganizationModel, systemPath: string, pipelineLocalId: string): Stage[] {
98
- const allSystems = listAllSystems(model)
99
- const entry = allSystems.find((s) => s.path === systemPath)
100
- if (!entry) return []
101
-
102
- const content = entry.system.content ?? {}
103
- return Object.entries(content)
104
- .filter(([, node]) => node.kind === 'schema' && node.type === 'stage' && node.parentContentId === pipelineLocalId)
105
- .map(([stageLocalId, s]) => {
106
- const sd = (s.data ?? {}) as Record<string, unknown>
107
- return {
108
- id: stageLocalId,
109
- label: s.label ?? stageLocalId,
110
- order: typeof sd.order === 'number' ? sd.order : 0,
111
- semanticClass: (sd.semanticClass as Stage['semanticClass']) ?? 'open',
112
- surfaceIds: Array.isArray(sd.surfaceIds) ? (sd.surfaceIds as string[]) : [],
113
- resourceIds: Array.isArray(sd.resourceIds) ? (sd.resourceIds as string[]) : [],
114
- color: typeof sd.color === 'string' ? sd.color : undefined
115
- } satisfies Stage
116
- })
117
- .sort((a, b) => a.order - b.order)
118
- }
119
-
120
- // ---------------------------------------------------------------------------
121
- // Prospecting Build templates
122
- // ---------------------------------------------------------------------------
123
-
124
- /**
125
- * Return all prospecting build templates defined in the model.
126
- *
127
- * Phase 4: walks every system, finds content nodes where
128
- * (kind, type) === ('schema', 'template'), reconstructs BuildTemplate shape
129
- * by pulling sibling template-step nodes (parentContentId === template local id).
130
- */
131
- export function getAllBuildTemplates(model: OrganizationModel): BuildTemplate[] {
132
- const results: BuildTemplate[] = []
133
-
134
- for (const { system } of listAllSystems(model)) {
135
- const content = system.content ?? {}
136
-
137
- for (const [localId, node] of Object.entries(content)) {
138
- if (node.kind !== 'schema' || node.type !== 'template') continue
139
- const nd = (node.data ?? {}) as Record<string, unknown>
140
-
141
- const steps = Object.entries(content)
142
- .filter(([, s]) => s.kind === 'schema' && s.type === 'template-step' && s.parentContentId === localId)
143
- .map(([stepLocalId, s]) => {
144
- const sd = (s.data ?? {}) as Record<string, unknown>
145
- return {
146
- id: stepLocalId,
147
- label: s.label ?? stepLocalId,
148
- ...(s.description ? { description: s.description } : {}),
149
- // Pass through all data fields — template-step payload is richer than Pipeline;
150
- // Wave 2 authors the canonical shape; Wave 4 verifies round-trip fidelity.
151
- ...sd
152
- }
153
- })
154
-
155
- results.push({
156
- id: localId,
157
- label: node.label ?? localId,
158
- ...(node.description ? { description: node.description } : {}),
159
- ...(typeof nd.color === 'string' ? { color: nd.color } : {}),
160
- // BuildTemplate requires steps array — cast via spread; Wave 4 adds type-safe assertions.
161
- steps: steps as BuildTemplate['steps']
162
- })
163
- }
164
- }
165
-
166
- return results
167
- }
168
-
169
- /**
170
- * Return the prospecting lifecycle stages for a given entity kind.
171
- *
172
- * Phase 4: walks every system, finds content nodes where
173
- * (kind, type) === ('schema', 'stage') AND data.entityKind === kind.
174
- * Prospecting stages are distinguished from pipeline stages by the presence of
175
- * data.entityKind ('company' | 'contact') authored by Wave 2.
176
- *
177
- * @param kind - 'company' or 'contact'.
178
- */
179
- export function getAllProspectingStages(model: OrganizationModel, kind: 'company' | 'contact'): ProspectingStage[] {
180
- const results: ProspectingStage[] = []
181
-
182
- for (const { system } of listAllSystems(model)) {
183
- const content = system.content ?? {}
184
-
185
- for (const [localId, node] of Object.entries(content)) {
186
- if (node.kind !== 'schema' || node.type !== 'stage') continue
187
- const sd = (node.data ?? {}) as Record<string, unknown>
188
- if (sd.entityKind !== kind) continue
189
-
190
- results.push({
191
- id: localId,
192
- label: node.label ?? localId,
193
- order: typeof sd.order === 'number' ? sd.order : 0,
194
- ...(typeof sd.color === 'string' ? { color: sd.color } : {}),
195
- ...(node.description ? { description: node.description } : {})
196
- } satisfies ProspectingStage)
197
- }
198
- }
199
-
200
- return results.sort((a, b) => a.order - b.order)
201
- }
202
-
203
- // ---------------------------------------------------------------------------
204
- // Projects Statuses
205
- // ---------------------------------------------------------------------------
206
-
207
- /**
208
- * Return the project statuses for a given entity type.
209
- *
210
- * Phase 4: walks every system, finds status-flow content nodes where
211
- * data.appliesTo === appliesTo, then collects their child status nodes
212
- * (parentContentId === status-flow local id), sorted by order.
213
- *
214
- * @param appliesTo - 'project', 'milestone', or 'task'.
215
- */
216
- export function getAllProjectStatuses(
217
- model: OrganizationModel,
218
- appliesTo: 'project' | 'milestone' | 'task'
219
- ): ProjectStatus[] {
220
- const results: ProjectStatus[] = []
221
-
222
- for (const { system } of listAllSystems(model)) {
223
- const content = system.content ?? {}
224
-
225
- // Find the status-flow node for this appliesTo scope.
226
- for (const [flowLocalId, flowNode] of Object.entries(content)) {
227
- if (flowNode.kind !== 'schema' || flowNode.type !== 'status-flow') continue
228
- const fd = (flowNode.data ?? {}) as Record<string, unknown>
229
- if (fd.appliesTo !== appliesTo) continue
230
-
231
- // Collect child status nodes.
232
- for (const [statusLocalId, statusNode] of Object.entries(content)) {
233
- if (statusNode.kind !== 'schema' || statusNode.type !== 'status') continue
234
- if (statusNode.parentContentId !== flowLocalId) continue
235
-
236
- const sd = (statusNode.data ?? {}) as Record<string, unknown>
237
- results.push({
238
- id: statusLocalId,
239
- label: statusNode.label ?? statusLocalId,
240
- order: typeof sd.order === 'number' ? sd.order : 0,
241
- ...(typeof sd.color === 'string' ? { color: sd.color } : {}),
242
- ...(statusNode.description ? { description: statusNode.description } : {})
243
- } satisfies ProjectStatus)
244
- }
245
- }
246
- }
247
-
248
- return results.sort((a, b) => a.order - b.order)
249
- }
24
+ // Compatibility boundary: these helpers intentionally keep old tenant
25
+ // System.content schema nodes readable. New schema/catalog authoring belongs in
26
+ // System.ontology, and new system-local settings belong in System.config.
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Locally-scoped inferred types — external signatures use these shapes.
30
+ // ---------------------------------------------------------------------------
31
+ type Pipeline = z.infer<typeof SalesPipelineSchema>
32
+ type Stage = z.infer<typeof SalesStageSchema>
33
+ type BuildTemplate = z.infer<typeof ProspectingBuildTemplateSchema>
34
+ type ProspectingStage = z.infer<typeof ProspectingLifecycleStageSchema>
35
+ type ProjectStatus = z.infer<typeof ProjectsDomainStateSchema>
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Sales Pipelines + Stages
39
+ // ---------------------------------------------------------------------------
40
+
41
+ /**
42
+ * Return all sales pipelines defined in the model, each tagged with the
43
+ * system path of the owning system.
44
+ *
45
+ * Compatibility bridge: walks every system via listAllSystems(), finds content nodes where
46
+ * (kind, type) === ('schema', 'pipeline'), and reconstructs the Pipeline shape
47
+ * by pulling sibling stage content nodes (parentContentId === pipeline local id).
48
+ */
49
+ export function getAllPipelines(model: OrganizationModel): Array<{ systemPath: string; pipeline: Pipeline }> {
50
+ const results: Array<{ systemPath: string; pipeline: Pipeline }> = []
51
+
52
+ for (const { path: systemPath, system } of listAllSystems(model)) {
53
+ const content = system.content ?? {}
54
+
55
+ for (const [localId, node] of Object.entries(content)) {
56
+ if (node.kind !== 'schema' || node.type !== 'pipeline') continue
57
+
58
+ const data = (node.data ?? {}) as Record<string, unknown>
59
+ const stages: Stage[] = Object.entries(content)
60
+ .filter(([, s]) => s.kind === 'schema' && s.type === 'stage' && s.parentContentId === localId)
61
+ .map(([stageLocalId, s]) => {
62
+ const sd = (s.data ?? {}) as Record<string, unknown>
63
+ return {
64
+ id: stageLocalId,
65
+ label: s.label ?? stageLocalId,
66
+ order: typeof sd.order === 'number' ? sd.order : 0,
67
+ semanticClass: (sd.semanticClass as Stage['semanticClass']) ?? 'open',
68
+ surfaceIds: Array.isArray(sd.surfaceIds) ? (sd.surfaceIds as string[]) : [],
69
+ resourceIds: Array.isArray(sd.resourceIds) ? (sd.resourceIds as string[]) : [],
70
+ color: typeof sd.color === 'string' ? sd.color : undefined
71
+ } satisfies Stage
72
+ })
73
+ .sort((a, b) => a.order - b.order)
74
+
75
+ const pipeline: Pipeline = {
76
+ id: localId,
77
+ label: node.label ?? localId,
78
+ entityId: typeof data.entityId === 'string' ? data.entityId : '',
79
+ stages,
80
+ ...(typeof node.description === 'string' ? { description: node.description } : {})
81
+ }
82
+
83
+ results.push({ systemPath, pipeline })
84
+ }
85
+ }
86
+
87
+ return results
88
+ }
89
+
90
+ /**
91
+ * Return the stages belonging to a given pipeline, identified by systemPath + pipelineLocalId.
92
+ *
93
+ * Compatibility bridge: resolves the system at systemPath, filters its content for stage nodes
94
+ * where parentContentId === pipelineLocalId.
95
+ *
96
+ * @param model - The resolved organization model.
97
+ * @param systemPath - Dot-separated path to the owning system (e.g. 'sales.crm').
98
+ * @param pipelineLocalId - The local content id of the target pipeline node.
99
+ */
100
+ export function getStagesInPipeline(model: OrganizationModel, systemPath: string, pipelineLocalId: string): Stage[] {
101
+ const allSystems = listAllSystems(model)
102
+ const entry = allSystems.find((s) => s.path === systemPath)
103
+ if (!entry) return []
104
+
105
+ const content = entry.system.content ?? {}
106
+ return Object.entries(content)
107
+ .filter(([, node]) => node.kind === 'schema' && node.type === 'stage' && node.parentContentId === pipelineLocalId)
108
+ .map(([stageLocalId, s]) => {
109
+ const sd = (s.data ?? {}) as Record<string, unknown>
110
+ return {
111
+ id: stageLocalId,
112
+ label: s.label ?? stageLocalId,
113
+ order: typeof sd.order === 'number' ? sd.order : 0,
114
+ semanticClass: (sd.semanticClass as Stage['semanticClass']) ?? 'open',
115
+ surfaceIds: Array.isArray(sd.surfaceIds) ? (sd.surfaceIds as string[]) : [],
116
+ resourceIds: Array.isArray(sd.resourceIds) ? (sd.resourceIds as string[]) : [],
117
+ color: typeof sd.color === 'string' ? sd.color : undefined
118
+ } satisfies Stage
119
+ })
120
+ .sort((a, b) => a.order - b.order)
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Prospecting Build templates
125
+ // ---------------------------------------------------------------------------
126
+
127
+ /**
128
+ * Return all prospecting build templates defined in the model.
129
+ *
130
+ * Compatibility bridge: walks every system, finds content nodes where
131
+ * (kind, type) === ('schema', 'template'), reconstructs BuildTemplate shape
132
+ * by pulling sibling template-step nodes (parentContentId === template local id).
133
+ */
134
+ export function getAllBuildTemplates(model: OrganizationModel): BuildTemplate[] {
135
+ const results: BuildTemplate[] = []
136
+
137
+ for (const { system } of listAllSystems(model)) {
138
+ const content = system.content ?? {}
139
+
140
+ for (const [localId, node] of Object.entries(content)) {
141
+ if (node.kind !== 'schema' || node.type !== 'template') continue
142
+ const nd = (node.data ?? {}) as Record<string, unknown>
143
+
144
+ const steps = Object.entries(content)
145
+ .filter(([, s]) => s.kind === 'schema' && s.type === 'template-step' && s.parentContentId === localId)
146
+ .map(([stepLocalId, s]) => {
147
+ const sd = (s.data ?? {}) as Record<string, unknown>
148
+ return {
149
+ id: stepLocalId,
150
+ label: s.label ?? stepLocalId,
151
+ ...(s.description ? { description: s.description } : {}),
152
+ // Pass through all data fields — template-step payload is richer than Pipeline;
153
+ // Bridge readers preserve the historical shape for round-trip fidelity.
154
+ ...sd
155
+ }
156
+ })
157
+
158
+ results.push({
159
+ id: localId,
160
+ label: node.label ?? localId,
161
+ ...(node.description ? { description: node.description } : {}),
162
+ ...(typeof nd.color === 'string' ? { color: nd.color } : {}),
163
+ // BuildTemplate requires steps array — cast via spread; Wave 4 adds type-safe assertions.
164
+ steps: steps as BuildTemplate['steps']
165
+ })
166
+ }
167
+ }
168
+
169
+ return results
170
+ }
171
+
172
+ /**
173
+ * Return the prospecting lifecycle stages for a given entity kind.
174
+ *
175
+ * Compatibility bridge: walks every system, finds content nodes where
176
+ * (kind, type) === ('schema', 'stage') AND data.entityKind === kind.
177
+ * Prospecting stages are distinguished from pipeline stages by the presence of
178
+ * data.entityKind ('company' | 'contact') retained on bridge compatibility nodes.
179
+ *
180
+ * @param kind - 'company' or 'contact'.
181
+ */
182
+ export function getAllProspectingStages(model: OrganizationModel, kind: 'company' | 'contact'): ProspectingStage[] {
183
+ const results: ProspectingStage[] = []
184
+
185
+ for (const { system } of listAllSystems(model)) {
186
+ const content = system.content ?? {}
187
+
188
+ for (const [localId, node] of Object.entries(content)) {
189
+ if (node.kind !== 'schema' || node.type !== 'stage') continue
190
+ const sd = (node.data ?? {}) as Record<string, unknown>
191
+ if (sd.entityKind !== kind) continue
192
+
193
+ results.push({
194
+ id: localId,
195
+ label: node.label ?? localId,
196
+ order: typeof sd.order === 'number' ? sd.order : 0,
197
+ ...(typeof sd.color === 'string' ? { color: sd.color } : {}),
198
+ ...(node.description ? { description: node.description } : {})
199
+ } satisfies ProspectingStage)
200
+ }
201
+ }
202
+
203
+ return results.sort((a, b) => a.order - b.order)
204
+ }
205
+
206
+ // ---------------------------------------------------------------------------
207
+ // Projects Statuses
208
+ // ---------------------------------------------------------------------------
209
+
210
+ /**
211
+ * Return the project statuses for a given entity type.
212
+ *
213
+ * Compatibility bridge: walks every system, finds status-flow content nodes where
214
+ * data.appliesTo === appliesTo, then collects their child status nodes
215
+ * (parentContentId === status-flow local id), sorted by order.
216
+ *
217
+ * @param appliesTo - 'project', 'milestone', or 'task'.
218
+ */
219
+ export function getAllProjectStatuses(
220
+ model: OrganizationModel,
221
+ appliesTo: 'project' | 'milestone' | 'task'
222
+ ): ProjectStatus[] {
223
+ const results: ProjectStatus[] = []
224
+
225
+ for (const { system } of listAllSystems(model)) {
226
+ const content = system.content ?? {}
227
+
228
+ // Find the status-flow node for this appliesTo scope.
229
+ for (const [flowLocalId, flowNode] of Object.entries(content)) {
230
+ if (flowNode.kind !== 'schema' || flowNode.type !== 'status-flow') continue
231
+ const fd = (flowNode.data ?? {}) as Record<string, unknown>
232
+ if (fd.appliesTo !== appliesTo) continue
233
+
234
+ // Collect child status nodes.
235
+ for (const [statusLocalId, statusNode] of Object.entries(content)) {
236
+ if (statusNode.kind !== 'schema' || statusNode.type !== 'status') continue
237
+ if (statusNode.parentContentId !== flowLocalId) continue
238
+
239
+ const sd = (statusNode.data ?? {}) as Record<string, unknown>
240
+ results.push({
241
+ id: statusLocalId,
242
+ label: statusNode.label ?? statusLocalId,
243
+ order: typeof sd.order === 'number' ? sd.order : 0,
244
+ ...(typeof sd.color === 'string' ? { color: sd.color } : {}),
245
+ ...(statusNode.description ? { description: statusNode.description } : {})
246
+ } satisfies ProjectStatus)
247
+ }
248
+ }
249
+ }
250
+
251
+ return results.sort((a, b) => a.order - b.order)
252
+ }