@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
package/dist/index.js
CHANGED
|
@@ -1,6 +1,190 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
// src/organization-model/schema.ts
|
|
4
|
+
|
|
5
|
+
// src/organization-model/content-kinds/registry.ts
|
|
6
|
+
function defineContentType(def) {
|
|
7
|
+
return def;
|
|
8
|
+
}
|
|
9
|
+
var ContentNodeBaseSchema = z.object({
|
|
10
|
+
/** Human-readable label for the content node. */
|
|
11
|
+
label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
|
|
12
|
+
/** Optional one-paragraph description. */
|
|
13
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
|
|
14
|
+
/** Optional display order within the system content map. */
|
|
15
|
+
order: z.number().int().optional().meta({ label: "Order" }),
|
|
16
|
+
/**
|
|
17
|
+
* Local NodeId of the parent content node within the SAME system.
|
|
18
|
+
* Per B4/L9: MUST resolve to a sibling in the same `system.content` map.
|
|
19
|
+
* Per L19: parent and child MUST share the same `kind` (meta-category).
|
|
20
|
+
*/
|
|
21
|
+
parentContentId: z.string().trim().min(1).max(200).optional().meta({ label: "Parent content id" })
|
|
22
|
+
});
|
|
23
|
+
var ContentNodeSchema = ContentNodeBaseSchema.extend({
|
|
24
|
+
/** Meta-category (e.g. 'schema', 'config', 'knowledge', tenant-defined). */
|
|
25
|
+
kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
|
|
26
|
+
/** Specific family within the meta-category (e.g. 'pipeline', 'kv'). */
|
|
27
|
+
type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
|
|
28
|
+
/** Payload data; validated against registered payloadSchema when (kind, type) is known. */
|
|
29
|
+
data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
|
|
30
|
+
});
|
|
31
|
+
z.object({
|
|
32
|
+
/** Meta-category (tenant-defined or registry-shipped). */
|
|
33
|
+
kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
|
|
34
|
+
/** Specific family within the meta-category. */
|
|
35
|
+
type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
|
|
36
|
+
/** Human-readable label shown in the KB tree and describe views. */
|
|
37
|
+
label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
|
|
38
|
+
/** Optional description. */
|
|
39
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
|
|
40
|
+
/**
|
|
41
|
+
* Which KB tree group this extension renders in.
|
|
42
|
+
* Per L6: 'business-model' places it alongside Customers / Offerings / Goals.
|
|
43
|
+
*/
|
|
44
|
+
treeGroup: z.union([z.enum(["profile", "business-model", "systems", "graph", "governance-wiring"]), z.string().min(1).max(100)]).meta({ label: "Tree group" }),
|
|
45
|
+
/** Untyped payload; shape governed by the registered payloadSchema when available. */
|
|
46
|
+
data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
|
|
47
|
+
});
|
|
48
|
+
var PipelinePayloadSchema = z.object({
|
|
49
|
+
/**
|
|
50
|
+
* Local NodeId of the entity this pipeline applies to (e.g. 'crm.deal').
|
|
51
|
+
* `.meta({ ref: 'entity' })` enables SchemaDrivenFieldList to render a
|
|
52
|
+
* clickable graph link to the referenced entity node.
|
|
53
|
+
*/
|
|
54
|
+
entityId: z.string().trim().min(1).max(200).meta({ label: "Entity", ref: "entity", hint: "The entity type this pipeline tracks" }),
|
|
55
|
+
/**
|
|
56
|
+
* Optional Kanban column color token for UI rendering.
|
|
57
|
+
*/
|
|
58
|
+
kanbanColor: z.string().trim().min(1).max(40).optional().meta({ label: "Kanban color", hint: "UI color token" })
|
|
59
|
+
});
|
|
60
|
+
var pipelineKind = defineContentType({
|
|
61
|
+
kind: "schema",
|
|
62
|
+
type: "pipeline",
|
|
63
|
+
label: "Pipeline",
|
|
64
|
+
description: "A named progression pipeline that applies to a specific entity type.",
|
|
65
|
+
payloadSchema: PipelinePayloadSchema,
|
|
66
|
+
parentTypes: []
|
|
67
|
+
});
|
|
68
|
+
var StagePayloadSchema = z.object({
|
|
69
|
+
/**
|
|
70
|
+
* Semantic classification for this stage.
|
|
71
|
+
* Drives color, icon, and CRM-priority logic in consuming views.
|
|
72
|
+
* Optional — prospecting stages use data.entityKind instead.
|
|
73
|
+
* Enum aligned with SalesStageSemanticClassSchema (sales.ts).
|
|
74
|
+
*/
|
|
75
|
+
semanticClass: z.enum(["open", "active", "nurturing", "closed_won", "closed_lost", "won", "lost", "closed"]).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this stage", color: "blue" })
|
|
76
|
+
});
|
|
77
|
+
var stageKind = defineContentType({
|
|
78
|
+
kind: "schema",
|
|
79
|
+
type: "stage",
|
|
80
|
+
label: "Stage",
|
|
81
|
+
description: "A stage within a pipeline. Must be parented under a schema:pipeline content node.",
|
|
82
|
+
payloadSchema: StagePayloadSchema,
|
|
83
|
+
parentTypes: ["schema:pipeline"]
|
|
84
|
+
});
|
|
85
|
+
var TemplatePayloadSchema = z.object({
|
|
86
|
+
/**
|
|
87
|
+
* Optional description surfaced in the KB describe view and tooling.
|
|
88
|
+
*/
|
|
89
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description", hint: "What this template is used for" })
|
|
90
|
+
});
|
|
91
|
+
var templateKind = defineContentType({
|
|
92
|
+
kind: "schema",
|
|
93
|
+
type: "template",
|
|
94
|
+
label: "Template",
|
|
95
|
+
description: "A named build template (e.g. a prospecting pipeline sequence).",
|
|
96
|
+
payloadSchema: TemplatePayloadSchema,
|
|
97
|
+
parentTypes: []
|
|
98
|
+
});
|
|
99
|
+
var TemplateStepPayloadSchema = z.object({
|
|
100
|
+
/**
|
|
101
|
+
* Which entity type this step primarily operates on.
|
|
102
|
+
*/
|
|
103
|
+
primaryEntity: z.enum(["company", "contact"]).meta({ label: "Primary entity", hint: "Entity type this step processes", color: "blue" }),
|
|
104
|
+
/**
|
|
105
|
+
* Action key identifying the workflow action executed by this step.
|
|
106
|
+
* `.meta({ ref: 'action' })` enables SchemaDrivenFieldList to render a
|
|
107
|
+
* clickable graph link.
|
|
108
|
+
*/
|
|
109
|
+
actionKey: z.string().trim().min(1).max(200).meta({ label: "Action", ref: "action", hint: "Workflow action executed by this step" }),
|
|
110
|
+
/**
|
|
111
|
+
* IDs of sibling step local NodeIds this step depends on.
|
|
112
|
+
*/
|
|
113
|
+
dependsOn: z.array(z.string().trim().min(1).max(200)).optional().meta({ label: "Depends on", hint: "Local NodeIds of prerequisite steps" })
|
|
114
|
+
});
|
|
115
|
+
var templateStepKind = defineContentType({
|
|
116
|
+
kind: "schema",
|
|
117
|
+
type: "template-step",
|
|
118
|
+
label: "Template Step",
|
|
119
|
+
description: "A step within a build template. Must be parented under a schema:template content node.",
|
|
120
|
+
payloadSchema: TemplateStepPayloadSchema,
|
|
121
|
+
parentTypes: ["schema:template"]
|
|
122
|
+
});
|
|
123
|
+
var StatusFlowPayloadSchema = z.object({
|
|
124
|
+
/**
|
|
125
|
+
* Which entity scope this status flow governs.
|
|
126
|
+
*/
|
|
127
|
+
appliesTo: z.enum(["project", "milestone", "task"]).meta({ label: "Applies to", hint: "Entity scope governed by this status flow", color: "blue" })
|
|
128
|
+
});
|
|
129
|
+
var statusFlowKind = defineContentType({
|
|
130
|
+
kind: "schema",
|
|
131
|
+
type: "status-flow",
|
|
132
|
+
label: "Status Flow",
|
|
133
|
+
description: "A named set of statuses governing a project, milestone, or task entity.",
|
|
134
|
+
payloadSchema: StatusFlowPayloadSchema,
|
|
135
|
+
parentTypes: []
|
|
136
|
+
});
|
|
137
|
+
var StatusPayloadSchema = z.object({
|
|
138
|
+
/**
|
|
139
|
+
* Semantic classification string for this status.
|
|
140
|
+
* Free-form to allow tenant-defined classifications (e.g. 'active', 'blocked',
|
|
141
|
+
* 'completed'). Used by UI to apply color and icon fallbacks.
|
|
142
|
+
* Optional — status nodes may omit this when the label is self-descriptive.
|
|
143
|
+
*/
|
|
144
|
+
semanticClass: z.string().trim().min(1).max(100).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this status (e.g. active, blocked, completed)" }),
|
|
145
|
+
/**
|
|
146
|
+
* Optional UI color token override for this status.
|
|
147
|
+
*/
|
|
148
|
+
color: z.string().trim().min(1).max(40).optional().meta({ label: "Color", hint: "UI color token" })
|
|
149
|
+
});
|
|
150
|
+
var statusKind = defineContentType({
|
|
151
|
+
kind: "schema",
|
|
152
|
+
type: "status",
|
|
153
|
+
label: "Status",
|
|
154
|
+
description: "A single status within a status flow. Must be parented under a schema:status-flow content node.",
|
|
155
|
+
payloadSchema: StatusPayloadSchema,
|
|
156
|
+
parentTypes: ["schema:status-flow"]
|
|
157
|
+
});
|
|
158
|
+
var ConfigKvPayloadSchema = z.object({
|
|
159
|
+
/**
|
|
160
|
+
* Flat key-value entries. Values are JSON primitives.
|
|
161
|
+
* Keys are short identifiers (e.g. 'maxBatchSize', 'featureEnabled').
|
|
162
|
+
*/
|
|
163
|
+
entries: z.record(z.string().trim().min(1).max(200), z.union([z.string(), z.number(), z.boolean(), z.null()])).meta({ label: "Entries", hint: "Key-value configuration entries (string, number, boolean, or null values)" })
|
|
164
|
+
});
|
|
165
|
+
var configKvKind = defineContentType({
|
|
166
|
+
kind: "config",
|
|
167
|
+
type: "kv",
|
|
168
|
+
label: "Key-Value Config",
|
|
169
|
+
description: "A flat key-value configuration store co-located with a system. Values are JSON primitives.",
|
|
170
|
+
payloadSchema: ConfigKvPayloadSchema,
|
|
171
|
+
parentTypes: []
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// src/organization-model/content-kinds/index.ts
|
|
175
|
+
var CONTENT_KIND_REGISTRY = {
|
|
176
|
+
"schema:pipeline": pipelineKind,
|
|
177
|
+
"schema:stage": stageKind,
|
|
178
|
+
"schema:template": templateKind,
|
|
179
|
+
"schema:template-step": templateStepKind,
|
|
180
|
+
"schema:status-flow": statusFlowKind,
|
|
181
|
+
"schema:status": statusKind,
|
|
182
|
+
"config:kv": configKvKind
|
|
183
|
+
};
|
|
184
|
+
function lookupContentType(kind, type) {
|
|
185
|
+
const key = `${kind}:${type}`;
|
|
186
|
+
return CONTENT_KIND_REGISTRY[key];
|
|
187
|
+
}
|
|
4
188
|
var ORGANIZATION_MODEL_ICON_TOKENS = [
|
|
5
189
|
"nav.dashboard",
|
|
6
190
|
"nav.calendar",
|
|
@@ -112,10 +296,10 @@ DisplayMetadataSchema.extend({
|
|
|
112
296
|
id: ModelIdSchema,
|
|
113
297
|
resourceId: z.string().trim().min(1).max(255),
|
|
114
298
|
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
115
|
-
|
|
299
|
+
systemIds: ReferenceIdsSchema,
|
|
116
300
|
entityIds: ReferenceIdsSchema,
|
|
117
301
|
surfaceIds: ReferenceIdsSchema,
|
|
118
|
-
|
|
302
|
+
actionIds: ReferenceIdsSchema,
|
|
119
303
|
/** Optional tech-stack metadata for external-SaaS integrations. */
|
|
120
304
|
techStack: TechStackEntrySchema.optional()
|
|
121
305
|
});
|
|
@@ -137,654 +321,7 @@ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
|
|
|
137
321
|
shortName: "Elevasis",
|
|
138
322
|
logos: {}
|
|
139
323
|
};
|
|
140
|
-
var
|
|
141
|
-
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
142
|
-
id: ModelIdSchema,
|
|
143
|
-
order: z.number().int().min(0),
|
|
144
|
-
semanticClass: SalesStageSemanticClassSchema,
|
|
145
|
-
surfaceIds: ReferenceIdsSchema,
|
|
146
|
-
resourceIds: ReferenceIdsSchema
|
|
147
|
-
});
|
|
148
|
-
var SalesPipelineSchema = z.object({
|
|
149
|
-
id: ModelIdSchema,
|
|
150
|
-
label: z.string().trim().min(1).max(120),
|
|
151
|
-
description: DescriptionSchema.optional(),
|
|
152
|
-
entityId: ModelIdSchema,
|
|
153
|
-
stages: z.array(SalesStageSchema).min(1)
|
|
154
|
-
});
|
|
155
|
-
var OrganizationModelSalesSchema = z.object({
|
|
156
|
-
entityId: ModelIdSchema,
|
|
157
|
-
defaultPipelineId: ModelIdSchema,
|
|
158
|
-
pipelines: z.array(SalesPipelineSchema).min(1)
|
|
159
|
-
});
|
|
160
|
-
var DEFAULT_ORGANIZATION_MODEL_SALES = {
|
|
161
|
-
entityId: "crm.deal",
|
|
162
|
-
defaultPipelineId: "default",
|
|
163
|
-
pipelines: [
|
|
164
|
-
{
|
|
165
|
-
id: "default",
|
|
166
|
-
label: "Default Pipeline",
|
|
167
|
-
entityId: "crm.deal",
|
|
168
|
-
stages: [
|
|
169
|
-
{
|
|
170
|
-
id: "interested",
|
|
171
|
-
label: "Interested",
|
|
172
|
-
color: "blue",
|
|
173
|
-
order: 1,
|
|
174
|
-
semanticClass: "open",
|
|
175
|
-
surfaceIds: ["crm.pipeline"],
|
|
176
|
-
resourceIds: []
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
id: "proposal",
|
|
180
|
-
label: "Proposal",
|
|
181
|
-
color: "yellow",
|
|
182
|
-
order: 2,
|
|
183
|
-
semanticClass: "active",
|
|
184
|
-
surfaceIds: ["crm.pipeline"],
|
|
185
|
-
resourceIds: []
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
id: "closing",
|
|
189
|
-
label: "Closing",
|
|
190
|
-
color: "lime",
|
|
191
|
-
order: 3,
|
|
192
|
-
semanticClass: "active",
|
|
193
|
-
surfaceIds: ["crm.pipeline"],
|
|
194
|
-
resourceIds: []
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
id: "closed_won",
|
|
198
|
-
label: "Closed Won",
|
|
199
|
-
color: "green",
|
|
200
|
-
order: 4,
|
|
201
|
-
semanticClass: "closed_won",
|
|
202
|
-
surfaceIds: ["crm.pipeline"],
|
|
203
|
-
resourceIds: []
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
id: "closed_lost",
|
|
207
|
-
label: "Closed Lost",
|
|
208
|
-
color: "red",
|
|
209
|
-
order: 5,
|
|
210
|
-
semanticClass: "closed_lost",
|
|
211
|
-
surfaceIds: ["crm.pipeline"],
|
|
212
|
-
resourceIds: []
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
id: "nurturing",
|
|
216
|
-
label: "Nurturing",
|
|
217
|
-
color: "grape",
|
|
218
|
-
order: 6,
|
|
219
|
-
semanticClass: "nurturing",
|
|
220
|
-
surfaceIds: ["crm.pipeline"],
|
|
221
|
-
resourceIds: []
|
|
222
|
-
}
|
|
223
|
-
]
|
|
224
|
-
}
|
|
225
|
-
]
|
|
226
|
-
};
|
|
227
|
-
var LEAD_GEN_STAGE_CATALOG = {
|
|
228
|
-
// Prospecting — company population
|
|
229
|
-
scraped: {
|
|
230
|
-
key: "scraped",
|
|
231
|
-
label: "Scraped",
|
|
232
|
-
description: "Company was scraped from a source directory (Apify actor run).",
|
|
233
|
-
order: 1,
|
|
234
|
-
entity: "company"
|
|
235
|
-
},
|
|
236
|
-
populated: {
|
|
237
|
-
key: "populated",
|
|
238
|
-
label: "Companies found",
|
|
239
|
-
description: "Companies have been found and added to the lead-gen list.",
|
|
240
|
-
order: 2,
|
|
241
|
-
entity: "company"
|
|
242
|
-
},
|
|
243
|
-
crawled: {
|
|
244
|
-
key: "crawled",
|
|
245
|
-
label: "Websites crawled",
|
|
246
|
-
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
247
|
-
order: 2.5,
|
|
248
|
-
entity: "company"
|
|
249
|
-
},
|
|
250
|
-
extracted: {
|
|
251
|
-
key: "extracted",
|
|
252
|
-
label: "Websites analyzed",
|
|
253
|
-
description: "Company websites have been analyzed for business signals.",
|
|
254
|
-
order: 3,
|
|
255
|
-
entity: "company"
|
|
256
|
-
},
|
|
257
|
-
enriched: {
|
|
258
|
-
key: "enriched",
|
|
259
|
-
label: "Enriched",
|
|
260
|
-
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
261
|
-
order: 4,
|
|
262
|
-
entity: "company"
|
|
263
|
-
},
|
|
264
|
-
"decision-makers-enriched": {
|
|
265
|
-
key: "decision-makers-enriched",
|
|
266
|
-
label: "Decision-makers found",
|
|
267
|
-
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
268
|
-
order: 6,
|
|
269
|
-
entity: "company",
|
|
270
|
-
recordEntity: "contact",
|
|
271
|
-
recordStageKey: "discovered"
|
|
272
|
-
},
|
|
273
|
-
// Prospecting — contact discovery
|
|
274
|
-
discovered: {
|
|
275
|
-
key: "discovered",
|
|
276
|
-
label: "Decision-makers found",
|
|
277
|
-
description: "Decision-maker contact details have been found.",
|
|
278
|
-
order: 5,
|
|
279
|
-
entity: "contact"
|
|
280
|
-
},
|
|
281
|
-
verified: {
|
|
282
|
-
key: "verified",
|
|
283
|
-
label: "Emails verified",
|
|
284
|
-
description: "Contact email addresses have been checked for deliverability.",
|
|
285
|
-
order: 7,
|
|
286
|
-
entity: "contact"
|
|
287
|
-
},
|
|
288
|
-
// Qualification
|
|
289
|
-
qualified: {
|
|
290
|
-
key: "qualified",
|
|
291
|
-
label: "Companies qualified",
|
|
292
|
-
description: "Companies have been scored against the qualification criteria.",
|
|
293
|
-
order: 8,
|
|
294
|
-
entity: "company"
|
|
295
|
-
},
|
|
296
|
-
// Outreach
|
|
297
|
-
personalized: {
|
|
298
|
-
key: "personalized",
|
|
299
|
-
label: "Personalized",
|
|
300
|
-
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
301
|
-
order: 9,
|
|
302
|
-
entity: "contact"
|
|
303
|
-
},
|
|
304
|
-
uploaded: {
|
|
305
|
-
key: "uploaded",
|
|
306
|
-
label: "Reviewed and exported",
|
|
307
|
-
description: "Approved records have been reviewed and exported for handoff.",
|
|
308
|
-
order: 10,
|
|
309
|
-
entity: "company",
|
|
310
|
-
additionalEntities: ["contact"]
|
|
311
|
-
},
|
|
312
|
-
interested: {
|
|
313
|
-
key: "interested",
|
|
314
|
-
label: "Interested",
|
|
315
|
-
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
316
|
-
order: 11,
|
|
317
|
-
entity: "contact"
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
var ProjectsDomainStateSchema = DisplayMetadataSchema.extend({
|
|
321
|
-
id: ModelIdSchema,
|
|
322
|
-
order: z.number().int().min(0)
|
|
323
|
-
});
|
|
324
|
-
var OrganizationModelProjectsSchema = z.object({
|
|
325
|
-
projectEntityId: ModelIdSchema,
|
|
326
|
-
milestoneEntityId: ModelIdSchema,
|
|
327
|
-
taskEntityId: ModelIdSchema,
|
|
328
|
-
projectStatuses: z.array(ProjectsDomainStateSchema).min(1),
|
|
329
|
-
milestoneStatuses: z.array(ProjectsDomainStateSchema).min(1),
|
|
330
|
-
taskStatuses: z.array(ProjectsDomainStateSchema).min(1)
|
|
331
|
-
});
|
|
332
|
-
var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
|
|
333
|
-
projectEntityId: "delivery.project",
|
|
334
|
-
milestoneEntityId: "delivery.milestone",
|
|
335
|
-
taskEntityId: "delivery.task",
|
|
336
|
-
projectStatuses: [
|
|
337
|
-
{ id: "active", label: "Active", order: 1 },
|
|
338
|
-
{ id: "on_track", label: "On Track", order: 2 },
|
|
339
|
-
{ id: "at_risk", label: "At Risk", order: 3 },
|
|
340
|
-
{ id: "blocked", label: "Blocked", order: 4 },
|
|
341
|
-
{ id: "paused", label: "Paused", order: 5 },
|
|
342
|
-
{ id: "completed", label: "Completed", order: 6 }
|
|
343
|
-
],
|
|
344
|
-
milestoneStatuses: [
|
|
345
|
-
{ id: "upcoming", label: "Upcoming", order: 1 },
|
|
346
|
-
{ id: "in_progress", label: "In Progress", order: 2 },
|
|
347
|
-
{ id: "blocked", label: "Blocked", order: 3 },
|
|
348
|
-
{ id: "overdue", label: "Overdue", order: 4 },
|
|
349
|
-
{ id: "completed", label: "Completed", order: 5 }
|
|
350
|
-
],
|
|
351
|
-
taskStatuses: [
|
|
352
|
-
{ id: "planned", label: "Planned", order: 1 },
|
|
353
|
-
{ id: "in_progress", label: "In Progress", order: 2 },
|
|
354
|
-
{ id: "blocked", label: "Blocked", order: 3 },
|
|
355
|
-
{ id: "submitted", label: "Submitted", order: 4 },
|
|
356
|
-
{ id: "approved", label: "Approved", order: 5 },
|
|
357
|
-
{ id: "revision_requested", label: "Revision Requested", order: 6 },
|
|
358
|
-
{ id: "rejected", label: "Rejected", order: 7 },
|
|
359
|
-
{ id: "cancelled", label: "Cancelled", order: 8 },
|
|
360
|
-
{ id: "completed", label: "Completed", order: 9 }
|
|
361
|
-
]
|
|
362
|
-
};
|
|
363
|
-
var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
|
|
364
|
-
var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node references must use kind:dotted-path");
|
|
365
|
-
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
|
|
366
|
-
var FeatureSchema = z.object({
|
|
367
|
-
id: NodeIdPathSchema,
|
|
368
|
-
label: LabelSchema,
|
|
369
|
-
description: DescriptionSchema.optional(),
|
|
370
|
-
enabled: z.boolean().default(true),
|
|
371
|
-
path: PathSchema.optional(),
|
|
372
|
-
icon: IconNameSchema.optional(),
|
|
373
|
-
color: ColorTokenSchema.optional(),
|
|
374
|
-
uiPosition: UiPositionSchema.optional(),
|
|
375
|
-
requiresAdmin: z.boolean().optional(),
|
|
376
|
-
devOnly: z.boolean().optional()
|
|
377
|
-
});
|
|
378
|
-
var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
|
|
379
|
-
id: ModelIdSchema,
|
|
380
|
-
order: z.number().min(0)
|
|
381
|
-
});
|
|
382
|
-
var RecordColumnConfigSchema = z.object({
|
|
383
|
-
key: ModelIdSchema,
|
|
384
|
-
label: z.string().trim().min(1).max(120),
|
|
385
|
-
path: z.string().trim().min(1).max(500),
|
|
386
|
-
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
387
|
-
renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
|
|
388
|
-
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
389
|
-
});
|
|
390
|
-
var RecordColumnsConfigSchema = z.object({
|
|
391
|
-
company: z.array(RecordColumnConfigSchema).optional(),
|
|
392
|
-
contact: z.array(RecordColumnConfigSchema).optional()
|
|
393
|
-
}).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
|
|
394
|
-
message: "recordColumns must include at least one entity column set"
|
|
395
|
-
});
|
|
396
|
-
var CredentialRequirementSchema = z.object({
|
|
397
|
-
key: ModelIdSchema,
|
|
398
|
-
provider: ModelIdSchema,
|
|
399
|
-
credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
|
|
400
|
-
label: z.string().trim().min(1).max(120),
|
|
401
|
-
required: z.boolean(),
|
|
402
|
-
selectionMode: z.enum(["single", "multiple"]).optional(),
|
|
403
|
-
inputPath: z.string().trim().min(1).max(500),
|
|
404
|
-
verifyOnRun: z.boolean().optional()
|
|
405
|
-
});
|
|
406
|
-
var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
407
|
-
id: ModelIdSchema,
|
|
408
|
-
primaryEntity: z.enum(["company", "contact"]),
|
|
409
|
-
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
410
|
-
stageKey: ModelIdSchema,
|
|
411
|
-
recordEntity: z.enum(["company", "contact"]).optional(),
|
|
412
|
-
recordsStageKey: ModelIdSchema.optional(),
|
|
413
|
-
recordSourceStageKey: ModelIdSchema.optional(),
|
|
414
|
-
dependsOn: z.array(ModelIdSchema).optional(),
|
|
415
|
-
dependencyMode: z.literal("per-record-eligibility"),
|
|
416
|
-
capabilityKey: ModelIdSchema,
|
|
417
|
-
defaultBatchSize: z.number().int().positive(),
|
|
418
|
-
maxBatchSize: z.number().int().positive(),
|
|
419
|
-
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
420
|
-
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
421
|
-
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
422
|
-
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
423
|
-
path: ["defaultBatchSize"]
|
|
424
|
-
});
|
|
425
|
-
var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
|
|
426
|
-
id: ModelIdSchema,
|
|
427
|
-
steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
|
|
428
|
-
});
|
|
429
|
-
var DTC_RECORD_COLUMNS = {
|
|
430
|
-
populated: {
|
|
431
|
-
company: [
|
|
432
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
433
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
434
|
-
{ key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
|
|
435
|
-
{ key: "apollo-industry", label: "Apollo industry", path: "company.category" },
|
|
436
|
-
{ key: "location", label: "Location", path: "company.locationState" }
|
|
437
|
-
]
|
|
438
|
-
},
|
|
439
|
-
crawled: {
|
|
440
|
-
company: [
|
|
441
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
442
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
443
|
-
{ key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
|
|
444
|
-
{ key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
|
|
445
|
-
]
|
|
446
|
-
},
|
|
447
|
-
extracted: {
|
|
448
|
-
company: [
|
|
449
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
450
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
451
|
-
{ key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
|
|
452
|
-
{ key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
|
|
453
|
-
{ key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
|
|
454
|
-
{ key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
|
|
455
|
-
]
|
|
456
|
-
},
|
|
457
|
-
qualified: {
|
|
458
|
-
company: [
|
|
459
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
460
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
461
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
462
|
-
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
463
|
-
{ key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
|
|
464
|
-
]
|
|
465
|
-
},
|
|
466
|
-
decisionMakers: {
|
|
467
|
-
contact: [
|
|
468
|
-
{ key: "name", label: "Name", path: "contact.name" },
|
|
469
|
-
{ key: "title", label: "Title", path: "contact.title" },
|
|
470
|
-
{ key: "email", label: "Email", path: "contact.email" },
|
|
471
|
-
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
472
|
-
{ key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
|
|
473
|
-
]
|
|
474
|
-
},
|
|
475
|
-
uploaded: {
|
|
476
|
-
company: [
|
|
477
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
478
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
479
|
-
{ key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
|
|
480
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
481
|
-
{ key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
|
|
482
|
-
]
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
z.object({
|
|
486
|
-
id: ModelIdSchema,
|
|
487
|
-
label: z.string(),
|
|
488
|
-
description: z.string(),
|
|
489
|
-
resourceId: ModelIdSchema
|
|
490
|
-
});
|
|
491
|
-
var PROSPECTING_STEPS = {
|
|
492
|
-
localServices: {
|
|
493
|
-
sourceCompanies: {
|
|
494
|
-
id: "source-companies",
|
|
495
|
-
label: "Companies found",
|
|
496
|
-
primaryEntity: "company",
|
|
497
|
-
outputs: ["company"],
|
|
498
|
-
stageKey: "populated",
|
|
499
|
-
dependencyMode: "per-record-eligibility",
|
|
500
|
-
capabilityKey: "lead-gen.company.source",
|
|
501
|
-
defaultBatchSize: 100,
|
|
502
|
-
maxBatchSize: 250
|
|
503
|
-
},
|
|
504
|
-
analyzeWebsites: {
|
|
505
|
-
id: "analyze-websites",
|
|
506
|
-
label: "Websites analyzed",
|
|
507
|
-
primaryEntity: "company",
|
|
508
|
-
outputs: ["company"],
|
|
509
|
-
stageKey: "extracted",
|
|
510
|
-
dependsOn: ["source-companies"],
|
|
511
|
-
dependencyMode: "per-record-eligibility",
|
|
512
|
-
capabilityKey: "lead-gen.company.website-extract",
|
|
513
|
-
defaultBatchSize: 50,
|
|
514
|
-
maxBatchSize: 100
|
|
515
|
-
},
|
|
516
|
-
qualifyCompanies: {
|
|
517
|
-
id: "qualify-companies",
|
|
518
|
-
label: "Companies qualified",
|
|
519
|
-
primaryEntity: "company",
|
|
520
|
-
outputs: ["company"],
|
|
521
|
-
stageKey: "qualified",
|
|
522
|
-
dependsOn: ["analyze-websites"],
|
|
523
|
-
dependencyMode: "per-record-eligibility",
|
|
524
|
-
capabilityKey: "lead-gen.company.qualify",
|
|
525
|
-
defaultBatchSize: 100,
|
|
526
|
-
maxBatchSize: 250
|
|
527
|
-
},
|
|
528
|
-
findContacts: {
|
|
529
|
-
id: "find-contacts",
|
|
530
|
-
label: "Decision-makers found",
|
|
531
|
-
primaryEntity: "contact",
|
|
532
|
-
outputs: ["contact"],
|
|
533
|
-
stageKey: "discovered",
|
|
534
|
-
dependsOn: ["qualify-companies"],
|
|
535
|
-
dependencyMode: "per-record-eligibility",
|
|
536
|
-
capabilityKey: "lead-gen.contact.discover",
|
|
537
|
-
defaultBatchSize: 50,
|
|
538
|
-
maxBatchSize: 100
|
|
539
|
-
},
|
|
540
|
-
verifyEmails: {
|
|
541
|
-
id: "verify-emails",
|
|
542
|
-
label: "Emails verified",
|
|
543
|
-
primaryEntity: "contact",
|
|
544
|
-
outputs: ["contact"],
|
|
545
|
-
stageKey: "verified",
|
|
546
|
-
dependsOn: ["find-contacts"],
|
|
547
|
-
dependencyMode: "per-record-eligibility",
|
|
548
|
-
capabilityKey: "lead-gen.contact.verify-email",
|
|
549
|
-
defaultBatchSize: 100,
|
|
550
|
-
maxBatchSize: 500
|
|
551
|
-
},
|
|
552
|
-
personalize: {
|
|
553
|
-
id: "personalize",
|
|
554
|
-
label: "Personalize",
|
|
555
|
-
primaryEntity: "contact",
|
|
556
|
-
outputs: ["contact"],
|
|
557
|
-
stageKey: "personalized",
|
|
558
|
-
dependsOn: ["verify-emails"],
|
|
559
|
-
dependencyMode: "per-record-eligibility",
|
|
560
|
-
capabilityKey: "lead-gen.contact.personalize",
|
|
561
|
-
defaultBatchSize: 25,
|
|
562
|
-
maxBatchSize: 100
|
|
563
|
-
},
|
|
564
|
-
review: {
|
|
565
|
-
id: "review",
|
|
566
|
-
label: "Reviewed and exported",
|
|
567
|
-
primaryEntity: "contact",
|
|
568
|
-
outputs: ["export"],
|
|
569
|
-
stageKey: "uploaded",
|
|
570
|
-
dependsOn: ["personalize"],
|
|
571
|
-
dependencyMode: "per-record-eligibility",
|
|
572
|
-
capabilityKey: "lead-gen.review.outreach-ready",
|
|
573
|
-
defaultBatchSize: 25,
|
|
574
|
-
maxBatchSize: 100
|
|
575
|
-
}
|
|
576
|
-
},
|
|
577
|
-
dtcApolloClickup: {
|
|
578
|
-
importApolloSearch: {
|
|
579
|
-
id: "import-apollo-search",
|
|
580
|
-
label: "Companies found",
|
|
581
|
-
description: "Pull companies and seed contact data from a predefined Apollo search or list.",
|
|
582
|
-
primaryEntity: "company",
|
|
583
|
-
outputs: ["company", "contact"],
|
|
584
|
-
stageKey: "populated",
|
|
585
|
-
dependencyMode: "per-record-eligibility",
|
|
586
|
-
capabilityKey: "lead-gen.company.apollo-import",
|
|
587
|
-
defaultBatchSize: 250,
|
|
588
|
-
maxBatchSize: 1e3,
|
|
589
|
-
recordColumns: DTC_RECORD_COLUMNS.populated,
|
|
590
|
-
credentialRequirements: [
|
|
591
|
-
{
|
|
592
|
-
key: "apollo",
|
|
593
|
-
provider: "apollo",
|
|
594
|
-
credentialType: "api-key-secret",
|
|
595
|
-
label: "Apollo API key",
|
|
596
|
-
required: true,
|
|
597
|
-
selectionMode: "single",
|
|
598
|
-
inputPath: "credential"
|
|
599
|
-
}
|
|
600
|
-
]
|
|
601
|
-
},
|
|
602
|
-
apifyCrawl: {
|
|
603
|
-
id: "apify-crawl",
|
|
604
|
-
label: "Websites crawled",
|
|
605
|
-
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
|
|
606
|
-
primaryEntity: "company",
|
|
607
|
-
outputs: ["company"],
|
|
608
|
-
stageKey: "crawled",
|
|
609
|
-
dependsOn: ["import-apollo-search"],
|
|
610
|
-
dependencyMode: "per-record-eligibility",
|
|
611
|
-
capabilityKey: "lead-gen.company.apify-crawl",
|
|
612
|
-
defaultBatchSize: 50,
|
|
613
|
-
maxBatchSize: 100,
|
|
614
|
-
recordColumns: DTC_RECORD_COLUMNS.crawled,
|
|
615
|
-
credentialRequirements: [
|
|
616
|
-
{
|
|
617
|
-
key: "apify",
|
|
618
|
-
provider: "apify",
|
|
619
|
-
credentialType: "api-key-secret",
|
|
620
|
-
label: "Apify API token",
|
|
621
|
-
required: true,
|
|
622
|
-
selectionMode: "single",
|
|
623
|
-
inputPath: "credential",
|
|
624
|
-
verifyOnRun: true
|
|
625
|
-
}
|
|
626
|
-
]
|
|
627
|
-
},
|
|
628
|
-
analyzeWebsites: {
|
|
629
|
-
id: "analyze-websites",
|
|
630
|
-
label: "Websites analyzed",
|
|
631
|
-
description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
|
|
632
|
-
primaryEntity: "company",
|
|
633
|
-
outputs: ["company"],
|
|
634
|
-
stageKey: "extracted",
|
|
635
|
-
dependsOn: ["apify-crawl"],
|
|
636
|
-
dependencyMode: "per-record-eligibility",
|
|
637
|
-
capabilityKey: "lead-gen.company.website-extract",
|
|
638
|
-
defaultBatchSize: 50,
|
|
639
|
-
maxBatchSize: 100,
|
|
640
|
-
recordColumns: DTC_RECORD_COLUMNS.extracted
|
|
641
|
-
},
|
|
642
|
-
scoreDtcFit: {
|
|
643
|
-
id: "score-dtc-fit",
|
|
644
|
-
label: "Companies qualified",
|
|
645
|
-
description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
|
|
646
|
-
primaryEntity: "company",
|
|
647
|
-
outputs: ["company"],
|
|
648
|
-
stageKey: "qualified",
|
|
649
|
-
dependsOn: ["analyze-websites"],
|
|
650
|
-
dependencyMode: "per-record-eligibility",
|
|
651
|
-
capabilityKey: "lead-gen.company.dtc-subscription-qualify",
|
|
652
|
-
defaultBatchSize: 100,
|
|
653
|
-
maxBatchSize: 250,
|
|
654
|
-
recordColumns: DTC_RECORD_COLUMNS.qualified
|
|
655
|
-
},
|
|
656
|
-
enrichDecisionMakers: {
|
|
657
|
-
id: "enrich-decision-makers",
|
|
658
|
-
label: "Decision-makers found",
|
|
659
|
-
description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
|
|
660
|
-
primaryEntity: "company",
|
|
661
|
-
outputs: ["contact"],
|
|
662
|
-
stageKey: "decision-makers-enriched",
|
|
663
|
-
recordEntity: "contact",
|
|
664
|
-
dependsOn: ["score-dtc-fit"],
|
|
665
|
-
dependencyMode: "per-record-eligibility",
|
|
666
|
-
capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
667
|
-
defaultBatchSize: 100,
|
|
668
|
-
maxBatchSize: 250,
|
|
669
|
-
recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
|
|
670
|
-
credentialRequirements: [
|
|
671
|
-
{
|
|
672
|
-
key: "apollo",
|
|
673
|
-
provider: "apollo",
|
|
674
|
-
credentialType: "api-key-secret",
|
|
675
|
-
label: "Apollo API key",
|
|
676
|
-
required: true,
|
|
677
|
-
selectionMode: "single",
|
|
678
|
-
inputPath: "credential"
|
|
679
|
-
}
|
|
680
|
-
]
|
|
681
|
-
},
|
|
682
|
-
reviewAndExport: {
|
|
683
|
-
id: "review-and-export",
|
|
684
|
-
label: "Reviewed and exported",
|
|
685
|
-
description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
|
|
686
|
-
primaryEntity: "company",
|
|
687
|
-
outputs: ["export"],
|
|
688
|
-
stageKey: "uploaded",
|
|
689
|
-
recordsStageKey: "uploaded",
|
|
690
|
-
recordSourceStageKey: "qualified",
|
|
691
|
-
dependsOn: ["enrich-decision-makers"],
|
|
692
|
-
dependencyMode: "per-record-eligibility",
|
|
693
|
-
capabilityKey: "lead-gen.export.list",
|
|
694
|
-
defaultBatchSize: 100,
|
|
695
|
-
maxBatchSize: 250,
|
|
696
|
-
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
697
|
-
credentialRequirements: [
|
|
698
|
-
{
|
|
699
|
-
key: "clickup",
|
|
700
|
-
provider: "clickup",
|
|
701
|
-
credentialType: "api-key-secret",
|
|
702
|
-
label: "ClickUp API token",
|
|
703
|
-
required: true,
|
|
704
|
-
selectionMode: "single",
|
|
705
|
-
inputPath: "clickupCredential",
|
|
706
|
-
verifyOnRun: true
|
|
707
|
-
}
|
|
708
|
-
]
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
};
|
|
712
|
-
var OrganizationModelProspectingSchema = z.object({
|
|
713
|
-
listEntityId: ModelIdSchema,
|
|
714
|
-
companyEntityId: ModelIdSchema,
|
|
715
|
-
contactEntityId: ModelIdSchema,
|
|
716
|
-
description: DescriptionSchema.optional(),
|
|
717
|
-
companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
718
|
-
contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
719
|
-
defaultBuildTemplateId: ModelIdSchema,
|
|
720
|
-
buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
|
|
721
|
-
});
|
|
722
|
-
function toProspectingLifecycleStage(stage) {
|
|
723
|
-
return {
|
|
724
|
-
id: stage.key,
|
|
725
|
-
label: stage.label,
|
|
726
|
-
order: stage.order
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
function leadGenStagesForEntity(entity) {
|
|
730
|
-
return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity)).sort((a, b) => a.order - b.order).map(toProspectingLifecycleStage);
|
|
731
|
-
}
|
|
732
|
-
var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
|
|
733
|
-
listEntityId: "leadgen.list",
|
|
734
|
-
companyEntityId: "leadgen.company",
|
|
735
|
-
contactEntityId: "leadgen.contact",
|
|
736
|
-
companyStages: leadGenStagesForEntity("company"),
|
|
737
|
-
contactStages: leadGenStagesForEntity("contact"),
|
|
738
|
-
defaultBuildTemplateId: "local-services",
|
|
739
|
-
buildTemplates: [
|
|
740
|
-
{
|
|
741
|
-
id: "local-services",
|
|
742
|
-
label: "Local Services Prospecting",
|
|
743
|
-
description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
|
|
744
|
-
steps: [
|
|
745
|
-
PROSPECTING_STEPS.localServices.sourceCompanies,
|
|
746
|
-
PROSPECTING_STEPS.localServices.analyzeWebsites,
|
|
747
|
-
PROSPECTING_STEPS.localServices.qualifyCompanies,
|
|
748
|
-
PROSPECTING_STEPS.localServices.findContacts,
|
|
749
|
-
PROSPECTING_STEPS.localServices.verifyEmails,
|
|
750
|
-
PROSPECTING_STEPS.localServices.personalize,
|
|
751
|
-
PROSPECTING_STEPS.localServices.review
|
|
752
|
-
]
|
|
753
|
-
},
|
|
754
|
-
{
|
|
755
|
-
id: "dtc-subscription-apollo-clickup",
|
|
756
|
-
label: "DTC Subscription Apollo Export",
|
|
757
|
-
description: "Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.",
|
|
758
|
-
steps: [
|
|
759
|
-
PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
|
|
760
|
-
PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
|
|
761
|
-
PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
|
|
762
|
-
PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
|
|
763
|
-
PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
|
|
764
|
-
PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
|
|
765
|
-
]
|
|
766
|
-
}
|
|
767
|
-
]
|
|
768
|
-
};
|
|
769
|
-
|
|
770
|
-
// src/organization-model/contracts.ts
|
|
771
|
-
var KNOWLEDGE_FEATURE_ID = "knowledge";
|
|
772
|
-
var PROJECTS_FEATURE_ID = "projects";
|
|
773
|
-
var PROJECTS_INDEX_SURFACE_ID = "projects.index";
|
|
774
|
-
var PROJECTS_VIEW_CAPABILITY_ID = "delivery.projects.view";
|
|
775
|
-
var SALES_FEATURE_ID = "crm";
|
|
776
|
-
var PROSPECTING_FEATURE_ID = "lead-gen";
|
|
777
|
-
var OPERATIONS_FEATURE_ID = "operations";
|
|
778
|
-
var MONITORING_FEATURE_ID = "monitoring";
|
|
779
|
-
var SETTINGS_FEATURE_ID = "settings";
|
|
780
|
-
var SEO_FEATURE_ID = "seo";
|
|
781
|
-
var SALES_PIPELINE_SURFACE_ID = "crm.pipeline";
|
|
782
|
-
var PROSPECTING_LISTS_SURFACE_ID = "lead-gen.lists";
|
|
783
|
-
var OPERATIONS_COMMAND_VIEW_SURFACE_ID = "knowledge.command-view";
|
|
784
|
-
var SETTINGS_ROLES_SURFACE_ID = "settings.roles";
|
|
785
|
-
|
|
786
|
-
// src/organization-model/domains/navigation.ts
|
|
787
|
-
var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]);
|
|
324
|
+
var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
|
|
788
325
|
var SurfaceDefinitionSchema = z.object({
|
|
789
326
|
id: ModelIdSchema,
|
|
790
327
|
label: LabelSchema,
|
|
@@ -794,23 +331,67 @@ var SurfaceDefinitionSchema = z.object({
|
|
|
794
331
|
enabled: z.boolean().default(true),
|
|
795
332
|
devOnly: z.boolean().optional(),
|
|
796
333
|
icon: IconNameSchema.optional(),
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
parentId: ModelIdSchema.optional()
|
|
334
|
+
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
335
|
+
entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
|
|
336
|
+
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
337
|
+
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
338
|
+
parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
|
|
803
339
|
});
|
|
340
|
+
var SidebarSurfaceTargetsSchema = z.object({
|
|
341
|
+
systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
|
|
342
|
+
entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
|
|
343
|
+
resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
|
|
344
|
+
actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
|
|
345
|
+
}).default({});
|
|
346
|
+
var SidebarNodeSchema = z.lazy(
|
|
347
|
+
() => z.discriminatedUnion("type", [
|
|
348
|
+
z.object({
|
|
349
|
+
type: z.literal("group"),
|
|
350
|
+
label: LabelSchema,
|
|
351
|
+
description: DescriptionSchema.optional(),
|
|
352
|
+
icon: IconNameSchema.optional(),
|
|
353
|
+
order: z.number().int().optional(),
|
|
354
|
+
children: z.record(z.string(), SidebarNodeSchema).default({})
|
|
355
|
+
}),
|
|
356
|
+
z.object({
|
|
357
|
+
type: z.literal("surface"),
|
|
358
|
+
label: LabelSchema,
|
|
359
|
+
path: PathSchema,
|
|
360
|
+
surfaceType: SurfaceTypeSchema,
|
|
361
|
+
description: DescriptionSchema.optional(),
|
|
362
|
+
icon: IconNameSchema.optional(),
|
|
363
|
+
order: z.number().int().optional(),
|
|
364
|
+
targets: SidebarSurfaceTargetsSchema.optional(),
|
|
365
|
+
devOnly: z.boolean().optional(),
|
|
366
|
+
requiresAdmin: z.boolean().optional()
|
|
367
|
+
})
|
|
368
|
+
])
|
|
369
|
+
);
|
|
370
|
+
var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
|
|
371
|
+
var SidebarNavigationSchema = z.object({
|
|
372
|
+
primary: SidebarSectionSchema,
|
|
373
|
+
bottom: SidebarSectionSchema
|
|
374
|
+
}).default({ primary: {}, bottom: {} });
|
|
375
|
+
var OrganizationModelNavigationSchema = z.object({
|
|
376
|
+
sidebar: SidebarNavigationSchema
|
|
377
|
+
}).default({ sidebar: { primary: {}, bottom: {} } });
|
|
378
|
+
var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
|
|
379
|
+
sidebar: {
|
|
380
|
+
primary: {},
|
|
381
|
+
bottom: {}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
function getSortedSidebarEntries(nodes) {
|
|
385
|
+
return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
|
|
386
|
+
const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
|
|
387
|
+
return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
804
390
|
var NavigationGroupSchema = z.object({
|
|
805
391
|
id: ModelIdSchema,
|
|
806
392
|
label: LabelSchema,
|
|
807
393
|
placement: z.string().trim().min(1).max(50),
|
|
808
|
-
surfaceIds: z.array(ModelIdSchema).default([])
|
|
809
|
-
});
|
|
810
|
-
var OrganizationModelNavigationSchema = z.object({
|
|
811
|
-
defaultSurfaceId: ModelIdSchema.optional(),
|
|
812
|
-
surfaces: z.array(SurfaceDefinitionSchema).default([]),
|
|
813
|
-
groups: z.array(NavigationGroupSchema).default([])
|
|
394
|
+
surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
|
|
814
395
|
});
|
|
815
396
|
var BusinessHoursDaySchema = z.object({
|
|
816
397
|
open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
|
|
@@ -895,6 +476,8 @@ var FirmographicsSchema = z.object({
|
|
|
895
476
|
var CustomerSegmentSchema = z.object({
|
|
896
477
|
/** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
|
|
897
478
|
id: z.string().trim().min(1).max(100),
|
|
479
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
480
|
+
order: z.number(),
|
|
898
481
|
/** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
|
|
899
482
|
name: z.string().trim().max(200).default(""),
|
|
900
483
|
/** One or two sentences describing who this segment is. */
|
|
@@ -922,16 +505,16 @@ var CustomerSegmentSchema = z.object({
|
|
|
922
505
|
*/
|
|
923
506
|
valueProp: z.string().trim().max(2e3).default("")
|
|
924
507
|
});
|
|
925
|
-
var CustomersDomainSchema = z.
|
|
926
|
-
|
|
927
|
-
});
|
|
928
|
-
var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {
|
|
929
|
-
|
|
930
|
-
};
|
|
931
|
-
var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]);
|
|
508
|
+
var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
509
|
+
message: "Each segment entry id must match its map key"
|
|
510
|
+
}).default({});
|
|
511
|
+
var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
|
|
512
|
+
var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
|
|
932
513
|
var ProductSchema = z.object({
|
|
933
514
|
/** Stable unique identifier for the product (e.g. "product-starter-plan"). */
|
|
934
515
|
id: z.string().trim().min(1).max(100),
|
|
516
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
517
|
+
order: z.number(),
|
|
935
518
|
/** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
|
|
936
519
|
name: z.string().trim().max(200).default(""),
|
|
937
520
|
/** One or two sentences describing what this product/service delivers. */
|
|
@@ -958,96 +541,507 @@ var ProductSchema = z.object({
|
|
|
958
541
|
*/
|
|
959
542
|
targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
|
|
960
543
|
/**
|
|
961
|
-
* Optional: ID of the platform
|
|
962
|
-
* When present, must reference a declared `
|
|
544
|
+
* Optional: ID of the platform system responsible for delivering this product.
|
|
545
|
+
* When present, must reference a declared `systems.systems[].id`.
|
|
963
546
|
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
964
547
|
*/
|
|
965
548
|
deliveryFeatureId: z.string().trim().min(1).optional()
|
|
966
549
|
});
|
|
967
|
-
var OfferingsDomainSchema = z.
|
|
968
|
-
|
|
550
|
+
var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
551
|
+
message: "Each product entry id must match its map key"
|
|
552
|
+
}).default({});
|
|
553
|
+
var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
|
|
554
|
+
var EntityIdSchema = ModelIdSchema;
|
|
555
|
+
var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
|
|
556
|
+
var EntityLinkSchema = z.object({
|
|
557
|
+
toEntity: EntityIdSchema.meta({ ref: "entity" }),
|
|
558
|
+
kind: EntityLinkKindSchema,
|
|
559
|
+
via: z.string().trim().min(1).max(255).optional(),
|
|
560
|
+
label: LabelSchema.optional()
|
|
969
561
|
});
|
|
970
|
-
var
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
562
|
+
var EntitySchema = z.object({
|
|
563
|
+
id: EntityIdSchema,
|
|
564
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
565
|
+
order: z.number(),
|
|
566
|
+
label: LabelSchema,
|
|
567
|
+
description: DescriptionSchema.optional(),
|
|
568
|
+
ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
|
|
569
|
+
table: z.string().trim().min(1).max(255).optional(),
|
|
570
|
+
rowSchema: ModelIdSchema.optional(),
|
|
571
|
+
stateCatalogId: ModelIdSchema.optional(),
|
|
572
|
+
links: z.array(EntityLinkSchema).optional()
|
|
573
|
+
});
|
|
574
|
+
var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
575
|
+
message: "Each entity entry id must match its map key"
|
|
576
|
+
}).default({});
|
|
577
|
+
var ENTITY_ENTRY_INPUTS = [
|
|
578
|
+
{
|
|
579
|
+
id: "crm.deal",
|
|
580
|
+
order: 10,
|
|
581
|
+
label: "Deal",
|
|
582
|
+
description: "A CRM opportunity or sales pipeline record.",
|
|
583
|
+
ownedBySystemId: "sales.crm",
|
|
584
|
+
table: "crm_deals",
|
|
585
|
+
stateCatalogId: "crm.pipeline",
|
|
586
|
+
links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
id: "crm.contact",
|
|
590
|
+
order: 20,
|
|
591
|
+
label: "CRM Contact",
|
|
592
|
+
description: "A person associated with a CRM relationship or deal.",
|
|
593
|
+
ownedBySystemId: "sales.crm",
|
|
594
|
+
table: "crm_contacts"
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
id: "leadgen.list",
|
|
598
|
+
order: 30,
|
|
599
|
+
label: "Lead List",
|
|
600
|
+
description: "A prospecting list that groups companies and contacts for acquisition workflows.",
|
|
601
|
+
ownedBySystemId: "sales.lead-gen",
|
|
602
|
+
table: "acq_lists",
|
|
603
|
+
links: [
|
|
604
|
+
{ toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
|
|
605
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
|
|
606
|
+
]
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
id: "leadgen.company",
|
|
610
|
+
order: 40,
|
|
611
|
+
label: "Lead Company",
|
|
612
|
+
description: "A company record sourced, enriched, and qualified during prospecting.",
|
|
613
|
+
ownedBySystemId: "sales.lead-gen",
|
|
614
|
+
table: "acq_list_companies",
|
|
615
|
+
stateCatalogId: "lead-gen.company",
|
|
616
|
+
links: [
|
|
617
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
618
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
|
|
619
|
+
]
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
id: "leadgen.contact",
|
|
623
|
+
order: 50,
|
|
624
|
+
label: "Lead Contact",
|
|
625
|
+
description: "A prospect contact discovered or enriched during lead generation.",
|
|
626
|
+
ownedBySystemId: "sales.lead-gen",
|
|
627
|
+
table: "acq_list_members",
|
|
628
|
+
stateCatalogId: "lead-gen.contact",
|
|
629
|
+
links: [
|
|
630
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
631
|
+
{ toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
|
|
632
|
+
]
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
id: "delivery.project",
|
|
636
|
+
order: 60,
|
|
637
|
+
label: "Project",
|
|
638
|
+
description: "A client delivery project.",
|
|
639
|
+
ownedBySystemId: "projects",
|
|
640
|
+
table: "projects",
|
|
641
|
+
links: [
|
|
642
|
+
{ toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
|
|
643
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
|
|
644
|
+
]
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
id: "delivery.milestone",
|
|
648
|
+
order: 70,
|
|
649
|
+
label: "Milestone",
|
|
650
|
+
description: "A delivery checkpoint within a project.",
|
|
651
|
+
ownedBySystemId: "projects",
|
|
652
|
+
table: "project_milestones",
|
|
653
|
+
links: [
|
|
654
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
655
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
id: "delivery.task",
|
|
660
|
+
order: 80,
|
|
661
|
+
label: "Task",
|
|
662
|
+
description: "A delivery task that can move through the task status catalog.",
|
|
663
|
+
ownedBySystemId: "projects",
|
|
664
|
+
table: "project_tasks",
|
|
665
|
+
stateCatalogId: "delivery.task",
|
|
666
|
+
links: [
|
|
667
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
668
|
+
{ toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
|
|
669
|
+
]
|
|
670
|
+
}
|
|
671
|
+
];
|
|
672
|
+
var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
|
|
673
|
+
ENTITY_ENTRY_INPUTS.map((entity) => {
|
|
674
|
+
const parsed = EntitySchema.parse(entity);
|
|
675
|
+
return [parsed.id, parsed];
|
|
676
|
+
})
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
// src/organization-model/domains/actions.ts
|
|
680
|
+
var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
|
|
681
|
+
var ActionInvocationKindSchema = z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
|
|
682
|
+
var ActionIdSchema = ModelIdSchema;
|
|
683
|
+
var ActionScopeSchema = z.union([
|
|
684
|
+
z.literal("global"),
|
|
685
|
+
z.object({
|
|
686
|
+
domain: ModelIdSchema
|
|
687
|
+
})
|
|
688
|
+
]);
|
|
689
|
+
var ActionRefSchema = z.object({
|
|
690
|
+
actionId: ActionIdSchema.meta({ ref: "action" }),
|
|
691
|
+
intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
|
|
692
|
+
});
|
|
693
|
+
var SlashCommandInvocationSchema = z.object({
|
|
694
|
+
kind: z.literal("slash-command"),
|
|
695
|
+
command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
|
|
696
|
+
toolFactory: ModelIdSchema.optional()
|
|
697
|
+
});
|
|
698
|
+
var McpToolInvocationSchema = z.object({
|
|
699
|
+
kind: z.literal("mcp-tool"),
|
|
700
|
+
server: ModelIdSchema,
|
|
701
|
+
name: ModelIdSchema
|
|
702
|
+
});
|
|
703
|
+
var ApiEndpointInvocationSchema = z.object({
|
|
704
|
+
kind: z.literal("api-endpoint"),
|
|
705
|
+
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
|
|
706
|
+
path: z.string().trim().startsWith("/").max(500),
|
|
707
|
+
requestSchema: ModelIdSchema.optional(),
|
|
708
|
+
responseSchema: ModelIdSchema.optional()
|
|
709
|
+
});
|
|
710
|
+
var ScriptExecutionInvocationSchema = z.object({
|
|
711
|
+
kind: z.literal("script-execution"),
|
|
712
|
+
resourceId: ActionResourceIdSchema
|
|
713
|
+
});
|
|
714
|
+
var ActionInvocationSchema = z.discriminatedUnion("kind", [
|
|
715
|
+
SlashCommandInvocationSchema,
|
|
716
|
+
McpToolInvocationSchema,
|
|
717
|
+
ApiEndpointInvocationSchema,
|
|
718
|
+
ScriptExecutionInvocationSchema
|
|
719
|
+
]);
|
|
720
|
+
var ActionSchema = z.object({
|
|
721
|
+
id: ActionIdSchema,
|
|
722
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
723
|
+
order: z.number(),
|
|
724
|
+
label: LabelSchema,
|
|
725
|
+
description: DescriptionSchema.optional(),
|
|
726
|
+
scope: ActionScopeSchema.default("global"),
|
|
727
|
+
resourceId: ActionResourceIdSchema.optional(),
|
|
728
|
+
affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
|
|
729
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
730
|
+
knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
731
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
732
|
+
});
|
|
733
|
+
var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
734
|
+
message: "Each action entry id must match its map key"
|
|
735
|
+
}).default({});
|
|
736
|
+
var LEAD_GEN_ACTION_ENTRY_INPUTS = [
|
|
737
|
+
{
|
|
738
|
+
id: "lead-gen.company.source",
|
|
739
|
+
order: 10,
|
|
740
|
+
label: "Source companies",
|
|
741
|
+
description: "Import source companies from a list provider.",
|
|
742
|
+
scope: { domain: "sales" },
|
|
743
|
+
resourceId: "lgn-import-workflow",
|
|
744
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/source" }]
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
id: "lead-gen.company.apollo-import",
|
|
748
|
+
order: 20,
|
|
749
|
+
label: "Import from Apollo",
|
|
750
|
+
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
751
|
+
scope: { domain: "sales" },
|
|
752
|
+
resourceId: "lgn-01c-apollo-import-workflow",
|
|
753
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apollo-import" }]
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
id: "lead-gen.contact.discover",
|
|
757
|
+
order: 30,
|
|
758
|
+
label: "Discover contact emails",
|
|
759
|
+
description: "Find email addresses for contacts at qualified companies.",
|
|
760
|
+
scope: { domain: "sales" },
|
|
761
|
+
resourceId: "lgn-04-email-discovery-workflow",
|
|
762
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/discover" }]
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
id: "lead-gen.contact.verify-email",
|
|
766
|
+
order: 40,
|
|
767
|
+
label: "Verify emails",
|
|
768
|
+
description: "Check email deliverability before outreach.",
|
|
769
|
+
scope: { domain: "sales" },
|
|
770
|
+
resourceId: "lgn-05-email-verification-workflow",
|
|
771
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/verify-email" }]
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
id: "lead-gen.company.apify-crawl",
|
|
775
|
+
order: 50,
|
|
776
|
+
label: "Crawl websites",
|
|
777
|
+
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
|
|
778
|
+
scope: { domain: "sales" },
|
|
779
|
+
resourceId: "lgn-02a-apify-website-crawl-workflow",
|
|
780
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apify-crawl" }]
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
id: "lead-gen.company.website-extract",
|
|
784
|
+
order: 60,
|
|
785
|
+
label: "Extract website signals",
|
|
786
|
+
description: "Scrape and analyze company websites for qualification signals.",
|
|
787
|
+
scope: { domain: "sales" },
|
|
788
|
+
resourceId: "lgn-02-website-extract-workflow",
|
|
789
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/website-extract" }]
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
id: "lead-gen.company.qualify",
|
|
793
|
+
order: 70,
|
|
794
|
+
label: "Qualify companies",
|
|
795
|
+
description: "Score and filter companies against the ICP rubric.",
|
|
796
|
+
scope: { domain: "sales" },
|
|
797
|
+
resourceId: "lgn-03-company-qualification-workflow",
|
|
798
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/qualify" }]
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
id: "lead-gen.company.dtc-subscription-qualify",
|
|
802
|
+
order: 80,
|
|
803
|
+
label: "Qualify DTC subscription fit",
|
|
804
|
+
description: "Classify subscription potential and consumable-product fit for DTC brands.",
|
|
805
|
+
scope: { domain: "sales" },
|
|
806
|
+
resourceId: "lgn-03b-dtc-subscription-score-workflow",
|
|
807
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/dtc-subscription-qualify" }]
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
id: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
811
|
+
order: 90,
|
|
812
|
+
label: "Enrich decision-makers",
|
|
813
|
+
description: "Find and enrich qualified contacts at qualified companies via Apollo.",
|
|
814
|
+
scope: { domain: "sales" },
|
|
815
|
+
resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow",
|
|
816
|
+
invocations: [
|
|
817
|
+
{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/apollo-decision-maker-enrich" }
|
|
818
|
+
]
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
id: "lead-gen.contact.personalize",
|
|
822
|
+
order: 100,
|
|
823
|
+
label: "Personalize outreach",
|
|
824
|
+
description: "Generate personalized opening lines for each contact.",
|
|
825
|
+
scope: { domain: "sales" },
|
|
826
|
+
resourceId: "ist-personalization-workflow",
|
|
827
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/personalize" }]
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
id: "lead-gen.review.outreach-ready",
|
|
831
|
+
order: 110,
|
|
832
|
+
label: "Upload to outreach",
|
|
833
|
+
description: "Upload approved contacts to the outreach sequence after QC review.",
|
|
834
|
+
scope: { domain: "sales" },
|
|
835
|
+
resourceId: "ist-upload-contacts-workflow",
|
|
836
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/review/outreach-ready" }]
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
id: "lead-gen.export.list",
|
|
840
|
+
order: 120,
|
|
841
|
+
label: "Export lead list",
|
|
842
|
+
description: "Export approved leads as a downloadable lead list.",
|
|
843
|
+
scope: { domain: "sales" },
|
|
844
|
+
resourceId: "lgn-06-export-list-workflow",
|
|
845
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/export/list" }]
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
id: "lead-gen.company.cleanup",
|
|
849
|
+
order: 130,
|
|
850
|
+
label: "Clean up companies",
|
|
851
|
+
description: "Remove disqualified or duplicate companies from the list.",
|
|
852
|
+
scope: { domain: "sales" },
|
|
853
|
+
resourceId: "lgn-company-cleanup-workflow",
|
|
854
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
|
|
855
|
+
}
|
|
856
|
+
];
|
|
857
|
+
var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
|
|
858
|
+
LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
|
|
859
|
+
const parsed = ActionSchema.parse(action);
|
|
860
|
+
return [parsed.id, parsed];
|
|
861
|
+
})
|
|
862
|
+
);
|
|
863
|
+
var DEFAULT_ORGANIZATION_MODEL_ACTIONS = LEAD_GEN_ACTION_ENTRIES;
|
|
864
|
+
function findOrganizationActionById(id, actions = DEFAULT_ORGANIZATION_MODEL_ACTIONS) {
|
|
865
|
+
return actions[id];
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// src/organization-model/domains/systems.ts
|
|
869
|
+
var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
|
|
870
|
+
var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
|
|
871
|
+
var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
|
|
975
872
|
var SystemIdSchema = ModelIdSchema;
|
|
873
|
+
var SystemPathSchema = z.string().trim().min(1).regex(
|
|
874
|
+
/^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
|
|
875
|
+
'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
|
|
876
|
+
);
|
|
877
|
+
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
|
|
878
|
+
var NodeIdPathSchema = SystemIdSchema;
|
|
879
|
+
var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
|
|
880
|
+
/^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
|
|
881
|
+
"Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)"
|
|
882
|
+
);
|
|
883
|
+
var SystemUiSchema = z.object({
|
|
884
|
+
path: PathSchema,
|
|
885
|
+
surfaces: ReferenceIdsSchema,
|
|
886
|
+
icon: IconNameSchema.optional(),
|
|
887
|
+
order: z.number().int().optional()
|
|
888
|
+
});
|
|
976
889
|
var SystemEntrySchema = z.object({
|
|
977
|
-
/** Stable tenant-defined system id (e.g. "sys.lead-gen"). */
|
|
890
|
+
/** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
|
|
978
891
|
id: SystemIdSchema,
|
|
979
|
-
/** Human-readable system
|
|
980
|
-
|
|
892
|
+
/** Human-readable system label shown in UI, governance, and operations surfaces. */
|
|
893
|
+
label: LabelSchema.optional(),
|
|
894
|
+
/** @deprecated Use label. Accepted for pre-consolidation System declarations. */
|
|
895
|
+
title: LabelSchema.optional(),
|
|
981
896
|
/** One-paragraph purpose statement for the bounded context. */
|
|
982
|
-
description: DescriptionSchema,
|
|
897
|
+
description: DescriptionSchema.optional(),
|
|
983
898
|
/** Closed system shape enum; catalog values remain tenant-defined. */
|
|
984
|
-
kind: SystemKindSchema,
|
|
899
|
+
kind: SystemKindSchema.optional(),
|
|
900
|
+
/** Optional self-reference for System hierarchy. */
|
|
901
|
+
parentSystemId: SystemIdSchema.optional(),
|
|
902
|
+
/** Optional UI presence. Systems without UI omit this. */
|
|
903
|
+
ui: SystemUiSchema.optional(),
|
|
904
|
+
/** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
|
|
905
|
+
lifecycle: SystemLifecycleSchema.optional(),
|
|
985
906
|
/** Optional role responsible for this system. */
|
|
986
|
-
responsibleRoleId: ModelIdSchema.optional(),
|
|
907
|
+
responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
987
908
|
/** Optional knowledge nodes that govern this system. */
|
|
988
|
-
governedByKnowledge:
|
|
909
|
+
governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
910
|
+
/** Optional actions this system exposes or consumes. */
|
|
911
|
+
actions: z.array(ActionRefSchema).optional(),
|
|
912
|
+
/** Optional operational policies that apply to this system. */
|
|
913
|
+
policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
|
|
989
914
|
/** Optional goals this system contributes to. */
|
|
990
|
-
drivesGoals:
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
915
|
+
drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
|
|
916
|
+
/** @deprecated Use lifecycle. Accepted for one publish cycle. */
|
|
917
|
+
status: SystemStatusSchema.optional(),
|
|
918
|
+
/** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
|
|
919
|
+
path: PathSchema.optional(),
|
|
920
|
+
/** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
|
|
921
|
+
icon: IconNameSchema.optional(),
|
|
922
|
+
/** @deprecated Feature color token, retained for one-cycle compatibility. */
|
|
923
|
+
color: ColorTokenSchema.optional(),
|
|
924
|
+
/** @deprecated UI placement hint, retained for one-cycle compatibility. */
|
|
925
|
+
uiPosition: UiPositionSchema.optional(),
|
|
926
|
+
/** @deprecated Use lifecycle. */
|
|
927
|
+
enabled: z.boolean().optional(),
|
|
928
|
+
/** @deprecated Use lifecycle: "beta". */
|
|
929
|
+
devOnly: z.boolean().optional(),
|
|
930
|
+
requiresAdmin: z.boolean().optional(),
|
|
931
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
932
|
+
order: z.number(),
|
|
933
|
+
/**
|
|
934
|
+
* System-scoped operational data, co-located with the owning system.
|
|
935
|
+
* Per L1, L3, L13: keyed by local NodeId (the key is the local id; qualified
|
|
936
|
+
* id is `<system-path>:<local-id>`, computed by graph projection).
|
|
937
|
+
* Per L14: every ContentNode carries both `kind` and `type`.
|
|
938
|
+
* Per D2: unregistered (kind, type) pairs parse successfully.
|
|
939
|
+
*/
|
|
940
|
+
content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
|
|
941
|
+
/**
|
|
942
|
+
* Recursive child systems, authored via nesting (per L11).
|
|
943
|
+
* The key is the local system id; the full path is computed by joining
|
|
944
|
+
* ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
|
|
945
|
+
* Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
|
|
946
|
+
* position-derived paths. Both still exist on this schema for backward compat.
|
|
947
|
+
*/
|
|
948
|
+
subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
|
|
949
|
+
}).refine((system) => system.label !== void 0 || system.title !== void 0, {
|
|
950
|
+
path: ["label"],
|
|
951
|
+
message: "System must provide label or title"
|
|
952
|
+
}).transform((system) => {
|
|
953
|
+
if (system.status === void 0) return system;
|
|
954
|
+
console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
|
|
955
|
+
return system.lifecycle === void 0 ? { ...system, lifecycle: system.status } : system;
|
|
995
956
|
});
|
|
996
|
-
var
|
|
997
|
-
|
|
998
|
-
};
|
|
957
|
+
var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
958
|
+
message: "Each system entry id must match its map key"
|
|
959
|
+
}).default({});
|
|
960
|
+
var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
|
|
999
961
|
|
|
1000
962
|
// src/organization-model/domains/resources.ts
|
|
1001
|
-
var ResourceKindSchema = z.enum(["workflow", "agent", "integration"]);
|
|
1002
|
-
var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]);
|
|
1003
|
-
var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "
|
|
963
|
+
var ResourceKindSchema = z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
|
|
964
|
+
var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
|
|
965
|
+
var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
|
|
966
|
+
var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
|
|
1004
967
|
var ResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
|
|
968
|
+
var EventIdSchema = z.string().trim().min(1).max(300).regex(
|
|
969
|
+
/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
|
|
970
|
+
"Event IDs must use <owner-id>:<event-key>"
|
|
971
|
+
);
|
|
972
|
+
var EventKeySchema = ModelIdSchema;
|
|
973
|
+
var EventEmissionDescriptorSchema = z.object({
|
|
974
|
+
eventKey: EventKeySchema,
|
|
975
|
+
label: z.string().trim().min(1).max(120),
|
|
976
|
+
payloadSchema: ModelIdSchema.optional(),
|
|
977
|
+
lifecycle: SystemLifecycleSchema.optional()
|
|
978
|
+
});
|
|
979
|
+
var EventDescriptorSchema = EventEmissionDescriptorSchema.extend({
|
|
980
|
+
id: EventIdSchema,
|
|
981
|
+
ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
|
|
982
|
+
ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
|
|
983
|
+
});
|
|
1005
984
|
var ResourceEntryBaseSchema = z.object({
|
|
1006
985
|
/** Canonical resource id; runtime resourceId derives from this value. */
|
|
1007
986
|
id: ResourceIdSchema,
|
|
1008
|
-
/**
|
|
1009
|
-
|
|
987
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
988
|
+
order: z.number().default(0),
|
|
989
|
+
/** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
|
|
990
|
+
systemPath: SystemPathSchema.meta({ ref: "system" }),
|
|
1010
991
|
/** Optional role responsible for maintaining this resource. */
|
|
1011
|
-
ownerRoleId: ModelIdSchema.optional(),
|
|
992
|
+
ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
1012
993
|
status: ResourceGovernanceStatusSchema
|
|
1013
994
|
});
|
|
1014
995
|
var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1015
996
|
kind: z.literal("workflow"),
|
|
1016
|
-
/** Mirrors WorkflowConfig.
|
|
1017
|
-
|
|
997
|
+
/** Mirrors WorkflowConfig.actionKey when the runtime workflow has one. */
|
|
998
|
+
actionKey: z.string().trim().min(1).max(255).optional(),
|
|
999
|
+
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
1018
1000
|
});
|
|
1019
1001
|
var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1020
1002
|
kind: z.literal("agent"),
|
|
1021
1003
|
/** Mirrors code-side AgentConfig.kind. */
|
|
1022
1004
|
agentKind: AgentKindSchema,
|
|
1023
1005
|
/** Role this agent embodies, if any. */
|
|
1024
|
-
actsAsRoleId: ModelIdSchema.optional(),
|
|
1006
|
+
actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
1025
1007
|
/** Mirrors AgentConfig.sessionCapable. */
|
|
1026
|
-
sessionCapable: z.boolean()
|
|
1008
|
+
sessionCapable: z.boolean(),
|
|
1009
|
+
/** Broad/composite callable entry points orchestrated by this agent. */
|
|
1010
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
1011
|
+
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
1027
1012
|
});
|
|
1028
1013
|
var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1029
1014
|
kind: z.literal("integration"),
|
|
1030
1015
|
provider: z.string().trim().min(1).max(100)
|
|
1031
1016
|
});
|
|
1017
|
+
var ScriptResourceSourceSchema = z.union([
|
|
1018
|
+
z.string().trim().min(1).max(5e4),
|
|
1019
|
+
z.object({
|
|
1020
|
+
file: z.string().trim().min(1).max(500)
|
|
1021
|
+
})
|
|
1022
|
+
]);
|
|
1023
|
+
var ScriptResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1024
|
+
kind: z.literal("script"),
|
|
1025
|
+
language: ScriptResourceLanguageSchema,
|
|
1026
|
+
source: ScriptResourceSourceSchema
|
|
1027
|
+
});
|
|
1032
1028
|
var ResourceEntrySchema = z.discriminatedUnion("kind", [
|
|
1033
1029
|
WorkflowResourceEntrySchema,
|
|
1034
1030
|
AgentResourceEntrySchema,
|
|
1035
|
-
IntegrationResourceEntrySchema
|
|
1031
|
+
IntegrationResourceEntrySchema,
|
|
1032
|
+
ScriptResourceEntrySchema
|
|
1036
1033
|
]);
|
|
1037
|
-
var ResourcesDomainSchema = z.
|
|
1038
|
-
|
|
1039
|
-
});
|
|
1040
|
-
var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {
|
|
1041
|
-
entries: []
|
|
1042
|
-
};
|
|
1034
|
+
var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1035
|
+
message: "Each resource entry id must match its map key"
|
|
1036
|
+
}).default({});
|
|
1037
|
+
var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
|
|
1043
1038
|
function defineResource(resource) {
|
|
1044
1039
|
return ResourceEntrySchema.parse(resource);
|
|
1045
1040
|
}
|
|
1046
1041
|
function defineResources(resources) {
|
|
1047
|
-
|
|
1048
|
-
ResourceEntrySchema.parse(resource)
|
|
1049
|
-
|
|
1050
|
-
return resources;
|
|
1042
|
+
return Object.fromEntries(
|
|
1043
|
+
Object.entries(resources).map(([key, resource]) => [key, ResourceEntrySchema.parse(resource)])
|
|
1044
|
+
);
|
|
1051
1045
|
}
|
|
1052
1046
|
|
|
1053
1047
|
// src/organization-model/domains/roles.ts
|
|
@@ -1058,7 +1052,7 @@ var HumanRoleHolderSchema = z.object({
|
|
|
1058
1052
|
});
|
|
1059
1053
|
var AgentRoleHolderSchema = z.object({
|
|
1060
1054
|
kind: z.literal("agent"),
|
|
1061
|
-
agentId: ResourceIdSchema
|
|
1055
|
+
agentId: ResourceIdSchema.meta({ ref: "resource" })
|
|
1062
1056
|
});
|
|
1063
1057
|
var TeamRoleHolderSchema = z.object({
|
|
1064
1058
|
kind: z.literal("team"),
|
|
@@ -1073,6 +1067,8 @@ var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min
|
|
|
1073
1067
|
var RoleSchema = z.object({
|
|
1074
1068
|
/** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
|
|
1075
1069
|
id: RoleIdSchema,
|
|
1070
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
1071
|
+
order: z.number(),
|
|
1076
1072
|
/** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
|
|
1077
1073
|
title: z.string().trim().min(1).max(200),
|
|
1078
1074
|
/**
|
|
@@ -1085,7 +1081,7 @@ var RoleSchema = z.object({
|
|
|
1085
1081
|
* Optional: ID of another role this role reports to.
|
|
1086
1082
|
* When present, must reference another `roles[].id` in the same organization.
|
|
1087
1083
|
*/
|
|
1088
|
-
reportsToId: RoleIdSchema.optional(),
|
|
1084
|
+
reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
|
|
1089
1085
|
/**
|
|
1090
1086
|
* Optional: human, agent, or team holder currently filling this role.
|
|
1091
1087
|
* Agent holders reference OM Resource IDs and are validated at the model level.
|
|
@@ -1095,14 +1091,12 @@ var RoleSchema = z.object({
|
|
|
1095
1091
|
* Optional Systems this role is accountable for.
|
|
1096
1092
|
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
1097
1093
|
*/
|
|
1098
|
-
responsibleFor: z.array(SystemIdSchema).optional()
|
|
1094
|
+
responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
|
|
1099
1095
|
});
|
|
1100
|
-
var RolesDomainSchema = z.
|
|
1101
|
-
|
|
1102
|
-
});
|
|
1103
|
-
var DEFAULT_ORGANIZATION_MODEL_ROLES = {
|
|
1104
|
-
roles: []
|
|
1105
|
-
};
|
|
1096
|
+
var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1097
|
+
message: "Each role entry id must match its map key"
|
|
1098
|
+
}).default({});
|
|
1099
|
+
var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
|
|
1106
1100
|
var KeyResultSchema = z.object({
|
|
1107
1101
|
/** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
|
|
1108
1102
|
id: z.string().trim().min(1).max(100),
|
|
@@ -1126,6 +1120,8 @@ var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
1126
1120
|
var ObjectiveSchema = z.object({
|
|
1127
1121
|
/** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
|
|
1128
1122
|
id: z.string().trim().min(1).max(100),
|
|
1123
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
1124
|
+
order: z.number(),
|
|
1129
1125
|
/** Plain-language description of what the organization wants to achieve. */
|
|
1130
1126
|
description: z.string().trim().min(1).max(1e3),
|
|
1131
1127
|
/**
|
|
@@ -1145,180 +1141,63 @@ var ObjectiveSchema = z.object({
|
|
|
1145
1141
|
*/
|
|
1146
1142
|
keyResults: z.array(KeyResultSchema).default([])
|
|
1147
1143
|
});
|
|
1148
|
-
var GoalsDomainSchema = z.
|
|
1149
|
-
|
|
1144
|
+
var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1145
|
+
message: "Each objective entry id must match its map key"
|
|
1146
|
+
}).default({});
|
|
1147
|
+
var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
|
|
1148
|
+
var KnowledgeTargetKindSchema = z.enum([
|
|
1149
|
+
"system",
|
|
1150
|
+
"resource",
|
|
1151
|
+
"knowledge",
|
|
1152
|
+
"stage",
|
|
1153
|
+
"action",
|
|
1154
|
+
"role",
|
|
1155
|
+
"goal",
|
|
1156
|
+
"customer-segment",
|
|
1157
|
+
"offering",
|
|
1158
|
+
// D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
|
|
1159
|
+
"content-node"
|
|
1160
|
+
]).meta({ label: "Target kind" });
|
|
1161
|
+
var KnowledgeTargetRefSchema = z.object({
|
|
1162
|
+
kind: KnowledgeTargetKindSchema,
|
|
1163
|
+
// D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'
|
|
1164
|
+
// which contains a colon separator and cannot satisfy ModelIdSchema. Use a permissive
|
|
1165
|
+
// string schema here; business-logic validation of target existence is done in
|
|
1166
|
+
// OrganizationModelSchema.superRefine (knowledgeTargetExists).
|
|
1167
|
+
id: z.string().trim().min(1).max(300)
|
|
1150
1168
|
});
|
|
1151
|
-
var
|
|
1152
|
-
|
|
1153
|
-
};
|
|
1154
|
-
var OperationSemanticClassSchema = z.enum(["queue", "executions", "sessions", "notifications", "schedules"]);
|
|
1155
|
-
var OperationEntrySchema = z.object({
|
|
1156
|
-
id: z.string().trim().min(1).max(100),
|
|
1157
|
-
label: z.string().trim().min(1).max(120),
|
|
1158
|
-
semanticClass: OperationSemanticClassSchema,
|
|
1159
|
-
/** Optional reference to the feature that owns this runtime entity. */
|
|
1160
|
-
featureId: z.string().trim().min(1).max(100).optional(),
|
|
1161
|
-
/**
|
|
1162
|
-
* Optional pointer to the status semanticClass values that apply to this
|
|
1163
|
-
* entity — ties operations back to the statuses domain for vibe rendering.
|
|
1164
|
-
*/
|
|
1165
|
-
supportedStatusSemanticClass: z.array(z.string().trim().min(1).max(80)).optional()
|
|
1166
|
-
});
|
|
1167
|
-
var OperationsDomainSchema = z.object({
|
|
1168
|
-
entries: z.array(OperationEntrySchema).default([])
|
|
1169
|
-
});
|
|
1170
|
-
var DEFAULT_ORGANIZATION_MODEL_OPERATIONS = {
|
|
1171
|
-
entries: [
|
|
1172
|
-
// --- queue (HITL command queue) ---
|
|
1173
|
-
{
|
|
1174
|
-
id: "operations.queue",
|
|
1175
|
-
label: "HITL Queue",
|
|
1176
|
-
semanticClass: "queue",
|
|
1177
|
-
featureId: "operations",
|
|
1178
|
-
supportedStatusSemanticClass: ["queue"]
|
|
1179
|
-
},
|
|
1180
|
-
// --- executions (workflow / agent executions) ---
|
|
1181
|
-
{
|
|
1182
|
-
id: "operations.executions",
|
|
1183
|
-
label: "Executions",
|
|
1184
|
-
semanticClass: "executions",
|
|
1185
|
-
featureId: "operations",
|
|
1186
|
-
supportedStatusSemanticClass: ["execution"]
|
|
1187
|
-
},
|
|
1188
|
-
// --- sessions (agent conversation sessions) ---
|
|
1189
|
-
{
|
|
1190
|
-
id: "operations.sessions",
|
|
1191
|
-
label: "Sessions",
|
|
1192
|
-
semanticClass: "sessions",
|
|
1193
|
-
featureId: "operations"
|
|
1194
|
-
},
|
|
1195
|
-
// --- notifications (platform in-app notifications) ---
|
|
1196
|
-
{
|
|
1197
|
-
id: "operations.notifications",
|
|
1198
|
-
label: "Notifications",
|
|
1199
|
-
semanticClass: "notifications",
|
|
1200
|
-
featureId: "monitoring"
|
|
1201
|
-
},
|
|
1202
|
-
// --- schedules (task scheduler) ---
|
|
1203
|
-
{
|
|
1204
|
-
id: "operations.schedules",
|
|
1205
|
-
label: "Schedules",
|
|
1206
|
-
semanticClass: "schedules",
|
|
1207
|
-
featureId: "operations",
|
|
1208
|
-
supportedStatusSemanticClass: ["schedule", "schedule.run"]
|
|
1209
|
-
}
|
|
1210
|
-
]
|
|
1211
|
-
};
|
|
1212
|
-
var StatusSemanticClassSchema = z.enum([
|
|
1213
|
-
"delivery.task",
|
|
1214
|
-
"delivery.project",
|
|
1215
|
-
"delivery.milestone",
|
|
1216
|
-
"queue",
|
|
1217
|
-
"execution",
|
|
1218
|
-
"schedule",
|
|
1219
|
-
"schedule.run",
|
|
1220
|
-
"request"
|
|
1221
|
-
]);
|
|
1222
|
-
var StatusEntrySchema = z.object({
|
|
1223
|
-
id: z.string().trim().min(1).max(100),
|
|
1224
|
-
label: z.string().trim().min(1).max(120),
|
|
1225
|
-
semanticClass: StatusSemanticClassSchema,
|
|
1226
|
-
category: z.string().trim().min(1).max(80).optional()
|
|
1169
|
+
var LegacyKnowledgeLinkSchema = z.object({
|
|
1170
|
+
nodeId: NodeIdStringSchema
|
|
1227
1171
|
});
|
|
1228
|
-
var
|
|
1229
|
-
|
|
1172
|
+
var CanonicalKnowledgeLinkSchema = z.object({
|
|
1173
|
+
target: KnowledgeTargetRefSchema
|
|
1230
1174
|
});
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
{ id: "delivery.task.completed", label: "Completed", semanticClass: "delivery.task", category: "delivery" },
|
|
1248
|
-
// --- delivery.project (ProjectStatus — 6 values) ---
|
|
1249
|
-
{ id: "delivery.project.active", label: "Active", semanticClass: "delivery.project", category: "delivery" },
|
|
1250
|
-
{ id: "delivery.project.on_track", label: "On Track", semanticClass: "delivery.project", category: "delivery" },
|
|
1251
|
-
{ id: "delivery.project.at_risk", label: "At Risk", semanticClass: "delivery.project", category: "delivery" },
|
|
1252
|
-
{ id: "delivery.project.blocked", label: "Blocked", semanticClass: "delivery.project", category: "delivery" },
|
|
1253
|
-
{ id: "delivery.project.paused", label: "Paused", semanticClass: "delivery.project", category: "delivery" },
|
|
1254
|
-
{ id: "delivery.project.completed", label: "Completed", semanticClass: "delivery.project", category: "delivery" },
|
|
1255
|
-
// --- delivery.milestone (MilestoneStatus — 5 values) ---
|
|
1256
|
-
{
|
|
1257
|
-
id: "delivery.milestone.upcoming",
|
|
1258
|
-
label: "Upcoming",
|
|
1259
|
-
semanticClass: "delivery.milestone",
|
|
1260
|
-
category: "delivery"
|
|
1261
|
-
},
|
|
1262
|
-
{
|
|
1263
|
-
id: "delivery.milestone.in_progress",
|
|
1264
|
-
label: "In Progress",
|
|
1265
|
-
semanticClass: "delivery.milestone",
|
|
1266
|
-
category: "delivery"
|
|
1267
|
-
},
|
|
1268
|
-
{
|
|
1269
|
-
id: "delivery.milestone.blocked",
|
|
1270
|
-
label: "Blocked",
|
|
1271
|
-
semanticClass: "delivery.milestone",
|
|
1272
|
-
category: "delivery"
|
|
1273
|
-
},
|
|
1274
|
-
{ id: "delivery.milestone.overdue", label: "Overdue", semanticClass: "delivery.milestone", category: "delivery" },
|
|
1275
|
-
{
|
|
1276
|
-
id: "delivery.milestone.completed",
|
|
1277
|
-
label: "Completed",
|
|
1278
|
-
semanticClass: "delivery.milestone",
|
|
1279
|
-
category: "delivery"
|
|
1280
|
-
},
|
|
1281
|
-
// --- queue (QueueTaskStatus — 5 values, maps hitl/command-queue tasks) ---
|
|
1282
|
-
{ id: "queue.pending", label: "Pending", semanticClass: "queue", category: "queue" },
|
|
1283
|
-
{ id: "queue.processing", label: "Processing", semanticClass: "queue", category: "queue" },
|
|
1284
|
-
{ id: "queue.completed", label: "Completed", semanticClass: "queue", category: "queue" },
|
|
1285
|
-
{ id: "queue.failed", label: "Failed", semanticClass: "queue", category: "queue" },
|
|
1286
|
-
{ id: "queue.expired", label: "Expired", semanticClass: "queue", category: "queue" },
|
|
1287
|
-
// --- execution (ExecutionStatus — 5 values) ---
|
|
1288
|
-
{ id: "execution.pending", label: "Pending", semanticClass: "execution", category: "execution" },
|
|
1289
|
-
{ id: "execution.running", label: "Running", semanticClass: "execution", category: "execution" },
|
|
1290
|
-
{ id: "execution.completed", label: "Completed", semanticClass: "execution", category: "execution" },
|
|
1291
|
-
{ id: "execution.failed", label: "Failed", semanticClass: "execution", category: "execution" },
|
|
1292
|
-
{ id: "execution.warning", label: "Warning", semanticClass: "execution", category: "execution" },
|
|
1293
|
-
// --- schedule (schedule status — 4 values) ---
|
|
1294
|
-
{ id: "schedule.active", label: "Active", semanticClass: "schedule", category: "schedule" },
|
|
1295
|
-
{ id: "schedule.paused", label: "Paused", semanticClass: "schedule", category: "schedule" },
|
|
1296
|
-
{ id: "schedule.completed", label: "Completed", semanticClass: "schedule", category: "schedule" },
|
|
1297
|
-
{ id: "schedule.cancelled", label: "Cancelled", semanticClass: "schedule", category: "schedule" },
|
|
1298
|
-
// --- schedule.run (schedule run status — 4 values) ---
|
|
1299
|
-
{ id: "schedule.run.running", label: "Running", semanticClass: "schedule.run", category: "schedule" },
|
|
1300
|
-
{ id: "schedule.run.completed", label: "Completed", semanticClass: "schedule.run", category: "schedule" },
|
|
1301
|
-
{ id: "schedule.run.failed", label: "Failed", semanticClass: "schedule.run", category: "schedule" },
|
|
1302
|
-
{ id: "schedule.run.cancelled", label: "Cancelled", semanticClass: "schedule.run", category: "schedule" },
|
|
1303
|
-
// --- request (RequestStatus — 4 values, maps reported_requests) ---
|
|
1304
|
-
{ id: "request.open", label: "Open", semanticClass: "request", category: "request" },
|
|
1305
|
-
{ id: "request.investigating", label: "Investigating", semanticClass: "request", category: "request" },
|
|
1306
|
-
{ id: "request.resolved", label: "Resolved", semanticClass: "request", category: "request" },
|
|
1307
|
-
{ id: "request.wont_fix", label: "Won't Fix", semanticClass: "request", category: "request" }
|
|
1308
|
-
]
|
|
1309
|
-
};
|
|
1310
|
-
var KnowledgeLinkSchema = z.object({
|
|
1311
|
-
nodeId: NodeIdStringSchema
|
|
1175
|
+
function nodeIdFromTarget(target) {
|
|
1176
|
+
return `${target.kind}:${target.id}`;
|
|
1177
|
+
}
|
|
1178
|
+
function targetFromNodeId(nodeId) {
|
|
1179
|
+
const [kind, ...idParts] = nodeId.split(":");
|
|
1180
|
+
return {
|
|
1181
|
+
kind: KnowledgeTargetKindSchema.parse(kind),
|
|
1182
|
+
id: idParts.join(":")
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
|
|
1186
|
+
const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
|
|
1187
|
+
return {
|
|
1188
|
+
target,
|
|
1189
|
+
nodeId: nodeIdFromTarget(target)
|
|
1190
|
+
};
|
|
1312
1191
|
});
|
|
1313
|
-
var
|
|
1314
|
-
var KnowledgeDomainBindingSchema = z.string().trim().min(1).max(80);
|
|
1315
|
-
var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]);
|
|
1192
|
+
var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
|
|
1316
1193
|
var OrgKnowledgeNodeSchema = z.object({
|
|
1317
1194
|
id: ModelIdSchema,
|
|
1318
1195
|
kind: OrgKnowledgeKindSchema,
|
|
1319
1196
|
title: z.string().trim().min(1).max(200),
|
|
1320
1197
|
summary: z.string().trim().min(1).max(1e3),
|
|
1321
1198
|
icon: IconNameSchema.optional(),
|
|
1199
|
+
/** Canonical documentation URL when body content is a local summary. */
|
|
1200
|
+
externalUrl: z.string().trim().url().max(500).optional(),
|
|
1322
1201
|
/** Raw MDX string. Phase 2 will introduce a structured block format. */
|
|
1323
1202
|
body: z.string().trim().min(1),
|
|
1324
1203
|
/**
|
|
@@ -1326,28 +1205,142 @@ var OrgKnowledgeNodeSchema = z.object({
|
|
|
1326
1205
|
* Each link emits a `governs` edge: knowledge-node -> target node.
|
|
1327
1206
|
*/
|
|
1328
1207
|
links: z.array(KnowledgeLinkSchema).default([]),
|
|
1329
|
-
/** Operator skill or command bindings relevant to this node. */
|
|
1330
|
-
skills: z.array(KnowledgeSkillBindingSchema).optional(),
|
|
1331
|
-
/** Domain key used to derive fast graph->skill registries. */
|
|
1332
|
-
domain: KnowledgeDomainBindingSchema.optional(),
|
|
1333
1208
|
/** Role identifiers that own this knowledge node. */
|
|
1334
|
-
ownerIds: z.array(RoleIdSchema).default([]),
|
|
1209
|
+
ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
|
|
1335
1210
|
/** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
|
|
1336
1211
|
updatedAt: z.string().trim().min(1).max(50)
|
|
1337
1212
|
});
|
|
1338
|
-
var KnowledgeDomainSchema = z.
|
|
1339
|
-
|
|
1213
|
+
var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
|
|
1214
|
+
var PolicyIdSchema = ModelIdSchema;
|
|
1215
|
+
var PolicyApplicabilitySchema = z.object({
|
|
1216
|
+
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
1217
|
+
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
1218
|
+
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
1219
|
+
roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
|
|
1340
1220
|
});
|
|
1221
|
+
var PolicyTriggerSchema = z.discriminatedUnion("kind", [
|
|
1222
|
+
z.object({
|
|
1223
|
+
kind: z.literal("event"),
|
|
1224
|
+
eventId: EventIdSchema.meta({ ref: "event" })
|
|
1225
|
+
}),
|
|
1226
|
+
z.object({
|
|
1227
|
+
kind: z.literal("action-invocation"),
|
|
1228
|
+
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
1229
|
+
}),
|
|
1230
|
+
z.object({
|
|
1231
|
+
kind: z.literal("schedule"),
|
|
1232
|
+
cron: z.string().trim().min(1).max(120)
|
|
1233
|
+
}),
|
|
1234
|
+
z.object({
|
|
1235
|
+
kind: z.literal("manual")
|
|
1236
|
+
})
|
|
1237
|
+
]);
|
|
1238
|
+
var PolicyPredicateSchema = z.discriminatedUnion("kind", [
|
|
1239
|
+
z.object({
|
|
1240
|
+
kind: z.literal("always")
|
|
1241
|
+
}),
|
|
1242
|
+
z.object({
|
|
1243
|
+
kind: z.literal("expression"),
|
|
1244
|
+
expression: z.string().trim().min(1).max(2e3)
|
|
1245
|
+
}),
|
|
1246
|
+
z.object({
|
|
1247
|
+
kind: z.literal("threshold"),
|
|
1248
|
+
metric: ModelIdSchema,
|
|
1249
|
+
operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
|
|
1250
|
+
value: z.number()
|
|
1251
|
+
})
|
|
1252
|
+
]);
|
|
1253
|
+
var PolicyEffectSchema = z.discriminatedUnion("kind", [
|
|
1254
|
+
z.object({
|
|
1255
|
+
kind: z.literal("require-approval"),
|
|
1256
|
+
roleId: ModelIdSchema.meta({ ref: "role" }).optional()
|
|
1257
|
+
}),
|
|
1258
|
+
z.object({
|
|
1259
|
+
kind: z.literal("invoke-action"),
|
|
1260
|
+
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
1261
|
+
}),
|
|
1262
|
+
z.object({
|
|
1263
|
+
kind: z.literal("notify-role"),
|
|
1264
|
+
roleId: ModelIdSchema.meta({ ref: "role" })
|
|
1265
|
+
}),
|
|
1266
|
+
z.object({
|
|
1267
|
+
kind: z.literal("block")
|
|
1268
|
+
})
|
|
1269
|
+
]);
|
|
1270
|
+
var PolicySchema = z.object({
|
|
1271
|
+
id: PolicyIdSchema,
|
|
1272
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
1273
|
+
order: z.number(),
|
|
1274
|
+
label: LabelSchema,
|
|
1275
|
+
description: DescriptionSchema.optional(),
|
|
1276
|
+
trigger: PolicyTriggerSchema,
|
|
1277
|
+
predicate: PolicyPredicateSchema.default({ kind: "always" }),
|
|
1278
|
+
actions: z.array(PolicyEffectSchema).min(1),
|
|
1279
|
+
appliesTo: PolicyApplicabilitySchema.default({
|
|
1280
|
+
systemIds: [],
|
|
1281
|
+
actionIds: [],
|
|
1282
|
+
resourceIds: [],
|
|
1283
|
+
roleIds: []
|
|
1284
|
+
}),
|
|
1285
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
1286
|
+
});
|
|
1287
|
+
var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1288
|
+
message: "Each policy entry id must match its map key"
|
|
1289
|
+
}).default({});
|
|
1290
|
+
var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
|
|
1341
1291
|
|
|
1342
1292
|
// src/organization-model/schema.ts
|
|
1293
|
+
var OrganizationModelDomainKeySchema = z.enum([
|
|
1294
|
+
"branding",
|
|
1295
|
+
"identity",
|
|
1296
|
+
"customers",
|
|
1297
|
+
"offerings",
|
|
1298
|
+
"roles",
|
|
1299
|
+
"goals",
|
|
1300
|
+
"systems",
|
|
1301
|
+
"resources",
|
|
1302
|
+
"actions",
|
|
1303
|
+
"entities",
|
|
1304
|
+
"policies",
|
|
1305
|
+
"knowledge"
|
|
1306
|
+
]);
|
|
1307
|
+
var OrganizationModelDomainMetadataSchema = z.object({
|
|
1308
|
+
version: z.literal(1).default(1),
|
|
1309
|
+
lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
|
|
1310
|
+
});
|
|
1311
|
+
var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
|
|
1312
|
+
branding: { version: 1, lastModified: "2026-05-10" },
|
|
1313
|
+
identity: { version: 1, lastModified: "2026-05-10" },
|
|
1314
|
+
customers: { version: 1, lastModified: "2026-05-10" },
|
|
1315
|
+
offerings: { version: 1, lastModified: "2026-05-10" },
|
|
1316
|
+
roles: { version: 1, lastModified: "2026-05-10" },
|
|
1317
|
+
goals: { version: 1, lastModified: "2026-05-10" },
|
|
1318
|
+
systems: { version: 1, lastModified: "2026-05-10" },
|
|
1319
|
+
resources: { version: 1, lastModified: "2026-05-10" },
|
|
1320
|
+
actions: { version: 1, lastModified: "2026-05-10" },
|
|
1321
|
+
entities: { version: 1, lastModified: "2026-05-10" },
|
|
1322
|
+
policies: { version: 1, lastModified: "2026-05-10" },
|
|
1323
|
+
knowledge: { version: 1, lastModified: "2026-05-10" }
|
|
1324
|
+
};
|
|
1325
|
+
var OrganizationModelDomainMetadataByDomainSchema = z.object({
|
|
1326
|
+
branding: OrganizationModelDomainMetadataSchema,
|
|
1327
|
+
identity: OrganizationModelDomainMetadataSchema,
|
|
1328
|
+
customers: OrganizationModelDomainMetadataSchema,
|
|
1329
|
+
offerings: OrganizationModelDomainMetadataSchema,
|
|
1330
|
+
roles: OrganizationModelDomainMetadataSchema,
|
|
1331
|
+
goals: OrganizationModelDomainMetadataSchema,
|
|
1332
|
+
systems: OrganizationModelDomainMetadataSchema,
|
|
1333
|
+
resources: OrganizationModelDomainMetadataSchema,
|
|
1334
|
+
actions: OrganizationModelDomainMetadataSchema,
|
|
1335
|
+
entities: OrganizationModelDomainMetadataSchema,
|
|
1336
|
+
policies: OrganizationModelDomainMetadataSchema,
|
|
1337
|
+
knowledge: OrganizationModelDomainMetadataSchema
|
|
1338
|
+
}).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
|
|
1343
1339
|
var OrganizationModelSchemaBase = z.object({
|
|
1344
1340
|
version: z.literal(1).default(1),
|
|
1345
|
-
|
|
1341
|
+
domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
|
|
1346
1342
|
branding: OrganizationModelBrandingSchema,
|
|
1347
|
-
navigation: OrganizationModelNavigationSchema
|
|
1348
|
-
sales: OrganizationModelSalesSchema,
|
|
1349
|
-
prospecting: OrganizationModelProspectingSchema,
|
|
1350
|
-
projects: OrganizationModelProjectsSchema,
|
|
1343
|
+
navigation: OrganizationModelNavigationSchema,
|
|
1351
1344
|
identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
|
|
1352
1345
|
customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
|
|
1353
1346
|
offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
|
|
@@ -1355,9 +1348,11 @@ var OrganizationModelSchemaBase = z.object({
|
|
|
1355
1348
|
goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
|
|
1356
1349
|
systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
|
|
1357
1350
|
resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1351
|
+
actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
|
|
1352
|
+
entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
|
|
1353
|
+
policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
|
|
1354
|
+
// D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
|
|
1355
|
+
knowledge: KnowledgeDomainSchema.default({})
|
|
1361
1356
|
});
|
|
1362
1357
|
function addIssue(ctx, path, message) {
|
|
1363
1358
|
ctx.addIssue({
|
|
@@ -1366,217 +1361,412 @@ function addIssue(ctx, path, message) {
|
|
|
1366
1361
|
message
|
|
1367
1362
|
});
|
|
1368
1363
|
}
|
|
1369
|
-
function
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
if (itemsById.has(item.id)) {
|
|
1373
|
-
addIssue(ctx, [...collectionPath, index, "id"], `${label} id "${item.id}" must be unique`);
|
|
1374
|
-
return;
|
|
1375
|
-
}
|
|
1376
|
-
itemsById.set(item.id, item);
|
|
1377
|
-
});
|
|
1378
|
-
return itemsById;
|
|
1379
|
-
}
|
|
1380
|
-
var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
|
|
1381
|
-
["crm", "sales.crm"],
|
|
1382
|
-
["lead-gen", "sales.lead-gen"],
|
|
1383
|
-
["submitted-requests", "monitoring.submitted-requests"]
|
|
1384
|
-
]);
|
|
1385
|
-
function hasFeature(featuresById, featureId) {
|
|
1386
|
-
return featuresById.has(featureId) || featuresById.has(LEGACY_FEATURE_ALIASES.get(featureId) ?? "");
|
|
1364
|
+
function isLifecycleEnabled(lifecycle, enabled) {
|
|
1365
|
+
if (enabled === false) return false;
|
|
1366
|
+
return lifecycle !== "deprecated" && lifecycle !== "archived";
|
|
1387
1367
|
}
|
|
1388
|
-
function
|
|
1368
|
+
function defaultSystemPathFor(id) {
|
|
1389
1369
|
return `/${id.replaceAll(".", "/")}`;
|
|
1390
1370
|
}
|
|
1391
1371
|
function asRoleHolderArray(heldBy) {
|
|
1392
1372
|
return Array.isArray(heldBy) ? heldBy : [heldBy];
|
|
1393
1373
|
}
|
|
1374
|
+
function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
|
|
1375
|
+
if (knowledgeKind === "reference") return true;
|
|
1376
|
+
if (knowledgeKind === "playbook") {
|
|
1377
|
+
return ["system", "resource", "stage", "action"].includes(targetKind);
|
|
1378
|
+
}
|
|
1379
|
+
if (knowledgeKind === "strategy") {
|
|
1380
|
+
return ["system", "goal", "offering", "customer-segment"].includes(targetKind);
|
|
1381
|
+
}
|
|
1382
|
+
return false;
|
|
1383
|
+
}
|
|
1394
1384
|
var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
if (
|
|
1402
|
-
|
|
1403
|
-
ctx,
|
|
1404
|
-
["features", featureIndex, "id"],
|
|
1405
|
-
`Feature "${feature.id}" references unknown parent "${parentId}"`
|
|
1406
|
-
);
|
|
1385
|
+
function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
|
|
1386
|
+
const result = [];
|
|
1387
|
+
for (const [key, system] of Object.entries(systems)) {
|
|
1388
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
1389
|
+
const currentSchemaPath = [...schemaPath, key];
|
|
1390
|
+
result.push({ path, schemaPath: currentSchemaPath, system });
|
|
1391
|
+
if (system.subsystems !== void 0) {
|
|
1392
|
+
result.push(...collectAllSystems(system.subsystems, path, [...currentSchemaPath, "subsystems"]));
|
|
1407
1393
|
}
|
|
1408
1394
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1395
|
+
return result;
|
|
1396
|
+
}
|
|
1397
|
+
const allSystems = collectAllSystems(model.systems);
|
|
1398
|
+
const systemsById = /* @__PURE__ */ new Map();
|
|
1399
|
+
for (const { path, system } of allSystems) {
|
|
1400
|
+
systemsById.set(path, system);
|
|
1401
|
+
systemsById.set(system.id, system);
|
|
1402
|
+
}
|
|
1403
|
+
const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
|
|
1404
|
+
allSystems.forEach(({ path, schemaPath, system }) => {
|
|
1405
|
+
if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
|
|
1406
|
+
addIssue(
|
|
1407
|
+
ctx,
|
|
1408
|
+
[...schemaPath, "parentSystemId"],
|
|
1409
|
+
`System "${system.id}" references unknown parent "${system.parentSystemId}"`
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
const hasChildren = Object.keys(system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
|
|
1413
|
+
const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
|
|
1413
1414
|
if (contributesRoutePath) {
|
|
1414
|
-
const effectivePath =
|
|
1415
|
-
const
|
|
1416
|
-
if (
|
|
1415
|
+
const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
|
|
1416
|
+
const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
|
|
1417
|
+
if (existingSystemId !== void 0) {
|
|
1417
1418
|
addIssue(
|
|
1418
1419
|
ctx,
|
|
1419
|
-
[
|
|
1420
|
-
`
|
|
1420
|
+
[...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
|
|
1421
|
+
`System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
|
|
1421
1422
|
);
|
|
1422
1423
|
} else {
|
|
1423
|
-
|
|
1424
|
+
systemIdsByEffectivePath.set(effectivePath, path);
|
|
1424
1425
|
}
|
|
1425
1426
|
}
|
|
1426
|
-
if (hasChildren &&
|
|
1427
|
-
const hasEnabledDescendant =
|
|
1428
|
-
(candidate) => candidate.
|
|
1427
|
+
if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
|
|
1428
|
+
const hasEnabledDescendant = Object.values(system.subsystems ?? {}).some(
|
|
1429
|
+
(candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
|
|
1430
|
+
) || allSystems.some(
|
|
1431
|
+
(candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
|
|
1429
1432
|
);
|
|
1430
1433
|
if (!hasEnabledDescendant) {
|
|
1431
1434
|
addIssue(
|
|
1432
1435
|
ctx,
|
|
1433
|
-
[
|
|
1434
|
-
`
|
|
1436
|
+
[...schemaPath, "lifecycle"],
|
|
1437
|
+
`System "${path}" is active but has no active descendants`
|
|
1435
1438
|
);
|
|
1436
1439
|
}
|
|
1437
1440
|
}
|
|
1438
1441
|
});
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1442
|
+
allSystems.forEach(({ schemaPath, system }) => {
|
|
1443
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1444
|
+
let currentParentId = system.parentSystemId;
|
|
1445
|
+
while (currentParentId !== void 0) {
|
|
1446
|
+
if (currentParentId === system.id || visited.has(currentParentId)) {
|
|
1447
|
+
addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
visited.add(currentParentId);
|
|
1451
|
+
currentParentId = systemsById.get(currentParentId)?.parentSystemId;
|
|
1452
|
+
}
|
|
1453
|
+
});
|
|
1454
|
+
function normalizeRoutePath(path) {
|
|
1455
|
+
return path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
1456
|
+
}
|
|
1457
|
+
const sidebarNodeIds = /* @__PURE__ */ new Map();
|
|
1458
|
+
const sidebarSurfacePaths = /* @__PURE__ */ new Map();
|
|
1459
|
+
const sidebarSurfaces = [];
|
|
1460
|
+
function collectSidebarNodes(nodes, schemaPath) {
|
|
1461
|
+
Object.entries(nodes).forEach(([nodeId, node]) => {
|
|
1462
|
+
const nodePath = [...schemaPath, nodeId];
|
|
1463
|
+
const existingNodePath = sidebarNodeIds.get(nodeId);
|
|
1464
|
+
if (existingNodePath !== void 0) {
|
|
1465
|
+
addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
|
|
1466
|
+
} else {
|
|
1467
|
+
sidebarNodeIds.set(nodeId, nodePath);
|
|
1468
|
+
}
|
|
1469
|
+
if (node.type === "group") {
|
|
1470
|
+
collectSidebarNodes(node.children, [...nodePath, "children"]);
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
|
|
1474
|
+
const normalizedPath = normalizeRoutePath(node.path);
|
|
1475
|
+
const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
|
|
1476
|
+
if (existingSurfaceId !== void 0) {
|
|
1477
|
+
addIssue(
|
|
1478
|
+
ctx,
|
|
1479
|
+
[...nodePath, "path"],
|
|
1480
|
+
`Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
|
|
1481
|
+
);
|
|
1482
|
+
} else {
|
|
1483
|
+
sidebarSurfacePaths.set(normalizedPath, nodeId);
|
|
1484
|
+
}
|
|
1485
|
+
node.targets?.systems?.forEach((systemId, systemIndex) => {
|
|
1486
|
+
if (!systemsById.has(systemId)) {
|
|
1487
|
+
addIssue(
|
|
1488
|
+
ctx,
|
|
1489
|
+
[...nodePath, "targets", "systems", systemIndex],
|
|
1490
|
+
`Sidebar surface "${nodeId}" references unknown system "${systemId}"`
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
});
|
|
1446
1495
|
}
|
|
1447
|
-
model.navigation.
|
|
1448
|
-
|
|
1449
|
-
|
|
1496
|
+
collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
|
|
1497
|
+
collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
|
|
1498
|
+
const segmentsById = new Map(Object.entries(model.customers));
|
|
1499
|
+
Object.values(model.offerings).forEach((product) => {
|
|
1500
|
+
product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
|
|
1501
|
+
if (!segmentsById.has(segmentId)) {
|
|
1450
1502
|
addIssue(
|
|
1451
1503
|
ctx,
|
|
1452
|
-
["
|
|
1453
|
-
`
|
|
1504
|
+
["offerings", product.id, "targetSegmentIds", segmentIndex],
|
|
1505
|
+
`Product "${product.id}" references unknown customer segment "${segmentId}"`
|
|
1454
1506
|
);
|
|
1455
1507
|
}
|
|
1456
1508
|
});
|
|
1509
|
+
if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
|
|
1510
|
+
addIssue(
|
|
1511
|
+
ctx,
|
|
1512
|
+
["offerings", product.id, "deliveryFeatureId"],
|
|
1513
|
+
`Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1457
1516
|
});
|
|
1458
|
-
model.
|
|
1459
|
-
if (
|
|
1517
|
+
Object.values(model.goals).forEach((objective) => {
|
|
1518
|
+
if (objective.periodEnd <= objective.periodStart) {
|
|
1460
1519
|
addIssue(
|
|
1461
1520
|
ctx,
|
|
1462
|
-
["
|
|
1463
|
-
`
|
|
1521
|
+
["goals", objective.id, "periodEnd"],
|
|
1522
|
+
`Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
|
|
1464
1523
|
);
|
|
1465
1524
|
}
|
|
1466
|
-
|
|
1467
|
-
|
|
1525
|
+
});
|
|
1526
|
+
const goalsById = new Map(Object.entries(model.goals));
|
|
1527
|
+
const knowledgeById = new Map(Object.entries(model.knowledge));
|
|
1528
|
+
const actionsById = new Map(Object.entries(model.actions));
|
|
1529
|
+
const entitiesById = new Map(Object.entries(model.entities));
|
|
1530
|
+
const policiesById = new Map(Object.entries(model.policies));
|
|
1531
|
+
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
1532
|
+
node.targets?.entities?.forEach((entityId, entityIndex) => {
|
|
1533
|
+
if (!entitiesById.has(entityId)) {
|
|
1468
1534
|
addIssue(
|
|
1469
1535
|
ctx,
|
|
1470
|
-
[
|
|
1471
|
-
`
|
|
1536
|
+
[...path, "targets", "entities", entityIndex],
|
|
1537
|
+
`Sidebar surface "${id}" references unknown entity "${entityId}"`
|
|
1472
1538
|
);
|
|
1473
1539
|
}
|
|
1474
1540
|
});
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
model.offerings.products.forEach((product, productIndex) => {
|
|
1478
|
-
product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
|
|
1479
|
-
if (!segmentsById.has(segmentId)) {
|
|
1541
|
+
node.targets?.actions?.forEach((actionId, actionIndex) => {
|
|
1542
|
+
if (!actionsById.has(actionId)) {
|
|
1480
1543
|
addIssue(
|
|
1481
1544
|
ctx,
|
|
1482
|
-
[
|
|
1483
|
-
`
|
|
1545
|
+
[...path, "targets", "actions", actionIndex],
|
|
1546
|
+
`Sidebar surface "${id}" references unknown action "${actionId}"`
|
|
1484
1547
|
);
|
|
1485
1548
|
}
|
|
1486
1549
|
});
|
|
1487
|
-
|
|
1550
|
+
});
|
|
1551
|
+
Object.values(model.entities).forEach((entity) => {
|
|
1552
|
+
if (!systemsById.has(entity.ownedBySystemId)) {
|
|
1488
1553
|
addIssue(
|
|
1489
1554
|
ctx,
|
|
1490
|
-
["
|
|
1491
|
-
`
|
|
1555
|
+
["entities", entity.id, "ownedBySystemId"],
|
|
1556
|
+
`Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
|
|
1492
1557
|
);
|
|
1493
1558
|
}
|
|
1559
|
+
entity.links?.forEach((link, linkIndex) => {
|
|
1560
|
+
if (!entitiesById.has(link.toEntity)) {
|
|
1561
|
+
addIssue(
|
|
1562
|
+
ctx,
|
|
1563
|
+
["entities", entity.id, "links", linkIndex, "toEntity"],
|
|
1564
|
+
`Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1494
1568
|
});
|
|
1495
|
-
model.
|
|
1496
|
-
|
|
1569
|
+
const rolesById = new Map(Object.entries(model.roles));
|
|
1570
|
+
Object.values(model.roles).forEach((role) => {
|
|
1571
|
+
if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
|
|
1497
1572
|
addIssue(
|
|
1498
1573
|
ctx,
|
|
1499
|
-
["
|
|
1500
|
-
`
|
|
1574
|
+
["roles", role.id, "reportsToId"],
|
|
1575
|
+
`Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
|
|
1501
1576
|
);
|
|
1502
1577
|
}
|
|
1503
1578
|
});
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1579
|
+
Object.values(model.roles).forEach((role) => {
|
|
1580
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1581
|
+
let currentReportsToId = role.reportsToId;
|
|
1582
|
+
while (currentReportsToId !== void 0) {
|
|
1583
|
+
if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
|
|
1584
|
+
addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
visited.add(currentReportsToId);
|
|
1588
|
+
currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
|
|
1589
|
+
}
|
|
1590
|
+
});
|
|
1591
|
+
Object.values(model.roles).forEach((role) => {
|
|
1592
|
+
role.responsibleFor?.forEach((systemId, systemIndex) => {
|
|
1593
|
+
if (!systemsById.has(systemId)) {
|
|
1594
|
+
addIssue(
|
|
1595
|
+
ctx,
|
|
1596
|
+
["roles", role.id, "responsibleFor", systemIndex],
|
|
1597
|
+
`Role "${role.id}" references unknown responsibleFor system "${systemId}"`
|
|
1598
|
+
);
|
|
1599
|
+
}
|
|
1600
|
+
});
|
|
1601
|
+
});
|
|
1602
|
+
allSystems.forEach(({ schemaPath, system }) => {
|
|
1603
|
+
if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
|
|
1509
1604
|
addIssue(
|
|
1510
1605
|
ctx,
|
|
1511
|
-
[
|
|
1512
|
-
`
|
|
1606
|
+
[...schemaPath, "responsibleRoleId"],
|
|
1607
|
+
`System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
|
|
1513
1608
|
);
|
|
1514
1609
|
}
|
|
1610
|
+
system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
|
|
1611
|
+
if (!knowledgeById.has(nodeId)) {
|
|
1612
|
+
addIssue(
|
|
1613
|
+
ctx,
|
|
1614
|
+
[...schemaPath, "governedByKnowledge", nodeIndex],
|
|
1615
|
+
`System "${system.id}" references unknown knowledge node "${nodeId}"`
|
|
1616
|
+
);
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
system.drivesGoals?.forEach((goalId, goalIndex) => {
|
|
1620
|
+
if (!goalsById.has(goalId)) {
|
|
1621
|
+
addIssue(
|
|
1622
|
+
ctx,
|
|
1623
|
+
[...schemaPath, "drivesGoals", goalIndex],
|
|
1624
|
+
`System "${system.id}" references unknown goal "${goalId}"`
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
system.actions?.forEach((actionRef, actionIndex) => {
|
|
1629
|
+
if (!actionsById.has(actionRef.actionId)) {
|
|
1630
|
+
addIssue(
|
|
1631
|
+
ctx,
|
|
1632
|
+
[...schemaPath, "actions", actionIndex, "actionId"],
|
|
1633
|
+
`System "${system.id}" references unknown action "${actionRef.actionId}"`
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
});
|
|
1637
|
+
system.policies?.forEach((policyId, policyIndex) => {
|
|
1638
|
+
if (!policiesById.has(policyId)) {
|
|
1639
|
+
addIssue(
|
|
1640
|
+
ctx,
|
|
1641
|
+
[...schemaPath, "policies", policyIndex],
|
|
1642
|
+
`System "${system.id}" references unknown policy "${policyId}"`
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
});
|
|
1515
1646
|
});
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1647
|
+
Object.values(model.actions).forEach((action) => {
|
|
1648
|
+
action.affects?.forEach((entityId, entityIndex) => {
|
|
1649
|
+
if (!entitiesById.has(entityId)) {
|
|
1650
|
+
addIssue(
|
|
1651
|
+
ctx,
|
|
1652
|
+
["actions", action.id, "affects", entityIndex],
|
|
1653
|
+
`Action "${action.id}" affects unknown entity "${entityId}"`
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
});
|
|
1657
|
+
});
|
|
1658
|
+
const resourcesById = new Map(Object.entries(model.resources));
|
|
1659
|
+
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
1660
|
+
node.targets?.resources?.forEach((resourceId, resourceIndex) => {
|
|
1661
|
+
if (!resourcesById.has(resourceId)) {
|
|
1662
|
+
addIssue(
|
|
1663
|
+
ctx,
|
|
1664
|
+
[...path, "targets", "resources", resourceIndex],
|
|
1665
|
+
`Sidebar surface "${id}" references unknown resource "${resourceId}"`
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
});
|
|
1669
|
+
});
|
|
1670
|
+
const stageIds = /* @__PURE__ */ new Set();
|
|
1671
|
+
const actionIds = new Set(Object.keys(model.actions));
|
|
1672
|
+
const offeringsById = new Map(Object.entries(model.offerings));
|
|
1673
|
+
Object.values(model.policies).forEach((policy) => {
|
|
1674
|
+
policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
|
|
1519
1675
|
if (!systemsById.has(systemId)) {
|
|
1520
1676
|
addIssue(
|
|
1521
1677
|
ctx,
|
|
1522
|
-
["
|
|
1523
|
-
`
|
|
1678
|
+
["policies", policy.id, "appliesTo", "systemIds", systemIndex],
|
|
1679
|
+
`Policy "${policy.id}" applies to unknown system "${systemId}"`
|
|
1680
|
+
);
|
|
1681
|
+
}
|
|
1682
|
+
});
|
|
1683
|
+
policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
|
|
1684
|
+
if (!actionsById.has(actionId)) {
|
|
1685
|
+
addIssue(
|
|
1686
|
+
ctx,
|
|
1687
|
+
["policies", policy.id, "appliesTo", "actionIds", actionIndex],
|
|
1688
|
+
`Policy "${policy.id}" applies to unknown action "${actionId}"`
|
|
1689
|
+
);
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
policy.actions.forEach((action, actionIndex) => {
|
|
1693
|
+
if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
|
|
1694
|
+
addIssue(
|
|
1695
|
+
ctx,
|
|
1696
|
+
["policies", policy.id, "actions", actionIndex, "actionId"],
|
|
1697
|
+
`Policy "${policy.id}" invokes unknown action "${action.actionId}"`
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
|
|
1701
|
+
addIssue(
|
|
1702
|
+
ctx,
|
|
1703
|
+
["policies", policy.id, "actions", actionIndex, "roleId"],
|
|
1704
|
+
`Policy "${policy.id}" references unknown role "${action.roleId}"`
|
|
1524
1705
|
);
|
|
1525
1706
|
}
|
|
1526
1707
|
});
|
|
1527
|
-
|
|
1528
|
-
model.systems.systems.forEach((system, systemIndex) => {
|
|
1529
|
-
if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
|
|
1708
|
+
if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
|
|
1530
1709
|
addIssue(
|
|
1531
1710
|
ctx,
|
|
1532
|
-
["
|
|
1533
|
-
`
|
|
1711
|
+
["policies", policy.id, "trigger", "actionId"],
|
|
1712
|
+
`Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
|
|
1534
1713
|
);
|
|
1535
1714
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1715
|
+
});
|
|
1716
|
+
function knowledgeTargetExists(kind, id) {
|
|
1717
|
+
if (kind === "system") return systemsById.has(id);
|
|
1718
|
+
if (kind === "resource") return resourcesById.has(id);
|
|
1719
|
+
if (kind === "knowledge") return knowledgeById.has(id);
|
|
1720
|
+
if (kind === "stage") return stageIds.has(id);
|
|
1721
|
+
if (kind === "action") return actionIds.has(id);
|
|
1722
|
+
if (kind === "role") return rolesById.has(id);
|
|
1723
|
+
if (kind === "goal") return goalsById.has(id);
|
|
1724
|
+
if (kind === "customer-segment") return segmentsById.has(id);
|
|
1725
|
+
if (kind === "offering") return offeringsById.has(id);
|
|
1726
|
+
return false;
|
|
1727
|
+
}
|
|
1728
|
+
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
1729
|
+
node.links.forEach((link, linkIndex) => {
|
|
1730
|
+
if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
|
|
1538
1731
|
addIssue(
|
|
1539
1732
|
ctx,
|
|
1540
|
-
["
|
|
1541
|
-
`
|
|
1733
|
+
["knowledge", nodeId, "links", linkIndex, "target"],
|
|
1734
|
+
`Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
|
|
1542
1735
|
);
|
|
1543
1736
|
}
|
|
1544
|
-
|
|
1545
|
-
system.drivesGoals.forEach((goalId, goalIndex) => {
|
|
1546
|
-
if (!goalsById.has(goalId)) {
|
|
1737
|
+
if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
|
|
1547
1738
|
addIssue(
|
|
1548
1739
|
ctx,
|
|
1549
|
-
["
|
|
1550
|
-
`
|
|
1740
|
+
["knowledge", nodeId, "links", linkIndex, "target", "kind"],
|
|
1741
|
+
`Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
|
|
1551
1742
|
);
|
|
1552
1743
|
}
|
|
1553
1744
|
});
|
|
1554
1745
|
});
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
if (!systemsById.has(resource.systemId)) {
|
|
1746
|
+
Object.values(model.resources).forEach((resource) => {
|
|
1747
|
+
if (!systemsById.has(resource.systemPath)) {
|
|
1558
1748
|
addIssue(
|
|
1559
1749
|
ctx,
|
|
1560
|
-
["resources",
|
|
1561
|
-
`Resource "${resource.id}" references unknown
|
|
1750
|
+
["resources", resource.id, "systemPath"],
|
|
1751
|
+
`Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
|
|
1562
1752
|
);
|
|
1563
1753
|
}
|
|
1564
1754
|
if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
|
|
1565
1755
|
addIssue(
|
|
1566
1756
|
ctx,
|
|
1567
|
-
["resources",
|
|
1757
|
+
["resources", resource.id, "ownerRoleId"],
|
|
1568
1758
|
`Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
|
|
1569
1759
|
);
|
|
1570
1760
|
}
|
|
1571
1761
|
if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
|
|
1572
1762
|
addIssue(
|
|
1573
1763
|
ctx,
|
|
1574
|
-
["resources",
|
|
1764
|
+
["resources", resource.id, "actsAsRoleId"],
|
|
1575
1765
|
`Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
|
|
1576
1766
|
);
|
|
1577
1767
|
}
|
|
1578
1768
|
});
|
|
1579
|
-
model.roles.
|
|
1769
|
+
Object.values(model.roles).forEach((role) => {
|
|
1580
1770
|
if (role.heldBy === void 0) return;
|
|
1581
1771
|
asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
|
|
1582
1772
|
if (holder.kind !== "agent") return;
|
|
@@ -1584,7 +1774,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
|
|
|
1584
1774
|
if (resource === void 0) {
|
|
1585
1775
|
addIssue(
|
|
1586
1776
|
ctx,
|
|
1587
|
-
["roles",
|
|
1777
|
+
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
1588
1778
|
`Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
|
|
1589
1779
|
);
|
|
1590
1780
|
return;
|
|
@@ -1592,42 +1782,126 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
|
|
|
1592
1782
|
if (resource.kind !== "agent") {
|
|
1593
1783
|
addIssue(
|
|
1594
1784
|
ctx,
|
|
1595
|
-
["roles",
|
|
1785
|
+
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
1596
1786
|
`Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
|
|
1597
1787
|
);
|
|
1598
1788
|
}
|
|
1599
1789
|
});
|
|
1600
1790
|
});
|
|
1601
|
-
model.knowledge.
|
|
1791
|
+
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
1602
1792
|
node.ownerIds.forEach((roleId, ownerIndex) => {
|
|
1603
1793
|
if (!rolesById.has(roleId)) {
|
|
1604
1794
|
addIssue(
|
|
1605
1795
|
ctx,
|
|
1606
|
-
["knowledge",
|
|
1796
|
+
["knowledge", nodeId, "ownerIds", ownerIndex],
|
|
1607
1797
|
`Knowledge node "${node.id}" references unknown owner role "${roleId}"`
|
|
1608
1798
|
);
|
|
1609
1799
|
}
|
|
1610
1800
|
});
|
|
1611
1801
|
});
|
|
1802
|
+
function validateSystemContent(system, systemPath) {
|
|
1803
|
+
const content = system.content;
|
|
1804
|
+
if (content === void 0 || Object.keys(content).length === 0) {
|
|
1805
|
+
if (system.subsystems !== void 0) {
|
|
1806
|
+
Object.entries(system.subsystems).forEach(([childKey, child]) => {
|
|
1807
|
+
validateSystemContent(child, [...systemPath, "subsystems", childKey]);
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1812
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
1813
|
+
if (node.parentContentId !== void 0 && !(node.parentContentId in content)) {
|
|
1814
|
+
addIssue(
|
|
1815
|
+
ctx,
|
|
1816
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
1817
|
+
`Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
1822
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1823
|
+
let currentId = node.parentContentId;
|
|
1824
|
+
while (currentId !== void 0) {
|
|
1825
|
+
if (currentId === localId || visited.has(currentId)) {
|
|
1826
|
+
addIssue(
|
|
1827
|
+
ctx,
|
|
1828
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
1829
|
+
`Content node "${localId}" has a parentContentId cycle`
|
|
1830
|
+
);
|
|
1831
|
+
break;
|
|
1832
|
+
}
|
|
1833
|
+
visited.add(currentId);
|
|
1834
|
+
currentId = content[currentId]?.parentContentId;
|
|
1835
|
+
}
|
|
1836
|
+
});
|
|
1837
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
1838
|
+
const childDef = lookupContentType(node.kind, node.type);
|
|
1839
|
+
if (childDef !== void 0 && node.data !== void 0) {
|
|
1840
|
+
const result = childDef.payloadSchema.safeParse(node.data);
|
|
1841
|
+
if (!result.success) {
|
|
1842
|
+
addIssue(
|
|
1843
|
+
ctx,
|
|
1844
|
+
[...systemPath, "content", localId, "data"],
|
|
1845
|
+
`Content node "${localId}" (${node.kind}:${node.type}) data failed payload validation: ${result.error.message}`
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
if (node.parentContentId !== void 0 && childDef !== void 0) {
|
|
1850
|
+
const parentNode = content[node.parentContentId];
|
|
1851
|
+
if (parentNode !== void 0) {
|
|
1852
|
+
const parentDef = lookupContentType(parentNode.kind, parentNode.type);
|
|
1853
|
+
if (parentDef !== void 0 && childDef.kind !== parentDef.kind) {
|
|
1854
|
+
addIssue(
|
|
1855
|
+
ctx,
|
|
1856
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
1857
|
+
`Content node "${localId}" kind "${childDef.kind}" cannot parent under "${node.parentContentId}" kind "${parentDef.kind}": parentContentId must be same-meta-kind (per L19)`
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
if (system.subsystems !== void 0) {
|
|
1864
|
+
Object.entries(system.subsystems).forEach(([childKey, child]) => {
|
|
1865
|
+
validateSystemContent(child, [...systemPath, "subsystems", childKey]);
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
Object.entries(model.systems).forEach(([systemKey, system]) => {
|
|
1870
|
+
validateSystemContent(system, ["systems", systemKey]);
|
|
1871
|
+
});
|
|
1612
1872
|
});
|
|
1613
1873
|
var OrganizationGraphNodeKindSchema = z.enum([
|
|
1614
1874
|
"organization",
|
|
1615
|
-
"
|
|
1616
|
-
"
|
|
1875
|
+
"system",
|
|
1876
|
+
"role",
|
|
1877
|
+
"action",
|
|
1617
1878
|
"entity",
|
|
1618
|
-
"
|
|
1879
|
+
"event",
|
|
1880
|
+
"policy",
|
|
1619
1881
|
"stage",
|
|
1620
1882
|
"resource",
|
|
1621
|
-
"knowledge"
|
|
1883
|
+
"knowledge",
|
|
1884
|
+
"customer-segment",
|
|
1885
|
+
"offering",
|
|
1886
|
+
"goal",
|
|
1887
|
+
"surface",
|
|
1888
|
+
"navigation-group",
|
|
1889
|
+
// Phase 3 preview — Phase 4 populates via graph projection of system.content entries.
|
|
1890
|
+
"content-node"
|
|
1622
1891
|
]);
|
|
1623
1892
|
var OrganizationGraphEdgeKindSchema = z.enum([
|
|
1624
1893
|
"contains",
|
|
1625
1894
|
"references",
|
|
1626
|
-
"exposes",
|
|
1627
1895
|
"maps_to",
|
|
1628
|
-
"operates-on",
|
|
1629
1896
|
"uses",
|
|
1630
|
-
"governs"
|
|
1897
|
+
"governs",
|
|
1898
|
+
"links",
|
|
1899
|
+
"affects",
|
|
1900
|
+
"emits",
|
|
1901
|
+
"originates_from",
|
|
1902
|
+
"triggers",
|
|
1903
|
+
"applies_to",
|
|
1904
|
+
"effects"
|
|
1631
1905
|
]);
|
|
1632
1906
|
var OrganizationGraphNodeSchema = z.object({
|
|
1633
1907
|
id: z.string().trim().min(1).max(200),
|
|
@@ -1637,8 +1911,7 @@ var OrganizationGraphNodeSchema = z.object({
|
|
|
1637
1911
|
description: DescriptionSchema.optional(),
|
|
1638
1912
|
icon: IconNameSchema.optional(),
|
|
1639
1913
|
enabled: z.boolean().optional(),
|
|
1640
|
-
|
|
1641
|
-
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]).optional()
|
|
1914
|
+
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint", "script"]).optional()
|
|
1642
1915
|
});
|
|
1643
1916
|
var OrganizationGraphEdgeSchema = z.object({
|
|
1644
1917
|
id: z.string().trim().min(1).max(250),
|
|
@@ -1665,347 +1938,1173 @@ var LinkSchema = z.object({
|
|
|
1665
1938
|
kind: OrganizationGraphEdgeKindSchema
|
|
1666
1939
|
});
|
|
1667
1940
|
|
|
1941
|
+
// src/organization-model/contracts.ts
|
|
1942
|
+
var KNOWLEDGE_FEATURE_ID = "knowledge";
|
|
1943
|
+
var KNOWLEDGE_SYSTEM_ID = "knowledge";
|
|
1944
|
+
var PROJECTS_SYSTEM_ID = "projects";
|
|
1945
|
+
var PROJECTS_FEATURE_ID = PROJECTS_SYSTEM_ID;
|
|
1946
|
+
var PROJECTS_INDEX_SURFACE_ID = "projects.index";
|
|
1947
|
+
var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
|
|
1948
|
+
var SALES_FEATURE_ID = "crm";
|
|
1949
|
+
var PROSPECTING_FEATURE_ID = "lead-gen";
|
|
1950
|
+
var MONITORING_FEATURE_ID = "monitoring";
|
|
1951
|
+
var SETTINGS_FEATURE_ID = "settings";
|
|
1952
|
+
var SEO_FEATURE_ID = "seo";
|
|
1953
|
+
var SALES_SYSTEM_ID = "sales.crm";
|
|
1954
|
+
var PROSPECTING_SYSTEM_ID = "sales.lead-gen";
|
|
1955
|
+
var OPERATIONS_SYSTEM_ID = "operations";
|
|
1956
|
+
var OPERATIONS_FEATURE_ID = OPERATIONS_SYSTEM_ID;
|
|
1957
|
+
var MONITORING_SYSTEM_ID = "monitoring";
|
|
1958
|
+
var SETTINGS_SYSTEM_ID = "settings";
|
|
1959
|
+
var SEO_SYSTEM_ID = "seo";
|
|
1960
|
+
var SALES_PIPELINE_SURFACE_ID = "crm.pipeline";
|
|
1961
|
+
var PROSPECTING_LISTS_SURFACE_ID = "lead-gen.lists";
|
|
1962
|
+
var OPERATIONS_COMMAND_VIEW_SURFACE_ID = "knowledge.command-view";
|
|
1963
|
+
var SETTINGS_ROLES_SURFACE_ID = "settings.roles";
|
|
1964
|
+
|
|
1668
1965
|
// src/organization-model/defaults.ts
|
|
1669
|
-
var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {
|
|
1670
|
-
|
|
1966
|
+
var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
|
|
1967
|
+
var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = DEFAULT_ORGANIZATION_MODEL_ENTITIES;
|
|
1968
|
+
var DEFAULT_ORGANIZATION_MODEL_NAVIGATION2 = {
|
|
1969
|
+
sidebar: {
|
|
1970
|
+
primary: {
|
|
1971
|
+
dashboard: {
|
|
1972
|
+
type: "surface",
|
|
1973
|
+
label: "Dashboard",
|
|
1974
|
+
path: "/",
|
|
1975
|
+
surfaceType: "dashboard",
|
|
1976
|
+
icon: "feature.dashboard",
|
|
1977
|
+
order: 10,
|
|
1978
|
+
targets: { systems: ["dashboard"] }
|
|
1979
|
+
},
|
|
1980
|
+
business: {
|
|
1981
|
+
type: "group",
|
|
1982
|
+
label: "Business",
|
|
1983
|
+
icon: "feature.business",
|
|
1984
|
+
order: 20,
|
|
1985
|
+
children: {
|
|
1986
|
+
sales: {
|
|
1987
|
+
type: "surface",
|
|
1988
|
+
label: "Sales",
|
|
1989
|
+
path: "/sales",
|
|
1990
|
+
surfaceType: "page",
|
|
1991
|
+
icon: "feature.sales",
|
|
1992
|
+
order: 10,
|
|
1993
|
+
targets: { systems: ["sales"] }
|
|
1994
|
+
},
|
|
1995
|
+
clients: {
|
|
1996
|
+
type: "surface",
|
|
1997
|
+
label: "Clients",
|
|
1998
|
+
path: "/clients",
|
|
1999
|
+
surfaceType: "list",
|
|
2000
|
+
icon: "feature.projects",
|
|
2001
|
+
order: 20,
|
|
2002
|
+
targets: { systems: ["clients"] }
|
|
2003
|
+
},
|
|
2004
|
+
projects: {
|
|
2005
|
+
type: "surface",
|
|
2006
|
+
label: "Projects",
|
|
2007
|
+
path: "/projects",
|
|
2008
|
+
surfaceType: "page",
|
|
2009
|
+
icon: "feature.projects",
|
|
2010
|
+
order: 30,
|
|
2011
|
+
targets: { systems: ["projects"] }
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
},
|
|
2015
|
+
operations: {
|
|
2016
|
+
type: "group",
|
|
2017
|
+
label: "Operations",
|
|
2018
|
+
icon: "feature.operations",
|
|
2019
|
+
order: 30,
|
|
2020
|
+
children: {
|
|
2021
|
+
"operations-overview": {
|
|
2022
|
+
type: "surface",
|
|
2023
|
+
label: "Overview",
|
|
2024
|
+
path: "/operations",
|
|
2025
|
+
surfaceType: "page",
|
|
2026
|
+
order: 10,
|
|
2027
|
+
targets: { systems: ["operations.overview"] }
|
|
2028
|
+
},
|
|
2029
|
+
"operations-systems": {
|
|
2030
|
+
type: "surface",
|
|
2031
|
+
label: "Systems",
|
|
2032
|
+
path: "/operations/systems",
|
|
2033
|
+
surfaceType: "page",
|
|
2034
|
+
order: 20,
|
|
2035
|
+
targets: { systems: ["operations"] }
|
|
2036
|
+
},
|
|
2037
|
+
"operations-resources": {
|
|
2038
|
+
type: "surface",
|
|
2039
|
+
label: "Resources",
|
|
2040
|
+
path: "/operations/resources",
|
|
2041
|
+
surfaceType: "list",
|
|
2042
|
+
order: 30,
|
|
2043
|
+
targets: { systems: ["operations.resources"] }
|
|
2044
|
+
},
|
|
2045
|
+
"operations-command-queue": {
|
|
2046
|
+
type: "surface",
|
|
2047
|
+
label: "Command Queue",
|
|
2048
|
+
path: "/operations/command-queue",
|
|
2049
|
+
surfaceType: "list",
|
|
2050
|
+
order: 40,
|
|
2051
|
+
targets: { systems: ["operations.command-queue"] }
|
|
2052
|
+
},
|
|
2053
|
+
"operations-task-scheduler": {
|
|
2054
|
+
type: "surface",
|
|
2055
|
+
label: "Task Scheduler",
|
|
2056
|
+
path: "/operations/task-scheduler",
|
|
2057
|
+
surfaceType: "list",
|
|
2058
|
+
order: 50,
|
|
2059
|
+
targets: { systems: ["operations.task-scheduler"] }
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
},
|
|
2063
|
+
monitoring: {
|
|
2064
|
+
type: "group",
|
|
2065
|
+
label: "Monitoring",
|
|
2066
|
+
icon: "feature.monitoring",
|
|
2067
|
+
order: 40,
|
|
2068
|
+
children: {
|
|
2069
|
+
"monitoring-overview": {
|
|
2070
|
+
type: "surface",
|
|
2071
|
+
label: "Overview",
|
|
2072
|
+
path: "/monitoring",
|
|
2073
|
+
surfaceType: "page",
|
|
2074
|
+
order: 10,
|
|
2075
|
+
targets: { systems: ["monitoring"] }
|
|
2076
|
+
},
|
|
2077
|
+
"monitoring-calendar": {
|
|
2078
|
+
type: "surface",
|
|
2079
|
+
label: "Calendar",
|
|
2080
|
+
path: "/monitoring/calendar",
|
|
2081
|
+
surfaceType: "page",
|
|
2082
|
+
order: 20,
|
|
2083
|
+
targets: { systems: ["monitoring.calendar"] }
|
|
2084
|
+
},
|
|
2085
|
+
"monitoring-activity-log": {
|
|
2086
|
+
type: "surface",
|
|
2087
|
+
label: "Activity Log",
|
|
2088
|
+
path: "/monitoring/activity-log",
|
|
2089
|
+
surfaceType: "list",
|
|
2090
|
+
order: 30,
|
|
2091
|
+
targets: { systems: ["monitoring.activity-log"] }
|
|
2092
|
+
},
|
|
2093
|
+
"monitoring-execution-logs": {
|
|
2094
|
+
type: "surface",
|
|
2095
|
+
label: "Execution Logs",
|
|
2096
|
+
path: "/monitoring/execution-logs",
|
|
2097
|
+
surfaceType: "list",
|
|
2098
|
+
order: 40,
|
|
2099
|
+
targets: { systems: ["monitoring.execution-logs"] }
|
|
2100
|
+
},
|
|
2101
|
+
"monitoring-execution-health": {
|
|
2102
|
+
type: "surface",
|
|
2103
|
+
label: "Execution Health",
|
|
2104
|
+
path: "/monitoring/execution-health",
|
|
2105
|
+
surfaceType: "dashboard",
|
|
2106
|
+
order: 50,
|
|
2107
|
+
targets: { systems: ["monitoring.execution-health"] }
|
|
2108
|
+
},
|
|
2109
|
+
"monitoring-notifications": {
|
|
2110
|
+
type: "surface",
|
|
2111
|
+
label: "Notifications",
|
|
2112
|
+
path: "/monitoring/notifications",
|
|
2113
|
+
surfaceType: "list",
|
|
2114
|
+
order: 60,
|
|
2115
|
+
targets: { systems: ["monitoring.notifications"] }
|
|
2116
|
+
},
|
|
2117
|
+
"monitoring-requests": {
|
|
2118
|
+
type: "surface",
|
|
2119
|
+
label: "Requests",
|
|
2120
|
+
path: "/monitoring/requests",
|
|
2121
|
+
surfaceType: "list",
|
|
2122
|
+
order: 70,
|
|
2123
|
+
targets: { systems: ["monitoring.submitted-requests"] }
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
},
|
|
2127
|
+
knowledge: {
|
|
2128
|
+
type: "group",
|
|
2129
|
+
label: "Knowledge",
|
|
2130
|
+
icon: "feature.knowledge",
|
|
2131
|
+
order: 50,
|
|
2132
|
+
children: {
|
|
2133
|
+
"knowledge-base": {
|
|
2134
|
+
type: "surface",
|
|
2135
|
+
label: "Knowledge Base",
|
|
2136
|
+
path: "/knowledge",
|
|
2137
|
+
surfaceType: "page",
|
|
2138
|
+
order: 10,
|
|
2139
|
+
targets: { systems: ["knowledge.base"] }
|
|
2140
|
+
},
|
|
2141
|
+
"knowledge-command-view": {
|
|
2142
|
+
type: "surface",
|
|
2143
|
+
label: "Command View",
|
|
2144
|
+
path: "/knowledge/command-view",
|
|
2145
|
+
surfaceType: "graph",
|
|
2146
|
+
order: 20,
|
|
2147
|
+
targets: { systems: ["knowledge.command-view"] },
|
|
2148
|
+
devOnly: true
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
},
|
|
2153
|
+
bottom: {
|
|
2154
|
+
settings: {
|
|
2155
|
+
type: "group",
|
|
2156
|
+
label: "Settings",
|
|
2157
|
+
icon: "feature.settings",
|
|
2158
|
+
order: 10,
|
|
2159
|
+
children: {
|
|
2160
|
+
"settings-account": {
|
|
2161
|
+
type: "surface",
|
|
2162
|
+
label: "Account",
|
|
2163
|
+
path: "/settings/account",
|
|
2164
|
+
surfaceType: "settings",
|
|
2165
|
+
order: 10,
|
|
2166
|
+
targets: { systems: ["settings.account"] }
|
|
2167
|
+
},
|
|
2168
|
+
"settings-appearance": {
|
|
2169
|
+
type: "surface",
|
|
2170
|
+
label: "Appearance",
|
|
2171
|
+
path: "/settings/appearance",
|
|
2172
|
+
surfaceType: "settings",
|
|
2173
|
+
order: 20,
|
|
2174
|
+
targets: { systems: ["settings.appearance"] }
|
|
2175
|
+
},
|
|
2176
|
+
"settings-roles": {
|
|
2177
|
+
type: "surface",
|
|
2178
|
+
label: "My Roles",
|
|
2179
|
+
path: "/settings/roles",
|
|
2180
|
+
surfaceType: "settings",
|
|
2181
|
+
order: 30,
|
|
2182
|
+
targets: { systems: ["settings.roles"] }
|
|
2183
|
+
},
|
|
2184
|
+
"settings-organization": {
|
|
2185
|
+
type: "surface",
|
|
2186
|
+
label: "Organization",
|
|
2187
|
+
path: "/settings/organization",
|
|
2188
|
+
surfaceType: "settings",
|
|
2189
|
+
order: 40,
|
|
2190
|
+
targets: { systems: ["settings.organization"] }
|
|
2191
|
+
},
|
|
2192
|
+
"settings-credentials": {
|
|
2193
|
+
type: "surface",
|
|
2194
|
+
label: "Credentials",
|
|
2195
|
+
path: "/settings/credentials",
|
|
2196
|
+
surfaceType: "settings",
|
|
2197
|
+
order: 50,
|
|
2198
|
+
targets: { systems: ["settings.credentials"] }
|
|
2199
|
+
},
|
|
2200
|
+
"settings-api-keys": {
|
|
2201
|
+
type: "surface",
|
|
2202
|
+
label: "API Keys",
|
|
2203
|
+
path: "/settings/api-keys",
|
|
2204
|
+
surfaceType: "settings",
|
|
2205
|
+
order: 60,
|
|
2206
|
+
targets: { systems: ["settings.api-keys"] }
|
|
2207
|
+
},
|
|
2208
|
+
"settings-webhooks": {
|
|
2209
|
+
type: "surface",
|
|
2210
|
+
label: "Webhooks",
|
|
2211
|
+
path: "/settings/webhooks",
|
|
2212
|
+
surfaceType: "settings",
|
|
2213
|
+
order: 70,
|
|
2214
|
+
targets: { systems: ["settings.webhooks"] }
|
|
2215
|
+
},
|
|
2216
|
+
"settings-deployments": {
|
|
2217
|
+
type: "surface",
|
|
2218
|
+
label: "Deployments",
|
|
2219
|
+
path: "/settings/deployments",
|
|
2220
|
+
surfaceType: "settings",
|
|
2221
|
+
order: 80,
|
|
2222
|
+
targets: { systems: ["settings.deployments"] }
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
},
|
|
2226
|
+
admin: {
|
|
2227
|
+
type: "group",
|
|
2228
|
+
label: "Admin",
|
|
2229
|
+
icon: "feature.admin",
|
|
2230
|
+
order: 20,
|
|
2231
|
+
children: {
|
|
2232
|
+
"admin-dashboard": {
|
|
2233
|
+
type: "surface",
|
|
2234
|
+
label: "Dashboard",
|
|
2235
|
+
path: "/admin/dashboard",
|
|
2236
|
+
surfaceType: "dashboard",
|
|
2237
|
+
order: 10,
|
|
2238
|
+
targets: { systems: ["admin"] },
|
|
2239
|
+
requiresAdmin: true
|
|
2240
|
+
},
|
|
2241
|
+
"admin-system-health": {
|
|
2242
|
+
type: "surface",
|
|
2243
|
+
label: "System Health",
|
|
2244
|
+
path: "/admin/system-health",
|
|
2245
|
+
surfaceType: "dashboard",
|
|
2246
|
+
order: 20,
|
|
2247
|
+
targets: { systems: ["admin.system-health"] },
|
|
2248
|
+
requiresAdmin: true
|
|
2249
|
+
},
|
|
2250
|
+
"admin-organizations": {
|
|
2251
|
+
type: "surface",
|
|
2252
|
+
label: "Organizations",
|
|
2253
|
+
path: "/admin/organizations",
|
|
2254
|
+
surfaceType: "list",
|
|
2255
|
+
order: 30,
|
|
2256
|
+
targets: { systems: ["admin.organizations"] },
|
|
2257
|
+
requiresAdmin: true
|
|
2258
|
+
},
|
|
2259
|
+
"admin-users": {
|
|
2260
|
+
type: "surface",
|
|
2261
|
+
label: "Users",
|
|
2262
|
+
path: "/admin/users",
|
|
2263
|
+
surfaceType: "list",
|
|
2264
|
+
order: 40,
|
|
2265
|
+
targets: { systems: ["admin.users"] },
|
|
2266
|
+
requiresAdmin: true
|
|
2267
|
+
},
|
|
2268
|
+
"admin-design-showcase": {
|
|
2269
|
+
type: "surface",
|
|
2270
|
+
label: "Design Showcase",
|
|
2271
|
+
path: "/admin/design-showcase",
|
|
2272
|
+
surfaceType: "page",
|
|
2273
|
+
order: 50,
|
|
2274
|
+
targets: { systems: ["admin.design-showcase"] },
|
|
2275
|
+
requiresAdmin: true
|
|
2276
|
+
},
|
|
2277
|
+
"admin-debug": {
|
|
2278
|
+
type: "surface",
|
|
2279
|
+
label: "Debug",
|
|
2280
|
+
path: "/admin/debug",
|
|
2281
|
+
surfaceType: "page",
|
|
2282
|
+
order: 60,
|
|
2283
|
+
targets: { systems: ["admin.debug"] },
|
|
2284
|
+
requiresAdmin: true
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
1671
2290
|
};
|
|
1672
2291
|
var DEFAULT_ORGANIZATION_MODEL = {
|
|
1673
2292
|
version: 1,
|
|
1674
|
-
|
|
1675
|
-
|
|
2293
|
+
domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
|
|
2294
|
+
branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
|
|
2295
|
+
navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION2,
|
|
2296
|
+
identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
|
|
2297
|
+
customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
|
|
2298
|
+
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
2299
|
+
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
2300
|
+
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
2301
|
+
systems: {
|
|
2302
|
+
dashboard: {
|
|
1676
2303
|
id: "dashboard",
|
|
2304
|
+
order: 10,
|
|
1677
2305
|
label: "Dashboard",
|
|
1678
2306
|
enabled: true,
|
|
2307
|
+
lifecycle: "active",
|
|
1679
2308
|
path: "/",
|
|
1680
|
-
icon: "feature.dashboard"
|
|
1681
|
-
uiPosition: "sidebar-primary"
|
|
2309
|
+
icon: "feature.dashboard"
|
|
1682
2310
|
},
|
|
1683
|
-
{
|
|
1684
|
-
id: "identity",
|
|
1685
|
-
label: "Identity",
|
|
1686
|
-
description: "Company identity, positioning, and market context",
|
|
1687
|
-
enabled: true,
|
|
1688
|
-
color: "indigo"
|
|
1689
|
-
},
|
|
1690
|
-
{
|
|
2311
|
+
platform: {
|
|
1691
2312
|
id: "platform",
|
|
2313
|
+
order: 30,
|
|
1692
2314
|
label: "Platform",
|
|
1693
2315
|
description: "Elevasis platform architecture, capabilities, and implementation patterns",
|
|
1694
2316
|
enabled: true,
|
|
2317
|
+
lifecycle: "active",
|
|
1695
2318
|
color: "cyan",
|
|
1696
2319
|
icon: "feature.platform"
|
|
1697
2320
|
},
|
|
1698
|
-
{
|
|
2321
|
+
finance: {
|
|
1699
2322
|
id: "finance",
|
|
2323
|
+
order: 40,
|
|
1700
2324
|
label: "Finance",
|
|
1701
2325
|
description: "Finance operations, accounting, billing, reconciliation, and tax prep",
|
|
1702
2326
|
enabled: true,
|
|
2327
|
+
lifecycle: "active",
|
|
1703
2328
|
color: "green",
|
|
1704
2329
|
icon: "feature.finance"
|
|
1705
2330
|
},
|
|
1706
|
-
{
|
|
1707
|
-
id: "business",
|
|
1708
|
-
label: "Business",
|
|
1709
|
-
description: "Revenue, client relationships, and project delivery",
|
|
1710
|
-
enabled: true,
|
|
1711
|
-
color: "blue",
|
|
1712
|
-
icon: "feature.business",
|
|
1713
|
-
uiPosition: "sidebar-primary"
|
|
1714
|
-
},
|
|
1715
|
-
{
|
|
2331
|
+
sales: {
|
|
1716
2332
|
id: "sales",
|
|
2333
|
+
order: 60,
|
|
1717
2334
|
label: "Sales",
|
|
1718
2335
|
description: "Revenue workflows and customer acquisition",
|
|
1719
2336
|
enabled: true,
|
|
2337
|
+
lifecycle: "active",
|
|
1720
2338
|
color: "blue",
|
|
1721
2339
|
icon: "feature.sales",
|
|
1722
2340
|
path: "/sales"
|
|
1723
2341
|
},
|
|
1724
|
-
{
|
|
2342
|
+
"sales.crm": {
|
|
1725
2343
|
id: "sales.crm",
|
|
2344
|
+
order: 70,
|
|
1726
2345
|
label: "CRM",
|
|
1727
2346
|
description: "Relationship pipeline and deal management",
|
|
1728
2347
|
enabled: true,
|
|
2348
|
+
lifecycle: "active",
|
|
1729
2349
|
color: "blue",
|
|
1730
2350
|
icon: "feature.crm",
|
|
1731
2351
|
path: "/crm"
|
|
1732
2352
|
},
|
|
1733
|
-
{
|
|
2353
|
+
"sales.lead-gen": {
|
|
1734
2354
|
id: "sales.lead-gen",
|
|
2355
|
+
order: 80,
|
|
1735
2356
|
label: "Lead Gen",
|
|
1736
2357
|
description: "Prospecting, qualification, and outreach preparation",
|
|
1737
2358
|
enabled: true,
|
|
2359
|
+
lifecycle: "active",
|
|
2360
|
+
actions: Object.values(DEFAULT_ORGANIZATION_MODEL_ACTIONS).map((action) => ({
|
|
2361
|
+
actionId: action.id,
|
|
2362
|
+
intent: "exposes"
|
|
2363
|
+
})),
|
|
1738
2364
|
color: "cyan",
|
|
1739
2365
|
icon: "feature.lead-gen",
|
|
1740
2366
|
path: "/lead-gen"
|
|
1741
2367
|
},
|
|
1742
|
-
{
|
|
2368
|
+
projects: {
|
|
1743
2369
|
id: "projects",
|
|
2370
|
+
order: 90,
|
|
1744
2371
|
label: "Projects",
|
|
1745
2372
|
description: "Projects, milestones, and client work execution",
|
|
1746
2373
|
enabled: true,
|
|
2374
|
+
lifecycle: "active",
|
|
1747
2375
|
color: "orange",
|
|
1748
2376
|
icon: "feature.projects",
|
|
1749
2377
|
path: "/projects"
|
|
1750
2378
|
},
|
|
1751
|
-
{
|
|
2379
|
+
clients: {
|
|
1752
2380
|
id: "clients",
|
|
2381
|
+
order: 100,
|
|
1753
2382
|
label: "Clients",
|
|
1754
2383
|
description: "Client relationships, accounts, and business context",
|
|
1755
2384
|
enabled: true,
|
|
2385
|
+
lifecycle: "active",
|
|
1756
2386
|
color: "orange",
|
|
1757
2387
|
icon: "feature.projects",
|
|
1758
|
-
path: "/
|
|
2388
|
+
path: "/clients"
|
|
1759
2389
|
},
|
|
1760
|
-
{
|
|
2390
|
+
operations: {
|
|
1761
2391
|
id: "operations",
|
|
2392
|
+
order: 110,
|
|
1762
2393
|
label: "Operations",
|
|
1763
2394
|
description: "Operational resources, topology, and orchestration visibility",
|
|
1764
2395
|
enabled: true,
|
|
2396
|
+
lifecycle: "active",
|
|
1765
2397
|
color: "violet",
|
|
1766
|
-
icon: "feature.operations"
|
|
1767
|
-
uiPosition: "sidebar-primary"
|
|
2398
|
+
icon: "feature.operations"
|
|
1768
2399
|
},
|
|
1769
|
-
{
|
|
2400
|
+
"knowledge.command-view": {
|
|
1770
2401
|
id: "knowledge.command-view",
|
|
2402
|
+
order: 120,
|
|
1771
2403
|
label: "Command View",
|
|
1772
2404
|
enabled: true,
|
|
2405
|
+
lifecycle: "active",
|
|
1773
2406
|
path: "/knowledge/command-view",
|
|
1774
2407
|
devOnly: true
|
|
1775
2408
|
},
|
|
1776
|
-
{
|
|
2409
|
+
"operations.overview": {
|
|
1777
2410
|
id: "operations.overview",
|
|
2411
|
+
order: 130,
|
|
1778
2412
|
label: "Overview",
|
|
1779
2413
|
enabled: true,
|
|
2414
|
+
lifecycle: "active",
|
|
1780
2415
|
path: "/operations"
|
|
1781
2416
|
},
|
|
1782
|
-
{
|
|
2417
|
+
"operations.resources": {
|
|
1783
2418
|
id: "operations.resources",
|
|
2419
|
+
order: 140,
|
|
1784
2420
|
label: "Resources",
|
|
1785
2421
|
enabled: true,
|
|
2422
|
+
lifecycle: "active",
|
|
1786
2423
|
path: "/operations/resources"
|
|
1787
2424
|
},
|
|
1788
|
-
{
|
|
2425
|
+
"operations.command-queue": {
|
|
1789
2426
|
id: "operations.command-queue",
|
|
2427
|
+
order: 150,
|
|
1790
2428
|
label: "Command Queue",
|
|
1791
2429
|
enabled: true,
|
|
2430
|
+
lifecycle: "active",
|
|
1792
2431
|
path: "/operations/command-queue"
|
|
1793
2432
|
},
|
|
1794
|
-
{
|
|
2433
|
+
"operations.sessions": {
|
|
1795
2434
|
id: "operations.sessions",
|
|
2435
|
+
order: 160,
|
|
1796
2436
|
label: "Sessions",
|
|
1797
2437
|
enabled: false,
|
|
2438
|
+
lifecycle: "deprecated",
|
|
1798
2439
|
path: "/operations/sessions"
|
|
1799
2440
|
},
|
|
1800
|
-
{
|
|
2441
|
+
"operations.task-scheduler": {
|
|
1801
2442
|
id: "operations.task-scheduler",
|
|
2443
|
+
order: 170,
|
|
1802
2444
|
label: "Task Scheduler",
|
|
1803
2445
|
enabled: true,
|
|
2446
|
+
lifecycle: "active",
|
|
1804
2447
|
path: "/operations/task-scheduler"
|
|
1805
2448
|
},
|
|
1806
|
-
{
|
|
2449
|
+
monitoring: {
|
|
1807
2450
|
id: "monitoring",
|
|
2451
|
+
order: 180,
|
|
1808
2452
|
label: "Monitoring",
|
|
1809
2453
|
enabled: true,
|
|
1810
|
-
|
|
2454
|
+
lifecycle: "active"
|
|
1811
2455
|
},
|
|
1812
|
-
{
|
|
2456
|
+
"monitoring.calendar": {
|
|
1813
2457
|
id: "monitoring.calendar",
|
|
2458
|
+
order: 190,
|
|
1814
2459
|
label: "Calendar",
|
|
1815
2460
|
description: "Google Calendar events and agenda views",
|
|
1816
2461
|
enabled: true,
|
|
2462
|
+
lifecycle: "active",
|
|
1817
2463
|
path: "/monitoring/calendar",
|
|
1818
2464
|
icon: "feature.calendar"
|
|
1819
2465
|
},
|
|
1820
|
-
{
|
|
2466
|
+
"monitoring.activity-log": {
|
|
1821
2467
|
id: "monitoring.activity-log",
|
|
2468
|
+
order: 200,
|
|
1822
2469
|
label: "Activity Log",
|
|
1823
2470
|
enabled: true,
|
|
2471
|
+
lifecycle: "active",
|
|
1824
2472
|
path: "/monitoring/activity-log"
|
|
1825
2473
|
},
|
|
1826
|
-
{
|
|
2474
|
+
"monitoring.execution-logs": {
|
|
1827
2475
|
id: "monitoring.execution-logs",
|
|
2476
|
+
order: 210,
|
|
1828
2477
|
label: "Execution Logs",
|
|
1829
2478
|
enabled: true,
|
|
2479
|
+
lifecycle: "active",
|
|
1830
2480
|
path: "/monitoring/execution-logs"
|
|
1831
2481
|
},
|
|
1832
|
-
{
|
|
2482
|
+
"monitoring.execution-health": {
|
|
1833
2483
|
id: "monitoring.execution-health",
|
|
2484
|
+
order: 220,
|
|
1834
2485
|
label: "Execution Health",
|
|
1835
2486
|
enabled: true,
|
|
2487
|
+
lifecycle: "active",
|
|
1836
2488
|
path: "/monitoring/execution-health"
|
|
1837
2489
|
},
|
|
1838
|
-
{
|
|
2490
|
+
"monitoring.cost-analytics": {
|
|
1839
2491
|
id: "monitoring.cost-analytics",
|
|
2492
|
+
order: 230,
|
|
1840
2493
|
label: "Cost Analytics",
|
|
1841
2494
|
enabled: false,
|
|
2495
|
+
lifecycle: "deprecated",
|
|
1842
2496
|
path: "/monitoring/cost-analytics"
|
|
1843
2497
|
},
|
|
1844
|
-
{
|
|
2498
|
+
"monitoring.notifications": {
|
|
1845
2499
|
id: "monitoring.notifications",
|
|
2500
|
+
order: 240,
|
|
1846
2501
|
label: "Notifications",
|
|
1847
2502
|
enabled: true,
|
|
2503
|
+
lifecycle: "active",
|
|
1848
2504
|
path: "/monitoring/notifications"
|
|
1849
2505
|
},
|
|
1850
|
-
{
|
|
2506
|
+
"monitoring.submitted-requests": {
|
|
1851
2507
|
id: "monitoring.submitted-requests",
|
|
2508
|
+
order: 250,
|
|
1852
2509
|
label: "Submitted Requests",
|
|
1853
2510
|
enabled: true,
|
|
2511
|
+
lifecycle: "active",
|
|
1854
2512
|
path: "/monitoring/requests"
|
|
1855
2513
|
},
|
|
1856
|
-
{
|
|
2514
|
+
settings: {
|
|
1857
2515
|
id: "settings",
|
|
2516
|
+
order: 260,
|
|
1858
2517
|
label: "Settings",
|
|
1859
2518
|
enabled: true,
|
|
1860
|
-
|
|
1861
|
-
|
|
2519
|
+
lifecycle: "active",
|
|
2520
|
+
icon: "feature.settings"
|
|
1862
2521
|
},
|
|
1863
|
-
{
|
|
2522
|
+
"settings.account": {
|
|
1864
2523
|
id: "settings.account",
|
|
2524
|
+
order: 270,
|
|
1865
2525
|
label: "Account",
|
|
1866
2526
|
enabled: true,
|
|
2527
|
+
lifecycle: "active",
|
|
1867
2528
|
path: "/settings/account"
|
|
1868
2529
|
},
|
|
1869
|
-
{
|
|
2530
|
+
"settings.appearance": {
|
|
1870
2531
|
id: "settings.appearance",
|
|
2532
|
+
order: 280,
|
|
1871
2533
|
label: "Appearance",
|
|
1872
2534
|
enabled: true,
|
|
2535
|
+
lifecycle: "active",
|
|
1873
2536
|
path: "/settings/appearance"
|
|
1874
2537
|
},
|
|
1875
|
-
{
|
|
2538
|
+
"settings.roles": {
|
|
1876
2539
|
id: "settings.roles",
|
|
2540
|
+
order: 290,
|
|
1877
2541
|
label: "My Roles",
|
|
1878
2542
|
enabled: true,
|
|
2543
|
+
lifecycle: "active",
|
|
1879
2544
|
path: "/settings/roles"
|
|
1880
2545
|
},
|
|
1881
|
-
{
|
|
2546
|
+
"settings.organization": {
|
|
1882
2547
|
id: "settings.organization",
|
|
2548
|
+
order: 300,
|
|
1883
2549
|
label: "Organization",
|
|
1884
2550
|
enabled: true,
|
|
2551
|
+
lifecycle: "active",
|
|
1885
2552
|
path: "/settings/organization"
|
|
1886
2553
|
},
|
|
1887
|
-
{
|
|
2554
|
+
"settings.credentials": {
|
|
1888
2555
|
id: "settings.credentials",
|
|
2556
|
+
order: 310,
|
|
1889
2557
|
label: "Credentials",
|
|
1890
2558
|
enabled: true,
|
|
2559
|
+
lifecycle: "active",
|
|
1891
2560
|
path: "/settings/credentials"
|
|
1892
2561
|
},
|
|
1893
|
-
{
|
|
2562
|
+
"settings.api-keys": {
|
|
1894
2563
|
id: "settings.api-keys",
|
|
2564
|
+
order: 320,
|
|
1895
2565
|
label: "API Keys",
|
|
1896
2566
|
enabled: true,
|
|
2567
|
+
lifecycle: "active",
|
|
1897
2568
|
path: "/settings/api-keys"
|
|
1898
2569
|
},
|
|
1899
|
-
{
|
|
2570
|
+
"settings.webhooks": {
|
|
1900
2571
|
id: "settings.webhooks",
|
|
2572
|
+
order: 330,
|
|
1901
2573
|
label: "Webhooks",
|
|
1902
2574
|
enabled: true,
|
|
2575
|
+
lifecycle: "active",
|
|
1903
2576
|
path: "/settings/webhooks"
|
|
1904
2577
|
},
|
|
1905
|
-
{
|
|
2578
|
+
"settings.deployments": {
|
|
1906
2579
|
id: "settings.deployments",
|
|
2580
|
+
order: 340,
|
|
1907
2581
|
label: "Deployments",
|
|
1908
2582
|
enabled: true,
|
|
2583
|
+
lifecycle: "active",
|
|
1909
2584
|
path: "/settings/deployments"
|
|
1910
2585
|
},
|
|
1911
|
-
{
|
|
2586
|
+
admin: {
|
|
1912
2587
|
id: "admin",
|
|
2588
|
+
order: 350,
|
|
1913
2589
|
label: "Admin",
|
|
1914
2590
|
enabled: true,
|
|
2591
|
+
lifecycle: "active",
|
|
1915
2592
|
path: "/admin",
|
|
1916
2593
|
icon: "feature.admin",
|
|
1917
|
-
uiPosition: "sidebar-bottom",
|
|
1918
2594
|
requiresAdmin: true
|
|
1919
2595
|
},
|
|
1920
|
-
{
|
|
2596
|
+
"admin.system-health": {
|
|
1921
2597
|
id: "admin.system-health",
|
|
2598
|
+
order: 360,
|
|
1922
2599
|
label: "System Health",
|
|
1923
2600
|
enabled: true,
|
|
2601
|
+
lifecycle: "active",
|
|
1924
2602
|
path: "/admin/system-health"
|
|
1925
2603
|
},
|
|
1926
|
-
{
|
|
2604
|
+
"admin.organizations": {
|
|
1927
2605
|
id: "admin.organizations",
|
|
2606
|
+
order: 370,
|
|
1928
2607
|
label: "Organizations",
|
|
1929
2608
|
enabled: true,
|
|
2609
|
+
lifecycle: "active",
|
|
1930
2610
|
path: "/admin/organizations"
|
|
1931
2611
|
},
|
|
1932
|
-
{
|
|
2612
|
+
"admin.users": {
|
|
1933
2613
|
id: "admin.users",
|
|
2614
|
+
order: 380,
|
|
1934
2615
|
label: "Users",
|
|
1935
2616
|
enabled: true,
|
|
2617
|
+
lifecycle: "active",
|
|
1936
2618
|
path: "/admin/users"
|
|
1937
2619
|
},
|
|
1938
|
-
{
|
|
2620
|
+
"admin.design-showcase": {
|
|
1939
2621
|
id: "admin.design-showcase",
|
|
2622
|
+
order: 390,
|
|
1940
2623
|
label: "Design Showcase",
|
|
1941
2624
|
enabled: true,
|
|
2625
|
+
lifecycle: "active",
|
|
1942
2626
|
path: "/admin/design-showcase"
|
|
1943
2627
|
},
|
|
1944
|
-
{
|
|
2628
|
+
"admin.debug": {
|
|
1945
2629
|
id: "admin.debug",
|
|
2630
|
+
order: 400,
|
|
1946
2631
|
label: "Debug",
|
|
1947
2632
|
enabled: true,
|
|
2633
|
+
lifecycle: "active",
|
|
1948
2634
|
path: "/admin/debug"
|
|
1949
2635
|
},
|
|
1950
|
-
{
|
|
2636
|
+
archive: {
|
|
1951
2637
|
id: "archive",
|
|
2638
|
+
order: 410,
|
|
1952
2639
|
label: "Archive",
|
|
1953
2640
|
enabled: true,
|
|
2641
|
+
lifecycle: "active",
|
|
1954
2642
|
path: "/archive",
|
|
1955
2643
|
icon: "feature.archive",
|
|
1956
|
-
uiPosition: "sidebar-bottom",
|
|
1957
2644
|
devOnly: true
|
|
1958
2645
|
},
|
|
1959
|
-
{
|
|
2646
|
+
"archive.agent-chat": {
|
|
1960
2647
|
id: "archive.agent-chat",
|
|
2648
|
+
order: 420,
|
|
1961
2649
|
label: "Agent Chat",
|
|
1962
2650
|
enabled: true,
|
|
2651
|
+
lifecycle: "active",
|
|
1963
2652
|
path: "/archive/agent-chat"
|
|
1964
2653
|
},
|
|
1965
|
-
{
|
|
2654
|
+
"archive.execution-runner": {
|
|
1966
2655
|
id: "archive.execution-runner",
|
|
2656
|
+
order: 430,
|
|
1967
2657
|
label: "Execution Runner",
|
|
1968
2658
|
enabled: true,
|
|
2659
|
+
lifecycle: "active",
|
|
1969
2660
|
path: "/archive/execution-runner"
|
|
1970
2661
|
},
|
|
1971
|
-
{
|
|
2662
|
+
seo: {
|
|
1972
2663
|
id: "seo",
|
|
2664
|
+
order: 440,
|
|
1973
2665
|
label: "SEO",
|
|
1974
2666
|
enabled: false,
|
|
2667
|
+
lifecycle: "deprecated",
|
|
1975
2668
|
path: "/seo"
|
|
1976
2669
|
},
|
|
1977
|
-
{
|
|
2670
|
+
knowledge: {
|
|
1978
2671
|
id: "knowledge",
|
|
2672
|
+
order: 450,
|
|
1979
2673
|
label: "Knowledge",
|
|
1980
2674
|
description: "Operational knowledge, playbooks, and strategy docs",
|
|
1981
2675
|
enabled: true,
|
|
2676
|
+
lifecycle: "active",
|
|
1982
2677
|
color: "teal",
|
|
1983
|
-
icon: "feature.knowledge"
|
|
1984
|
-
uiPosition: "sidebar-primary"
|
|
2678
|
+
icon: "feature.knowledge"
|
|
1985
2679
|
},
|
|
1986
|
-
{
|
|
2680
|
+
"knowledge.base": {
|
|
1987
2681
|
id: "knowledge.base",
|
|
2682
|
+
order: 460,
|
|
1988
2683
|
label: "Knowledge Base",
|
|
1989
2684
|
enabled: true,
|
|
2685
|
+
lifecycle: "active",
|
|
1990
2686
|
path: "/knowledge"
|
|
1991
2687
|
}
|
|
1992
|
-
|
|
1993
|
-
branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
|
|
1994
|
-
navigation: { surfaces: [], groups: [] },
|
|
1995
|
-
sales: DEFAULT_ORGANIZATION_MODEL_SALES,
|
|
1996
|
-
prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
|
|
1997
|
-
projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
|
|
1998
|
-
identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
|
|
1999
|
-
customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
|
|
2000
|
-
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
2001
|
-
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
2002
|
-
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
2003
|
-
systems: DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
|
|
2688
|
+
},
|
|
2004
2689
|
resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
|
|
2005
|
-
|
|
2006
|
-
|
|
2690
|
+
actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
|
|
2691
|
+
entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
|
|
2692
|
+
policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
|
|
2693
|
+
// Phase 4 (D1): statuses top-level field removed; status data lives in system.content.
|
|
2007
2694
|
knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
|
|
2008
2695
|
};
|
|
2696
|
+
var StatusSemanticClassSchema = z.enum([
|
|
2697
|
+
"delivery.task",
|
|
2698
|
+
"delivery.project",
|
|
2699
|
+
"delivery.milestone",
|
|
2700
|
+
"queue",
|
|
2701
|
+
"execution",
|
|
2702
|
+
"schedule",
|
|
2703
|
+
"schedule.run",
|
|
2704
|
+
"request"
|
|
2705
|
+
]);
|
|
2706
|
+
var StatusEntrySchema = z.object({
|
|
2707
|
+
id: z.string().trim().min(1).max(100),
|
|
2708
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
2709
|
+
order: z.number(),
|
|
2710
|
+
label: z.string().trim().min(1).max(120),
|
|
2711
|
+
semanticClass: StatusSemanticClassSchema,
|
|
2712
|
+
category: z.string().trim().min(1).max(80).optional()
|
|
2713
|
+
});
|
|
2714
|
+
var StatusesDomainSchema = z.record(z.string(), StatusEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
2715
|
+
message: "Each status entry id must match its map key"
|
|
2716
|
+
}).default({});
|
|
2717
|
+
var DEFAULT_ORGANIZATION_MODEL_STATUSES = {
|
|
2718
|
+
// --- delivery.task (TaskStatus — 9 values) ---
|
|
2719
|
+
"delivery.task.planned": {
|
|
2720
|
+
id: "delivery.task.planned",
|
|
2721
|
+
order: 10,
|
|
2722
|
+
label: "Planned",
|
|
2723
|
+
semanticClass: "delivery.task",
|
|
2724
|
+
category: "delivery"
|
|
2725
|
+
},
|
|
2726
|
+
"delivery.task.in_progress": {
|
|
2727
|
+
id: "delivery.task.in_progress",
|
|
2728
|
+
order: 20,
|
|
2729
|
+
label: "In Progress",
|
|
2730
|
+
semanticClass: "delivery.task",
|
|
2731
|
+
category: "delivery"
|
|
2732
|
+
},
|
|
2733
|
+
"delivery.task.blocked": {
|
|
2734
|
+
id: "delivery.task.blocked",
|
|
2735
|
+
order: 30,
|
|
2736
|
+
label: "Blocked",
|
|
2737
|
+
semanticClass: "delivery.task",
|
|
2738
|
+
category: "delivery"
|
|
2739
|
+
},
|
|
2740
|
+
"delivery.task.submitted": {
|
|
2741
|
+
id: "delivery.task.submitted",
|
|
2742
|
+
order: 40,
|
|
2743
|
+
label: "Submitted",
|
|
2744
|
+
semanticClass: "delivery.task",
|
|
2745
|
+
category: "delivery"
|
|
2746
|
+
},
|
|
2747
|
+
"delivery.task.approved": {
|
|
2748
|
+
id: "delivery.task.approved",
|
|
2749
|
+
order: 50,
|
|
2750
|
+
label: "Approved",
|
|
2751
|
+
semanticClass: "delivery.task",
|
|
2752
|
+
category: "delivery"
|
|
2753
|
+
},
|
|
2754
|
+
"delivery.task.revision_requested": {
|
|
2755
|
+
id: "delivery.task.revision_requested",
|
|
2756
|
+
order: 60,
|
|
2757
|
+
label: "Revision Requested",
|
|
2758
|
+
semanticClass: "delivery.task",
|
|
2759
|
+
category: "delivery"
|
|
2760
|
+
},
|
|
2761
|
+
"delivery.task.rejected": {
|
|
2762
|
+
id: "delivery.task.rejected",
|
|
2763
|
+
order: 70,
|
|
2764
|
+
label: "Rejected",
|
|
2765
|
+
semanticClass: "delivery.task",
|
|
2766
|
+
category: "delivery"
|
|
2767
|
+
},
|
|
2768
|
+
"delivery.task.cancelled": {
|
|
2769
|
+
id: "delivery.task.cancelled",
|
|
2770
|
+
order: 80,
|
|
2771
|
+
label: "Cancelled",
|
|
2772
|
+
semanticClass: "delivery.task",
|
|
2773
|
+
category: "delivery"
|
|
2774
|
+
},
|
|
2775
|
+
"delivery.task.completed": {
|
|
2776
|
+
id: "delivery.task.completed",
|
|
2777
|
+
order: 90,
|
|
2778
|
+
label: "Completed",
|
|
2779
|
+
semanticClass: "delivery.task",
|
|
2780
|
+
category: "delivery"
|
|
2781
|
+
},
|
|
2782
|
+
// --- delivery.project (ProjectStatus — 6 values) ---
|
|
2783
|
+
"delivery.project.active": {
|
|
2784
|
+
id: "delivery.project.active",
|
|
2785
|
+
order: 100,
|
|
2786
|
+
label: "Active",
|
|
2787
|
+
semanticClass: "delivery.project",
|
|
2788
|
+
category: "delivery"
|
|
2789
|
+
},
|
|
2790
|
+
"delivery.project.on_track": {
|
|
2791
|
+
id: "delivery.project.on_track",
|
|
2792
|
+
order: 110,
|
|
2793
|
+
label: "On Track",
|
|
2794
|
+
semanticClass: "delivery.project",
|
|
2795
|
+
category: "delivery"
|
|
2796
|
+
},
|
|
2797
|
+
"delivery.project.at_risk": {
|
|
2798
|
+
id: "delivery.project.at_risk",
|
|
2799
|
+
order: 120,
|
|
2800
|
+
label: "At Risk",
|
|
2801
|
+
semanticClass: "delivery.project",
|
|
2802
|
+
category: "delivery"
|
|
2803
|
+
},
|
|
2804
|
+
"delivery.project.blocked": {
|
|
2805
|
+
id: "delivery.project.blocked",
|
|
2806
|
+
order: 130,
|
|
2807
|
+
label: "Blocked",
|
|
2808
|
+
semanticClass: "delivery.project",
|
|
2809
|
+
category: "delivery"
|
|
2810
|
+
},
|
|
2811
|
+
"delivery.project.paused": {
|
|
2812
|
+
id: "delivery.project.paused",
|
|
2813
|
+
order: 140,
|
|
2814
|
+
label: "Paused",
|
|
2815
|
+
semanticClass: "delivery.project",
|
|
2816
|
+
category: "delivery"
|
|
2817
|
+
},
|
|
2818
|
+
"delivery.project.completed": {
|
|
2819
|
+
id: "delivery.project.completed",
|
|
2820
|
+
order: 150,
|
|
2821
|
+
label: "Completed",
|
|
2822
|
+
semanticClass: "delivery.project",
|
|
2823
|
+
category: "delivery"
|
|
2824
|
+
},
|
|
2825
|
+
// --- delivery.milestone (MilestoneStatus — 5 values) ---
|
|
2826
|
+
"delivery.milestone.upcoming": {
|
|
2827
|
+
id: "delivery.milestone.upcoming",
|
|
2828
|
+
order: 160,
|
|
2829
|
+
label: "Upcoming",
|
|
2830
|
+
semanticClass: "delivery.milestone",
|
|
2831
|
+
category: "delivery"
|
|
2832
|
+
},
|
|
2833
|
+
"delivery.milestone.in_progress": {
|
|
2834
|
+
id: "delivery.milestone.in_progress",
|
|
2835
|
+
order: 170,
|
|
2836
|
+
label: "In Progress",
|
|
2837
|
+
semanticClass: "delivery.milestone",
|
|
2838
|
+
category: "delivery"
|
|
2839
|
+
},
|
|
2840
|
+
"delivery.milestone.blocked": {
|
|
2841
|
+
id: "delivery.milestone.blocked",
|
|
2842
|
+
order: 180,
|
|
2843
|
+
label: "Blocked",
|
|
2844
|
+
semanticClass: "delivery.milestone",
|
|
2845
|
+
category: "delivery"
|
|
2846
|
+
},
|
|
2847
|
+
"delivery.milestone.overdue": {
|
|
2848
|
+
id: "delivery.milestone.overdue",
|
|
2849
|
+
order: 190,
|
|
2850
|
+
label: "Overdue",
|
|
2851
|
+
semanticClass: "delivery.milestone",
|
|
2852
|
+
category: "delivery"
|
|
2853
|
+
},
|
|
2854
|
+
"delivery.milestone.completed": {
|
|
2855
|
+
id: "delivery.milestone.completed",
|
|
2856
|
+
order: 200,
|
|
2857
|
+
label: "Completed",
|
|
2858
|
+
semanticClass: "delivery.milestone",
|
|
2859
|
+
category: "delivery"
|
|
2860
|
+
},
|
|
2861
|
+
// --- queue (QueueTaskStatus — 5 values, maps hitl/command-queue tasks) ---
|
|
2862
|
+
"queue.pending": { id: "queue.pending", order: 210, label: "Pending", semanticClass: "queue", category: "queue" },
|
|
2863
|
+
"queue.processing": {
|
|
2864
|
+
id: "queue.processing",
|
|
2865
|
+
order: 220,
|
|
2866
|
+
label: "Processing",
|
|
2867
|
+
semanticClass: "queue",
|
|
2868
|
+
category: "queue"
|
|
2869
|
+
},
|
|
2870
|
+
"queue.completed": {
|
|
2871
|
+
id: "queue.completed",
|
|
2872
|
+
order: 230,
|
|
2873
|
+
label: "Completed",
|
|
2874
|
+
semanticClass: "queue",
|
|
2875
|
+
category: "queue"
|
|
2876
|
+
},
|
|
2877
|
+
"queue.failed": { id: "queue.failed", order: 240, label: "Failed", semanticClass: "queue", category: "queue" },
|
|
2878
|
+
"queue.expired": { id: "queue.expired", order: 250, label: "Expired", semanticClass: "queue", category: "queue" },
|
|
2879
|
+
// --- execution (ExecutionStatus — 5 values) ---
|
|
2880
|
+
"execution.pending": {
|
|
2881
|
+
id: "execution.pending",
|
|
2882
|
+
order: 260,
|
|
2883
|
+
label: "Pending",
|
|
2884
|
+
semanticClass: "execution",
|
|
2885
|
+
category: "execution"
|
|
2886
|
+
},
|
|
2887
|
+
"execution.running": {
|
|
2888
|
+
id: "execution.running",
|
|
2889
|
+
order: 270,
|
|
2890
|
+
label: "Running",
|
|
2891
|
+
semanticClass: "execution",
|
|
2892
|
+
category: "execution"
|
|
2893
|
+
},
|
|
2894
|
+
"execution.completed": {
|
|
2895
|
+
id: "execution.completed",
|
|
2896
|
+
order: 280,
|
|
2897
|
+
label: "Completed",
|
|
2898
|
+
semanticClass: "execution",
|
|
2899
|
+
category: "execution"
|
|
2900
|
+
},
|
|
2901
|
+
"execution.failed": {
|
|
2902
|
+
id: "execution.failed",
|
|
2903
|
+
order: 290,
|
|
2904
|
+
label: "Failed",
|
|
2905
|
+
semanticClass: "execution",
|
|
2906
|
+
category: "execution"
|
|
2907
|
+
},
|
|
2908
|
+
"execution.warning": {
|
|
2909
|
+
id: "execution.warning",
|
|
2910
|
+
order: 300,
|
|
2911
|
+
label: "Warning",
|
|
2912
|
+
semanticClass: "execution",
|
|
2913
|
+
category: "execution"
|
|
2914
|
+
},
|
|
2915
|
+
// --- schedule (schedule status — 4 values) ---
|
|
2916
|
+
"schedule.active": {
|
|
2917
|
+
id: "schedule.active",
|
|
2918
|
+
order: 310,
|
|
2919
|
+
label: "Active",
|
|
2920
|
+
semanticClass: "schedule",
|
|
2921
|
+
category: "schedule"
|
|
2922
|
+
},
|
|
2923
|
+
"schedule.paused": {
|
|
2924
|
+
id: "schedule.paused",
|
|
2925
|
+
order: 320,
|
|
2926
|
+
label: "Paused",
|
|
2927
|
+
semanticClass: "schedule",
|
|
2928
|
+
category: "schedule"
|
|
2929
|
+
},
|
|
2930
|
+
"schedule.completed": {
|
|
2931
|
+
id: "schedule.completed",
|
|
2932
|
+
order: 330,
|
|
2933
|
+
label: "Completed",
|
|
2934
|
+
semanticClass: "schedule",
|
|
2935
|
+
category: "schedule"
|
|
2936
|
+
},
|
|
2937
|
+
"schedule.cancelled": {
|
|
2938
|
+
id: "schedule.cancelled",
|
|
2939
|
+
order: 340,
|
|
2940
|
+
label: "Cancelled",
|
|
2941
|
+
semanticClass: "schedule",
|
|
2942
|
+
category: "schedule"
|
|
2943
|
+
},
|
|
2944
|
+
// --- schedule.run (schedule run status — 4 values) ---
|
|
2945
|
+
"schedule.run.running": {
|
|
2946
|
+
id: "schedule.run.running",
|
|
2947
|
+
order: 350,
|
|
2948
|
+
label: "Running",
|
|
2949
|
+
semanticClass: "schedule.run",
|
|
2950
|
+
category: "schedule"
|
|
2951
|
+
},
|
|
2952
|
+
"schedule.run.completed": {
|
|
2953
|
+
id: "schedule.run.completed",
|
|
2954
|
+
order: 360,
|
|
2955
|
+
label: "Completed",
|
|
2956
|
+
semanticClass: "schedule.run",
|
|
2957
|
+
category: "schedule"
|
|
2958
|
+
},
|
|
2959
|
+
"schedule.run.failed": {
|
|
2960
|
+
id: "schedule.run.failed",
|
|
2961
|
+
order: 370,
|
|
2962
|
+
label: "Failed",
|
|
2963
|
+
semanticClass: "schedule.run",
|
|
2964
|
+
category: "schedule"
|
|
2965
|
+
},
|
|
2966
|
+
"schedule.run.cancelled": {
|
|
2967
|
+
id: "schedule.run.cancelled",
|
|
2968
|
+
order: 380,
|
|
2969
|
+
label: "Cancelled",
|
|
2970
|
+
semanticClass: "schedule.run",
|
|
2971
|
+
category: "schedule"
|
|
2972
|
+
},
|
|
2973
|
+
// --- request (RequestStatus — 4 values, maps reported_requests) ---
|
|
2974
|
+
"request.open": { id: "request.open", order: 390, label: "Open", semanticClass: "request", category: "request" },
|
|
2975
|
+
"request.investigating": {
|
|
2976
|
+
id: "request.investigating",
|
|
2977
|
+
order: 400,
|
|
2978
|
+
label: "Investigating",
|
|
2979
|
+
semanticClass: "request",
|
|
2980
|
+
category: "request"
|
|
2981
|
+
},
|
|
2982
|
+
"request.resolved": {
|
|
2983
|
+
id: "request.resolved",
|
|
2984
|
+
order: 410,
|
|
2985
|
+
label: "Resolved",
|
|
2986
|
+
semanticClass: "request",
|
|
2987
|
+
category: "request"
|
|
2988
|
+
},
|
|
2989
|
+
"request.wont_fix": {
|
|
2990
|
+
id: "request.wont_fix",
|
|
2991
|
+
order: 420,
|
|
2992
|
+
label: "Won't Fix",
|
|
2993
|
+
semanticClass: "request",
|
|
2994
|
+
category: "request"
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2998
|
+
// src/organization-model/catalogs/lead-gen.ts
|
|
2999
|
+
var LEAD_GEN_STAGE_CATALOG = {
|
|
3000
|
+
// Prospecting - company population
|
|
3001
|
+
scraped: {
|
|
3002
|
+
key: "scraped",
|
|
3003
|
+
label: "Scraped",
|
|
3004
|
+
description: "Company was scraped from a source directory (Apify actor run).",
|
|
3005
|
+
order: 1,
|
|
3006
|
+
entity: "company"
|
|
3007
|
+
},
|
|
3008
|
+
populated: {
|
|
3009
|
+
key: "populated",
|
|
3010
|
+
label: "Companies found",
|
|
3011
|
+
description: "Companies have been found and added to the lead-gen list.",
|
|
3012
|
+
order: 2,
|
|
3013
|
+
entity: "company"
|
|
3014
|
+
},
|
|
3015
|
+
crawled: {
|
|
3016
|
+
key: "crawled",
|
|
3017
|
+
label: "Websites crawled",
|
|
3018
|
+
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
3019
|
+
order: 2.5,
|
|
3020
|
+
entity: "company"
|
|
3021
|
+
},
|
|
3022
|
+
extracted: {
|
|
3023
|
+
key: "extracted",
|
|
3024
|
+
label: "Websites analyzed",
|
|
3025
|
+
description: "Company websites have been analyzed for business signals.",
|
|
3026
|
+
order: 3,
|
|
3027
|
+
entity: "company"
|
|
3028
|
+
},
|
|
3029
|
+
enriched: {
|
|
3030
|
+
key: "enriched",
|
|
3031
|
+
label: "Enriched",
|
|
3032
|
+
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
3033
|
+
order: 4,
|
|
3034
|
+
entity: "company"
|
|
3035
|
+
},
|
|
3036
|
+
"decision-makers-enriched": {
|
|
3037
|
+
key: "decision-makers-enriched",
|
|
3038
|
+
label: "Decision-makers found",
|
|
3039
|
+
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
3040
|
+
order: 6,
|
|
3041
|
+
entity: "company",
|
|
3042
|
+
recordEntity: "contact",
|
|
3043
|
+
recordStageKey: "discovered"
|
|
3044
|
+
},
|
|
3045
|
+
// Prospecting - contact discovery
|
|
3046
|
+
discovered: {
|
|
3047
|
+
key: "discovered",
|
|
3048
|
+
label: "Decision-makers found",
|
|
3049
|
+
description: "Decision-maker contact details have been found.",
|
|
3050
|
+
order: 5,
|
|
3051
|
+
entity: "contact"
|
|
3052
|
+
},
|
|
3053
|
+
verified: {
|
|
3054
|
+
key: "verified",
|
|
3055
|
+
label: "Emails verified",
|
|
3056
|
+
description: "Contact email addresses have been checked for deliverability.",
|
|
3057
|
+
order: 7,
|
|
3058
|
+
entity: "contact"
|
|
3059
|
+
},
|
|
3060
|
+
// Qualification
|
|
3061
|
+
qualified: {
|
|
3062
|
+
key: "qualified",
|
|
3063
|
+
label: "Companies qualified",
|
|
3064
|
+
description: "Companies have been scored against the qualification criteria.",
|
|
3065
|
+
order: 8,
|
|
3066
|
+
entity: "company"
|
|
3067
|
+
},
|
|
3068
|
+
// Outreach
|
|
3069
|
+
personalized: {
|
|
3070
|
+
key: "personalized",
|
|
3071
|
+
label: "Personalized",
|
|
3072
|
+
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
3073
|
+
order: 9,
|
|
3074
|
+
entity: "contact"
|
|
3075
|
+
},
|
|
3076
|
+
uploaded: {
|
|
3077
|
+
key: "uploaded",
|
|
3078
|
+
label: "Reviewed and exported",
|
|
3079
|
+
description: "Approved records have been reviewed and exported for handoff.",
|
|
3080
|
+
order: 10,
|
|
3081
|
+
entity: "company",
|
|
3082
|
+
additionalEntities: ["contact"]
|
|
3083
|
+
},
|
|
3084
|
+
interested: {
|
|
3085
|
+
key: "interested",
|
|
3086
|
+
label: "Interested",
|
|
3087
|
+
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
3088
|
+
order: 11,
|
|
3089
|
+
entity: "contact"
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
|
|
3093
|
+
// src/organization-model/helpers.ts
|
|
3094
|
+
function listAllSystems(model) {
|
|
3095
|
+
const results = [];
|
|
3096
|
+
function walk(map, prefix) {
|
|
3097
|
+
for (const [localId, system] of Object.entries(map)) {
|
|
3098
|
+
const fullPath = prefix ? `${prefix}.${localId}` : localId;
|
|
3099
|
+
results.push({ path: fullPath, system });
|
|
3100
|
+
if (system.subsystems) {
|
|
3101
|
+
walk(system.subsystems, fullPath);
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
walk(model.systems, "");
|
|
3106
|
+
return results;
|
|
3107
|
+
}
|
|
2009
3108
|
|
|
2010
3109
|
// src/organization-model/resolve.ts
|
|
2011
3110
|
function isPlainObject(value) {
|
|
@@ -2034,43 +3133,119 @@ function defineOrganizationModel(model) {
|
|
|
2034
3133
|
}
|
|
2035
3134
|
function resolveOrganizationModel(override, organizationId) {
|
|
2036
3135
|
const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override);
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
3136
|
+
return OrganizationModelSchema.parse(merged);
|
|
3137
|
+
}
|
|
3138
|
+
function resolveOrganizationModelWithResources(override, organizationId) {
|
|
3139
|
+
const model = resolveOrganizationModel(override);
|
|
3140
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
3141
|
+
for (const resource of Object.values(model.resources ?? {})) {
|
|
3142
|
+
const existing = byPath.get(resource.systemPath);
|
|
3143
|
+
if (existing) {
|
|
3144
|
+
existing.push(resource);
|
|
3145
|
+
} else {
|
|
3146
|
+
byPath.set(resource.systemPath, [resource]);
|
|
3147
|
+
}
|
|
2043
3148
|
}
|
|
2044
|
-
|
|
3149
|
+
const enrichedSystems = {};
|
|
3150
|
+
for (const { path, system } of listAllSystems(model)) {
|
|
3151
|
+
const resources = byPath.get(path) ?? byPath.get(system.id);
|
|
3152
|
+
enrichedSystems[path] = resources !== void 0 ? { ...system, id: path, resources } : { ...system, id: path };
|
|
3153
|
+
}
|
|
3154
|
+
return { ...model, systems: enrichedSystems };
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
// src/organization-model/surface-projection.ts
|
|
3158
|
+
function collectSystemsById(model) {
|
|
3159
|
+
const systemsById = /* @__PURE__ */ new Map();
|
|
3160
|
+
for (const { path, system } of listAllSystems(model)) {
|
|
3161
|
+
systemsById.set(path, system);
|
|
3162
|
+
systemsById.set(system.id, system);
|
|
3163
|
+
}
|
|
3164
|
+
return systemsById;
|
|
3165
|
+
}
|
|
3166
|
+
function getSystemWithAncestors(systemsById, systemId) {
|
|
3167
|
+
const systems = [];
|
|
3168
|
+
let current = systemsById.get(systemId);
|
|
3169
|
+
while (current !== void 0) {
|
|
3170
|
+
systems.unshift(current);
|
|
3171
|
+
current = current.parentSystemId ? systemsById.get(current.parentSystemId) : void 0;
|
|
3172
|
+
}
|
|
3173
|
+
return systems;
|
|
3174
|
+
}
|
|
3175
|
+
function hasInheritedFlag(systemsById, systemIds, flag) {
|
|
3176
|
+
return systemIds.some(
|
|
3177
|
+
(systemId) => getSystemWithAncestors(systemsById, systemId).some((system) => system[flag] === true)
|
|
3178
|
+
);
|
|
3179
|
+
}
|
|
3180
|
+
function isLifecycleEnabled2(system) {
|
|
3181
|
+
if (system.enabled === false) return false;
|
|
3182
|
+
return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
|
|
3183
|
+
}
|
|
3184
|
+
function isLifecycleDevOnly(system) {
|
|
3185
|
+
return system.devOnly === true || system.lifecycle === "beta";
|
|
3186
|
+
}
|
|
3187
|
+
function isSystemEnabled(systemsById, systemId) {
|
|
3188
|
+
const systemLineage = getSystemWithAncestors(systemsById, systemId);
|
|
3189
|
+
return systemLineage.length > 0 && systemLineage.every(isLifecycleEnabled2);
|
|
3190
|
+
}
|
|
3191
|
+
function unique(values) {
|
|
3192
|
+
return [...new Set(values)];
|
|
3193
|
+
}
|
|
3194
|
+
function collectSidebarSurfaces(nodes, schemaPath, surfaces = []) {
|
|
3195
|
+
getSortedSidebarEntries(nodes).forEach(([id, node]) => {
|
|
3196
|
+
const nodePath = [...schemaPath, id];
|
|
3197
|
+
if (node.type === "group") {
|
|
3198
|
+
collectSidebarSurfaces(node.children, [...nodePath, "children"], surfaces);
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
surfaces.push({ id, surface: node, path: nodePath });
|
|
3202
|
+
});
|
|
3203
|
+
return surfaces;
|
|
3204
|
+
}
|
|
3205
|
+
function getSidebarSurfaces(model) {
|
|
3206
|
+
return [
|
|
3207
|
+
...collectSidebarSurfaces(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]),
|
|
3208
|
+
...collectSidebarSurfaces(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"])
|
|
3209
|
+
];
|
|
3210
|
+
}
|
|
3211
|
+
function projectOrganizationSurfaces(model) {
|
|
3212
|
+
const systemsById = collectSystemsById(model);
|
|
3213
|
+
return getSidebarSurfaces(model).map(({ id, surface }) => {
|
|
3214
|
+
const targets = surface.targets ?? {};
|
|
3215
|
+
const systemIds = unique((targets.systems ?? []).filter((systemId) => systemsById.has(systemId)));
|
|
3216
|
+
const enabled = systemIds.every((candidate) => isSystemEnabled(systemsById, candidate));
|
|
3217
|
+
const devOnly = surface.devOnly === true || hasInheritedFlag(systemsById, systemIds, "devOnly") || systemIds.some((candidate) => getSystemWithAncestors(systemsById, candidate).some(isLifecycleDevOnly));
|
|
3218
|
+
const requiresAdmin = hasInheritedFlag(systemsById, systemIds, "requiresAdmin");
|
|
3219
|
+
return {
|
|
3220
|
+
id,
|
|
3221
|
+
label: surface.label,
|
|
3222
|
+
path: surface.path,
|
|
3223
|
+
surfaceType: surface.surfaceType,
|
|
3224
|
+
...surface.description !== void 0 ? { description: surface.description } : {},
|
|
3225
|
+
...surface.icon !== void 0 ? { icon: surface.icon } : {},
|
|
3226
|
+
...surface.order !== void 0 ? { order: surface.order } : {},
|
|
3227
|
+
systemIds,
|
|
3228
|
+
entityIds: [...targets.entities ?? []],
|
|
3229
|
+
resourceIds: [...targets.resources ?? []],
|
|
3230
|
+
actionIds: [...targets.actions ?? []],
|
|
3231
|
+
enabled,
|
|
3232
|
+
...devOnly ? { devOnly } : {},
|
|
3233
|
+
...surface.requiresAdmin === true || requiresAdmin ? { requiresAdmin: true } : {}
|
|
3234
|
+
};
|
|
3235
|
+
});
|
|
2045
3236
|
}
|
|
2046
3237
|
|
|
2047
3238
|
// src/organization-model/foundation.ts
|
|
2048
3239
|
function createFoundationOrganizationModel(override) {
|
|
2049
3240
|
const canonical = resolveOrganizationModel(override);
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
}
|
|
2055
|
-
return feature;
|
|
2056
|
-
}
|
|
2057
|
-
const operationsFeature = requireCoreFeature("operations");
|
|
2058
|
-
const projectsFeature = requireCoreFeature("projects");
|
|
2059
|
-
const leadGenFeature = requireCoreFeature("sales.lead-gen");
|
|
2060
|
-
const crmFeature = requireCoreFeature("sales.crm");
|
|
2061
|
-
const navigationSurfaces = [
|
|
2062
|
-
{ ...operationsFeature, id: "operations", path: "/operations", icon: "feature.operations", surfaceType: "dashboard" },
|
|
2063
|
-
{ ...projectsFeature, icon: "feature.projects", surfaceType: "list" },
|
|
2064
|
-
{ ...leadGenFeature, id: "lead-gen", icon: "feature.lead-gen", surfaceType: "list" },
|
|
2065
|
-
{ ...crmFeature, id: "crm", icon: "feature.crm", surfaceType: "graph" },
|
|
2066
|
-
{ ...requireCoreFeature("settings.account"), id: "settings", icon: "feature.settings", surfaceType: "settings" }
|
|
2067
|
-
];
|
|
2068
|
-
const homeLabel = "Dashboard";
|
|
2069
|
-
const quickAccessSurfaceIds = ["operations", "projects", "lead-gen", "crm"];
|
|
3241
|
+
const navigationSurfaces = projectOrganizationSurfaces(canonical);
|
|
3242
|
+
const defaultSurface = navigationSurfaces.find((surface) => surface.path === "/") ?? navigationSurfaces[0];
|
|
3243
|
+
const homeLabel = defaultSurface?.label ?? "Dashboard";
|
|
3244
|
+
const quickAccessSurfaceIds = navigationSurfaces.filter((surface) => surface.id !== defaultSurface?.id && surface.surfaceType !== "settings").slice(0, 4).map((surface) => surface.id);
|
|
2070
3245
|
const model = {
|
|
2071
3246
|
...canonical,
|
|
2072
3247
|
navigation: {
|
|
2073
|
-
defaultSurfaceId: "
|
|
3248
|
+
defaultSurfaceId: defaultSurface?.id ?? "",
|
|
2074
3249
|
homeLabel,
|
|
2075
3250
|
quickAccessSurfaceIds: [...quickAccessSurfaceIds],
|
|
2076
3251
|
surfaces: navigationSurfaces
|
|
@@ -2088,4 +3263,4 @@ function createFoundationOrganizationModel(override) {
|
|
|
2088
3263
|
};
|
|
2089
3264
|
}
|
|
2090
3265
|
|
|
2091
|
-
export { AgentKindSchema, AgentResourceEntrySchema, AgentRoleHolderSchema, CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
3266
|
+
export { ActionIdSchema, ActionInvocationKindSchema, ActionInvocationSchema, ActionRefSchema, ActionSchema, ActionScopeSchema, ActionsDomainSchema, AgentKindSchema, AgentResourceEntrySchema, AgentRoleHolderSchema, ApiEndpointInvocationSchema, CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_ACTIONS, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, DEFAULT_ORGANIZATION_MODEL_ENTITIES, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_NAVIGATION, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_POLICIES, DEFAULT_ORGANIZATION_MODEL_RESOURCES, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, EntitiesDomainSchema, EntityIdSchema, EntityLinkKindSchema, EntityLinkSchema, EntitySchema, EventDescriptorSchema, EventEmissionDescriptorSchema, EventIdSchema, FirmographicsSchema, GoalsDomainSchema, HumanRoleHolderSchema, IconNameSchema, IntegrationResourceEntrySchema, KNOWLEDGE_FEATURE_ID, KNOWLEDGE_SYSTEM_ID, KeyResultSchema, KnowledgeDomainSchema, KnowledgeLinkSchema, KnowledgeTargetKindSchema, KnowledgeTargetRefSchema, LEAD_GEN_ACTION_ENTRIES, LEAD_GEN_STAGE_CATALOG, LinkSchema, MONITORING_FEATURE_ID, MONITORING_SYSTEM_ID, McpToolInvocationSchema, NavigationGroupSchema, NodeIdPathSchema, NodeIdStringSchema, OPERATIONS_COMMAND_VIEW_SURFACE_ID, OPERATIONS_FEATURE_ID, OPERATIONS_SYSTEM_ID, ORGANIZATION_MODEL_ICON_TOKENS, ObjectiveSchema, OfferingsDomainSchema, OrgKnowledgeKindSchema, OrgKnowledgeNodeSchema, OrganizationModelBuiltinIconTokenSchema, OrganizationModelDomainKeySchema, OrganizationModelDomainMetadataByDomainSchema, OrganizationModelDomainMetadataSchema, OrganizationModelIconTokenSchema, OrganizationModelNavigationSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_SYSTEM_ID, PROJECTS_VIEW_ACTION_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PROSPECTING_SYSTEM_ID, PoliciesDomainSchema, PolicyApplicabilitySchema, PolicyEffectSchema, PolicyIdSchema, PolicyPredicateSchema, PolicySchema, PolicyTriggerSchema, PricingModelSchema, ProductSchema, ResourceEntrySchema, ResourceGovernanceStatusSchema, ResourceIdSchema, ResourceKindSchema, ResourcesDomainSchema, RoleHolderSchema, RoleHoldersSchema, RoleIdSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SALES_SYSTEM_ID, SEO_FEATURE_ID, SEO_SYSTEM_ID, SETTINGS_FEATURE_ID, SETTINGS_ROLES_SURFACE_ID, SETTINGS_SYSTEM_ID, ScriptExecutionInvocationSchema, ScriptResourceEntrySchema, ScriptResourceLanguageSchema, ScriptResourceSourceSchema, SidebarNavigationSchema, SidebarNodeSchema, SidebarSectionSchema, SidebarSurfaceTargetsSchema, SlashCommandInvocationSchema, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, SurfaceDefinitionSchema, SurfaceTypeSchema, SystemEntrySchema, SystemIdSchema, SystemKindSchema, SystemLifecycleSchema, SystemPathSchema, SystemStatusSchema, SystemUiSchema, SystemsDomainSchema, TeamRoleHolderSchema, TechStackEntrySchema, UiPositionSchema, WorkflowResourceEntrySchema, createFoundationOrganizationModel, defineOrganizationModel, defineResource, defineResources, findOrganizationActionById, getSortedSidebarEntries, resolveOrganizationModel, resolveOrganizationModelWithResources };
|