@elevasis/core 0.22.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 (112) hide show
  1. package/dist/index.d.ts +2330 -2391
  2. package/dist/index.js +2322 -1147
  3. package/dist/knowledge/index.d.ts +702 -1136
  4. package/dist/knowledge/index.js +9 -9
  5. package/dist/organization-model/index.d.ts +2330 -2391
  6. package/dist/organization-model/index.js +2322 -1147
  7. package/dist/test-utils/index.d.ts +703 -1106
  8. package/dist/test-utils/index.js +1735 -1089
  9. package/package.json +1 -1
  10. package/src/__tests__/template-core-compatibility.test.ts +11 -79
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +360 -98
  12. package/src/business/acquisition/api-schemas.test.ts +2 -2
  13. package/src/business/acquisition/api-schemas.ts +7 -9
  14. package/src/business/acquisition/build-templates.test.ts +4 -4
  15. package/src/business/acquisition/build-templates.ts +72 -30
  16. package/src/business/acquisition/crm-state-actions.test.ts +13 -11
  17. package/src/business/acquisition/types.ts +7 -3
  18. package/src/execution/engine/agent/core/types.ts +1 -1
  19. package/src/execution/engine/workflow/types.ts +2 -2
  20. package/src/knowledge/README.md +8 -7
  21. package/src/knowledge/__tests__/queries.test.ts +74 -73
  22. package/src/knowledge/format.ts +10 -9
  23. package/src/knowledge/index.ts +1 -1
  24. package/src/knowledge/published.ts +1 -1
  25. package/src/knowledge/queries.ts +26 -25
  26. package/src/organization-model/README.md +66 -26
  27. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  28. package/src/organization-model/__tests__/defaults.test.ts +72 -98
  29. package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
  30. package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
  31. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  32. package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
  33. package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
  34. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
  35. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
  36. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  37. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
  38. package/src/organization-model/__tests__/domains/resources.test.ts +159 -37
  39. package/src/organization-model/__tests__/domains/roles.test.ts +147 -86
  40. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
  41. package/src/organization-model/__tests__/domains/systems.test.ts +67 -51
  42. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
  43. package/src/organization-model/__tests__/foundation.test.ts +74 -102
  44. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  45. package/src/organization-model/__tests__/graph.test.ts +899 -71
  46. package/src/organization-model/__tests__/knowledge.test.ts +173 -52
  47. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  48. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  49. package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
  50. package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
  51. package/src/organization-model/__tests__/resolve.test.ts +174 -23
  52. package/src/organization-model/__tests__/schema.test.ts +291 -114
  53. package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
  54. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  55. package/src/organization-model/content-kinds/config.ts +36 -0
  56. package/src/organization-model/content-kinds/index.ts +74 -0
  57. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  58. package/src/organization-model/content-kinds/registry.ts +44 -0
  59. package/src/organization-model/content-kinds/status.ts +71 -0
  60. package/src/organization-model/content-kinds/template.ts +83 -0
  61. package/src/organization-model/content-kinds/types.ts +117 -0
  62. package/src/organization-model/contracts.ts +13 -3
  63. package/src/organization-model/defaults.ts +488 -96
  64. package/src/organization-model/domains/actions.ts +239 -0
  65. package/src/organization-model/domains/customers.ts +78 -75
  66. package/src/organization-model/domains/entities.ts +144 -0
  67. package/src/organization-model/domains/goals.ts +83 -80
  68. package/src/organization-model/domains/knowledge.ts +74 -16
  69. package/src/organization-model/domains/navigation.ts +107 -384
  70. package/src/organization-model/domains/offerings.ts +71 -66
  71. package/src/organization-model/domains/policies.ts +102 -0
  72. package/src/organization-model/domains/projects.ts +14 -48
  73. package/src/organization-model/domains/prospecting.ts +62 -181
  74. package/src/organization-model/domains/resources.ts +81 -24
  75. package/src/organization-model/domains/roles.ts +13 -10
  76. package/src/organization-model/domains/sales.ts +10 -219
  77. package/src/organization-model/domains/shared.ts +57 -57
  78. package/src/organization-model/domains/statuses.ts +339 -130
  79. package/src/organization-model/domains/systems.ts +186 -29
  80. package/src/organization-model/foundation.ts +54 -67
  81. package/src/organization-model/graph/build.ts +682 -54
  82. package/src/organization-model/graph/link.ts +1 -1
  83. package/src/organization-model/graph/schema.ts +24 -9
  84. package/src/organization-model/graph/types.ts +20 -7
  85. package/src/organization-model/helpers.ts +231 -26
  86. package/src/organization-model/index.ts +116 -5
  87. package/src/organization-model/migration-helpers.ts +249 -0
  88. package/src/organization-model/organization-graph.mdx +16 -15
  89. package/src/organization-model/organization-model.mdx +89 -41
  90. package/src/organization-model/published.ts +120 -18
  91. package/src/organization-model/resolve.ts +117 -54
  92. package/src/organization-model/schema.ts +561 -140
  93. package/src/organization-model/surface-projection.ts +116 -122
  94. package/src/organization-model/types.ts +102 -21
  95. package/src/platform/constants/versions.ts +1 -1
  96. package/src/platform/registry/__tests__/command-view.test.ts +6 -8
  97. package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
  98. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
  99. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  100. package/src/platform/registry/__tests__/resource-registry.test.ts +9 -7
  101. package/src/platform/registry/__tests__/validation.test.ts +15 -11
  102. package/src/platform/registry/resource-registry.ts +20 -8
  103. package/src/platform/registry/serialization.ts +7 -7
  104. package/src/platform/registry/types.ts +3 -3
  105. package/src/platform/registry/validation.ts +17 -15
  106. package/src/reference/_generated/contracts.md +362 -99
  107. package/src/reference/glossary.md +18 -18
  108. package/src/supabase/database.types.ts +60 -0
  109. package/src/test-utils/test-utils.test.ts +1 -6
  110. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  111. package/src/organization-model/domains/features.ts +0 -31
  112. package/src/organization-model/domains/operations.ts +0 -85
