@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.
- package/dist/index.d.ts +2330 -2391
- package/dist/index.js +2322 -1147
- package/dist/knowledge/index.d.ts +702 -1136
- package/dist/knowledge/index.js +9 -9
- package/dist/organization-model/index.d.ts +2330 -2391
- package/dist/organization-model/index.js +2322 -1147
- package/dist/test-utils/index.d.ts +703 -1106
- package/dist/test-utils/index.js +1735 -1089
- package/package.json +1 -1
- package/src/__tests__/template-core-compatibility.test.ts +11 -79
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +360 -98
- package/src/business/acquisition/api-schemas.test.ts +2 -2
- package/src/business/acquisition/api-schemas.ts +7 -9
- package/src/business/acquisition/build-templates.test.ts +4 -4
- package/src/business/acquisition/build-templates.ts +72 -30
- package/src/business/acquisition/crm-state-actions.test.ts +13 -11
- package/src/business/acquisition/types.ts +7 -3
- package/src/execution/engine/agent/core/types.ts +1 -1
- package/src/execution/engine/workflow/types.ts +2 -2
- package/src/knowledge/README.md +8 -7
- package/src/knowledge/__tests__/queries.test.ts +74 -73
- package/src/knowledge/format.ts +10 -9
- package/src/knowledge/index.ts +1 -1
- package/src/knowledge/published.ts +1 -1
- package/src/knowledge/queries.ts +26 -25
- package/src/organization-model/README.md +66 -26
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +72 -98
- package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
- package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
- package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
- package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
- package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
- package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
- package/src/organization-model/__tests__/domains/resources.test.ts +159 -37
- package/src/organization-model/__tests__/domains/roles.test.ts +147 -86
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
- package/src/organization-model/__tests__/domains/systems.test.ts +67 -51
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
- package/src/organization-model/__tests__/foundation.test.ts +74 -102
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
- package/src/organization-model/__tests__/graph.test.ts +899 -71
- package/src/organization-model/__tests__/knowledge.test.ts +173 -52
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
- package/src/organization-model/__tests__/resolve.test.ts +174 -23
- package/src/organization-model/__tests__/schema.test.ts +291 -114
- package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
- package/src/organization-model/catalogs/lead-gen.ts +144 -0
- package/src/organization-model/content-kinds/config.ts +36 -0
- package/src/organization-model/content-kinds/index.ts +74 -0
- package/src/organization-model/content-kinds/pipeline.ts +68 -0
- package/src/organization-model/content-kinds/registry.ts +44 -0
- package/src/organization-model/content-kinds/status.ts +71 -0
- package/src/organization-model/content-kinds/template.ts +83 -0
- package/src/organization-model/content-kinds/types.ts +117 -0
- package/src/organization-model/contracts.ts +13 -3
- package/src/organization-model/defaults.ts +488 -96
- package/src/organization-model/domains/actions.ts +239 -0
- package/src/organization-model/domains/customers.ts +78 -75
- package/src/organization-model/domains/entities.ts +144 -0
- package/src/organization-model/domains/goals.ts +83 -80
- package/src/organization-model/domains/knowledge.ts +74 -16
- package/src/organization-model/domains/navigation.ts +107 -384
- package/src/organization-model/domains/offerings.ts +71 -66
- package/src/organization-model/domains/policies.ts +102 -0
- package/src/organization-model/domains/projects.ts +14 -48
- package/src/organization-model/domains/prospecting.ts +62 -181
- package/src/organization-model/domains/resources.ts +81 -24
- package/src/organization-model/domains/roles.ts +13 -10
- package/src/organization-model/domains/sales.ts +10 -219
- package/src/organization-model/domains/shared.ts +57 -57
- package/src/organization-model/domains/statuses.ts +339 -130
- package/src/organization-model/domains/systems.ts +186 -29
- package/src/organization-model/foundation.ts +54 -67
- package/src/organization-model/graph/build.ts +682 -54
- package/src/organization-model/graph/link.ts +1 -1
- package/src/organization-model/graph/schema.ts +24 -9
- package/src/organization-model/graph/types.ts +20 -7
- package/src/organization-model/helpers.ts +231 -26
- package/src/organization-model/index.ts +116 -5
- package/src/organization-model/migration-helpers.ts +249 -0
- package/src/organization-model/organization-graph.mdx +16 -15
- package/src/organization-model/organization-model.mdx +89 -41
- package/src/organization-model/published.ts +120 -18
- package/src/organization-model/resolve.ts +117 -54
- package/src/organization-model/schema.ts +561 -140
- package/src/organization-model/surface-projection.ts +116 -122
- package/src/organization-model/types.ts +102 -21
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/command-view.test.ts +6 -8
- package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +9 -7
- package/src/platform/registry/__tests__/validation.test.ts +15 -11
- package/src/platform/registry/resource-registry.ts +20 -8
- package/src/platform/registry/serialization.ts +7 -7
- package/src/platform/registry/types.ts +3 -3
- package/src/platform/registry/validation.ts +17 -15
- package/src/reference/_generated/contracts.md +362 -99
- package/src/reference/glossary.md +18 -18
- package/src/supabase/database.types.ts +60 -0
- package/src/test-utils/test-utils.test.ts +1 -6
- package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
- package/src/organization-model/domains/features.ts +0 -31
- 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
|
|
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
|
-
- `
|
|
28
|
-
- `
|
|
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
|
-
|
|
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
|
|
45
|
+
Resource and capability edges are derived from canonical OM maps:
|
|
45
46
|
|
|
46
47
|
```ts
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
65
|
-
2. Reads
|
|
66
|
-
3. Emits
|
|
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
|
|
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
|
|
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
|
-
- `
|
|
27
|
+
- `domainMetadata`
|
|
28
28
|
- `branding`
|
|
29
29
|
- `navigation`
|
|
30
30
|
- `sales`
|
|
@@ -37,23 +37,26 @@ Top-level fields on `OrganizationModel`:
|
|
|
37
37
|
- `goals`
|
|
38
38
|
- `systems`
|
|
39
39
|
- `resources`
|
|
40
|
+
- `capabilities`
|
|
41
|
+
- `policies`
|
|
40
42
|
- `statuses`
|
|
41
|
-
- `operations`
|
|
42
43
|
- `knowledge`
|
|
43
44
|
|
|
44
|
-
|
|
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.
|
|
45
46
|
|
|
46
|
-
|
|
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.
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
## System Shape
|
|
50
|
+
|
|
51
|
+
`OrganizationModel.systems` is the canonical semantic domain map. Hierarchy is derived from `parentSystemId` and dotted IDs:
|
|
49
52
|
|
|
50
53
|
```ts
|
|
51
|
-
|
|
52
|
-
{ id: 'dashboard',
|
|
53
|
-
{ id: 'sales', label: 'Sales',
|
|
54
|
-
{ id: '
|
|
55
|
-
{ id: '
|
|
56
|
-
|
|
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
|
+
}
|
|
57
60
|
```
|
|
58
61
|
|
|
59
62
|
Authored fields:
|
|
@@ -61,29 +64,74 @@ Authored fields:
|
|
|
61
64
|
- `id`
|
|
62
65
|
- `label`
|
|
63
66
|
- `description`
|
|
64
|
-
- `
|
|
65
|
-
- `
|
|
66
|
-
- `
|
|
67
|
-
- `
|
|
68
|
-
- `uiPosition`
|
|
67
|
+
- `kind`
|
|
68
|
+
- `parentSystemId`
|
|
69
|
+
- `ui`
|
|
70
|
+
- `lifecycle`
|
|
69
71
|
- `requiresAdmin`
|
|
70
|
-
- `
|
|
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.
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
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.
|
|
78
|
+
## Navigation Shape
|
|
74
79
|
|
|
75
|
-
|
|
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:
|
|
81
|
+
|
|
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
|
+
```
|
|
122
|
+
|
|
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)`.
|
|
76
124
|
|
|
77
125
|
## Graph IDs and Resource Descriptors
|
|
78
126
|
|
|
79
127
|
Cross-collection links use kind-prefixed graph IDs:
|
|
80
128
|
|
|
81
|
-
- `
|
|
129
|
+
- `system:sales.crm`
|
|
82
130
|
- `integration:instantly`
|
|
83
131
|
- `resource:lead-import`
|
|
84
|
-
- `
|
|
132
|
+
- `action:operations.queue.review`
|
|
85
133
|
|
|
86
|
-
Resource identity is authored in the OM Resources domain. Operations imports descriptors from `organizationModel.resources
|
|
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.
|
|
87
135
|
|
|
88
136
|
```ts
|
|
89
137
|
import { defineResources } from '@elevasis/core/organization-model'
|
|
@@ -92,23 +140,22 @@ export const resourceDescriptors = defineResources({
|
|
|
92
140
|
leadImport: {
|
|
93
141
|
id: 'lead-import',
|
|
94
142
|
kind: 'workflow',
|
|
95
|
-
|
|
143
|
+
systemPath: 'sales.lead-gen',
|
|
96
144
|
ownerRoleId: 'role-ops-lead',
|
|
97
145
|
status: 'active',
|
|
98
|
-
|
|
146
|
+
actionKey: 'prospecting.lead-import'
|
|
99
147
|
}
|
|
100
148
|
})
|
|
101
149
|
|
|
102
150
|
export const resourceGovernanceModel = {
|
|
103
|
-
systems
|
|
104
|
-
|
|
105
|
-
},
|
|
106
|
-
resources: {
|
|
107
|
-
entries: Object.values(resourceDescriptors)
|
|
108
|
-
}
|
|
151
|
+
systems,
|
|
152
|
+
resources: resourceDescriptors
|
|
109
153
|
} as const
|
|
110
154
|
```
|
|
111
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
|
+
|
|
112
159
|
## Domain Semantics
|
|
113
160
|
|
|
114
161
|
The model keeps business semantics in named domains:
|
|
@@ -119,7 +166,7 @@ The model keeps business semantics in named domains:
|
|
|
119
166
|
- `identity`, `customers`, `offerings`, `roles`, `goals` -- organizational reality
|
|
120
167
|
- `systems` -- bounded contexts that group governed operational resources
|
|
121
168
|
- `resources` -- governance-only workflow, agent, and integration descriptors
|
|
122
|
-
- `statuses`
|
|
169
|
+
- `statuses` -- runtime/vibe-layer semantic registry
|
|
123
170
|
- `knowledge` -- playbooks, strategies, references, and graph-governing links
|
|
124
171
|
|
|
125
172
|
## Authoring and Resolution
|
|
@@ -128,15 +175,16 @@ The model keeps business semantics in named domains:
|
|
|
128
175
|
- `resolveOrganizationModel(partial)` deep-merges a partial override into `DEFAULT_ORGANIZATION_MODEL` and validates the result.
|
|
129
176
|
- `createFoundationOrganizationModel(partial)` resolves the canonical model and returns template-facing helpers.
|
|
130
177
|
- Plain objects merge recursively.
|
|
178
|
+
- Id-keyed domain maps merge additively by key.
|
|
131
179
|
- Arrays replace defaults.
|
|
132
180
|
|
|
133
181
|
## Referential Integrity
|
|
134
182
|
|
|
135
183
|
`OrganizationModelSchema` validates:
|
|
136
184
|
|
|
137
|
-
- unique
|
|
138
|
-
- ancestor existence for dotted
|
|
139
|
-
-
|
|
185
|
+
- unique System IDs
|
|
186
|
+
- ancestor existence for dotted System IDs and `parentSystemId`
|
|
187
|
+
- UI path rules for Systems with UI presence
|
|
140
188
|
- valid sidebar positions
|
|
141
189
|
- reality-domain cross references such as offering target segments and role reporting lines
|
|
142
190
|
- system, resource, role, knowledge, and goal cross references used by resource governance
|
|
@@ -145,11 +193,11 @@ The model keeps business semantics in named domains:
|
|
|
145
193
|
|
|
146
194
|
## Provider Integration
|
|
147
195
|
|
|
148
|
-
`
|
|
196
|
+
`ElevasisSystemsProvider` uses the organization model to:
|
|
149
197
|
|
|
150
|
-
1. validate each manifest's `
|
|
151
|
-
2. resolve effective
|
|
152
|
-
3. derive sidebar entries from `
|
|
198
|
+
1. validate each manifest's `systemId`
|
|
199
|
+
2. resolve effective system access
|
|
200
|
+
3. derive sidebar entries from `navigation.sidebar`
|
|
153
201
|
4. expose shell helpers such as `childrenOf`, `ancestorsOf`, and `findByPath`
|
|
154
202
|
5. bridge the operations graph into shared UI
|
|
155
203
|
|