@elevasis/core 0.15.0 → 0.16.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 (88) hide show
  1. package/dist/index.d.ts +1718 -19
  2. package/dist/index.js +369 -25
  3. package/dist/organization-model/index.d.ts +1718 -19
  4. package/dist/organization-model/index.js +369 -25
  5. package/dist/test-utils/index.d.ts +1108 -371
  6. package/dist/test-utils/index.js +357 -17
  7. package/package.json +5 -1
  8. package/src/__tests__/publish.test.ts +14 -13
  9. package/src/__tests__/template-core-compatibility.test.ts +4 -4
  10. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +1109 -882
  11. package/src/auth/multi-tenancy/index.ts +3 -0
  12. package/src/auth/multi-tenancy/theme-presets.ts +45 -0
  13. package/src/auth/multi-tenancy/types.ts +57 -83
  14. package/src/auth/multi-tenancy/users/api-schemas.ts +165 -194
  15. package/src/business/acquisition/activity-events.ts +13 -4
  16. package/src/business/acquisition/api-schemas.test.ts +315 -4
  17. package/src/business/acquisition/api-schemas.ts +122 -8
  18. package/src/business/acquisition/build-templates.ts +44 -0
  19. package/src/business/acquisition/crm-next-action.test.ts +262 -0
  20. package/src/business/acquisition/crm-next-action.ts +220 -0
  21. package/src/business/acquisition/crm-priority.test.ts +216 -0
  22. package/src/business/acquisition/crm-priority.ts +349 -0
  23. package/src/business/acquisition/crm-state-actions.test.ts +151 -160
  24. package/src/business/acquisition/deal-ownership.test.ts +351 -0
  25. package/src/business/acquisition/deal-ownership.ts +120 -0
  26. package/src/business/acquisition/derive-actions.test.ts +101 -37
  27. package/src/business/acquisition/derive-actions.ts +102 -87
  28. package/src/business/acquisition/index.ts +10 -0
  29. package/src/business/acquisition/types.ts +400 -366
  30. package/src/business/crm/api-schemas.ts +40 -0
  31. package/src/business/crm/index.ts +1 -0
  32. package/src/business/deals/api-schemas.ts +79 -0
  33. package/src/business/deals/index.ts +1 -0
  34. package/src/business/projects/types.ts +124 -88
  35. package/src/execution/core/runner-types.ts +61 -80
  36. package/src/execution/engine/index.ts +4 -3
  37. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +105 -104
  38. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1474 -1473
  39. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +103 -102
  40. package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +182 -179
  41. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +310 -309
  42. package/src/execution/engine/tools/integration/tool.ts +255 -253
  43. package/src/execution/engine/tools/lead-service-types.ts +939 -924
  44. package/src/execution/engine/tools/messages.ts +43 -0
  45. package/src/execution/engine/tools/platform/acquisition/list-tools.ts +6 -5
  46. package/src/execution/engine/tools/platform/acquisition/types.ts +5 -2
  47. package/src/execution/engine/tools/platform/email/types.ts +97 -96
  48. package/src/execution/engine/tools/registry.ts +4 -3
  49. package/src/execution/engine/tools/tool-maps.ts +3 -1
  50. package/src/execution/engine/tools/types.ts +234 -233
  51. package/src/execution/engine/workflow/types.ts +195 -193
  52. package/src/execution/external/api-schemas.ts +40 -0
  53. package/src/execution/external/index.ts +1 -0
  54. package/src/knowledge/README.md +32 -0
  55. package/src/knowledge/__tests__/queries.test.ts +504 -0
  56. package/src/knowledge/format.ts +99 -0
  57. package/src/knowledge/index.ts +5 -0
  58. package/src/knowledge/queries.ts +256 -0
  59. package/src/organization-model/__tests__/defaults.test.ts +172 -172
  60. package/src/organization-model/__tests__/foundation.test.ts +7 -7
  61. package/src/organization-model/__tests__/icons.test.ts +27 -0
  62. package/src/organization-model/__tests__/knowledge.test.ts +214 -0
  63. package/src/organization-model/contracts.ts +17 -15
  64. package/src/organization-model/defaults.ts +74 -19
  65. package/src/organization-model/domains/knowledge.ts +53 -0
  66. package/src/organization-model/domains/navigation.ts +416 -399
  67. package/src/organization-model/domains/prospecting.ts +204 -1
  68. package/src/organization-model/domains/sales.test.ts +29 -0
  69. package/src/organization-model/domains/sales.ts +102 -0
  70. package/src/organization-model/domains/shared.ts +6 -5
  71. package/src/organization-model/foundation.ts +10 -6
  72. package/src/organization-model/graph/build.ts +209 -182
  73. package/src/organization-model/graph/schema.ts +37 -34
  74. package/src/organization-model/graph/types.ts +47 -31
  75. package/src/organization-model/icons.ts +81 -0
  76. package/src/organization-model/index.ts +8 -3
  77. package/src/organization-model/organization-model.mdx +1 -1
  78. package/src/organization-model/published.ts +103 -86
  79. package/src/organization-model/schema.ts +90 -85
  80. package/src/organization-model/types.ts +42 -35
  81. package/src/platform/constants/versions.ts +1 -1
  82. package/src/platform/index.ts +23 -27
  83. package/src/platform/registry/index.ts +0 -4
  84. package/src/platform/registry/resource-registry.ts +0 -77
  85. package/src/platform/registry/serialized-types.ts +148 -219
  86. package/src/platform/registry/stats-types.ts +60 -60
  87. package/src/reference/_generated/contracts.md +829 -595
  88. package/src/supabase/database.types.ts +2978 -2958