@@ -1,20 +1,19 @@
1
1
  # Organization Model
2
2
 
3
- The organization model is the published semantic contract that maps a tenant's product shape to flat feature hierarchy, shell navigation, business semantics, and graph bindings.
3
+ The organization model is the published semantic contract that maps a tenant's System hierarchy, shell navigation, business semantics, resource governance, and graph bindings.
4
4
 
5
- Use this module when resolving or validating an organization's contract before wiring UI shells, routing, feature gates, or domain-specific capability checks.
5
+ Use this module when resolving or validating an organization's contract before wiring UI shells, routing, system gates, or domain-specific capability checks.
6
6
 
7
7
  ## Published Exports
8
8
 
9
9
  The public entry point exposes:
10
10
 
11
11
  - `OrganizationModelSchema`
12
- - `FeatureSchema`
13
12
  - `DEFAULT_ORGANIZATION_MODEL`
14
13
  - `defineOrganizationModel`
15
14
  - `resolveOrganizationModel`
16
15
  - `createFoundationOrganizationModel`
17
- - node ID and feature helper types
16
+ - node ID and System helper types
18
17
  - `OrganizationModel` and supporting domain types
19
18
 
20
19
  Import it from the published subpath:
@@ -36,8 +35,8 @@ The model is versioned and currently validates against `version: 1`.
36
35
  Top-level fields:
37
36
 
38
37
  - `version`
38
+ - `domainMetadata`
39
39
  - `branding`
40
- - `features`
41
40
  - `navigation`
42
41
  - `sales`
43
42
  - `prospecting`
@@ -49,40 +48,81 @@ Top-level fields:
49
48
  - `goals`
50
49
  - `systems`
51
50
  - `resources`
51
+ - `capabilities`
52
+ - `policies`
52
53
  - `statuses`
53
- - `operations`
54
54
  - `knowledge`
55
55
 
56
- Resource identity is authored in `resources.entries`. Runtime workflows, agents, and integrations import those descriptors, derive `resourceId` and kind from them, and attach executable behavior in operations code.
56
+ The pure collection domains are id-keyed maps: `systems`, `roles`, `goals`, `customers`, `offerings`, `resources`, `capabilities`, `policies`, and `statuses`. The map key must match the entry `id`. Entries carry `order` for deterministic ordered views; use `listDomain(record)` when order matters.
57
57
 
58
- ## Feature Set
58
+ Resource identity is authored in `resources`. Runtime workflows, agents, integrations, and scripts import those descriptors, derive `resourceId` and kind from them, and attach executable behavior in operations code.
59
59
 
60
- Feature hierarchy is authored as a flat array. Dotted IDs define parent/child relationships:
60
+ ## System Set
61
+
62
+ System hierarchy is authored as an id-keyed `systems` map. Dotted IDs and `parentSystemId` define parent/child relationships:
63
+
64
+ ```ts
65
+ systems: {
66
+ dashboard: { id: 'dashboard', order: 10, label: 'Dashboard', lifecycle: 'active' },
67
+ sales: { id: 'sales', order: 20, label: 'Sales', lifecycle: 'active' },
68
+ clients: { id: 'clients', order: 30, label: 'Clients', lifecycle: 'active' },
69
+ projects: { id: 'projects', order: 40, label: 'Projects', lifecycle: 'active' }
70
+ }
71
+ ```
72
+
73
+ Systems describe semantic ownership, hierarchy, lifecycle, access, and governance. Sidebar presentation is authored separately under `navigation.sidebar`; UI-backed Systems may still provide `ui.path` for route matching during the migration, but they do not author composed surface lists. Lifecycle values such as `active`, `beta`, `deprecated`, and `archived` replace the old feature enabled/dev-only split.
74
+
75
+ ## Sidebar Navigation
76
+
77
+ Shell navigation is authored as a recursive sidebar tree:
61
78
 
