@elevasis/core 0.26.0 → 0.28.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 +162 -105
- package/dist/index.js +280 -174
- package/dist/knowledge/index.d.ts +43 -43
- package/dist/organization-model/index.d.ts +162 -105
- package/dist/organization-model/index.js +280 -174
- package/dist/test-utils/index.d.ts +20 -20
- package/dist/test-utils/index.js +184 -126
- package/package.json +3 -3
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +976 -1063
- package/src/business/acquisition/api-schemas.test.ts +1962 -1841
- package/src/business/acquisition/api-schemas.ts +1461 -1464
- package/src/business/acquisition/crm-next-action.test.ts +45 -25
- package/src/business/acquisition/crm-next-action.ts +227 -220
- package/src/business/acquisition/crm-priority.test.ts +41 -8
- package/src/business/acquisition/crm-priority.ts +365 -349
- package/src/business/acquisition/crm-state-actions.test.ts +208 -153
- package/src/business/acquisition/derive-actions.test.ts +90 -13
- package/src/business/acquisition/derive-actions.ts +8 -139
- package/src/business/acquisition/ontology-validation.ts +72 -158
- package/src/business/pdf/sections/investment.ts +1 -1
- package/src/business/pdf/sections/summary-investment.ts +1 -1
- package/src/execution/engine/tools/tool-maps.ts +872 -831
- package/src/organization-model/__tests__/cross-ref.test.ts +167 -0
- package/src/organization-model/__tests__/define-domain-record.test.ts +289 -0
- package/src/organization-model/__tests__/om-spine-doc-contract.test.ts +56 -0
- package/src/organization-model/__tests__/published-zero-leak.test.ts +60 -1
- package/src/organization-model/__tests__/resolve.test.ts +1 -1
- package/src/organization-model/__tests__/schema-refinements.test.ts +72 -0
- package/src/organization-model/cross-ref.ts +175 -0
- package/src/organization-model/domains/actions.ts +13 -0
- package/src/organization-model/domains/branding.ts +6 -6
- package/src/organization-model/domains/customers.ts +95 -78
- package/src/organization-model/domains/entities.ts +157 -144
- package/src/organization-model/domains/goals.ts +100 -83
- package/src/organization-model/domains/knowledge.ts +106 -93
- package/src/organization-model/domains/offerings.ts +88 -71
- package/src/organization-model/domains/policies.ts +115 -102
- package/src/organization-model/domains/roles.ts +109 -96
- package/src/organization-model/domains/sales.test.ts +104 -218
- package/src/organization-model/domains/sales.ts +212 -375
- package/src/organization-model/domains/statuses.ts +351 -339
- package/src/organization-model/domains/systems.ts +176 -164
- package/src/organization-model/helpers.ts +331 -306
- package/src/organization-model/index.ts +43 -0
- package/src/organization-model/published.ts +27 -2
- package/src/organization-model/schema-refinements.ts +667 -0
- package/src/organization-model/schema.ts +8 -715
- package/src/platform/constants/versions.ts +1 -1
- package/src/reference/_generated/contracts.md +1000 -1087
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe shared cross-reference index for the Organization Model.
|
|
3
|
+
*
|
|
4
|
+
* This module is the single source of truth for OM cross-reference resolution.
|
|
5
|
+
* It is consumed by:
|
|
6
|
+
* - `OrganizationModelSchema.superRefine` (Zod validation, browser-safe)
|
|
7
|
+
* - `packages/cli/src/knowledge/verify.ts` (CLI gate, Node-only)
|
|
8
|
+
*
|
|
9
|
+
* INVARIANT: No Node.js builtins, no `@repo/elevasis-core` import, no dynamic import().
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { compileOrganizationOntology } from './ontology'
|
|
13
|
+
import { listAllSystems } from './helpers'
|
|
14
|
+
import type { OntologyKind } from './ontology'
|
|
15
|
+
import type { OrganizationModel } from './types'
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Shared key-to-kind map
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Maps ontology reference field keys (as they appear inside ontology records
|
|
23
|
+
* and resource ontology bindings) to their expected OntologyKind.
|
|
24
|
+
*
|
|
25
|
+
* Single source of truth — replaces both the byte-identical
|
|
26
|
+
* `ontologyReferenceKeyKinds` in `schema.ts` and `genericReferenceKeyKinds`
|
|
27
|
+
* in `verify.ts`.
|
|
28
|
+
*/
|
|
29
|
+
export const ONTOLOGY_REFERENCE_KEY_KINDS: Record<string, OntologyKind> = {
|
|
30
|
+
valueType: 'value-type',
|
|
31
|
+
catalogType: 'catalog',
|
|
32
|
+
objectType: 'object',
|
|
33
|
+
eventType: 'event',
|
|
34
|
+
actionType: 'action',
|
|
35
|
+
linkType: 'link',
|
|
36
|
+
interfaceType: 'interface',
|
|
37
|
+
propertyType: 'property',
|
|
38
|
+
groupType: 'group',
|
|
39
|
+
surfaceType: 'surface',
|
|
40
|
+
stepCatalog: 'catalog'
|
|
41
|
+
} satisfies Record<string, OntologyKind>
|
|
42
|
+
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Cross-reference index
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Pre-built look-up sets derived from a resolved OrganizationModel.
|
|
49
|
+
* Built once, then consumed by both validation paths (superRefine + verify.ts).
|
|
50
|
+
*/
|
|
51
|
+
export interface OmCrossRefIndex {
|
|
52
|
+
/**
|
|
53
|
+
* Systems keyed by BOTH dotted path (e.g. "sales.lead-gen") AND system.id.
|
|
54
|
+
* Value is opaque (`unknown`) — consumers only call `.has()`.
|
|
55
|
+
*/
|
|
56
|
+
systemsById: Map<string, unknown>
|
|
57
|
+
resourceIds: Set<string>
|
|
58
|
+
knowledgeIds: Set<string>
|
|
59
|
+
roleIds: Set<string>
|
|
60
|
+
goalIds: Set<string>
|
|
61
|
+
actionIds: Set<string>
|
|
62
|
+
customerSegmentIds: Set<string>
|
|
63
|
+
offeringIds: Set<string>
|
|
64
|
+
ontologyIds: Set<string>
|
|
65
|
+
/** Ontology records indexed by kind (value is a plain id→record map). */
|
|
66
|
+
ontologyIndexByKind: Record<OntologyKind, Record<string, unknown>>
|
|
67
|
+
/** IDs of individual stage entries from all catalogs with `kind === 'stage'`. */
|
|
68
|
+
stageIds: Set<string>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Build the OmCrossRefIndex from a resolved OrganizationModel.
|
|
73
|
+
*
|
|
74
|
+
* Call once per validation pass and share the result across all checks.
|
|
75
|
+
*/
|
|
76
|
+
export function buildOmCrossRefIndex(model: OrganizationModel): OmCrossRefIndex {
|
|
77
|
+
// Systems: keyed by path AND by system.id (path-OR-id resolution)
|
|
78
|
+
const systemsById = new Map<string, unknown>()
|
|
79
|
+
for (const { path, system } of listAllSystems(model)) {
|
|
80
|
+
systemsById.set(path, system)
|
|
81
|
+
systemsById.set(system.id, system)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const resourceIds = new Set(Object.keys(model.resources ?? {}))
|
|
85
|
+
const knowledgeIds = new Set(Object.keys(model.knowledge ?? {}))
|
|
86
|
+
const roleIds = new Set(Object.keys(model.roles ?? {}))
|
|
87
|
+
const goalIds = new Set(Object.keys(model.goals ?? {}))
|
|
88
|
+
const actionIds = new Set(Object.keys(model.actions ?? {}))
|
|
89
|
+
const customerSegmentIds = new Set(Object.keys(model.customers ?? {}))
|
|
90
|
+
const offeringIds = new Set(Object.keys(model.offerings ?? {}))
|
|
91
|
+
|
|
92
|
+
const ontologyCompilation = compileOrganizationOntology(model)
|
|
93
|
+
|
|
94
|
+
const ontologyIndexByKind: Record<OntologyKind, Record<string, unknown>> = {
|
|
95
|
+
object: ontologyCompilation.ontology.objectTypes,
|
|
96
|
+
link: ontologyCompilation.ontology.linkTypes,
|
|
97
|
+
action: ontologyCompilation.ontology.actionTypes,
|
|
98
|
+
catalog: ontologyCompilation.ontology.catalogTypes,
|
|
99
|
+
event: ontologyCompilation.ontology.eventTypes,
|
|
100
|
+
interface: ontologyCompilation.ontology.interfaceTypes,
|
|
101
|
+
'value-type': ontologyCompilation.ontology.valueTypes,
|
|
102
|
+
property: ontologyCompilation.ontology.sharedProperties,
|
|
103
|
+
group: ontologyCompilation.ontology.groups,
|
|
104
|
+
surface: ontologyCompilation.ontology.surfaces
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)))
|
|
108
|
+
|
|
109
|
+
// Stage IDs: entry keys from all catalogs whose kind === 'stage'
|
|
110
|
+
const stageIds = new Set<string>()
|
|
111
|
+
for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
|
|
112
|
+
if ((catalog as { kind?: string }).kind !== 'stage') continue
|
|
113
|
+
const entries = (catalog as { entries?: Record<string, unknown> }).entries
|
|
114
|
+
if (entries !== undefined) {
|
|
115
|
+
for (const stageId of Object.keys(entries)) {
|
|
116
|
+
stageIds.add(stageId)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
systemsById,
|
|
123
|
+
resourceIds,
|
|
124
|
+
knowledgeIds,
|
|
125
|
+
roleIds,
|
|
126
|
+
goalIds,
|
|
127
|
+
actionIds,
|
|
128
|
+
customerSegmentIds,
|
|
129
|
+
offeringIds,
|
|
130
|
+
ontologyIds,
|
|
131
|
+
ontologyIndexByKind,
|
|
132
|
+
stageIds
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// Canonical resolution functions
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The ONLY definition of which (kind, id) knowledge-link targets resolve.
|
|
142
|
+
*
|
|
143
|
+
* Fixes two confirmed divergences vs. the old inline `exists()` in verify.ts:
|
|
144
|
+
* 1. `kind === 'stage'` — previously missing in verify.ts, causing a false-positive error.
|
|
145
|
+
* 2. `kind === 'system'` — resolves via `systemsById` which is keyed by BOTH path AND
|
|
146
|
+
* `system.id`, so a system referenced by its id (not its dotted path) is also found.
|
|
147
|
+
*/
|
|
148
|
+
export function knowledgeTargetExists(index: OmCrossRefIndex, kind: string, id: string): boolean {
|
|
149
|
+
if (kind === 'system') return index.systemsById.has(id)
|
|
150
|
+
if (kind === 'resource') return index.resourceIds.has(id)
|
|
151
|
+
if (kind === 'knowledge') return index.knowledgeIds.has(id)
|
|
152
|
+
if (kind === 'stage') return index.stageIds.has(id)
|
|
153
|
+
if (kind === 'action') return index.actionIds.has(id)
|
|
154
|
+
if (kind === 'role') return index.roleIds.has(id)
|
|
155
|
+
if (kind === 'goal') return index.goalIds.has(id)
|
|
156
|
+
if (kind === 'customer-segment') return index.customerSegmentIds.has(id)
|
|
157
|
+
if (kind === 'offering') return index.offeringIds.has(id)
|
|
158
|
+
if (kind === 'ontology') return index.ontologyIds.has(id)
|
|
159
|
+
return false
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Returns `true` when a resource ontology binding references an ontology ID
|
|
164
|
+
* that does not exist in the compiled index for the expected kind.
|
|
165
|
+
*
|
|
166
|
+
* Shared between `schema.ts` resource-ontology binding validation and
|
|
167
|
+
* `verify.ts` resource ontology reference checks.
|
|
168
|
+
*/
|
|
169
|
+
export function resourceOntologyBindingMissing(
|
|
170
|
+
index: OmCrossRefIndex,
|
|
171
|
+
expectedKind: OntologyKind,
|
|
172
|
+
ontologyId: string
|
|
173
|
+
): boolean {
|
|
174
|
+
return index.ontologyIndexByKind[expectedKind][ontologyId] === undefined
|
|
175
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { EntityIdSchema } from './entities'
|
|
3
3
|
import { DescriptionSchema, LabelSchema, ModelIdSchema } from './shared'
|
|
4
|
+
import { defineDomainRecord } from '../helpers'
|
|
4
5
|
|
|
5
6
|
export const ActionResourceIdSchema = z
|
|
6
7
|
.string()
|
|
@@ -107,6 +108,18 @@ export function findOrganizationActionById(
|
|
|
107
108
|
return actions[id]
|
|
108
109
|
}
|
|
109
110
|
|
|
111
|
+
/** Validate and return a single action entry. */
|
|
112
|
+
export function defineAction(entry: z.input<typeof ActionSchema>): z.infer<typeof ActionSchema> {
|
|
113
|
+
return ActionSchema.parse(entry)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Validate and return an id-keyed map of action entries. */
|
|
117
|
+
export function defineActions(
|
|
118
|
+
entries: readonly z.input<typeof ActionSchema>[]
|
|
119
|
+
): Record<string, z.infer<typeof ActionSchema>> {
|
|
120
|
+
return defineDomainRecord(ActionSchema, entries)
|
|
121
|
+
}
|
|
122
|
+
|
|
110
123
|
export type ActionId = z.infer<typeof ActionIdSchema>
|
|
111
124
|
export type ActionScope = z.infer<typeof ActionScopeSchema>
|
|
112
125
|
export type ActionRef = z.infer<typeof ActionRefSchema>
|
|
@@ -14,9 +14,9 @@ export const OrganizationModelBrandingSchema = z.object({
|
|
|
14
14
|
.default({})
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
export const DEFAULT_ORGANIZATION_MODEL_BRANDING: z.infer<typeof OrganizationModelBrandingSchema> = {
|
|
18
|
-
organizationName: 'Default Organization',
|
|
19
|
-
productName: '
|
|
20
|
-
shortName: '
|
|
21
|
-
logos: {}
|
|
22
|
-
}
|
|
17
|
+
export const DEFAULT_ORGANIZATION_MODEL_BRANDING: z.infer<typeof OrganizationModelBrandingSchema> = {
|
|
18
|
+
organizationName: 'Default Organization',
|
|
19
|
+
productName: 'Organization OS',
|
|
20
|
+
shortName: 'Org OS',
|
|
21
|
+
logos: {}
|
|
22
|
+
}
|
|
@@ -1,78 +1,95 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
order:
|
|
35
|
-
|
|
36
|
-
name
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
*
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { defineDomainRecord } from '../helpers'
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Firmographics — optional demographic/firmographic filters that describe the
|
|
6
|
+
// target customer segment's organizational profile. All fields are optional so
|
|
7
|
+
// a segment can declare only the axes relevant to targeting.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
export const FirmographicsSchema = z.object({
|
|
11
|
+
/** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
|
|
12
|
+
industry: z.string().trim().max(200).optional(),
|
|
13
|
+
/**
|
|
14
|
+
* Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
|
|
15
|
+
* Free-form string to accommodate any band notation.
|
|
16
|
+
*/
|
|
17
|
+
companySize: z.string().trim().max(100).optional(),
|
|
18
|
+
/**
|
|
19
|
+
* Primary geographic region the segment operates in or is targeted from
|
|
20
|
+
* (e.g. "North America", "Europe", "Global").
|
|
21
|
+
*/
|
|
22
|
+
region: z.string().trim().max(200).optional()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Customer segment schema — one entry per distinct buyer archetype.
|
|
27
|
+
// Modeled after Value Proposition Canvas (BMC / VPC) and Business Model Canvas
|
|
28
|
+
// customer-segment language. Fields use plain English throughout.
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
export const CustomerSegmentSchema = z.object({
|
|
32
|
+
/** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
|
|
33
|
+
id: z.string().trim().min(1).max(100),
|
|
34
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
35
|
+
order: z.number(),
|
|
36
|
+
/** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
|
|
37
|
+
name: z.string().trim().max(200).default(''),
|
|
38
|
+
/** One or two sentences describing who this segment is. */
|
|
39
|
+
description: z.string().trim().max(2000).default(''),
|
|
40
|
+
/**
|
|
41
|
+
* The primary job(s) this segment is trying to get done — the goal they hire
|
|
42
|
+
* a product/service to accomplish. Plain-language narrative or bullet list.
|
|
43
|
+
*/
|
|
44
|
+
jobsToBeDone: z.string().trim().max(2000).default(''),
|
|
45
|
+
/**
|
|
46
|
+
* Pains — frustrations, obstacles, and risks the segment experiences
|
|
47
|
+
* when trying to accomplish their jobs-to-be-done.
|
|
48
|
+
*/
|
|
49
|
+
pains: z.array(z.string().trim().max(500)).default([]),
|
|
50
|
+
/**
|
|
51
|
+
* Gains — outcomes and benefits the segment desires; positive motivators
|
|
52
|
+
* beyond merely resolving pains.
|
|
53
|
+
*/
|
|
54
|
+
gains: z.array(z.string().trim().max(500)).default([]),
|
|
55
|
+
/** Firmographic profile for targeting and filtering. */
|
|
56
|
+
firmographics: FirmographicsSchema.default({}),
|
|
57
|
+
/**
|
|
58
|
+
* Value proposition — one or two sentences stating why this organization's
|
|
59
|
+
* offering is uniquely suited for this segment's needs.
|
|
60
|
+
*/
|
|
61
|
+
valueProp: z.string().trim().max(2000).default('')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Customers domain schema — id-keyed map of customer segments.
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
export const CustomersDomainSchema = z
|
|
69
|
+
.record(z.string(), CustomerSegmentSchema)
|
|
70
|
+
.refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
71
|
+
message: 'Each segment entry id must match its map key'
|
|
72
|
+
})
|
|
73
|
+
.default({})
|
|
74
|
+
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Seed — empty by default; adapters populate with real segment definitions.
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
export const DEFAULT_ORGANIZATION_MODEL_CUSTOMERS: z.infer<typeof CustomersDomainSchema> = {}
|
|
80
|
+
|
|
81
|
+
/** Validate and return a single customer segment entry. */
|
|
82
|
+
export function defineCustomer(entry: z.input<typeof CustomerSegmentSchema>): z.infer<typeof CustomerSegmentSchema> {
|
|
83
|
+
return CustomerSegmentSchema.parse(entry)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Validate and return an id-keyed map of customer segment entries. */
|
|
87
|
+
export function defineCustomers(
|
|
88
|
+
entries: readonly z.input<typeof CustomerSegmentSchema>[]
|
|
89
|
+
): Record<string, z.infer<typeof CustomerSegmentSchema>> {
|
|
90
|
+
return defineDomainRecord(CustomerSegmentSchema, entries)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type CustomerSegment = z.infer<typeof CustomerSegmentSchema>
|
|
94
|
+
export type CustomersDomain = z.infer<typeof CustomersDomainSchema>
|
|
95
|
+
export type Firmographics = z.infer<typeof FirmographicsSchema>
|