@elevasis/core 0.21.0 → 0.23.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 (132) hide show
  1. package/dist/index.d.ts +2518 -2169
  2. package/dist/index.js +2495 -1095
  3. package/dist/knowledge/index.d.ts +706 -1044
  4. package/dist/knowledge/index.js +9 -9
  5. package/dist/organization-model/index.d.ts +2518 -2169
  6. package/dist/organization-model/index.js +2495 -1095
  7. package/dist/test-utils/index.d.ts +826 -1014
  8. package/dist/test-utils/index.js +1894 -1032
  9. package/package.json +3 -3
  10. package/src/__tests__/template-core-compatibility.test.ts +11 -79
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
  12. package/src/auth/multi-tenancy/permissions.ts +20 -8
  13. package/src/business/README.md +2 -2
  14. package/src/business/acquisition/api-schemas.test.ts +175 -2
  15. package/src/business/acquisition/api-schemas.ts +132 -16
  16. package/src/business/acquisition/build-templates.test.ts +4 -4
  17. package/src/business/acquisition/build-templates.ts +72 -30
  18. package/src/business/acquisition/crm-state-actions.test.ts +13 -11
  19. package/src/business/acquisition/index.ts +12 -0
  20. package/src/business/acquisition/types.ts +7 -3
  21. package/src/business/clients/api-schemas.test.ts +115 -0
  22. package/src/business/clients/api-schemas.ts +158 -0
  23. package/src/business/clients/index.ts +1 -0
  24. package/src/business/deals/api-schemas.ts +8 -0
  25. package/src/business/index.ts +5 -2
  26. package/src/business/projects/types.ts +19 -0
  27. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
  28. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
  29. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
  30. package/src/execution/engine/agent/core/types.ts +25 -15
  31. package/src/execution/engine/agent/index.ts +6 -4
  32. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
  33. package/src/execution/engine/index.ts +3 -0
  34. package/src/execution/engine/workflow/types.ts +9 -2
  35. package/src/knowledge/README.md +8 -7
  36. package/src/knowledge/__tests__/queries.test.ts +74 -73
  37. package/src/knowledge/format.ts +10 -9
  38. package/src/knowledge/index.ts +1 -1
  39. package/src/knowledge/published.ts +1 -1
  40. package/src/knowledge/queries.ts +26 -25
  41. package/src/organization-model/README.md +73 -26
  42. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  43. package/src/organization-model/__tests__/defaults.test.ts +76 -96
  44. package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
  45. package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
  46. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  47. package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
  48. package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
  49. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
  50. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
  51. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  52. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
  53. package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
  54. package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
  55. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
  56. package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
  57. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
  58. package/src/organization-model/__tests__/foundation.test.ts +74 -102
  59. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  60. package/src/organization-model/__tests__/graph.test.ts +899 -71
  61. package/src/organization-model/__tests__/knowledge.test.ts +209 -49
  62. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  63. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  64. package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
  65. package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
  66. package/src/organization-model/__tests__/resolve.test.ts +174 -23
  67. package/src/organization-model/__tests__/schema.test.ts +291 -114
  68. package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
  69. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  70. package/src/organization-model/content-kinds/config.ts +36 -0
  71. package/src/organization-model/content-kinds/index.ts +74 -0
  72. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  73. package/src/organization-model/content-kinds/registry.ts +44 -0
  74. package/src/organization-model/content-kinds/status.ts +71 -0
  75. package/src/organization-model/content-kinds/template.ts +83 -0
  76. package/src/organization-model/content-kinds/types.ts +117 -0
  77. package/src/organization-model/contracts.ts +13 -3
  78. package/src/organization-model/defaults.ts +499 -86
  79. package/src/organization-model/domains/actions.ts +239 -0
  80. package/src/organization-model/domains/customers.ts +78 -75
  81. package/src/organization-model/domains/entities.ts +144 -0
  82. package/src/organization-model/domains/goals.ts +83 -80
  83. package/src/organization-model/domains/knowledge.ts +76 -17
  84. package/src/organization-model/domains/navigation.ts +107 -384
  85. package/src/organization-model/domains/offerings.ts +71 -66
  86. package/src/organization-model/domains/policies.ts +102 -0
  87. package/src/organization-model/domains/projects.ts +14 -48
  88. package/src/organization-model/domains/prospecting.ts +62 -181
  89. package/src/organization-model/domains/resources.ts +145 -0
  90. package/src/organization-model/domains/roles.ts +96 -55
  91. package/src/organization-model/domains/sales.ts +10 -219
  92. package/src/organization-model/domains/shared.ts +57 -57
  93. package/src/organization-model/domains/statuses.ts +339 -130
  94. package/src/organization-model/domains/systems.ts +203 -0
  95. package/src/organization-model/foundation.ts +54 -67
  96. package/src/organization-model/graph/build.ts +682 -54
  97. package/src/organization-model/graph/link.ts +1 -1
  98. package/src/organization-model/graph/schema.ts +24 -9
  99. package/src/organization-model/graph/types.ts +20 -7
  100. package/src/organization-model/helpers.ts +231 -26
  101. package/src/organization-model/icons.ts +1 -0
  102. package/src/organization-model/index.ts +118 -5
  103. package/src/organization-model/migration-helpers.ts +249 -0
  104. package/src/organization-model/organization-graph.mdx +16 -15
  105. package/src/organization-model/organization-model.mdx +111 -44
  106. package/src/organization-model/published.ts +172 -19
  107. package/src/organization-model/resolve.ts +117 -54
  108. package/src/organization-model/schema.ts +654 -112
  109. package/src/organization-model/surface-projection.ts +116 -122
  110. package/src/organization-model/types.ts +146 -20
  111. package/src/platform/api/types.ts +38 -35
  112. package/src/platform/constants/versions.ts +1 -1
  113. package/src/platform/registry/__tests__/command-view.test.ts +6 -8
  114. package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
  115. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
  116. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  117. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
  118. package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
  119. package/src/platform/registry/index.ts +14 -0
  120. package/src/platform/registry/resource-registry.ts +52 -2
  121. package/src/platform/registry/serialization.ts +241 -202
  122. package/src/platform/registry/serialized-types.ts +1 -0
  123. package/src/platform/registry/types.ts +411 -361
  124. package/src/platform/registry/validation.ts +745 -513
  125. package/src/projects/api-schemas.ts +290 -267
  126. package/src/reference/_generated/contracts.md +853 -397
  127. package/src/reference/glossary.md +23 -18
  128. package/src/supabase/database.types.ts +181 -0
  129. package/src/test-utils/test-utils.test.ts +1 -6
  130. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  131. package/src/organization-model/domains/features.ts +0 -31
  132. package/src/organization-model/domains/operations.ts +0 -85