62
79
  ```ts
63
- features: [
64
- { id: 'dashboard', label: 'Dashboard', enabled: true, path: '/', uiPosition: 'sidebar-primary' },
65
- { id: 'sales', label: 'Sales', enabled: true, uiPosition: 'sidebar-primary' },
66
- { id: 'sales.crm', label: 'CRM', enabled: true, path: '/crm' },
67
- { id: 'operations.resources', label: 'Resources', enabled: true, path: '/operations/resources' }
68
- ]
80
+ navigation: {
81
+ sidebar: {
82
+ primary: {
83
+ dashboard: {
84
+ type: 'surface',
85
+ order: 10,
86
+ label: 'Dashboard',
87
+ path: '/',
88
+ surfaceType: 'dashboard',
89
+ targets: { systems: ['dashboard'] }
90
+ },
91
+ business: {
92
+ type: 'group',
93
+ order: 20,
94
+ label: 'Business',
95
+ children: {
96
+ clients: {
97
+ type: 'surface',
98
+ order: 20,
99
+ label: 'Clients',
100
+ path: '/clients',
101
+ surfaceType: 'list',
102
+ targets: { systems: ['clients'] }
103
+ }
104
+ }
105
+ }
106
+ },
107
+ bottom: {}
108
+ }
109
+ }
69
110
  ```
70
111
 
71
- Containers omit `path`; leaves provide `path`. `uiPosition`, `requiresAdmin`, and `devOnly` inherit from ancestors.
72
- Development-only features remain in the contract with `enabled: true` and `devOnly: true`; shell consumers hide them and guard their paths outside development mode.
112
+ Routeable sidebar leaves are projected into flat semantic surface DTOs by `projectOrganizationSurfaces(model)`. Do not author top-level `surfaces` or `navigationGroups` fields on `OrganizationModel`.
73
113
 
74
114
  ## Graph IDs
75
115
 
76
116
  Cross-collection links use kind-prefixed IDs:
77
117
 
78
- - `feature:sales.crm`
118
+ - `system:sales.crm`
79
119
  - `integration:instantly`
80
120
  - `resource:lead-import`
81
- - `capability:operations.queue.review`
121
+ - `action:operations.queue.review`
82
122
 
83
123
  ## Resource Descriptors
84
124
 
85
- The OM Resources domain is governance-only. Descriptors declare canonical `id`, required `systemId`, governance `status`, and optional role ownership. `DeploymentSpec` remains the runtime/deploy assembly around those descriptors, not a second resource identity catalog.
125
+ The OM Resources domain is governance-only. Descriptors declare canonical `id`, required `systemPath`, governance `status`, and optional role ownership. `DeploymentSpec` remains the runtime/deploy assembly around those descriptors, not a second resource identity catalog.
86
126
 
87
127
  ## Resolution Semantics
88
128
 
@@ -90,20 +130,20 @@ The OM Resources domain is governance-only. Descriptors declare canonical `id`,
90
130
  - `resolveOrganizationModel()` deep-merges a partial override into the default model, then validates it.
91
131
  - `createFoundationOrganizationModel()` resolves the canonical model and returns UI-facing helper outputs.
92
132
  - Plain objects merge recursively.
133
+ - Id-keyed domain maps merge additively by key.
93
134
  - Arrays replace the default value.
94
135
  - Missing fields fall back to `DEFAULT_ORGANIZATION_MODEL`.
95
136
 
96
137
  ## Referential Integrity
97
138
 
98
- - Feature IDs must be unique.
99
- - Child feature IDs require ancestor feature nodes.
100
- - Container features omit `path`.
101
- - Leaf features provide `path`.
139
+ - System IDs must be unique.
140
+ - Child System IDs require valid ancestors or `parentSystemId` links.
141
+ - Systems with UI provide `ui.path`.
102
142
  - Systems, resources, roles, knowledge nodes, and goals must resolve their declared cross-references.
103
143
 
104
144
  ## Practical Guidance
105
145
 
106
146
  - Use `resolveOrganizationModel()` when you need a runtime-safe model.
107
147
  - Use `defineOrganizationModel()` when authoring static overrides.