@@ -0,0 +1,214 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { OrgKnowledgeNodeSchema, OrgKnowledgeKindSchema, KnowledgeDomainSchema } from '../domains/knowledge'
3
+ import { OrganizationGraphEdgeKindSchema } from '../graph/schema'
4
+ import { buildOrganizationGraph } from '../graph/build'
5
+ import { DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE } from '../defaults'
6
+ import type { OrganizationModel } from '../types'
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // OrgKnowledgeNodeSchema — shape and validation
10
+ // ---------------------------------------------------------------------------
11
+
12
+ describe('OrgKnowledgeNodeSchema', () => {
13
+ function makeNode(kind: string) {
14
+ return {
15
+ id: `knowledge.test-${kind}`,
16
+ kind,
17
+ title: `Test ${kind}`,
18
+ summary: `A test ${kind} knowledge node.`,
19
+ body: `## Body\n\nContent for ${kind}.`,
20
+ links: [],
21
+ ownerIds: [],
22
+ updatedAt: '2026-05-01'
23
+ }
24
+ }
25
+
26
+ it('accepts kind: playbook', () => {
27
+ expect(() => OrgKnowledgeNodeSchema.parse(makeNode('playbook'))).not.toThrow()
28
+ })
29
+
30
+ it('accepts kind: strategy', () => {
31
+ expect(() => OrgKnowledgeNodeSchema.parse(makeNode('strategy'))).not.toThrow()
32
+ })
33
+
34
+ it('accepts kind: reference', () => {
35
+ expect(() => OrgKnowledgeNodeSchema.parse(makeNode('reference'))).not.toThrow()
36
+ })
37
+
38
+ it('rejects unknown kind', () => {
39
+ const result = OrgKnowledgeNodeSchema.safeParse(makeNode('guide'))
40
+ expect(result.success).toBe(false)
41
+ })
42
+
43
+ it('rejects missing required fields', () => {
44
+ const result = OrgKnowledgeNodeSchema.safeParse({ id: 'knowledge.x', kind: 'playbook' })
45
+ expect(result.success).toBe(false)
46
+ })
47
+
48
+ it('defaults links to empty array when omitted', () => {
49
+ const node = OrgKnowledgeNodeSchema.parse({
50
+ id: 'knowledge.test-default-links',
51
+ kind: 'reference',
52
+ title: 'Test',
53
+ summary: 'Test summary.',
54
+ body: 'Content.',
55
+ updatedAt: '2026-05-01'
56
+ })
57
+ expect(node.links).toEqual([])
58
+ })
59
+
60
+ it('defaults ownerIds to empty array when omitted', () => {
61
+ const node = OrgKnowledgeNodeSchema.parse({
62
+ id: 'knowledge.test-default-owners',
63
+ kind: 'strategy',
64
+ title: 'Test',
65
+ summary: 'Test summary.',
66
+ body: 'Content.',
67
+ updatedAt: '2026-05-01'
68
+ })
69
+ expect(node.ownerIds).toEqual([])
70
+ })
71
+
72
+ it('accepts an optional semantic icon token', () => {
73
+ const node = OrgKnowledgeNodeSchema.parse({
74
+ ...makeNode('playbook'),
75
+ icon: 'knowledge.playbook'
76
+ })
77
+
78
+ expect(node.icon).toBe('knowledge.playbook')
79
+ })
80
+
81
+ it('rejects an unknown icon token', () => {
82
+ const result = OrgKnowledgeNodeSchema.safeParse({
83
+ ...makeNode('reference'),
84
+ icon: 'book'
85
+ })
86
+
87
+ expect(result.success).toBe(false)
88
+ })
89
+ })
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // OrgKnowledgeKindSchema — enum shape
93
+ // ---------------------------------------------------------------------------
94
+
95
+ describe('OrgKnowledgeKindSchema', () => {
96
+ it('accepts all three valid kinds', () => {
97
+ for (const kind of ['playbook', 'strategy', 'reference']) {
98
+ expect(() => OrgKnowledgeKindSchema.parse(kind)).not.toThrow()
99
+ }
100
+ })
101
+
102
+ it('rejects invalid kind', () => {
103
+ expect(OrgKnowledgeKindSchema.safeParse('guide').success).toBe(false)
104
+ expect(OrgKnowledgeKindSchema.safeParse('').success).toBe(false)
105
+ })
106
+ })
107
+
108
+ // ---------------------------------------------------------------------------
109
+ // OrganizationGraphEdgeKindSchema — governs edge is present
110
+ // ---------------------------------------------------------------------------
111
+
112
+ describe('OrganizationGraphEdgeKindSchema', () => {
113
+ it('includes governs as a valid edge kind', () => {
114
+ expect(() => OrganizationGraphEdgeKindSchema.parse('governs')).not.toThrow()
115
+ })
116
+ })
117
+
118
+ // ---------------------------------------------------------------------------
119
+ // DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE — post Wave 2a: nodes is empty array
120
+ // ---------------------------------------------------------------------------
121
+
122
+ describe('DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE', () => {
123
+ it('has an empty nodes array after Wave 2a pilot literal removal', () => {
124
+ expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE.nodes).toEqual([])
125
+ })
126
+
127
+ it('passes KnowledgeDomainSchema.parse without throwing', () => {
128
+ expect(() => KnowledgeDomainSchema.parse(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE)).not.toThrow()
129
+ })
130
+ })
131
+
132
+ // ---------------------------------------------------------------------------
133
+ // buildOrganizationGraph — knowledge nodes + governs edges
134
+ // Synthetic OM used so tests are independent of DEFAULT_ORGANIZATION_MODEL
135
+ // knowledge nodes (empty after Wave 2a, Decision 2-B).
136
+ // ---------------------------------------------------------------------------
137
+
138
+ const SYNTHETIC_OM: OrganizationModel = {
139
+ ...DEFAULT_ORGANIZATION_MODEL,
140
+ knowledge: {
141
+ nodes: [
142
+ {
143
+ id: 'knowledge.test-playbook-1',
144
+ kind: 'playbook',
145
+ title: 'Test Playbook',
146
+ summary: 'Test playbook summary.',
147
+ body: '## Overview\n\nContent.',
148
+ links: [{ nodeId: 'feature:sales.crm' }, { nodeId: 'feature:sales.lead-gen' }],
149
+ ownerIds: [],
150
+ updatedAt: '2026-01-01'
151
+ },
152
+ {
153
+ id: 'knowledge.test-strategy-1',
154
+ kind: 'strategy',
155
+ title: 'Test Strategy',
156
+ summary: 'Test strategy summary.',
157
+ body: '## Strategy\n\nContent.',
158
+ links: [{ nodeId: 'feature:sales.lead-gen' }],
159
+ ownerIds: [],
160
+ updatedAt: '2026-01-02'
161
+ },
162
+ {
163
+ id: 'knowledge.test-reference-1',
164
+ kind: 'reference',
165
+ title: 'Test Reference',
166
+ summary: 'Test reference summary.',
167
+ body: '## Reference\n\nContent.',
168
+ links: [],
169
+ ownerIds: [],
170
+ updatedAt: '2026-01-03'
171
+ }
172
+ ]
173
+ }
174
+ }
175
+
176
+ describe('buildOrganizationGraph with knowledge', () => {
177
+ const graph = buildOrganizationGraph({ organizationModel: SYNTHETIC_OM })
178
+
179
+ it('emits a knowledge node for each synthetic node', () => {
180
+ const knowledgeNodes = graph.nodes.filter((n) => n.kind === 'knowledge')
181
+ expect(knowledgeNodes.length).toBe(SYNTHETIC_OM.knowledge.nodes.length)
182
+ })
183
+
184
+ it('knowledge nodes carry sourceId matching the OM node id', () => {
185
+ for (const omNode of SYNTHETIC_OM.knowledge.nodes) {
186
+ const graphNode = graph.nodes.find((n) => n.sourceId === omNode.id)
187
+ expect(graphNode).toBeDefined()
188
+ expect(graphNode?.kind).toBe('knowledge')
189
+ expect(graphNode?.label).toBe(omNode.title)
190
+ }
191
+ })
192
+
193
+ it('emits governs edges for nodes that have links', () => {
194
+ const governsEdges = graph.edges.filter((e) => e.kind === 'governs')
195
+ const totalLinks = SYNTHETIC_OM.knowledge.nodes.reduce((sum, n) => sum + n.links.length, 0)
196
+ expect(governsEdges.length).toBe(totalLinks)
197
+ })
198
+
199
+ it('links targetId resolves to an existing graph node id for at least one node', () => {
200
+ const nodeWithLinks = SYNTHETIC_OM.knowledge.nodes.find((n) => n.links.length > 0)
201
+ expect(nodeWithLinks).toBeDefined()
202
+
203
+ const graphNodeIds = new Set(graph.nodes.map((n) => n.id))
204
+ for (const link of nodeWithLinks!.links) {
205
+ expect(graphNodeIds.has(link.nodeId)).toBe(true)
206
+ }
207
+ })
208
+
209
+ it('DEFAULT_ORGANIZATION_MODEL produces zero knowledge nodes in graph', () => {
210
+ const defaultGraph = buildOrganizationGraph({ organizationModel: DEFAULT_ORGANIZATION_MODEL })
211
+ const defaultKnowledgeNodes = defaultGraph.nodes.filter((n) => n.kind === 'knowledge')
212
+ expect(defaultKnowledgeNodes).toHaveLength(0)
213
+ })
214
+ })
@@ -1,15 +1,17 @@
1
- export const PROJECTS_FEATURE_ID = 'projects' as const
2
- export const PROJECTS_INDEX_SURFACE_ID = 'projects.index' as const
3
- export const PROJECTS_VIEW_CAPABILITY_ID = 'delivery.projects.view' as const
4
-
5
- export const SALES_FEATURE_ID = 'crm' as const
6
- export const PROSPECTING_FEATURE_ID = 'lead-gen' as const
7
- export const OPERATIONS_FEATURE_ID = 'operations' as const
8
- export const MONITORING_FEATURE_ID = 'monitoring' as const
9
- export const SETTINGS_FEATURE_ID = 'settings' as const
10
- export const SEO_FEATURE_ID = 'seo' as const
11
-
12
- export const SALES_PIPELINE_SURFACE_ID = 'crm.pipeline' as const
13
- export const PROSPECTING_LISTS_SURFACE_ID = 'lead-gen.lists' as const
14
- export const OPERATIONS_COMMAND_VIEW_SURFACE_ID = 'operations.command-view' as const
15
- export const SETTINGS_ROLES_SURFACE_ID = 'settings.roles' as const
1
+ export const KNOWLEDGE_FEATURE_ID = 'knowledge' as const
2
+
3
+ export const PROJECTS_FEATURE_ID = 'projects' as const
4
+ export const PROJECTS_INDEX_SURFACE_ID = 'projects.index' as const
5
+ export const PROJECTS_VIEW_CAPABILITY_ID = 'delivery.projects.view' as const
6
+
7
+ export const SALES_FEATURE_ID = 'crm' as const
8
+ export const PROSPECTING_FEATURE_ID = 'lead-gen' as const
9
+ export const OPERATIONS_FEATURE_ID = 'operations' as const
10
+ export const MONITORING_FEATURE_ID = 'monitoring' as const
11
+ export const SETTINGS_FEATURE_ID = 'settings' as const
12
+ export const SEO_FEATURE_ID = 'seo' as const
13
+
14
+ export const SALES_PIPELINE_SURFACE_ID = 'crm.pipeline' as const
15
+ export const PROSPECTING_LISTS_SURFACE_ID = 'lead-gen.lists' as const
16
+ export const OPERATIONS_COMMAND_VIEW_SURFACE_ID = 'knowledge.command-view' as const
17
+ export const SETTINGS_ROLES_SURFACE_ID = 'settings.roles' as const
@@ -1,17 +1,33 @@
1
+ /**
2
+ * Fixture-only stub for the generic OrganizationModel merge base.
3
+ *
4
+ * This constant is used by:
5
+ * - `resolveOrganizationModel()` as the deep-merge base for every org's config
6
+ * - Unit tests and snapshot fixtures that need a structurally valid OrganizationModel
7
+ *
8
+ * It intentionally does NOT contain Elevasis-specific identity or knowledge content.
9
+ * Runtime consumers that need the full Elevasis canonical model should import
10
+ * `canonicalOrganizationModel` from `@repo/elevasis-core` instead.
11
+ */
1
12
  import type { OrganizationModel } from './types'
