@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
@@ -0,0 +1,249 @@
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
+
18
+ import type { OrganizationModel } from './types'
19
+ import type { z } from 'zod'
20
+ import type { SalesPipelineSchema, SalesStageSchema } from './domains/sales'
21
+ import type { ProspectingBuildTemplateSchema, ProspectingLifecycleStageSchema } from './domains/prospecting'
22
+ import type { ProjectsDomainStateSchema } from './domains/projects'
23
+ import { listAllSystems } from './helpers'
24
+
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
+ }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Organization Graph
3
- description: Organization OS graph layer documentation for the organization graph derived from flat Organization Model features and resource metadata links.
3
+ description: Organization OS graph layer documentation for the organization graph derived from Organization Model Systems, resources, capabilities, and typed links.
4
4
  ---
5
5
 
6
6
  ## Overview
@@ -24,30 +24,31 @@ Graph contracts live in `@repo/core`; rendering lives in `@repo/ui`.
24
24
  Node kinds:
25
25
 
26
26
  - `organization`
27
- - `feature`
28
- - `surface`
29
- - `entity`
27
+ - `system`
28
+ - `role`
30
29
  - `capability`
31
30
  - `resource`
31
+ - `knowledge`
32
+ - `policy`
32
33
 
33
34
  Edge kinds:
34
35
 
35
36
  - `contains`
36
37
  - `references`
37
- - `exposes`
38
38
  - `maps_to`
39
- - `operates-on`
40
39
  - `uses`
40
+ - `governs`
41
+ - `governed-by`
41
42
 
42
- Feature nodes come from the flat `OrganizationModel.features` array. Their graph IDs use `feature:<id>`, such as `feature:sales.crm`.
43
+ System nodes come from the id-keyed `OrganizationModel.systems` map. Their graph IDs use `system:<id>`, such as `system:sales.crm`.
43
44
 
44
- Resource edges come from resource metadata:
45
+ Resource and capability edges are derived from canonical OM maps:
45
46
 
46
47
  ```ts
47
- links: [
48
- { nodeId: 'feature:sales.lead-gen', kind: 'operates-on' },
49
- { nodeId: 'integration:instantly', kind: 'uses' }
50
- ]
48
+ // ResourceEntry.systemPath => system -> resource contains
49
+ // SystemEntry.capabilities[] => system -> capability uses
50
+ // Capability.resourceId => capability -> resource maps_to
51
+ // AgentResource.invocations[] => agent resource -> invocation target uses/references
51
52
  ```
52
53
 
53
54
  ## Build Pipeline