108
- - Keep feature IDs stable because shell routing, gating, breadcrumbs, and docs depend on them.
109
- - Put resource identity and governance in `resources.entries`; attach executable behavior in operations.
148
+ - Keep System IDs stable because shell routing, gating, breadcrumbs, and docs depend on them.
149
+ - Put resource identity and governance in `resources`; attach executable behavior in operations.
@@ -0,0 +1,210 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ CONTENT_KIND_REGISTRY,
4
+ defineContentType,
5
+ lookupContentType,
6
+ pipelineKind,
7
+ stageKind,
8
+ templateKind,
9
+ templateStepKind,
10
+ statusFlowKind,
11
+ statusKind,
12
+ configKvKind
13
+ } from '../content-kinds/index'
14
+ import type { ContentTypeDefinition, ContentTypeKey } from '../content-kinds/types'
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // CONTENT_KIND_REGISTRY shape (D8: static object literal)
18
+ // ---------------------------------------------------------------------------
19
+
20
+ describe('CONTENT_KIND_REGISTRY', () => {
21
+ it('contains all 7 expected keys', () => {
22
+ const expectedKeys: ContentTypeKey[] = [
23
+ 'schema:pipeline',
24
+ 'schema:stage',
25
+ 'schema:template',
26
+ 'schema:template-step',
27
+ 'schema:status-flow',
28
+ 'schema:status',
29
+ 'config:kv'
30
+ ]
31
+ for (const key of expectedKeys) {
32
+ expect(CONTENT_KIND_REGISTRY).toHaveProperty(key)
33
+ }
34
+ })
35
+
36
+ it('maps schema:pipeline to the pipelineKind definition', () => {
37
+ expect(CONTENT_KIND_REGISTRY['schema:pipeline']).toBe(pipelineKind)
38
+ })
39
+
40
+ it('maps schema:stage to the stageKind definition', () => {
41
+ expect(CONTENT_KIND_REGISTRY['schema:stage']).toBe(stageKind)
42
+ })
43
+
44
+ it('maps schema:template to the templateKind definition', () => {
45
+ expect(CONTENT_KIND_REGISTRY['schema:template']).toBe(templateKind)
46
+ })
47
+
48
+ it('maps schema:template-step to the templateStepKind definition', () => {
49
+ expect(CONTENT_KIND_REGISTRY['schema:template-step']).toBe(templateStepKind)
50
+ })
51
+
52
+ it('maps schema:status-flow to the statusFlowKind definition', () => {
53
+ expect(CONTENT_KIND_REGISTRY['schema:status-flow']).toBe(statusFlowKind)
54
+ })
55
+
56
+ it('maps schema:status to the statusKind definition', () => {
57
+ expect(CONTENT_KIND_REGISTRY['schema:status']).toBe(statusKind)
58
+ })
59
+
60
+ it('maps config:kv to the configKvKind definition', () => {
61
+ expect(CONTENT_KIND_REGISTRY['config:kv']).toBe(configKvKind)
62
+ })
63
+
64
+ it('has exactly 7 keys (no extra unintended entries)', () => {
65
+ expect(Object.keys(CONTENT_KIND_REGISTRY)).toHaveLength(7)
66
+ })
67
+
68
+ it('every entry has kind, type, payloadSchema, label, and description fields', () => {
69
+ for (const [key, def] of Object.entries(CONTENT_KIND_REGISTRY)) {
70
+ expect(def).toHaveProperty('kind')
71
+ expect(def).toHaveProperty('type')
72
+ expect(def).toHaveProperty('payloadSchema')
73
+ expect(typeof def.kind).toBe('string')
74
+ expect(typeof def.type).toBe('string')
75
+ expect(def.label).toBeTruthy()
76
+ expect(def.description).toBeTruthy()
77
+ // key must equal kind:type
78
+ expect(key).toBe(`${def.kind}:${def.type}`)
79
+ }
80
+ })
81
+ })
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // parentTypes constraint
85
+ // ---------------------------------------------------------------------------
86
+
87
+ describe('parentTypes constraints', () => {
88
+ it('schema:pipeline has empty parentTypes (top-level, no parent required)', () => {
89
+ expect(pipelineKind.parentTypes).toEqual([])
90
+ })
91
+
92
+ it('schema:stage parentTypes is ["schema:pipeline"]', () => {
93
+ expect(stageKind.parentTypes).toEqual(['schema:pipeline'])
94
+ })
95
+
96
+ it('schema:template has empty parentTypes', () => {
97
+ expect(templateKind.parentTypes).toEqual([])
98
+ })
99
+
100
+ it('schema:template-step parentTypes is ["schema:template"]', () => {
101
+ expect(templateStepKind.parentTypes).toEqual(['schema:template'])
102
+ })
103
+
104
+ it('schema:status-flow has empty parentTypes', () => {
105
+ expect(statusFlowKind.parentTypes).toEqual([])
106
+ })
107
+
108
+ it('schema:status parentTypes is ["schema:status-flow"]', () => {
109
+ expect(statusKind.parentTypes).toEqual(['schema:status-flow'])
110
+ })
111
+
112
+ it('config:kv has empty parentTypes', () => {
113
+ expect(configKvKind.parentTypes).toEqual([])
114
+ })
115
+ })
116
+
117
+ // ---------------------------------------------------------------------------
118
+ // lookupContentType
119
+ // ---------------------------------------------------------------------------
120
+
121
+ describe('lookupContentType', () => {
122
+ it('returns the correct definition for schema:pipeline', () => {
123
+ const def = lookupContentType('schema', 'pipeline')
124
+ expect(def).toBe(pipelineKind)
125
+ })
126
+
127
+ it('returns the correct definition for schema:stage', () => {
128
+ const def = lookupContentType('schema', 'stage')
129
+ expect(def).toBe(stageKind)
130
+ })
131
+
132
+ it('returns the correct definition for config:kv', () => {
133
+ const def = lookupContentType('config', 'kv')
134
+ expect(def).toBe(configKvKind)
135
+ })
136
+
137
+ it('returns undefined for an unregistered kind (D2: not an error)', () => {
138
+ const def = lookupContentType('tenant', 'custom-thing')
139
+ expect(def).toBeUndefined()
140
+ })
141
+
142
+ it('returns undefined for unknown kind with valid type', () => {
143
+ const def = lookupContentType('unknown', 'pipeline')
144
+ expect(def).toBeUndefined()
145
+ })
146
+
147
+ it('returns undefined for valid kind with unknown type', () => {
148
+ const def = lookupContentType('schema', 'not-a-real-type')
149
+ expect(def).toBeUndefined()
150
+ })
151
+
152
+ it('returns undefined for empty kind string', () => {
153
+ const def = lookupContentType('', 'pipeline')
154
+ expect(def).toBeUndefined()
155
+ })
156
+
157
+ it('returns undefined for empty type string', () => {
158
+ const def = lookupContentType('schema', '')
159
+ expect(def).toBeUndefined()
160
+ })
161
+ })
162
+
163
+ // ---------------------------------------------------------------------------
164
+ // defineContentType (identity factory, L16)
165
+ // ---------------------------------------------------------------------------
166
+
167
+ describe('defineContentType', () => {
168
+ it('is an identity function — returns the same object reference', () => {
169
+ const def: ContentTypeDefinition<{ name: string }> = {
170
+ kind: 'tenant',
171
+ type: 'custom',
172
+ payloadSchema: { safeParse: () => ({ success: true, data: { name: 'x' } }) } as unknown as ContentTypeDefinition<{
173
+ name: string
174
+ }>['payloadSchema'],
175
+ label: 'Custom',
176
+ description: 'A tenant-defined type.',
177
+ parentTypes: []
178
+ }
179
+ const result = defineContentType(def)
180
+ expect(result).toBe(def)
181
+ })
182
+
183
+ it('does NOT mutate the input definition', () => {
184
+ const def: ContentTypeDefinition<unknown> = {
185
+ kind: 'schema',
186
+ type: 'pipeline',
187
+ payloadSchema: {
188
+ safeParse: () => ({ success: true, data: {} })
189
+ } as unknown as ContentTypeDefinition<unknown>['payloadSchema'],
190
+ parentTypes: []
191
+ }
192
+ const original = { ...def }
193
+ defineContentType(def)
194
+ expect(def).toEqual(original)
195
+ })
196
+
197
+ it('does NOT register the definition globally (no side-effects on CONTENT_KIND_REGISTRY)', () => {
198
+ const tenantKey = 'tenant:my-new-type'
199
+ defineContentType({
200
+ kind: 'tenant',
201
+ type: 'my-new-type',
202
+ payloadSchema: {
203
+ safeParse: () => ({ success: true, data: {} })
204
+ } as unknown as ContentTypeDefinition<unknown>['payloadSchema'],
205
+ parentTypes: []
206
+ })
207
+ // After calling defineContentType, the registry must remain unchanged (D8: static)
208
+ expect(CONTENT_KIND_REGISTRY).not.toHaveProperty(tenantKey)
209
+ })
210
+ })
@@ -1,26 +1,22 @@
1
1
  import { describe, expect, it } from 'vitest'