2
13
  import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from './domains/branding'
3
14
  import { DEFAULT_ORGANIZATION_MODEL_IDENTITY } from './domains/identity'
4
15
  import { DEFAULT_ORGANIZATION_MODEL_CUSTOMERS } from './domains/customers'
5
- import { DEFAULT_ORGANIZATION_MODEL_OFFERINGS } from './domains/offerings'
16
+ import { DEFAULT_ORGANIZATION_MODEL_OFFERINGS } from './domains/offerings'
6
17
  import { DEFAULT_ORGANIZATION_MODEL_SALES } from './domains/sales'
7
18
  import { DEFAULT_ORGANIZATION_MODEL_PROJECTS } from './domains/projects'
8
19
  import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from './domains/prospecting'
9
20
  import { DEFAULT_ORGANIZATION_MODEL_OPERATIONS } from './domains/operations'
10
21
  import { DEFAULT_ORGANIZATION_MODEL_ROLES } from './domains/roles'
11
22
  import { DEFAULT_ORGANIZATION_MODEL_GOALS } from './domains/goals'
12
- import { DEFAULT_ORGANIZATION_MODEL_STATUSES } from './domains/statuses'
13
-
14
- export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
23
+ import { DEFAULT_ORGANIZATION_MODEL_STATUSES } from './domains/statuses'
24
+ import type { KnowledgeDomain } from './domains/knowledge'
25
+
26
+ export const DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE: KnowledgeDomain = {
27
+ nodes: []
28
+ }
29
+
30
+ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
15
31
  version: 1,