@@ -61,9 +62,9 @@ interface BuildOrganizationGraphInput {
61
62
 
62
63
  `buildOrganizationGraph`:
63
64
 
64
- 1. Reads flat Organization Model features and derives `feature:*` nodes.
65
- 2. Reads Command View resources, including integration resources, as `resource` nodes with `resourceType` metadata.
66
- 3. Emits authored graph links from resource/entity/capability metadata.
65
+ 1. Reads Organization Model Systems and derives `system:*` nodes.
66
+ 2. Reads OM resources, including workflow, agent, integration, and script resources, as `resource` nodes.
67
+ 3. Emits derived graph links from System, Resource, Capability, Agent invocation, and Knowledge contracts.
67
68
  4. Bridges Command View runtime topology into resource nodes and relationship edges.
68
69
  5. Returns a renderer-agnostic DTO.
69
70
 
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  title: Organization Model
3
- description: Organization OS Model layer documentation for the flat feature hierarchy, semantic domains, resource graph links, and curated @elevasis/core public API.
3
+ description: Organization OS Model layer documentation for the System hierarchy, semantic domains, resource descriptors, and curated @elevasis/core public API.
4
4
  ---
5
5
 
6
6
  ## Overview
7
7
 
8
- The organization model is the semantic contract that maps an organization's product shape to flat feature hierarchy, business semantics, shell navigation, and graph binding. It is schema-first, versioned, and validated.
8
+ The organization model is the semantic contract that maps an organization's System hierarchy, business semantics, shell navigation, resource governance, and graph binding. It is schema-first, versioned, and validated.
9
9
 
10
10
  The model is authored in `@repo/core` and published through the curated `@elevasis/core/organization-model` surface.
11
11
 
@@ -24,7 +24,7 @@ The model is authored in `@repo/core` and published through the curated `@elevas
24
24
  Top-level fields on `OrganizationModel`:
25
25
 
26
26
  - `version`
27
- - `features`
27
+ - `domainMetadata`
28
28
  - `branding`
29
29
  - `navigation`
30
30
  - `sales`
@@ -35,22 +35,28 @@ Top-level fields on `OrganizationModel`:
35
35
  - `offerings`
36
36
  - `roles`
37
37
  - `goals`
38
+ - `systems`
39
+ - `resources`
40
+ - `capabilities`
41
+ - `policies`
38
42
  - `statuses`
39
- - `operations`
43
+ - `knowledge`
40
44
 
41
- Resources are not authored inside `OrganizationModel`. Deployable workflows, agents, triggers, integrations, external resources, and human checkpoints declare graph links on their resource metadata.
45
+ 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.
42
46
 
43
- ## Feature Shape
47
+ Resource identity is authored inside `OrganizationModel.resources`. Runtime workflows, agents, integrations, and scripts import those descriptors, derive `resourceId` and kind from them, and attach executable behavior in operations code.
44
48
 
45
- `OrganizationModel.features` is a flat array. Hierarchy is derived from dotted IDs:
49
+ ## System Shape
50
+
51
+ `OrganizationModel.systems` is the canonical semantic domain map. Hierarchy is derived from `parentSystemId` and dotted IDs:
46
52
 
47
53
  ```ts
48
- features: [
49
- { id: 'dashboard', label: 'Dashboard', enabled: true, path: '/', uiPosition: 'sidebar-primary' },
50
- { id: 'sales', label: 'Sales', enabled: true, uiPosition: 'sidebar-primary' },
51
- { id: 'sales.crm', label: 'CRM', enabled: true, path: '/crm' },
52
- { id: 'operations.resources', label: 'Resources', enabled: true, path: '/operations/resources' }
53
- ]
54
+ systems: {
55
+ dashboard: { id: 'dashboard', order: 10, label: 'Dashboard', lifecycle: 'active' },
56
+ sales: { id: 'sales', order: 20, label: 'Sales', lifecycle: 'active' },
57
+ clients: { id: 'clients', order: 30, label: 'Clients', lifecycle: 'active' },
58
+ projects: { id: 'projects', order: 40, label: 'Projects', lifecycle: 'active' }
59
+ }
54
60
  ```
55
61
 
56
62
  Authored fields:
@@ -58,42 +64,98 @@ Authored fields:
58
64
  - `id`
59
65
  - `label`
60
66
  - `description`
61
- - `enabled`
62
- - `path`
63
- - `icon`
64
- - `color`
65
- - `uiPosition`
67
+ - `kind`
68
+ - `parentSystemId`
69
+ - `ui`
70
+ - `lifecycle`
66
71
  - `requiresAdmin`
67
- - `devOnly`
72
+ - `capabilities`
73
+ - `policies`
74
+ - `order`
75
+
76
+ Systems describe ownership, hierarchy, lifecycle, access, and governance. Sidebar presentation lives in `navigation.sidebar`, not on System entries. UI-backed Systems may still provide `ui.path` for route matching during the migration, but `ui.surfaces` is not an authored contract. `lifecycle` replaces the old feature enabled/dev-only split.
77
+
78
+ ## Navigation Shape
79
+
80
+ `OrganizationModel.navigation.sidebar` is the authored shell tree. It has `primary` and `bottom` sections whose records contain recursive group nodes and routeable surface nodes:
68
81
 
69
- Containers omit `path`; leaves provide `path`. `uiPosition`, `requiresAdmin`, and `devOnly` inherit from ancestors.
70
- Development-only features remain defined and enabled with `devOnly: true`; shell consumers hide those entries and route paths outside development mode while preserving the semantic contract.
82
+ ```ts
83
+ navigation: {
84
+ sidebar: {
85
+ primary: {
86
+ dashboard: {
87
+ type: 'surface',
88
+ order: 10,
89
+ label: 'Dashboard',
90
+ path: '/',
91
+ surfaceType: 'dashboard',
92
+ targets: { systems: ['dashboard'] }
93
+ },
94
+ business: {
95
+ type: 'group',
96
+ order: 20,
97
+ label: 'Business',
98
+ children: {
99
+ sales: {
100
+ type: 'surface',
101
+ order: 10,
102
+ label: 'Sales',
103
+ path: '/sales',
104
+ surfaceType: 'page',
105
+ targets: { systems: ['sales'] }
106
+ },
107
+ clients: {
108
+ type: 'surface',
109
+ order: 20,
110
+ label: 'Clients',
111
+ path: '/clients',
112
+ surfaceType: 'list',
113
+ targets: { systems: ['clients'] }
114
+ }
115
+ }
116
+ }
117
+ },
118
+ bottom: {}
119
+ }
120
+ }
121
+ ```
71
122
 
72
- Navigation surfaces may also carry `devOnly` for compatibility with the legacy/domain navigation model. `knowledge.command-view` is intentionally development-only while its graph visualization modes continue to mature.
123
+ Dashboard is ordered before Business in the primary sidebar. Business is a navigation group only; it is not a System and it is not a URL namespace. Routeable leaves are projected into flat surface DTOs by `projectOrganizationSurfaces(model)`.
73
124
 
74
- ## Graph IDs and Resource Links
125
+ ## Graph IDs and Resource Descriptors
75
126
 
76
127
  Cross-collection links use kind-prefixed graph IDs:
77
128
 
78
- - `feature:sales.crm`
129
+ - `system:sales.crm`
79
130
  - `integration:instantly`
80
131
  - `resource:lead-import`
81
- - `capability:operations.queue.review`
132
+ - `action:operations.queue.review`
82
133
 
83
- Example resource metadata:
134
+ Resource identity is authored in the OM Resources domain. Operations imports descriptors from `organizationModel.resources` and derives runtime `resourceId` / `type` while attaching executable behavior.
84
135
 
85
136
  ```ts
86
- config: {
87
- resourceId: 'lead-import',
88
- name: 'Lead Import',
89
- type: 'workflow',
90
- version: '1.0.0',
91
- status: 'prod',
92
- links: [{ nodeId: 'feature:sales.lead-gen', kind: 'operates-on' }],
93
- category: 'production'
94
- }
137
+ import { defineResources } from '@elevasis/core/organization-model'
138
+
139
+ export const resourceDescriptors = defineResources({
140
+ leadImport: {
141
+ id: 'lead-import',
142
+ kind: 'workflow',
143
+ systemPath: 'sales.lead-gen',
144
+ ownerRoleId: 'role-ops-lead',
145
+ status: 'active',
146
+ actionKey: 'prospecting.lead-import'
147
+ }
148
+ })
149
+
150
+ export const resourceGovernanceModel = {
151
+ systems,
152
+ resources: resourceDescriptors
153
+ } as const
95
154
  ```
96
155
 
156
+ Legacy `sys.*` paths may still appear in older examples and external compatibility mirrors.
157
+ For new Organization OS examples, prefer the current semantic System path.
158
+
97
159
  ## Domain Semantics
98
160
 
99
161
  The model keeps business semantics in named domains:
@@ -102,7 +164,10 @@ The model keeps business semantics in named domains:
102
164
  - `prospecting` -- company/contact lifecycle stages
103
165
  - `projects` -- project, milestone, and task statuses
104
166
  - `identity`, `customers`, `offerings`, `roles`, `goals` -- organizational reality
105
- - `statuses` and `operations` -- runtime/vibe-layer semantic registries
167
+ - `systems` -- bounded contexts that group governed operational resources
168
+ - `resources` -- governance-only workflow, agent, and integration descriptors
169
+ - `statuses` -- runtime/vibe-layer semantic registry
170
+ - `knowledge` -- playbooks, strategies, references, and graph-governing links
106
171
 
107
172
  ## Authoring and Resolution
108
173
 
@@ -110,27 +175,29 @@ The model keeps business semantics in named domains:
110
175
  - `resolveOrganizationModel(partial)` deep-merges a partial override into `DEFAULT_ORGANIZATION_MODEL` and validates the result.
111
176
  - `createFoundationOrganizationModel(partial)` resolves the canonical model and returns template-facing helpers.
112
177
  - Plain objects merge recursively.
178
+ - Id-keyed domain maps merge additively by key.
113
179
  - Arrays replace defaults.
114
180
 
115
181
  ## Referential Integrity
116
182
 
117
183
  `OrganizationModelSchema` validates:
118
184
 
119
- - unique feature IDs
120
- - ancestor existence for dotted feature IDs
121
- - container/leaf path rules
185
+ - unique System IDs
186
+ - ancestor existence for dotted System IDs and `parentSystemId`
187
+ - UI path rules for Systems with UI presence
122
188
  - valid sidebar positions
123
189
  - reality-domain cross references such as offering target segments and role reporting lines
190
+ - system, resource, role, knowledge, and goal cross references used by resource governance
124
191
 
125
- Resource graph links are validated during resource registry registration because resources live in deployment specs.
192
+ `DeploymentSpec` remains the runtime/deploy assembly around these descriptors. It is not the source of resource identity.
126
193
 
127
194
  ## Provider Integration
128
195
 
129
- `ElevasisFeaturesProvider` uses the organization model to:
196
+ `ElevasisSystemsProvider` uses the organization model to:
130
197
 
131
- 1. validate each manifest's `featureId`
132
- 2. resolve effective feature access
133
- 3. derive sidebar entries from `features`
198
+ 1. validate each manifest's `systemId`
199
+ 2. resolve effective system access
200
+ 3. derive sidebar entries from `navigation.sidebar`
134
201
  4. expose shell helpers such as `childrenOf`, `ancestorsOf`, and `findByPath`
135
202
  5. bridge the operations graph into shared UI
136
203