2
2
  import { DEFAULT_ORGANIZATION_MODEL } from '../defaults'
3
- import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from '../domains/branding'
4
- import { OrganizationModelBrandingSchema } from '../domains/branding'
5
- import { DEFAULT_ORGANIZATION_MODEL_SALES } from '../domains/sales'
6
- import { OrganizationModelSalesSchema } from '../domains/sales'
7
- import { DEFAULT_ORGANIZATION_MODEL_PROJECTS } from '../domains/projects'
8
- import { OrganizationModelProjectsSchema } from '../domains/projects'
9
- import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from '../domains/prospecting'
10
- import { OrganizationModelProspectingSchema } from '../domains/prospecting'
11
- import { DEFAULT_ORGANIZATION_MODEL_NAVIGATION } from '../domains/navigation'
12
- import { OrganizationModelNavigationSchema } from '../domains/navigation'
13
- import { DEFAULT_ORGANIZATION_MODEL_OPERATIONS } from '../domains/operations'
14
- import { OperationsDomainSchema } from '../domains/operations'
15
- import { DEFAULT_ORGANIZATION_MODEL_STATUSES } from '../domains/statuses'
16
- import { StatusesDomainSchema } from '../domains/statuses'
3
+ import { DEFAULT_ORGANIZATION_MODEL_BRANDING, OrganizationModelBrandingSchema } from '../domains/branding'
4
+ import { DEFAULT_ORGANIZATION_MODEL_ENTITIES, EntitiesDomainSchema } from '../domains/entities'
5
+ import { DEFAULT_ORGANIZATION_MODEL_STATUSES, StatusesDomainSchema } from '../domains/statuses'
17
6
  import { DEFAULT_ORGANIZATION_MODEL_SYSTEMS, SystemsDomainSchema } from '../domains/systems'