@@ -1,5 +1,11 @@
1
- export { OrganizationModelSchema } from './schema'
2
- export { FeatureSchema, NodeIdPathSchema, NodeIdStringSchema, UiPositionSchema } from './domains/features'
1
+ export {
2
+ DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
3
+ OrganizationModelDomainKeySchema,
4
+ OrganizationModelDomainMetadataByDomainSchema,
5
+ OrganizationModelDomainMetadataSchema,
6
+ OrganizationModelSchema
7
+ } from './schema'
8
+ export { NodeIdPathSchema, NodeIdStringSchema, UiPositionSchema } from './domains/systems'
3
9
  export { LinkSchema } from './graph/link'
4
10
  export { IconNameSchema, TechStackEntrySchema } from './domains/shared'
5
11
  export {
@@ -9,15 +15,23 @@ export {
9
15
  } from './icons'
10
16
  export {
11
17
  KNOWLEDGE_FEATURE_ID,
18
+ KNOWLEDGE_SYSTEM_ID,
12
19
  PROJECTS_FEATURE_ID,
20
+ PROJECTS_SYSTEM_ID,
13
21
  PROJECTS_INDEX_SURFACE_ID,
14
- PROJECTS_VIEW_CAPABILITY_ID,
22
+ PROJECTS_VIEW_ACTION_ID,
15
23
  SALES_FEATURE_ID,
16
24
  PROSPECTING_FEATURE_ID,
17
25
  OPERATIONS_FEATURE_ID,
26
+ SALES_SYSTEM_ID,
27
+ PROSPECTING_SYSTEM_ID,
28
+ OPERATIONS_SYSTEM_ID,
18
29
  MONITORING_FEATURE_ID,
30
+ MONITORING_SYSTEM_ID,
19
31
  SETTINGS_FEATURE_ID,
32
+ SETTINGS_SYSTEM_ID,
20
33
  SEO_FEATURE_ID,
34
+ SEO_SYSTEM_ID,
21
35
  SALES_PIPELINE_SURFACE_ID,
22
36
  PROSPECTING_LISTS_SURFACE_ID,
23
37
  OPERATIONS_COMMAND_VIEW_SURFACE_ID,
@@ -30,12 +44,6 @@ export {
30
44
  StatusEntrySchema,
31
45
  StatusSemanticClassSchema
32
46
  } from './domains/statuses'
33
- export {
34
- DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
35
- OperationsDomainSchema,
36
- OperationEntrySchema,
37
- OperationSemanticClassSchema
38
- } from './domains/operations'
39
47
  export {
40
48
  DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
41
49
  CustomersDomainSchema,
@@ -48,39 +56,178 @@ export {
48
56
  ProductSchema,
49
57
  PricingModelSchema
50
58
  } from './domains/offerings'
51
- export { DEFAULT_ORGANIZATION_MODEL_ROLES, RolesDomainSchema, RoleSchema } from './domains/roles'
59
+ export {
60
+ AgentRoleHolderSchema,
61
+ DEFAULT_ORGANIZATION_MODEL_ROLES,
62
+ HumanRoleHolderSchema,
63
+ RoleHolderSchema,
64
+ RoleHoldersSchema,
65
+ RoleIdSchema,
66
+ RolesDomainSchema,
67
+ RoleSchema,
68
+ TeamRoleHolderSchema
69
+ } from './domains/roles'
52
70
  export { DEFAULT_ORGANIZATION_MODEL_GOALS, GoalsDomainSchema, ObjectiveSchema, KeyResultSchema } from './domains/goals'
71
+ export {
72
+ DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
73
+ SystemEntrySchema,
74
+ SystemIdSchema,
75
+ SystemKindSchema,
76
+ SystemLifecycleSchema,
77
+ SystemPathSchema,
78
+ SystemUiSchema,
79
+ SystemsDomainSchema,
80
+ SystemStatusSchema
81
+ } from './domains/systems'
82
+ export {
83
+ AgentKindSchema,
84
+ AgentResourceEntrySchema,
85
+ DEFAULT_ORGANIZATION_MODEL_RESOURCES,
86
+ defineResource,
87
+ defineResources,
88
+ EventDescriptorSchema,
89
+ EventEmissionDescriptorSchema,
90
+ EventIdSchema,
91
+ IntegrationResourceEntrySchema,
92
+ ResourceEntrySchema,
93
+ ResourceGovernanceStatusSchema,
94
+ ResourceIdSchema,
95
+ ResourceKindSchema,
96
+ ResourcesDomainSchema,
97
+ ScriptResourceEntrySchema,
98
+ ScriptResourceLanguageSchema,
99
+ ScriptResourceSourceSchema,
100
+ WorkflowResourceEntrySchema
101
+ } from './domains/resources'
102
+ export {
103
+ ActionsDomainSchema,
104
+ ActionIdSchema,
105
+ ActionInvocationKindSchema,
106
+ ActionInvocationSchema,
107
+ ActionRefSchema,
108
+ ActionSchema,
109
+ ActionScopeSchema,
110
+ ApiEndpointInvocationSchema,
111
+ DEFAULT_ORGANIZATION_MODEL_ACTIONS,
112
+ findOrganizationActionById,
113
+ LEAD_GEN_ACTION_ENTRIES,
114
+ McpToolInvocationSchema,
115
+ ScriptExecutionInvocationSchema,
116
+ SlashCommandInvocationSchema
117
+ } from './domains/actions'
118
+ export {
119
+ DEFAULT_ORGANIZATION_MODEL_ENTITIES,
120
+ EntitiesDomainSchema,
121
+ EntityIdSchema,
122
+ EntityLinkKindSchema,
123
+ EntityLinkSchema,
124
+ EntitySchema
125
+ } from './domains/entities'
126
+ export {
127
+ DEFAULT_ORGANIZATION_MODEL_POLICIES,
128
+ PoliciesDomainSchema,
129
+ PolicyEffectSchema,
130
+ PolicyApplicabilitySchema,
131
+ PolicyIdSchema,
132
+ PolicyPredicateSchema,
133
+ PolicySchema,
134
+ PolicyTriggerSchema
135
+ } from './domains/policies'
136
+ export { LEAD_GEN_STAGE_CATALOG } from './catalogs/lead-gen'
137
+ export {
138
+ DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
139
+ getSortedSidebarEntries,
140
+ NavigationGroupSchema,
141
+ OrganizationModelNavigationSchema,
142
+ SidebarNavigationSchema,
143
+ SidebarNodeSchema,
144
+ SidebarSectionSchema,
145
+ SidebarSurfaceTargetsSchema,
146
+ SurfaceDefinitionSchema,
147
+ SurfaceTypeSchema
148
+ } from './domains/navigation'
53
149
  export {
54
150
  KnowledgeDomainSchema,
55
151
  KnowledgeLinkSchema,
152
+ KnowledgeTargetKindSchema,
153
+ KnowledgeTargetRefSchema,
56
154
  OrgKnowledgeNodeSchema,
57
155
  OrgKnowledgeKindSchema
58
156
  } from './domains/knowledge'
59
- export { defineOrganizationModel, resolveOrganizationModel } from './resolve'
157
+ export { defineOrganizationModel, resolveOrganizationModel, resolveOrganizationModelWithResources } from './resolve'
158
+ export type { ResolvedSystemEntry, ResolvedOrganizationModel } from './resolve'
60
159
  export { createFoundationOrganizationModel } from './foundation'
61
160
 
62
161
  export type {
63
162
  DeepPartial,
163
+ KnowledgeLink,
164
+ KnowledgeTargetKind,
165
+ KnowledgeTargetRef,
64
166
  OrganizationModel,
65
167
  OrganizationModelBranding,
66
- OrganizationModelSales,
67
- OrganizationModelProspecting,
68
- OrganizationModelProjects,
69
168
  OrganizationModelCustomerFirmographics,
70
169
  OrganizationModelCustomers,
71
170
  OrganizationModelCustomerSegment,
72
- OrganizationModelFeature,
73
171
  OrganizationModelGoals,
172
+ OrganizationModelNavigation,
173
+ OrganizationModelSidebar,
174
+ OrganizationModelSidebarGroupNode,
175
+ OrganizationModelSidebarNode,
176
+ OrganizationModelSidebarSection,
177
+ OrganizationModelSidebarSurfaceNode,
178
+ OrganizationModelSidebarSurfaceTargets,
74
179
  OrganizationModelKeyResult,
75
180
  OrganizationModelObjective,
181
+ OrganizationModelSystemEntry,
182
+ OrganizationModelSystemId,
183
+ OrganizationModelSystemKind,
184
+ OrganizationModelSystemLifecycle,
185
+ OrganizationModelSystems,
186
+ OrganizationModelSystemStatus,
187
+ OrganizationModelAgentKind,
188
+ OrganizationModelAgentResourceEntry,
189
+ EventDescriptor,
190
+ EventEmissionDescriptor,
191
+ EventId,
192
+ OrganizationModelIntegrationResourceEntry,
193
+ OrganizationModelResourceEntry,
194
+ OrganizationModelResourceGovernanceStatus,
195
+ OrganizationModelResourceId,
196
+ OrganizationModelResourceKind,
197
+ OrganizationModelResources,
198
+ OrganizationModelScriptResourceEntry,
199
+ OrganizationModelScriptResourceLanguage,
200
+ OrganizationModelScriptResourceSource,
201
+ OrganizationModelWorkflowResourceEntry,
202
+ OrganizationModelActions,
203
+ OrganizationModelAction,
204
+ OrganizationModelActionId,
205
+ OrganizationModelActionInvocation,
206
+ OrganizationModelActionInvocationKind,
207
+ OrganizationModelActionRef,
208
+ OrganizationModelActionScope,
209
+ Entity,
210
+ EntityId,
211
+ EntityLink,
212
+ OrganizationModelEntities,
213
+ OrganizationModelEntity,
214
+ OrganizationModelPolicies,
215
+ OrganizationModelPolicy,
216
+ OrganizationModelPolicyEffect,
217
+ OrganizationModelPolicyApplicability,
218
+ OrganizationModelPolicyId,
219
+ OrganizationModelPolicyPredicate,
220
+ OrganizationModelPolicyTrigger,
76
221
  OrganizationModelOfferings,
77
- OrganizationModelOperationEntry,
78
- OrganizationModelOperationSemanticClass,
79
- OrganizationModelOperations,
80
222
  OrganizationModelPricingModel,
81
223
  OrganizationModelProduct,
82
224
  OrganizationModelRole,
225
+ OrganizationModelAgentRoleHolder,
226
+ OrganizationModelHumanRoleHolder,
227
+ OrganizationModelRoleHolder,
228
+ OrganizationModelRoleId,
83
229
  OrganizationModelTechStackEntry,
230
+ OrganizationModelTeamRoleHolder,
84
231
  OrganizationModelRoles,
85
232
  OrganizationModelStatuses,
86
233
  OrganizationModelStatusEntry,
@@ -89,11 +236,17 @@ export type {
89
236
  NodeIdString,
90
237
  OrganizationModelKnowledge,
91
238
  OrgKnowledgeNode,
239
+ OrgKnowledgeNodeInput,
92
240
  OrgKnowledgeKind,
93
241
  OrganizationModelIconToken,
94
- OrganizationModelBuiltinIconToken
242
+ OrganizationModelBuiltinIconToken,
243
+ OrganizationModelDomainKey,
244
+ OrganizationModelDomainMetadata,
245
+ OrganizationModelDomainMetadataByDomain
95
246
  } from './types'
96
247
 
248
+ export type { LeadGenStageCatalogEntry } from './catalogs/lead-gen'
249
+
97
250
  export type {
98
251
  FoundationBranding,
99
252
  FoundationNavigationSurface,
@@ -1,54 +1,117 @@
1
- import { DEFAULT_ORGANIZATION_MODEL } from './defaults'
2
- import { OrganizationModelSchema } from './schema'
3
- import type { DeepPartial, OrganizationModel } from './types'
4
-
5
- function isPlainObject(value: unknown): value is Record<string, unknown> {
6
- return typeof value === 'object' && value !== null && !Array.isArray(value)
7
- }
8
-
9
- function deepMerge<T>(base: T, override: DeepPartial<T> | undefined): T {
10
- if (override === undefined) {
11
- return base
12
- }
13
-
14
- if (Array.isArray(base)) {
15
- return (override as T) ?? base
16
- }
17
-
18
- if (!isPlainObject(base) || !isPlainObject(override)) {
19
- return (override as T) ?? base
20
- }
21
-
22
- const result: Record<string, unknown> = { ...base }
23
-
24
- for (const [key, value] of Object.entries(override)) {
25
- if (value === undefined) continue
26
-
27
- const existing = result[key]
28
- result[key] = isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value
29
- }
30
-
31
- return result as T
32
- }
33
-
34
- export function defineOrganizationModel<T extends DeepPartial<OrganizationModel>>(model: T): T {
35
- return model
36
- }
37
-
38
- export function resolveOrganizationModel(
39
- override?: DeepPartial<OrganizationModel>,
40
- organizationId?: string
41
- ): OrganizationModel {
42
- const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override)
43
- const model = OrganizationModelSchema.parse(merged)
44
-
45
- if (!model.sales?.pipelines || model.sales.pipelines.length === 0) {
46
- const orgLabel = organizationId ? `Organization ${organizationId}` : 'Organization'
47
- throw new Error(
48
- `${orgLabel} has no sales pipeline configuration. ` +
49
- `This indicates an incomplete provisioning state. Run org provisioning to seed defaults.`
50
- )
51
- }
52
-
53
- return model
54
- }
1
+ import { DEFAULT_ORGANIZATION_MODEL } from './defaults'
2
+ import { listAllSystems } from './helpers'
3
+ import { OrganizationModelSchema } from './schema'
4
+ import type { DeepPartial, OrganizationModel, OrganizationModelSystemEntry } from './types'
5
+ import type { ResourceEntry } from './domains/resources'
6
+
7
+ /**
8
+ * A system entry enriched with the list of resources that directly attach to
9
+ * this system (i.e. `resource.systemPath` exactly matches the system's path).
10
+ *
11
+ * Descendant rollup is NOT included here — callers that need it should use
12
+ * `getResourcesForSystem(model, path, { includeDescendants: true })` from helpers.
13
+ */
14
+ export type ResolvedSystemEntry = OrganizationModelSystemEntry & {
15
+ /** Resources whose `systemPath` exactly matches this system's path. */
16
+ resources?: ResourceEntry[]
17
+ }
18
+
19
+ /**
20
+ * An `OrganizationModel` where every flat-system entry in `systems` has been
21
+ * enriched with its directly-attached `resources`.
22
+ *
23
+ * Produced by `resolveOrganizationModelWithResources`. The flat `systems` map
24
+ * only covers top-level keys (same shape as `OrganizationModel.systems`);
25
+ * hierarchical walk uses `listAllSystems` from helpers.
26
+ */
27
+ export type ResolvedOrganizationModel = Omit<OrganizationModel, 'systems'> & {
28
+ systems: Record<string, ResolvedSystemEntry>
29
+ }
30
+
31
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
32
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
33
+ }
34
+
35
+ function deepMerge<T>(base: T, override: DeepPartial<T> | undefined): T {
36
+ if (override === undefined) {
37
+ return base
38
+ }
39
+
40
+ if (Array.isArray(base)) {
41
+ return (override as T) ?? base
42
+ }
43
+
44
+ if (!isPlainObject(base) || !isPlainObject(override)) {
45
+ return (override as T) ?? base
46
+ }
47
+
48
+ const result: Record<string, unknown> = { ...base }
49
+
50
+ for (const [key, value] of Object.entries(override)) {
51
+ if (value === undefined) continue
52
+
53
+ const existing = result[key]
54
+ result[key] = isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value
55
+ }
56
+
57
+ return result as T
58
+ }
59
+
60
+ export function defineOrganizationModel<T extends DeepPartial<OrganizationModel>>(model: T): T {
61
+ return model
62
+ }
63
+
64
+ export function resolveOrganizationModel(
65
+ override?: DeepPartial<OrganizationModel>,
66
+ organizationId?: string
67
+ ): OrganizationModel {
68
+ void organizationId
69
+ const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override)
70
+ // Phase 4: compound-domain sanity gate for model.sales?.pipelines removed.
71
+ // Pipeline data now lives in system.content; use getAllPipelines(model) from
72
+ // migration-helpers to check pipeline presence when needed.
73
+ return OrganizationModelSchema.parse(merged)
74
+ }
75
+
76
+ /**
77
+ * Resolve the organization model and enrich each flat system entry in
78
+ * `model.systems` with the list of resources whose `systemPath` exactly
79
+ * matches that system's flat key.
80
+ *
81
+ * This is a pure additive view — no schema is changed. Descendant resource
82
+ * rollup is intentionally excluded; consumers that need it can call
83
+ * `getResourcesForSystem(model, path, { includeDescendants: true })`.
84
+ *
85
+ * @example
86
+ * const resolved = resolveOrganizationModelWithResources(override)
87
+ * resolved.systems['sys.lead-gen']?.resources
88
+ * // → ResourceEntry[] | undefined
89
+ */
90
+ export function resolveOrganizationModelWithResources(
91
+ override?: DeepPartial<OrganizationModel>,
92
+ organizationId?: string
93
+ ): ResolvedOrganizationModel {
94
+ const model = resolveOrganizationModel(override, organizationId)
95
+
96
+ // Build a path → resource[] index from the flat resources map.
97
+ // Only direct system-path matches (no descendant rollup).
98
+ const byPath = new Map<string, ResourceEntry[]>()
99
+ for (const resource of Object.values(model.resources ?? {})) {
100
+ const existing = byPath.get(resource.systemPath)
101
+ if (existing) {
102
+ existing.push(resource)
103
+ } else {
104
+ byPath.set(resource.systemPath, [resource])
105
+ }
106
+ }
107
+
108
+ // Enrich every system entry, including nested subsystems, with directly
109
+ // attached resources keyed by computed system path.
110
+ const enrichedSystems: Record<string, ResolvedSystemEntry> = {}
111
+ for (const { path, system } of listAllSystems(model)) {
112
+ const resources = byPath.get(path) ?? byPath.get(system.id)
113
+ enrichedSystems[path] = resources !== undefined ? { ...system, id: path, resources } : { ...system, id: path }
114
+ }
115
+
116
+ return { ...model, systems: enrichedSystems }
117
+ }