16
32
  features: [
17
33
  {
@@ -19,16 +35,39 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
19
35
  label: 'Dashboard',
20
36
  enabled: true,
21
37
  path: '/',
22
- icon: 'dashboard',
38
+ icon: 'feature.dashboard',
23
39
  uiPosition: 'sidebar-primary'
24
40
  },
41
+ {
42
+ id: 'identity',
43
+ label: 'Identity',
44
+ description: 'Company identity, positioning, and market context',
45
+ enabled: true,
46
+ color: 'indigo'
47
+ },
48
+ {
49
+ id: 'platform',
50
+ label: 'Platform',
51
+ description: 'Elevasis platform architecture, capabilities, and implementation patterns',
52
+ enabled: true,
53
+ color: 'cyan',
54
+ icon: 'feature.platform'
55
+ },
56
+ {
57
+ id: 'finance',
58
+ label: 'Finance',
59
+ description: 'Finance operations, accounting, billing, reconciliation, and tax prep',
60
+ enabled: true,
61
+ color: 'green',
62
+ icon: 'feature.finance'
63
+ },
25
64
  {
26
65
  id: 'sales',
27
66
  label: 'Sales',
28
67
  description: 'Revenue workflows and customer acquisition',
29
68
  enabled: true,
30
69
  color: 'blue',
31
- icon: 'crm',
70
+ icon: 'feature.sales',
32
71
  uiPosition: 'sidebar-primary'
33
72
  },
34
73
  {
@@ -37,7 +76,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
37
76
  description: 'Relationship pipeline and deal management',
38
77
  enabled: true,
39
78
  color: 'blue',
40
- icon: 'crm',
79
+ icon: 'feature.crm',
41
80
  path: '/crm'
42
81
  },
43
82
  {
@@ -46,7 +85,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
46
85
  description: 'Prospecting, qualification, and outreach preparation',
47
86
  enabled: true,
48
87
  color: 'cyan',
49
- icon: 'lead-gen',
88
+ icon: 'feature.lead-gen',
50
89
  path: '/lead-gen'
51
90
  },
52
91
  {
@@ -55,7 +94,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
55
94
  description: 'Projects, milestones, and client work execution',
56
95
  enabled: true,
57
96
  color: 'orange',
58
- icon: 'projects',
97
+ icon: 'feature.projects',
59
98
  path: '/projects',
60
99
  uiPosition: 'sidebar-primary'
61
100
  },
@@ -65,14 +104,14 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
65
104
  description: 'Operational resources, topology, and orchestration visibility',
66
105
  enabled: true,
67
106
  color: 'violet',
68
- icon: 'operations',
107
+ icon: 'feature.operations',
69
108
  uiPosition: 'sidebar-primary'
70
109
  },