18
7
  import { resolveOrganizationModel } from '../resolve'
19
8
  import { OrganizationModelSchema } from '../schema'
9
+ import { DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE } from '../defaults'
20
10
 
21
- // All DEFAULT_ORGANIZATION_MODEL* constants and the schemas used to validate them.
22
- // The composite constant lives in defaults.ts; domain sub-constants live in their
23
- // respective domain files. All are covered here for roundtrip integrity.
11
+ // Phase 4 (D8): sales, prospecting, projects, navigation top-level OM fields removed.
12
+ // DEFAULT_ORGANIZATION_MODEL_SALES / OrganizationModelSalesSchema,
13
+ // DEFAULT_ORGANIZATION_MODEL_PROJECTS / OrganizationModelProjectsSchema,
14
+ // DEFAULT_ORGANIZATION_MODEL_PROSPECTING / OrganizationModelProspectingSchema,
15
+ // DEFAULT_ORGANIZATION_MODEL_NAVIGATION / OrganizationModelNavigationSchema
16
+ // are no longer exported from their respective domain files.
17
+ // Tests that depended on these exports are skipped with explicit reason comments.
18
+
19
+ // Only the domain constants and schemas that still exist are covered here.
24
20
  const domainCases = [
25
21
  {
26
22
  name: 'DEFAULT_ORGANIZATION_MODEL_BRANDING',
@@ -28,35 +24,15 @@ const domainCases = [
28
24
  schema: OrganizationModelBrandingSchema
29
25
  },
30
26
  {
31
- name: 'DEFAULT_ORGANIZATION_MODEL_SALES',
32
- constant: DEFAULT_ORGANIZATION_MODEL_SALES,
33
- schema: OrganizationModelSalesSchema
34
- },
35
- {
36
- name: 'DEFAULT_ORGANIZATION_MODEL_PROJECTS',
37
- constant: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
38
- schema: OrganizationModelProjectsSchema
39
- },
40
- {
41
- name: 'DEFAULT_ORGANIZATION_MODEL_PROSPECTING',
42
- constant: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
43
- schema: OrganizationModelProspectingSchema
44
- },
45
- {
46
- name: 'DEFAULT_ORGANIZATION_MODEL_NAVIGATION',
47
- constant: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
48
- schema: OrganizationModelNavigationSchema
27
+ name: 'DEFAULT_ORGANIZATION_MODEL_ENTITIES',
28
+ constant: DEFAULT_ORGANIZATION_MODEL_ENTITIES,
29
+ schema: EntitiesDomainSchema
49
30
  },
50
31
  {
51
32
  name: 'DEFAULT_ORGANIZATION_MODEL_STATUSES',
52
33
  constant: DEFAULT_ORGANIZATION_MODEL_STATUSES,
53
34
  schema: StatusesDomainSchema
54
35
  },
55
- {
56
- name: 'DEFAULT_ORGANIZATION_MODEL_OPERATIONS',
57
- constant: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
58
- schema: OperationsDomainSchema
59
- },
60
36
  {
61
37
  name: 'DEFAULT_ORGANIZATION_MODEL_SYSTEMS',
62
38
  constant: DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
@@ -81,17 +57,14 @@ describe('organization-model defaults', () => {
81
57
  expect(fromDefault).toEqual(fromUndefined)
82
58
  })
83
59
 
84
- it('keeps Command View enabled but development-only in the default Knowledge navigation', () => {
85
- const result = resolveOrganizationModel(undefined)
86
- const commandViewFeature = result.features.find((feature) => feature.id === 'knowledge.command-view')
87
- const commandViewSurface = DEFAULT_ORGANIZATION_MODEL_NAVIGATION.surfaces.find(
88
- (surface) => surface.id === 'knowledge.command-view'
89
- )
90
-
91
- expect(commandViewFeature?.enabled).toBe(true)
92
- expect(commandViewFeature?.devOnly).toBe(true)
93
- expect(commandViewSurface?.enabled).toBe(true)
94
- expect(commandViewSurface?.devOnly).toBe(true)
60
+ // Phase 4 (D8): model.navigation removed. The knowledge.command-view surface tracking
61
+ // previously used DEFAULT_ORGANIZATION_MODEL_NAVIGATION.surfaces — skipped since that
62
+ // constant is deleted. The system itself still exists; only the navigation surface
63
+ // reference is gone from the top-level schema.
64
+ it.skip('keeps Command View enabled but development-only in the default Knowledge navigation (deferred — Phase 4: navigation domain removed)', () => {
65
+ // Previously checked DEFAULT_ORGANIZATION_MODEL_NAVIGATION.surfaces.
66
+ // The command-view system still exists in DEFAULT_ORGANIZATION_MODEL.systems.
67
+ // Re-enable with a top-level surfaces Record fixture if that assertion is needed.
95
68
  })
96
69
  })
97
70
 
@@ -101,84 +74,71 @@ describe('organization-model defaults', () => {
101
74
  })
102
75
  })
103
76
 
104
- describe('DEFAULT_ORGANIZATION_MODEL_BRANDING via resolveOrganizationModel', () => {
105
- it('resolving with branding override produces a schema-valid model', () => {
106
- const result = resolveOrganizationModel({ branding: DEFAULT_ORGANIZATION_MODEL_BRANDING })
107
- expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
108
- })
109
- })
110
-
111
- describe('DEFAULT_ORGANIZATION_MODEL_SALES via resolveOrganizationModel', () => {
77
+ // Phase 4 (D8): OrganizationModelSalesSchema, DEFAULT_ORGANIZATION_MODEL_SALES removed.
78
+ describe.skip('DEFAULT_ORGANIZATION_MODEL_SALES via resolveOrganizationModel (deferred Phase 4: sales domain removed)', () => {
112
79
  it('resolving with sales override produces a schema-valid model', () => {
113
- const result = resolveOrganizationModel({ sales: DEFAULT_ORGANIZATION_MODEL_SALES })
114
- expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
80
+ // Previously: resolveOrganizationModel({ sales: DEFAULT_ORGANIZATION_MODEL_SALES })
81
+ // Sales data now lives in system.content. Use getAllPipelines(model) from migration-helpers.
115
82
  })
116
83
  })
117
84
 
118
- describe('DEFAULT_ORGANIZATION_MODEL_PROJECTS via resolveOrganizationModel', () => {
85
+ // Phase 4 (D8): OrganizationModelProjectsSchema, DEFAULT_ORGANIZATION_MODEL_PROJECTS removed.
86
+ describe.skip('DEFAULT_ORGANIZATION_MODEL_PROJECTS via resolveOrganizationModel (deferred — Phase 4: projects domain removed)', () => {
119
87
  it('resolving with projects override produces a schema-valid model', () => {
120
- const result = resolveOrganizationModel({ projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS })
121
- expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
88
+ // Previously: resolveOrganizationModel({ projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS })
89
+ // Project statuses now live in system.content. Use getAllProjectStatuses(model) from migration-helpers.
122
90
  })
123
91
  })
124
92
 
125
- describe('DEFAULT_ORGANIZATION_MODEL_PROSPECTING via resolveOrganizationModel', () => {
93
+ // Phase 4 (D8): OrganizationModelProspectingSchema, DEFAULT_ORGANIZATION_MODEL_PROSPECTING removed.
94
+ describe.skip('DEFAULT_ORGANIZATION_MODEL_PROSPECTING via resolveOrganizationModel (deferred — Phase 4: prospecting domain removed)', () => {
126
95
  it('resolving with prospecting override produces a schema-valid model', () => {
127
- const result = resolveOrganizationModel({ prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING })
128
- expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
96
+ // Previously: resolveOrganizationModel({ prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING })
97
+ // Prospecting stages/templates now live in system.content. Use getAllProspectingStages() / getAllBuildTemplates().
129
98
  })
130
99
  })
131
100
 
132
- describe('DEFAULT_ORGANIZATION_MODEL_NAVIGATION via resolveOrganizationModel', () => {
101
+ // Phase 4 (D8): OrganizationModelNavigationSchema, DEFAULT_ORGANIZATION_MODEL_NAVIGATION removed.
102
+ describe.skip('DEFAULT_ORGANIZATION_MODEL_NAVIGATION via resolveOrganizationModel (deferred — Phase 4: navigation domain removed)', () => {
133
103
  it('resolving with navigation override produces a schema-valid model', () => {
134
- const result = resolveOrganizationModel({ navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION })
135
- expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
104
+ // Previously: resolveOrganizationModel({ navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION })
105
+ // Surfaces and navigation groups are now top-level Records on OrganizationModelSchemaBase.
136
106
  })
137
107
  })
138
108
 
139
- describe('DEFAULT_ORGANIZATION_MODEL_OPERATIONS via resolveOrganizationModel', () => {
140
- it('resolving with operations override produces a schema-valid model', () => {
141
- const result = resolveOrganizationModel({ operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS })
109
+ describe('DEFAULT_ORGANIZATION_MODEL_BRANDING via resolveOrganizationModel', () => {
110
+ it('resolving with branding override produces a schema-valid model', () => {
111
+ const result = resolveOrganizationModel({ branding: DEFAULT_ORGANIZATION_MODEL_BRANDING })
142
112
  expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
143
113
  })
144
-
145
- it('default operations seed covers all 5 entity categories', () => {
146
- expect(DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries).toHaveLength(5)
147
- })
148
-
149
- it('every entry has a non-empty id, label, and semanticClass', () => {
150
- for (const entry of DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries) {
151
- expect(entry.id.length).toBeGreaterThan(0)
152
- expect(entry.label.length).toBeGreaterThan(0)
153
- expect(entry.semanticClass.length).toBeGreaterThan(0)
154
- }
155
- })
156
-
157
- it('all entry ids are unique', () => {
158
- const ids = DEFAULT_ORGANIZATION_MODEL_OPERATIONS.entries.map((e) => e.id)
159
- const uniqueIds = new Set(ids)
160
- expect(uniqueIds.size).toBe(ids.length)
161
- })
162
114
  })
163
115
 
164
116
  describe('DEFAULT_ORGANIZATION_MODEL_STATUSES via resolveOrganizationModel', () => {
165
- it('resolving with statuses override produces a schema-valid model', () => {
166
- const result = resolveOrganizationModel({ statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES })
167
- expect(() => OrganizationModelSchema.parse(result)).not.toThrow()
117
+ // Phase 4 (D1): statuses top-level field removed from OM schema.
118
+ // DEFAULT_ORGANIZATION_MODEL_STATUSES is still exported from domains/statuses.ts
119
+ // (it's used by the UI statuses domain as a semantic registry, not OM-schema-level data).
120
+ // The resolveOrganizationModel override with { statuses: ... } was silently accepted
121
+ // before Phase 4 because statuses was an extra field; now statuses is gone from OM entirely.
122
+ // We keep the data-integrity checks below; the resolveOrganizationModel override test is skipped.
123
+ it.skip('resolving with statuses override produces a schema-valid model (deferred — Phase 4: statuses field removed from OM schema)', () => {
124
+ // Previously: resolveOrganizationModel({ statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES })
125
+ // Status data now lives in system.content via (schema:status-flow) + (schema:status) content nodes.
168
126
  })
169
127
 
170
128
  it('default statuses seed covers all 9 delivery.task values', () => {
171
- const taskEntries = DEFAULT_ORGANIZATION_MODEL_STATUSES.entries.filter((e) => e.semanticClass === 'delivery.task')
129
+ const taskEntries = Object.values(DEFAULT_ORGANIZATION_MODEL_STATUSES).filter(
130
+ (e) => e.semanticClass === 'delivery.task'
131
+ )
172
132
  expect(taskEntries).toHaveLength(9)
173
133
  })
174
134
 
175
135
  it('default statuses seed covers all 5 queue values', () => {
176
- const queueEntries = DEFAULT_ORGANIZATION_MODEL_STATUSES.entries.filter((e) => e.semanticClass === 'queue')
136
+ const queueEntries = Object.values(DEFAULT_ORGANIZATION_MODEL_STATUSES).filter((e) => e.semanticClass === 'queue')
177
137
  expect(queueEntries).toHaveLength(5)
178
138
  })
179
139
 
180
140
  it('every entry has a non-empty id, label, and semanticClass', () => {
181
- for (const entry of DEFAULT_ORGANIZATION_MODEL_STATUSES.entries) {
141
+ for (const entry of Object.values(DEFAULT_ORGANIZATION_MODEL_STATUSES)) {
182
142
  expect(entry.id.length).toBeGreaterThan(0)
183
143
  expect(entry.label.length).toBeGreaterThan(0)
184
144
  expect(entry.semanticClass.length).toBeGreaterThan(0)
@@ -186,9 +146,23 @@ describe('organization-model defaults', () => {
186
146
  })
187
147
 
188
148
  it('all entry ids are unique', () => {
189
- const ids = DEFAULT_ORGANIZATION_MODEL_STATUSES.entries.map((e) => e.id)
149
+ const ids = Object.values(DEFAULT_ORGANIZATION_MODEL_STATUSES).map((e) => e.id)
190
150
  const uniqueIds = new Set(ids)
191
151
  expect(uniqueIds.size).toBe(ids.length)
192
152
  })
193
153
  })
154
+
155
+ describe('DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE — flat Record (Phase 4 D3)', () => {
156
+ it('is an empty object (no pre-seeded nodes in generic base)', () => {
157
+ expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE).toEqual({})
158
+ })
159
+
160
+ it('does not have a .nodes array (old wrapper shape removed)', () => {
161
+ expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE).not.toHaveProperty('nodes')
162
+ })
163
+
164
+ it('does not have a .version field (moved to domainMetadata.knowledge)', () => {
165
+ expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE).not.toHaveProperty('version')
166
+ })
167
+ })
194
168
  })