@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.
- package/dist/index.d.ts +2518 -2169
- package/dist/index.js +2495 -1095
- package/dist/knowledge/index.d.ts +706 -1044
- package/dist/knowledge/index.js +9 -9
- package/dist/organization-model/index.d.ts +2518 -2169
- package/dist/organization-model/index.js +2495 -1095
- package/dist/test-utils/index.d.ts +826 -1014
- package/dist/test-utils/index.js +1894 -1032
- package/package.json +3 -3
- package/src/__tests__/template-core-compatibility.test.ts +11 -79
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
- package/src/auth/multi-tenancy/permissions.ts +20 -8
- package/src/business/README.md +2 -2
- package/src/business/acquisition/api-schemas.test.ts +175 -2
- package/src/business/acquisition/api-schemas.ts +132 -16
- 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/index.ts +12 -0
- package/src/business/acquisition/types.ts +7 -3
- package/src/business/clients/api-schemas.test.ts +115 -0
- package/src/business/clients/api-schemas.ts +158 -0
- package/src/business/clients/index.ts +1 -0
- package/src/business/deals/api-schemas.ts +8 -0
- package/src/business/index.ts +5 -2
- package/src/business/projects/types.ts +19 -0
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
- package/src/execution/engine/agent/core/types.ts +25 -15
- package/src/execution/engine/agent/index.ts +6 -4
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
- package/src/execution/engine/index.ts +3 -0
- package/src/execution/engine/workflow/types.ts +9 -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 +73 -26
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +76 -96
- 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 +310 -0
- package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
- package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
- 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 +209 -49
- 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 +499 -86
- 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 +76 -17
- 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 +145 -0
- package/src/organization-model/domains/roles.ts +96 -55
- 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 +203 -0
- 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/icons.ts +1 -0
- package/src/organization-model/index.ts +118 -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 +111 -44
- package/src/organization-model/published.ts +172 -19
- package/src/organization-model/resolve.ts +117 -54
- package/src/organization-model/schema.ts +654 -112
- package/src/organization-model/surface-projection.ts +116 -122
- package/src/organization-model/types.ts +146 -20
- package/src/platform/api/types.ts +38 -35
- 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 +2053 -2005
- package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
- package/src/platform/registry/index.ts +14 -0
- package/src/platform/registry/resource-registry.ts +52 -2
- package/src/platform/registry/serialization.ts +241 -202
- package/src/platform/registry/serialized-types.ts +1 -0
- package/src/platform/registry/types.ts +411 -361
- package/src/platform/registry/validation.ts +745 -513
- package/src/projects/api-schemas.ts +290 -267
- package/src/reference/_generated/contracts.md +853 -397
- package/src/reference/glossary.md +23 -18
- package/src/supabase/database.types.ts +181 -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
|
@@ -3,11 +3,14 @@ import {
|
|
|
3
3
|
OrgKnowledgeNodeSchema,
|
|
4
4
|
OrgKnowledgeKindSchema,
|
|
5
5
|
KnowledgeDomainSchema,
|
|
6
|
-
KnowledgeLinkSchema
|
|
6
|
+
KnowledgeLinkSchema,
|
|
7
|
+
KnowledgeTargetKindSchema,
|
|
8
|
+
KnowledgeTargetRefSchema
|
|
7
9
|
} from '../domains/knowledge'
|
|
8
10
|
import { OrganizationGraphEdgeKindSchema } from '../graph/schema'
|
|
9
11
|
import { buildOrganizationGraph } from '../graph/build'
|
|
10
12
|
import { DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE } from '../defaults'
|
|
13
|
+
import { resolveOrganizationModel } from '../resolve'
|
|
11
14
|
import type { OrganizationModel } from '../types'
|
|
12
15
|
|
|
13
16
|
// ---------------------------------------------------------------------------
|
|
@@ -74,6 +77,15 @@ describe('OrgKnowledgeNodeSchema', () => {
|
|
|
74
77
|
expect(node.ownerIds).toEqual([])
|
|
75
78
|
})
|
|
76
79
|
|
|
80
|
+
it('accepts role ids as knowledge owners', () => {
|
|
81
|
+
const node = OrgKnowledgeNodeSchema.parse({
|
|
82
|
+
...makeNode('strategy'),
|
|
83
|
+
ownerIds: ['role.ops-lead', 'role.ceo']
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
expect(node.ownerIds).toEqual(['role.ops-lead', 'role.ceo'])
|
|
87
|
+
})
|
|
88
|
+
|
|
77
89
|
it('accepts an optional semantic icon token', () => {
|
|
78
90
|
const node = OrgKnowledgeNodeSchema.parse({
|
|
79
91
|
...makeNode('playbook'),
|
|
@@ -91,6 +103,54 @@ describe('OrgKnowledgeNodeSchema', () => {
|
|
|
91
103
|
|
|
92
104
|
expect(result.success).toBe(false)
|
|
93
105
|
})
|
|
106
|
+
|
|
107
|
+
it('accepts an optional externalUrl', () => {
|
|
108
|
+
const node = OrgKnowledgeNodeSchema.parse({
|
|
109
|
+
...makeNode('reference'),
|
|
110
|
+
externalUrl: 'https://docs.elevasis.com/technical/architecture'
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
expect(node.externalUrl).toBe('https://docs.elevasis.com/technical/architecture')
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('rejects an invalid externalUrl', () => {
|
|
117
|
+
const result = OrgKnowledgeNodeSchema.safeParse({
|
|
118
|
+
...makeNode('reference'),
|
|
119
|
+
externalUrl: 'not-a-url'
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
expect(result.success).toBe(false)
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
describe('resolveOrganizationModel with knowledge owner roles', () => {
|
|
127
|
+
const node = {
|
|
128
|
+
id: 'knowledge.test-owner',
|
|
129
|
+
kind: 'playbook' as const,
|
|
130
|
+
title: 'Owned Knowledge',
|
|
131
|
+
summary: 'A knowledge node with role ownership.',
|
|
132
|
+
body: '## Body\n\nContent.',
|
|
133
|
+
ownerIds: ['role.ops-lead'],
|
|
134
|
+
updatedAt: '2026-05-08'
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
it('passes when ownerIds reference declared role ids', () => {
|
|
138
|
+
expect(() =>
|
|
139
|
+
resolveOrganizationModel({
|
|
140
|
+
roles: { 'role.ops-lead': { id: 'role.ops-lead', order: 10, title: 'Ops Lead' } },
|
|
141
|
+
// Phase 4: knowledge is a flat Record<id, OrgKnowledgeNode>
|
|
142
|
+
knowledge: { 'knowledge.test-owner': node }
|
|
143
|
+
})
|
|
144
|
+
).not.toThrow()
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('throws when ownerIds reference unknown role ids', () => {
|
|
148
|
+
expect(() =>
|
|
149
|
+
resolveOrganizationModel({
|
|
150
|
+
knowledge: { 'knowledge.test-owner': node }
|
|
151
|
+
})
|
|
152
|
+
).toThrow(/unknown owner role/)
|
|
153
|
+
})
|
|
94
154
|
})
|
|
95
155
|
|
|
96
156
|
// ---------------------------------------------------------------------------
|
|
@@ -121,60 +181,79 @@ describe('OrganizationGraphEdgeKindSchema', () => {
|
|
|
121
181
|
})
|
|
122
182
|
|
|
123
183
|
// ---------------------------------------------------------------------------
|
|
124
|
-
// DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE —
|
|
184
|
+
// DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE — Phase 4: flat Record<id, OrgKnowledgeNode> (D3).
|
|
185
|
+
// The wrapper shape { version, lastModified, nodes[] } was removed; versioning
|
|
186
|
+
// is in domainMetadata.knowledge. The default is an empty map {}.
|
|
125
187
|
// ---------------------------------------------------------------------------
|
|
126
188
|
|
|
127
189
|
describe('DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE', () => {
|
|
128
|
-
it('
|
|
129
|
-
expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
|
|
190
|
+
it('is an empty object (flat map with no pre-seeded nodes)', () => {
|
|
191
|
+
expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE).toEqual({})
|
|
130
192
|
})
|
|
131
193
|
|
|
132
194
|
it('passes KnowledgeDomainSchema.parse without throwing', () => {
|
|
133
195
|
expect(() => KnowledgeDomainSchema.parse(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE)).not.toThrow()
|
|
134
196
|
})
|
|
197
|
+
|
|
198
|
+
it('does not have a .nodes array (wrapper shape was removed in Phase 4)', () => {
|
|
199
|
+
expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE).not.toHaveProperty('nodes')
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
it('does not have a .version field (moved to domainMetadata.knowledge)', () => {
|
|
203
|
+
expect(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE).not.toHaveProperty('version')
|
|
204
|
+
})
|
|
135
205
|
})
|
|
136
206
|
|
|
137
207
|
// ---------------------------------------------------------------------------
|
|
138
208
|
// buildOrganizationGraph — knowledge nodes + governs edges
|
|
139
|
-
// Synthetic OM
|
|
140
|
-
// knowledge nodes (empty after Wave 2a, Decision 2-B).
|
|
209
|
+
// Synthetic OM authored via flat Record<id, OrgKnowledgeNode> per Phase 4 schema.
|
|
141
210
|
// ---------------------------------------------------------------------------
|
|
142
211
|
|
|
212
|
+
// Phase 4: knowledge is a flat Record<id, OrgKnowledgeNode> — no .nodes array wrapper.
|
|
143
213
|
const SYNTHETIC_OM: OrganizationModel = {
|
|
144
214
|
...DEFAULT_ORGANIZATION_MODEL,
|
|
215
|
+
systems: Object.fromEntries(
|
|
216
|
+
Object.entries(DEFAULT_ORGANIZATION_MODEL.systems).map(([key, system]) => [
|
|
217
|
+
key,
|
|
218
|
+
key === 'sales.crm' || key === 'sales.lead-gen'
|
|
219
|
+
? { ...system, governedByKnowledge: ['knowledge.test-playbook-1'] }
|
|
220
|
+
: system
|
|
221
|
+
])
|
|
222
|
+
),
|
|
145
223
|
knowledge: {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
224
|
+
'knowledge.test-playbook-1': {
|
|
225
|
+
id: 'knowledge.test-playbook-1',
|
|
226
|
+
kind: 'playbook',
|
|
227
|
+
title: 'Test Playbook',
|
|
228
|
+
summary: 'Test playbook summary.',
|
|
229
|
+
body: '## Overview\n\nContent.',
|
|
230
|
+
links: [
|
|
231
|
+
{ target: { kind: 'system', id: 'sales.crm' }, nodeId: 'system:sales.crm' },
|
|
232
|
+
{ target: { kind: 'system', id: 'sales.lead-gen' }, nodeId: 'system:sales.lead-gen' }
|
|
233
|
+
],
|
|
234
|
+
ownerIds: [],
|
|
235
|
+
updatedAt: '2026-01-01'
|
|
236
|
+
},
|
|
237
|
+
'knowledge.test-strategy-1': {
|
|
238
|
+
id: 'knowledge.test-strategy-1',
|
|
239
|
+
kind: 'strategy',
|
|
240
|
+
title: 'Test Strategy',
|
|
241
|
+
summary: 'Test strategy summary.',
|
|
242
|
+
body: '## Strategy\n\nContent.',
|
|
243
|
+
links: [],
|
|
244
|
+
ownerIds: [],
|
|
245
|
+
updatedAt: '2026-01-02'
|
|
246
|
+
},
|
|
247
|
+
'knowledge.test-reference-1': {
|
|
248
|
+
id: 'knowledge.test-reference-1',
|
|
249
|
+
kind: 'reference',
|
|
250
|
+
title: 'Test Reference',
|
|
251
|
+
summary: 'Test reference summary.',
|
|
252
|
+
body: '## Reference\n\nContent.',
|
|
253
|
+
links: [],
|
|
254
|
+
ownerIds: [],
|
|
255
|
+
updatedAt: '2026-01-03'
|
|
256
|
+
}
|
|
178
257
|
}
|
|
179
258
|
}
|
|
180
259
|
|
|
@@ -183,11 +262,11 @@ describe('buildOrganizationGraph with knowledge', () => {
|
|
|
183
262
|
|
|
184
263
|
it('emits a knowledge node for each synthetic node', () => {
|
|
185
264
|
const knowledgeNodes = graph.nodes.filter((n) => n.kind === 'knowledge')
|
|
186
|
-
expect(knowledgeNodes.length).toBe(SYNTHETIC_OM.knowledge.
|
|
265
|
+
expect(knowledgeNodes.length).toBe(Object.keys(SYNTHETIC_OM.knowledge).length)
|
|
187
266
|
})
|
|
188
267
|
|
|
189
268
|
it('knowledge nodes carry sourceId matching the OM node id', () => {
|
|
190
|
-
for (const omNode of SYNTHETIC_OM.knowledge
|
|
269
|
+
for (const omNode of Object.values(SYNTHETIC_OM.knowledge)) {
|
|
191
270
|
const graphNode = graph.nodes.find((n) => n.sourceId === omNode.id)
|
|
192
271
|
expect(graphNode).toBeDefined()
|
|
193
272
|
expect(graphNode?.kind).toBe('knowledge')
|
|
@@ -197,12 +276,12 @@ describe('buildOrganizationGraph with knowledge', () => {
|
|
|
197
276
|
|
|
198
277
|
it('emits governs edges for nodes that have links', () => {
|
|
199
278
|
const governsEdges = graph.edges.filter((e) => e.kind === 'governs')
|
|
200
|
-
const totalLinks = SYNTHETIC_OM.knowledge.
|
|
279
|
+
const totalLinks = Object.values(SYNTHETIC_OM.knowledge).reduce((sum, n) => sum + n.links.length, 0)
|
|
201
280
|
expect(governsEdges.length).toBe(totalLinks)
|
|
202
281
|
})
|
|
203
282
|
|
|
204
283
|
it('links targetId resolves to an existing graph node id for at least one node', () => {
|
|
205
|
-
const nodeWithLinks = SYNTHETIC_OM.knowledge.
|
|
284
|
+
const nodeWithLinks = Object.values(SYNTHETIC_OM.knowledge).find((n) => n.links.length > 0)
|
|
206
285
|
expect(nodeWithLinks).toBeDefined()
|
|
207
286
|
|
|
208
287
|
const graphNodeIds = new Set(graph.nodes.map((n) => n.id))
|
|
@@ -223,9 +302,22 @@ describe('buildOrganizationGraph with knowledge', () => {
|
|
|
223
302
|
// ---------------------------------------------------------------------------
|
|
224
303
|
|
|
225
304
|
describe('KnowledgeLinkSchema', () => {
|
|
226
|
-
it('accepts a
|
|
227
|
-
|
|
228
|
-
|
|
305
|
+
it('accepts and normalizes a canonical typed target', () => {
|
|
306
|
+
const link = KnowledgeLinkSchema.parse({ target: { kind: 'system', id: 'sales.crm' } })
|
|
307
|
+
|
|
308
|
+
expect(link).toEqual({
|
|
309
|
+
target: { kind: 'system', id: 'sales.crm' },
|
|
310
|
+
nodeId: 'system:sales.crm'
|
|
311
|
+
})
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
it('accepts and normalizes a legacy kind:dotted-path nodeId', () => {
|
|
315
|
+
const link = KnowledgeLinkSchema.parse({ nodeId: 'system:sales.lead-gen' })
|
|
316
|
+
|
|
317
|
+
expect(link).toEqual({
|
|
318
|
+
target: { kind: 'system', id: 'sales.lead-gen' },
|
|
319
|
+
nodeId: 'system:sales.lead-gen'
|
|
320
|
+
})
|
|
229
321
|
})
|
|
230
322
|
|
|
231
323
|
it('accepts resource: and knowledge: prefixed node IDs', () => {
|
|
@@ -233,8 +325,11 @@ describe('KnowledgeLinkSchema', () => {
|
|
|
233
325
|
expect(() => KnowledgeLinkSchema.parse({ nodeId: 'knowledge:knowledge.test-doc' })).not.toThrow()
|
|
234
326
|
})
|
|
235
327
|
|
|
328
|
+
it('accepts content-node: prefixed node IDs (D4 — KnowledgeTargetKindSchema includes content-node)', () => {
|
|
329
|
+
expect(() => KnowledgeLinkSchema.parse({ nodeId: 'content-node:sales.crm:default-pipeline' })).not.toThrow()
|
|
330
|
+
})
|
|
331
|
+
|
|
236
332
|
it('rejects a bare dotted ID with no kind: prefix', () => {
|
|
237
|
-
// NodeIdStringSchema requires kind:dotted-path format
|
|
238
333
|
expect(KnowledgeLinkSchema.safeParse({ nodeId: 'sales.crm' }).success).toBe(false)
|
|
239
334
|
})
|
|
240
335
|
|
|
@@ -243,8 +338,7 @@ describe('KnowledgeLinkSchema', () => {
|
|
|
243
338
|
})
|
|
244
339
|
|
|
245
340
|
it('rejects a nodeId with uppercase characters', () => {
|
|
246
|
-
|
|
247
|
-
expect(KnowledgeLinkSchema.safeParse({ nodeId: 'Feature:Sales.CRM' }).success).toBe(false)
|
|
341
|
+
expect(KnowledgeLinkSchema.safeParse({ nodeId: 'system:Sales.CRM' }).success).toBe(false)
|
|
248
342
|
})
|
|
249
343
|
|
|
250
344
|
it('rejects a link missing the nodeId field', () => {
|
|
@@ -256,6 +350,73 @@ describe('KnowledgeLinkSchema', () => {
|
|
|
256
350
|
})
|
|
257
351
|
})
|
|
258
352
|
|
|
353
|
+
describe('KnowledgeTargetRefSchema', () => {
|
|
354
|
+
it('accepts modeled target kinds', () => {
|
|
355
|
+
expect(KnowledgeTargetRefSchema.safeParse({ kind: 'system', id: 'sales.crm' }).success).toBe(true)
|
|
356
|
+
expect(KnowledgeTargetRefSchema.safeParse({ kind: 'customer-segment', id: 'customer.enterprise' }).success).toBe(
|
|
357
|
+
true
|
|
358
|
+
)
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
it('accepts content-node as a target kind (D4)', () => {
|
|
362
|
+
expect(KnowledgeTargetKindSchema.safeParse('content-node').success).toBe(true)
|
|
363
|
+
expect(KnowledgeTargetRefSchema.safeParse({ kind: 'content-node', id: 'sales.crm:default-pipeline' }).success).toBe(
|
|
364
|
+
true
|
|
365
|
+
)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
it('rejects unknown target kinds', () => {
|
|
369
|
+
expect(KnowledgeTargetKindSchema.safeParse('integration').success).toBe(false)
|
|
370
|
+
expect(KnowledgeTargetRefSchema.safeParse({ kind: 'integration', id: 'hubspot' }).success).toBe(false)
|
|
371
|
+
})
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
// ---------------------------------------------------------------------------
|
|
375
|
+
// KnowledgeDomainSchema — flat Record shape (Phase 4 D3)
|
|
376
|
+
// ---------------------------------------------------------------------------
|
|
377
|
+
|
|
378
|
+
describe('KnowledgeDomainSchema — flat Record<id, OrgKnowledgeNode>', () => {
|
|
379
|
+
it('accepts an empty map', () => {
|
|
380
|
+
expect(KnowledgeDomainSchema.safeParse({}).success).toBe(true)
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
it('defaults to empty map when undefined', () => {
|
|
384
|
+
const result = KnowledgeDomainSchema.safeParse(undefined)
|
|
385
|
+
expect(result.success).toBe(true)
|
|
386
|
+
if (result.success) {
|
|
387
|
+
expect(result.data).toEqual({})
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
it('accepts a Record keyed by knowledge node ids', () => {
|
|
392
|
+
const result = KnowledgeDomainSchema.safeParse({
|
|
393
|
+
'knowledge.my-playbook': {
|
|
394
|
+
id: 'knowledge.my-playbook',
|
|
395
|
+
kind: 'playbook',
|
|
396
|
+
title: 'My Playbook',
|
|
397
|
+
summary: 'A test playbook.',
|
|
398
|
+
body: '## Content',
|
|
399
|
+
links: [],
|
|
400
|
+
ownerIds: [],
|
|
401
|
+
updatedAt: '2026-05-01'
|
|
402
|
+
}
|
|
403
|
+
})
|
|
404
|
+
expect(result.success).toBe(true)
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
it('rejects the old wrapper shape { version, lastModified, nodes[] }', () => {
|
|
408
|
+
// The old wrapper-with-array shape does not parse as a Record<id, OrgKnowledgeNode>
|
|
409
|
+
const result = KnowledgeDomainSchema.safeParse({
|
|
410
|
+
version: 1,
|
|
411
|
+
lastModified: '2026-05-10',
|
|
412
|
+
nodes: []
|
|
413
|
+
})
|
|
414
|
+
// Each key ('version', 'lastModified', 'nodes') would be parsed as a knowledge node id,
|
|
415
|
+
// and the values are not valid OrgKnowledgeNodeSchema — so this should fail
|
|
416
|
+
expect(result.success).toBe(false)
|
|
417
|
+
})
|
|
418
|
+
})
|
|
419
|
+
|
|
259
420
|
// ---------------------------------------------------------------------------
|
|
260
421
|
// OrgKnowledgeNodeSchema — field length constraints
|
|
261
422
|
// ---------------------------------------------------------------------------
|
|
@@ -308,7 +469,6 @@ describe('OrgKnowledgeNodeSchema length constraints', () => {
|
|
|
308
469
|
})
|
|
309
470
|
|
|
310
471
|
it('rejects id with uppercase characters', () => {
|
|
311
|
-
// ModelIdSchema requires lowercase kebab/dot/underscore separated IDs
|
|
312
472
|
const result = OrgKnowledgeNodeSchema.safeParse({ ...BASE, id: 'Knowledge.Test' })
|
|
313
473
|
expect(result.success).toBe(false)
|
|
314
474
|
})
|