71
110
  {
72
- id: 'operations.command-view',
111
+ id: 'knowledge.command-view',
73
112
  label: 'Command View',
74
113
  enabled: true,
75
- path: '/operations/command-view',
114
+ path: '/knowledge/command-view',
76
115
  devOnly: true
77
116
  },
78
117
  {
@@ -151,7 +190,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
151
190
  id: 'settings',
152
191
  label: 'Settings',
153
192
  enabled: true,
154
- icon: 'settings',
193
+ icon: 'feature.settings',
155
194
  uiPosition: 'sidebar-bottom'
156
195
  },
157
196
  {
@@ -207,7 +246,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
207
246
  label: 'Admin',
208
247
  enabled: true,
209
248
  path: '/admin',
210
- icon: 'settings',
249
+ icon: 'feature.admin',
211
250
  uiPosition: 'sidebar-bottom',
212
251
  requiresAdmin: true
213
252
  },
@@ -246,7 +285,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
246
285
  label: 'Archive',
247
286
  enabled: true,
248
287
  path: '/archive',
249
- icon: 'archive',
288
+ icon: 'feature.archive',
250
289
  uiPosition: 'sidebar-bottom',
251
290
  devOnly: true
252
291
  },
@@ -267,6 +306,21 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
267
306
  label: 'SEO',
