@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
|
@@ -3,7 +3,9 @@ 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'
|
|
@@ -101,6 +103,24 @@ describe('OrgKnowledgeNodeSchema', () => {
|
|
|
101
103
|
|
|
102
104
|
expect(result.success).toBe(false)
|
|
103
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
|
+
})
|
|
104
124
|
})
|
|
105
125
|
|
|
106
126
|
describe('resolveOrganizationModel with knowledge owner roles', () => {
|
|
@@ -117,8 +137,9 @@ describe('resolveOrganizationModel with knowledge owner roles', () => {
|
|
|
117
137
|
it('passes when ownerIds reference declared role ids', () => {
|
|
118
138
|
expect(() =>
|
|
119
139
|
resolveOrganizationModel({
|
|
120
|
-
roles: {
|
|
121
|
-
|
|
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 }
|
|
122
143
|
})
|
|
123
144
|
).not.toThrow()
|
|
124
145
|
})
|
|
@@ -126,7 +147,7 @@ describe('resolveOrganizationModel with knowledge owner roles', () => {
|
|
|
126
147
|
it('throws when ownerIds reference unknown role ids', () => {
|
|
127
148
|
expect(() =>
|
|
128
149
|
resolveOrganizationModel({
|
|
129
|
-
knowledge: {
|
|
150
|
+
knowledge: { 'knowledge.test-owner': node }
|
|
130
151
|
})
|
|
131
152
|
).toThrow(/unknown owner role/)
|
|
132
153
|
})
|
|
@@ -160,60 +181,79 @@ describe('OrganizationGraphEdgeKindSchema', () => {
|
|
|
160
181
|
})
|
|
161
182
|
|
|
162
183
|
// ---------------------------------------------------------------------------
|
|
163
|
-
// 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 {}.
|
|
164
187
|
// ---------------------------------------------------------------------------
|
|
165
188
|
|
|
166
189
|
describe('DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE', () => {
|
|
167
|
-
it('
|
|
168
|
-
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({})
|
|
169
192
|
})
|
|
170
193
|
|
|
171
194
|
it('passes KnowledgeDomainSchema.parse without throwing', () => {
|
|
172
195
|
expect(() => KnowledgeDomainSchema.parse(DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE)).not.toThrow()
|
|
173
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
|
+
})
|
|
174
205
|
})
|
|
175
206
|
|
|
176
207
|
// ---------------------------------------------------------------------------
|
|
177
208
|
// buildOrganizationGraph — knowledge nodes + governs edges
|
|
178
|
-
// Synthetic OM
|
|
179
|
-
// knowledge nodes (empty after Wave 2a, Decision 2-B).
|
|
209
|
+
// Synthetic OM authored via flat Record<id, OrgKnowledgeNode> per Phase 4 schema.
|
|
180
210
|
// ---------------------------------------------------------------------------
|
|
181
211
|
|
|
212
|
+
// Phase 4: knowledge is a flat Record<id, OrgKnowledgeNode> — no .nodes array wrapper.
|
|
182
213
|
const SYNTHETIC_OM: OrganizationModel = {
|
|
183
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
|
+
),
|
|
184
223
|
knowledge: {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
+
}
|
|
217
257
|
}
|
|
218
258
|
}
|
|
219
259
|
|
|
@@ -222,11 +262,11 @@ describe('buildOrganizationGraph with knowledge', () => {
|
|
|
222
262
|
|
|
223
263
|
it('emits a knowledge node for each synthetic node', () => {
|
|
224
264
|
const knowledgeNodes = graph.nodes.filter((n) => n.kind === 'knowledge')
|
|
225
|
-
expect(knowledgeNodes.length).toBe(SYNTHETIC_OM.knowledge.
|
|
265
|
+
expect(knowledgeNodes.length).toBe(Object.keys(SYNTHETIC_OM.knowledge).length)
|
|
226
266
|
})
|
|
227
267
|
|
|
228
268
|
it('knowledge nodes carry sourceId matching the OM node id', () => {
|
|
229
|
-
for (const omNode of SYNTHETIC_OM.knowledge
|
|
269
|
+
for (const omNode of Object.values(SYNTHETIC_OM.knowledge)) {
|
|
230
270
|
const graphNode = graph.nodes.find((n) => n.sourceId === omNode.id)
|
|
231
271
|
expect(graphNode).toBeDefined()
|
|
232
272
|
expect(graphNode?.kind).toBe('knowledge')
|
|
@@ -236,12 +276,12 @@ describe('buildOrganizationGraph with knowledge', () => {
|
|
|
236
276
|
|
|
237
277
|
it('emits governs edges for nodes that have links', () => {
|
|
238
278
|
const governsEdges = graph.edges.filter((e) => e.kind === 'governs')
|
|
239
|
-
const totalLinks = SYNTHETIC_OM.knowledge.
|
|
279
|
+
const totalLinks = Object.values(SYNTHETIC_OM.knowledge).reduce((sum, n) => sum + n.links.length, 0)
|
|
240
280
|
expect(governsEdges.length).toBe(totalLinks)
|
|
241
281
|
})
|
|
242
282
|
|
|
243
283
|
it('links targetId resolves to an existing graph node id for at least one node', () => {
|
|
244
|
-
const nodeWithLinks = SYNTHETIC_OM.knowledge.
|
|
284
|
+
const nodeWithLinks = Object.values(SYNTHETIC_OM.knowledge).find((n) => n.links.length > 0)
|
|
245
285
|
expect(nodeWithLinks).toBeDefined()
|
|
246
286
|
|
|
247
287
|
const graphNodeIds = new Set(graph.nodes.map((n) => n.id))
|
|
@@ -262,9 +302,22 @@ describe('buildOrganizationGraph with knowledge', () => {
|
|
|
262
302
|
// ---------------------------------------------------------------------------
|
|
263
303
|
|
|
264
304
|
describe('KnowledgeLinkSchema', () => {
|
|
265
|
-
it('accepts a
|
|
266
|
-
|
|
267
|
-
|
|
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
|
+
})
|
|
268
321
|
})
|
|
269
322
|
|
|
270
323
|
it('accepts resource: and knowledge: prefixed node IDs', () => {
|
|
@@ -272,8 +325,11 @@ describe('KnowledgeLinkSchema', () => {
|
|
|
272
325
|
expect(() => KnowledgeLinkSchema.parse({ nodeId: 'knowledge:knowledge.test-doc' })).not.toThrow()
|
|
273
326
|
})
|
|
274
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
|
+
|
|
275
332
|
it('rejects a bare dotted ID with no kind: prefix', () => {
|
|
276
|
-
// NodeIdStringSchema requires kind:dotted-path format
|
|
277
333
|
expect(KnowledgeLinkSchema.safeParse({ nodeId: 'sales.crm' }).success).toBe(false)
|
|
278
334
|
})
|
|
279
335
|
|
|
@@ -282,8 +338,7 @@ describe('KnowledgeLinkSchema', () => {
|
|
|
282
338
|
})
|
|
283
339
|
|
|
284
340
|
it('rejects a nodeId with uppercase characters', () => {
|
|
285
|
-
|
|
286
|
-
expect(KnowledgeLinkSchema.safeParse({ nodeId: 'Feature:Sales.CRM' }).success).toBe(false)
|
|
341
|
+
expect(KnowledgeLinkSchema.safeParse({ nodeId: 'system:Sales.CRM' }).success).toBe(false)
|
|
287
342
|
})
|
|
288
343
|
|
|
289
344
|
it('rejects a link missing the nodeId field', () => {
|
|
@@ -295,6 +350,73 @@ describe('KnowledgeLinkSchema', () => {
|
|
|
295
350
|
})
|
|
296
351
|
})
|
|
297
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
|
+
|
|
298
420
|
// ---------------------------------------------------------------------------
|
|
299
421
|
// OrgKnowledgeNodeSchema — field length constraints
|
|
300
422
|
// ---------------------------------------------------------------------------
|
|
@@ -347,7 +469,6 @@ describe('OrgKnowledgeNodeSchema length constraints', () => {
|
|
|
347
469
|
})
|
|
348
470
|
|
|
349
471
|
it('rejects id with uppercase characters', () => {
|
|
350
|
-
// ModelIdSchema requires lowercase kebab/dot/underscore separated IDs
|
|
351
472
|
const result = OrgKnowledgeNodeSchema.safeParse({ ...BASE, id: 'Knowledge.Test' })
|
|
352
473
|
expect(result.success).toBe(false)
|
|
353
474
|
})
|