268
307
  enabled: false,
269
308
  path: '/seo'
309
+ },
310
+ {
311
+ id: 'knowledge',
312
+ label: 'Knowledge',
313
+ description: 'Operational knowledge, playbooks, and strategy docs',
314
+ enabled: true,
315
+ color: 'teal',
316
+ icon: 'feature.knowledge',
317
+ uiPosition: 'sidebar-primary'
318
+ },
319
+ {
320
+ id: 'knowledge.base',
321
+ label: 'Knowledge Base',
322
+ enabled: true,
323
+ path: '/knowledge'
270
324
  }
271
325
  ],
272
326
  branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
@@ -274,11 +328,12 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
274
328
  sales: DEFAULT_ORGANIZATION_MODEL_SALES,
275
329
  prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
276
330
  projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
277
- identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
278
- customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
279
- offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
331
+ identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
332
+ customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
333
+ offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
280
334
  roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
281
335
  goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
282
336
  statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
283
- operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS
337
+ operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
338
+ knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
284
339
  }
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod'
2
+ import { IconNameSchema, ModelIdSchema } from './shared'
3
+ import { NodeIdStringSchema } from './features'
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // KnowledgeLink — a typed graph link pointing to another OM node.
7
+ // Uses NodeIdStringSchema (kind:dotted-path) to resolve to a graph node.
8
+ // Phase 1 only emits 'governs' edges from knowledge nodes.
9
+ // ---------------------------------------------------------------------------
10
+
11
+ export const KnowledgeLinkSchema = z.object({
12
+ nodeId: NodeIdStringSchema
13
+ })
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // OrgKnowledgeNode — single schema, `kind` discriminator drives presentation.
17
+ // Phase 1: body is raw MDX string (lossless migration from operations/ docs).
18
+ // Phase 2 (deferred): structured block format (Supabase-backed authoring).
19
+ // ---------------------------------------------------------------------------
20
+
21
+ export const OrgKnowledgeKindSchema = z.enum(['playbook', 'strategy', 'reference'])
22
+
23
+ export const OrgKnowledgeNodeSchema = z.object({
24
+ id: ModelIdSchema,
25
+ kind: OrgKnowledgeKindSchema,
26
+ title: z.string().trim().min(1).max(200),
27
+ summary: z.string().trim().min(1).max(1000),
28
+ icon: IconNameSchema.optional(),
29
+ /** Raw MDX string. Phase 2 will introduce a structured block format. */
30
+ body: z.string().trim().min(1),
31
+ /**
32
+ * Graph links to other OM nodes this knowledge node governs.
33
+ * Each link emits a `governs` edge: knowledge-node -> target node.
34
+ */
35
+ links: z.array(KnowledgeLinkSchema).default([]),
36
+ /** Identifiers of the roles or members who own this knowledge node. */
37
+ ownerIds: z.array(ModelIdSchema).default([]),
38
+ /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
39
+ updatedAt: z.string().trim().min(1).max(50)
40
+ })
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Domain schema — flat array of knowledge nodes
44
+ // ---------------------------------------------------------------------------
45
+
46
+ export const KnowledgeDomainSchema = z.object({
47
+ nodes: z.array(OrgKnowledgeNodeSchema).default([])
48
+ })
49
+
50
+ export type OrgKnowledgeNode = z.infer<typeof OrgKnowledgeNodeSchema>
51
+ export type OrgKnowledgeKind = z.infer<typeof OrgKnowledgeKindSchema>
52
+ export type KnowledgeLink = z.infer<typeof KnowledgeLinkSchema>
53
+ export type KnowledgeDomain = z.infer<typeof KnowledgeDomainSchema>