@elevasis/core 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/index.d.ts +2518 -2169
  2. package/dist/index.js +2495 -1095
  3. package/dist/knowledge/index.d.ts +706 -1044
  4. package/dist/knowledge/index.js +9 -9
  5. package/dist/organization-model/index.d.ts +2518 -2169
  6. package/dist/organization-model/index.js +2495 -1095
  7. package/dist/test-utils/index.d.ts +826 -1014
  8. package/dist/test-utils/index.js +1894 -1032
  9. package/package.json +3 -3
  10. package/src/__tests__/template-core-compatibility.test.ts +11 -79
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
  12. package/src/auth/multi-tenancy/permissions.ts +20 -8
  13. package/src/business/README.md +2 -2
  14. package/src/business/acquisition/api-schemas.test.ts +175 -2
  15. package/src/business/acquisition/api-schemas.ts +132 -16
  16. package/src/business/acquisition/build-templates.test.ts +4 -4
  17. package/src/business/acquisition/build-templates.ts +72 -30
  18. package/src/business/acquisition/crm-state-actions.test.ts +13 -11
  19. package/src/business/acquisition/index.ts +12 -0
  20. package/src/business/acquisition/types.ts +7 -3
  21. package/src/business/clients/api-schemas.test.ts +115 -0
  22. package/src/business/clients/api-schemas.ts +158 -0
  23. package/src/business/clients/index.ts +1 -0
  24. package/src/business/deals/api-schemas.ts +8 -0
  25. package/src/business/index.ts +5 -2
  26. package/src/business/projects/types.ts +19 -0
  27. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
  28. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
  29. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
  30. package/src/execution/engine/agent/core/types.ts +25 -15
  31. package/src/execution/engine/agent/index.ts +6 -4
  32. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
  33. package/src/execution/engine/index.ts +3 -0
  34. package/src/execution/engine/workflow/types.ts +9 -2
  35. package/src/knowledge/README.md +8 -7
  36. package/src/knowledge/__tests__/queries.test.ts +74 -73
  37. package/src/knowledge/format.ts +10 -9
  38. package/src/knowledge/index.ts +1 -1
  39. package/src/knowledge/published.ts +1 -1
  40. package/src/knowledge/queries.ts +26 -25
  41. package/src/organization-model/README.md +73 -26
  42. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  43. package/src/organization-model/__tests__/defaults.test.ts +76 -96
  44. package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
  45. package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
  46. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  47. package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
  48. package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
  49. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
  50. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
  51. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  52. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
  53. package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
  54. package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
  55. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
  56. package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
  57. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
  58. package/src/organization-model/__tests__/foundation.test.ts +74 -102
  59. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  60. package/src/organization-model/__tests__/graph.test.ts +899 -71
  61. package/src/organization-model/__tests__/knowledge.test.ts +209 -49
  62. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  63. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  64. package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
  65. package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
  66. package/src/organization-model/__tests__/resolve.test.ts +174 -23
  67. package/src/organization-model/__tests__/schema.test.ts +291 -114
  68. package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
  69. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  70. package/src/organization-model/content-kinds/config.ts +36 -0
  71. package/src/organization-model/content-kinds/index.ts +74 -0
  72. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  73. package/src/organization-model/content-kinds/registry.ts +44 -0
  74. package/src/organization-model/content-kinds/status.ts +71 -0
  75. package/src/organization-model/content-kinds/template.ts +83 -0
  76. package/src/organization-model/content-kinds/types.ts +117 -0
  77. package/src/organization-model/contracts.ts +13 -3
  78. package/src/organization-model/defaults.ts +499 -86
  79. package/src/organization-model/domains/actions.ts +239 -0
  80. package/src/organization-model/domains/customers.ts +78 -75
  81. package/src/organization-model/domains/entities.ts +144 -0
  82. package/src/organization-model/domains/goals.ts +83 -80
  83. package/src/organization-model/domains/knowledge.ts +76 -17
  84. package/src/organization-model/domains/navigation.ts +107 -384
  85. package/src/organization-model/domains/offerings.ts +71 -66
  86. package/src/organization-model/domains/policies.ts +102 -0
  87. package/src/organization-model/domains/projects.ts +14 -48
  88. package/src/organization-model/domains/prospecting.ts +62 -181
  89. package/src/organization-model/domains/resources.ts +145 -0
  90. package/src/organization-model/domains/roles.ts +96 -55
  91. package/src/organization-model/domains/sales.ts +10 -219
  92. package/src/organization-model/domains/shared.ts +57 -57
  93. package/src/organization-model/domains/statuses.ts +339 -130
  94. package/src/organization-model/domains/systems.ts +203 -0
  95. package/src/organization-model/foundation.ts +54 -67
  96. package/src/organization-model/graph/build.ts +682 -54
  97. package/src/organization-model/graph/link.ts +1 -1
  98. package/src/organization-model/graph/schema.ts +24 -9
  99. package/src/organization-model/graph/types.ts +20 -7
  100. package/src/organization-model/helpers.ts +231 -26
  101. package/src/organization-model/icons.ts +1 -0
  102. package/src/organization-model/index.ts +118 -5
  103. package/src/organization-model/migration-helpers.ts +249 -0
  104. package/src/organization-model/organization-graph.mdx +16 -15
  105. package/src/organization-model/organization-model.mdx +111 -44
  106. package/src/organization-model/published.ts +172 -19
  107. package/src/organization-model/resolve.ts +117 -54
  108. package/src/organization-model/schema.ts +654 -112
  109. package/src/organization-model/surface-projection.ts +116 -122
  110. package/src/organization-model/types.ts +146 -20
  111. package/src/platform/api/types.ts +38 -35
  112. package/src/platform/constants/versions.ts +1 -1
  113. package/src/platform/registry/__tests__/command-view.test.ts +6 -8
  114. package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
  115. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
  116. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  117. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
  118. package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
  119. package/src/platform/registry/index.ts +14 -0
  120. package/src/platform/registry/resource-registry.ts +52 -2
  121. package/src/platform/registry/serialization.ts +241 -202
  122. package/src/platform/registry/serialized-types.ts +1 -0
  123. package/src/platform/registry/types.ts +411 -361
  124. package/src/platform/registry/validation.ts +745 -513
  125. package/src/projects/api-schemas.ts +290 -267
  126. package/src/reference/_generated/contracts.md +853 -397
  127. package/src/reference/glossary.md +23 -18
  128. package/src/supabase/database.types.ts +181 -0
  129. package/src/test-utils/test-utils.test.ts +1 -6
  130. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  131. package/src/organization-model/domains/features.ts +0 -31
  132. 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",
@@ -19,6 +203,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
19
203
  "knowledge.reference",
20
204
  "feature.dashboard",
21
205
  "feature.calendar",
206
+ "feature.business",
22
207
  "feature.sales",
23
208
  "feature.crm",
24
209
  "feature.finance",
@@ -111,10 +296,10 @@ DisplayMetadataSchema.extend({
111
296
  id: ModelIdSchema,
112
297
  resourceId: z.string().trim().min(1).max(255),
113
298
  resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
114
- featureIds: ReferenceIdsSchema,
299
+ systemIds: ReferenceIdsSchema,
115
300
  entityIds: ReferenceIdsSchema,
116
301
  surfaceIds: ReferenceIdsSchema,
117
- capabilityIds: ReferenceIdsSchema,
302
+ actionIds: ReferenceIdsSchema,
118
303
  /** Optional tech-stack metadata for external-SaaS integrations. */
119
304
  techStack: TechStackEntrySchema.optional()
120
305
  });
@@ -136,654 +321,7 @@ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
136
321
  shortName: "Elevasis",
137
322
  logos: {}
138
323
  };
139
- var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
140
- var SalesStageSchema = DisplayMetadataSchema.extend({
141
- id: ModelIdSchema,
142
- order: z.number().int().min(0),
143
- semanticClass: SalesStageSemanticClassSchema,
144
- surfaceIds: ReferenceIdsSchema,
145
- resourceIds: ReferenceIdsSchema
146
- });
147
- var SalesPipelineSchema = z.object({
148
- id: ModelIdSchema,
149
- label: z.string().trim().min(1).max(120),
150
- description: DescriptionSchema.optional(),
151
- entityId: ModelIdSchema,
152
- stages: z.array(SalesStageSchema).min(1)
153
- });
154
- var OrganizationModelSalesSchema = z.object({
155
- entityId: ModelIdSchema,
156
- defaultPipelineId: ModelIdSchema,
157
- pipelines: z.array(SalesPipelineSchema).min(1)
158
- });
159
- var DEFAULT_ORGANIZATION_MODEL_SALES = {
160
- entityId: "crm.deal",
161
- defaultPipelineId: "default",
162
- pipelines: [
163
- {
164
- id: "default",
165
- label: "Default Pipeline",
166
- entityId: "crm.deal",
167
- stages: [
168
- {
169
- id: "interested",
170
- label: "Interested",
171
- color: "blue",
172
- order: 1,
173
- semanticClass: "open",
174
- surfaceIds: ["crm.pipeline"],
175
- resourceIds: []
176
- },
177
- {
178
- id: "proposal",
179
- label: "Proposal",
180
- color: "yellow",
181
- order: 2,
182
- semanticClass: "active",
183
- surfaceIds: ["crm.pipeline"],
184
- resourceIds: []
185
- },
186
- {
187
- id: "closing",
188
- label: "Closing",
189
- color: "lime",
190
- order: 3,
191
- semanticClass: "active",
192
- surfaceIds: ["crm.pipeline"],
193
- resourceIds: []
194
- },
195
- {
196
- id: "closed_won",
197
- label: "Closed Won",
198
- color: "green",
199
- order: 4,
200
- semanticClass: "closed_won",
201
- surfaceIds: ["crm.pipeline"],
202
- resourceIds: []
203
- },
204
- {
205
- id: "closed_lost",
206
- label: "Closed Lost",
207
- color: "red",
208
- order: 5,
209
- semanticClass: "closed_lost",
210
- surfaceIds: ["crm.pipeline"],
211
- resourceIds: []
212
- },
213
- {
214
- id: "nurturing",
215
- label: "Nurturing",
216
- color: "grape",
217
- order: 6,
218
- semanticClass: "nurturing",
219
- surfaceIds: ["crm.pipeline"],
220
- resourceIds: []
221
- }
222
- ]
223
- }
224
- ]
225
- };
226
- var LEAD_GEN_STAGE_CATALOG = {
227
- // Prospecting — company population
228
- scraped: {
229
- key: "scraped",
230
- label: "Scraped",
231
- description: "Company was scraped from a source directory (Apify actor run).",
232
- order: 1,
233
- entity: "company"
234
- },
235
- populated: {
236
- key: "populated",
237
- label: "Companies found",
238
- description: "Companies have been found and added to the lead-gen list.",
239
- order: 2,
240
- entity: "company"
241
- },
242
- crawled: {
243
- key: "crawled",
244
- label: "Websites crawled",
245
- description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
246
- order: 2.5,
247
- entity: "company"
248
- },
249
- extracted: {
250
- key: "extracted",
251
- label: "Websites analyzed",
252
- description: "Company websites have been analyzed for business signals.",
253
- order: 3,
254
- entity: "company"
255
- },
256
- enriched: {
257
- key: "enriched",
258
- label: "Enriched",
259
- description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
260
- order: 4,
261
- entity: "company"
262
- },
263
- "decision-makers-enriched": {
264
- key: "decision-makers-enriched",
265
- label: "Decision-makers found",
266
- description: "Decision-maker contacts discovered and attached to a qualified company.",
267
- order: 6,
268
- entity: "company",
269
- recordEntity: "contact",
270
- recordStageKey: "discovered"
271
- },
272
- // Prospecting — contact discovery
273
- discovered: {
274
- key: "discovered",
275
- label: "Decision-makers found",
276
- description: "Decision-maker contact details have been found.",
277
- order: 5,
278
- entity: "contact"
279
- },
280
- verified: {
281
- key: "verified",
282
- label: "Emails verified",
283
- description: "Contact email addresses have been checked for deliverability.",
284
- order: 7,
285
- entity: "contact"
286
- },
287
- // Qualification
288
- qualified: {
289
- key: "qualified",
290
- label: "Companies qualified",
291
- description: "Companies have been scored against the qualification criteria.",
292
- order: 8,
293
- entity: "company"
294
- },
295
- // Outreach
296
- personalized: {
297
- key: "personalized",
298
- label: "Personalized",
299
- description: "Outreach message personalized for the contact (Instantly personalization workflow).",
300
- order: 9,
301
- entity: "contact"
302
- },
303
- uploaded: {
304
- key: "uploaded",
305
- label: "Reviewed and exported",
306
- description: "Approved records have been reviewed and exported for handoff.",
307
- order: 10,
308
- entity: "company",
309
- additionalEntities: ["contact"]
310
- },
311
- interested: {
312
- key: "interested",
313
- label: "Interested",
314
- description: "Contact replied with a positive signal (Instantly reply-handler transition).",
315
- order: 11,
316
- entity: "contact"
317
- }
318
- };
319
- var ProjectsDomainStateSchema = DisplayMetadataSchema.extend({
320
- id: ModelIdSchema,
321
- order: z.number().int().min(0)
322
- });
323
- var OrganizationModelProjectsSchema = z.object({
324
- projectEntityId: ModelIdSchema,
325
- milestoneEntityId: ModelIdSchema,
326
- taskEntityId: ModelIdSchema,
327
- projectStatuses: z.array(ProjectsDomainStateSchema).min(1),
328
- milestoneStatuses: z.array(ProjectsDomainStateSchema).min(1),
329
- taskStatuses: z.array(ProjectsDomainStateSchema).min(1)
330
- });
331
- var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
332
- projectEntityId: "delivery.project",
333
- milestoneEntityId: "delivery.milestone",
334
- taskEntityId: "delivery.task",
335
- projectStatuses: [
336
- { id: "active", label: "Active", order: 1 },
337
- { id: "on_track", label: "On Track", order: 2 },
338
- { id: "at_risk", label: "At Risk", order: 3 },
339
- { id: "blocked", label: "Blocked", order: 4 },
340
- { id: "paused", label: "Paused", order: 5 },
341
- { id: "completed", label: "Completed", order: 6 }
342
- ],
343
- milestoneStatuses: [
344
- { id: "upcoming", label: "Upcoming", order: 1 },
345
- { id: "in_progress", label: "In Progress", order: 2 },
346
- { id: "blocked", label: "Blocked", order: 3 },
347
- { id: "overdue", label: "Overdue", order: 4 },
348
- { id: "completed", label: "Completed", order: 5 }
349
- ],
350
- taskStatuses: [
351
- { id: "planned", label: "Planned", order: 1 },
352
- { id: "in_progress", label: "In Progress", order: 2 },
353
- { id: "blocked", label: "Blocked", order: 3 },
354
- { id: "submitted", label: "Submitted", order: 4 },
355
- { id: "approved", label: "Approved", order: 5 },
356
- { id: "revision_requested", label: "Revision Requested", order: 6 },
357
- { id: "rejected", label: "Rejected", order: 7 },
358
- { id: "cancelled", label: "Cancelled", order: 8 },
359
- { id: "completed", label: "Completed", order: 9 }
360
- ]
361
- };
362
- var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
363
- 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");
364
- var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
365
- var FeatureSchema = z.object({
366
- id: NodeIdPathSchema,
367
- label: LabelSchema,
368
- description: DescriptionSchema.optional(),
369
- enabled: z.boolean().default(true),
370
- path: PathSchema.optional(),
371
- icon: IconNameSchema.optional(),
372
- color: ColorTokenSchema.optional(),
373
- uiPosition: UiPositionSchema.optional(),
374
- requiresAdmin: z.boolean().optional(),
375
- devOnly: z.boolean().optional()
376
- });
377
- var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
378
- id: ModelIdSchema,
379
- order: z.number().min(0)
380
- });
381
- var RecordColumnConfigSchema = z.object({
382
- key: ModelIdSchema,
383
- label: z.string().trim().min(1).max(120),
384
- path: z.string().trim().min(1).max(500),
385
- width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
386
- renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
387
- badgeColor: z.string().trim().min(1).max(40).optional()
388
- });
389
- var RecordColumnsConfigSchema = z.object({
390
- company: z.array(RecordColumnConfigSchema).optional(),
391
- contact: z.array(RecordColumnConfigSchema).optional()
392
- }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
393
- message: "recordColumns must include at least one entity column set"
394
- });
395
- var CredentialRequirementSchema = z.object({
396
- key: ModelIdSchema,
397
- provider: ModelIdSchema,
398
- credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
399
- label: z.string().trim().min(1).max(120),
400
- required: z.boolean(),
401
- selectionMode: z.enum(["single", "multiple"]).optional(),
402
- inputPath: z.string().trim().min(1).max(500),
403
- verifyOnRun: z.boolean().optional()
404
- });
405
- var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
406
- id: ModelIdSchema,
407
- primaryEntity: z.enum(["company", "contact"]),
408
- outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
409
- stageKey: ModelIdSchema,
410
- recordEntity: z.enum(["company", "contact"]).optional(),
411
- recordsStageKey: ModelIdSchema.optional(),
412
- recordSourceStageKey: ModelIdSchema.optional(),
413
- dependsOn: z.array(ModelIdSchema).optional(),
414
- dependencyMode: z.literal("per-record-eligibility"),
415
- capabilityKey: ModelIdSchema,
416
- defaultBatchSize: z.number().int().positive(),
417
- maxBatchSize: z.number().int().positive(),
418
- recordColumns: RecordColumnsConfigSchema.optional(),
419
- credentialRequirements: z.array(CredentialRequirementSchema).optional()
420
- }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
421
- message: "defaultBatchSize must be less than or equal to maxBatchSize",
422
- path: ["defaultBatchSize"]
423
- });
424
- var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
425
- id: ModelIdSchema,
426
- steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
427
- });
428
- var DTC_RECORD_COLUMNS = {
429
- populated: {
430
- company: [
431
- { key: "name", label: "Company", path: "company.name" },
432
- { key: "domain", label: "Domain", path: "company.domain" },
433
- { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
434
- { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
435
- { key: "location", label: "Location", path: "company.locationState" }
436
- ]
437
- },
438
- crawled: {
439
- company: [
440
- { key: "name", label: "Company", path: "company.name" },
441
- { key: "domain", label: "Domain", path: "company.domain" },
442
- { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
443
- { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
444
- ]
445
- },
446
- extracted: {
447
- company: [
448
- { key: "name", label: "Company", path: "company.name" },
449
- { key: "domain", label: "Domain", path: "company.domain" },
450
- { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
451
- { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
452
- { key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
453
- { key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
454
- ]
455
- },
456
- qualified: {
457
- company: [
458
- { key: "name", label: "Company", path: "company.name" },
459
- { key: "domain", label: "Domain", path: "company.domain" },
460
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
461
- { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
462
- { key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
463
- ]
464
- },
465
- decisionMakers: {
466
- contact: [
467
- { key: "name", label: "Name", path: "contact.name" },
468
- { key: "title", label: "Title", path: "contact.title" },
469
- { key: "email", label: "Email", path: "contact.email" },
470
- { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
471
- { key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
472
- ]
473
- },
474
- uploaded: {
475
- company: [
476
- { key: "name", label: "Company", path: "company.name" },
477
- { key: "domain", label: "Domain", path: "company.domain" },
478
- { key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
479
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
480
- { key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
481
- ]
482
- }
483
- };
484
- z.object({
485
- id: ModelIdSchema,
486
- label: z.string(),
487
- description: z.string(),
488
- resourceId: ModelIdSchema
489
- });
490
- var PROSPECTING_STEPS = {
491
- localServices: {
492
- sourceCompanies: {
493
- id: "source-companies",
494
- label: "Companies found",
495
- primaryEntity: "company",
496
- outputs: ["company"],
497
- stageKey: "populated",
498
- dependencyMode: "per-record-eligibility",
499
- capabilityKey: "lead-gen.company.source",
500
- defaultBatchSize: 100,
501
- maxBatchSize: 250
502
- },
503
- analyzeWebsites: {
504
- id: "analyze-websites",
505
- label: "Websites analyzed",
506
- primaryEntity: "company",
507
- outputs: ["company"],
508
- stageKey: "extracted",
509
- dependsOn: ["source-companies"],
510
- dependencyMode: "per-record-eligibility",
511
- capabilityKey: "lead-gen.company.website-extract",
512
- defaultBatchSize: 50,
513
- maxBatchSize: 100
514
- },
515
- qualifyCompanies: {
516
- id: "qualify-companies",
517
- label: "Companies qualified",
518
- primaryEntity: "company",
519
- outputs: ["company"],
520
- stageKey: "qualified",
521
- dependsOn: ["analyze-websites"],
522
- dependencyMode: "per-record-eligibility",
523
- capabilityKey: "lead-gen.company.qualify",
524
- defaultBatchSize: 100,
525
- maxBatchSize: 250
526
- },
527
- findContacts: {
528
- id: "find-contacts",
529
- label: "Decision-makers found",
530
- primaryEntity: "contact",
531
- outputs: ["contact"],
532
- stageKey: "discovered",
533
- dependsOn: ["qualify-companies"],
534
- dependencyMode: "per-record-eligibility",
535
- capabilityKey: "lead-gen.contact.discover",
536
- defaultBatchSize: 50,
537
- maxBatchSize: 100
538
- },
539
- verifyEmails: {
540
- id: "verify-emails",
541
- label: "Emails verified",
542
- primaryEntity: "contact",
543
- outputs: ["contact"],
544
- stageKey: "verified",
545
- dependsOn: ["find-contacts"],
546
- dependencyMode: "per-record-eligibility",
547
- capabilityKey: "lead-gen.contact.verify-email",
548
- defaultBatchSize: 100,
549
- maxBatchSize: 500
550
- },
551
- personalize: {
552
- id: "personalize",
553
- label: "Personalize",
554
- primaryEntity: "contact",
555
- outputs: ["contact"],
556
- stageKey: "personalized",
557
- dependsOn: ["verify-emails"],
558
- dependencyMode: "per-record-eligibility",
559
- capabilityKey: "lead-gen.contact.personalize",
560
- defaultBatchSize: 25,
561
- maxBatchSize: 100
562
- },
563
- review: {
564
- id: "review",
565
- label: "Reviewed and exported",
566
- primaryEntity: "contact",
567
- outputs: ["export"],
568
- stageKey: "uploaded",
569
- dependsOn: ["personalize"],
570
- dependencyMode: "per-record-eligibility",
571
- capabilityKey: "lead-gen.review.outreach-ready",
572
- defaultBatchSize: 25,
573
- maxBatchSize: 100
574
- }
575
- },
576
- dtcApolloClickup: {
577
- importApolloSearch: {
578
- id: "import-apollo-search",
579
- label: "Companies found",
580
- description: "Pull companies and seed contact data from a predefined Apollo search or list.",
581
- primaryEntity: "company",
582
- outputs: ["company", "contact"],
583
- stageKey: "populated",
584
- dependencyMode: "per-record-eligibility",
585
- capabilityKey: "lead-gen.company.apollo-import",
586
- defaultBatchSize: 250,
587
- maxBatchSize: 1e3,
588
- recordColumns: DTC_RECORD_COLUMNS.populated,
589
- credentialRequirements: [
590
- {
591
- key: "apollo",
592
- provider: "apollo",
593
- credentialType: "api-key-secret",
594
- label: "Apollo API key",
595
- required: true,
596
- selectionMode: "single",
597
- inputPath: "credential"
598
- }
599
- ]
600
- },
601
- apifyCrawl: {
602
- id: "apify-crawl",
603
- label: "Websites crawled",
604
- 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.",
605
- primaryEntity: "company",
606
- outputs: ["company"],
607
- stageKey: "crawled",
608
- dependsOn: ["import-apollo-search"],
609
- dependencyMode: "per-record-eligibility",
610
- capabilityKey: "lead-gen.company.apify-crawl",
611
- defaultBatchSize: 50,
612
- maxBatchSize: 100,
613
- recordColumns: DTC_RECORD_COLUMNS.crawled,
614
- credentialRequirements: [
615
- {
616
- key: "apify",
617
- provider: "apify",
618
- credentialType: "api-key-secret",
619
- label: "Apify API token",
620
- required: true,
621
- selectionMode: "single",
622
- inputPath: "credential",
623
- verifyOnRun: true
624
- }
625
- ]
626
- },
627
- analyzeWebsites: {
628
- id: "analyze-websites",
629
- label: "Websites analyzed",
630
- description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
631
- primaryEntity: "company",
632
- outputs: ["company"],
633
- stageKey: "extracted",
634
- dependsOn: ["apify-crawl"],
635
- dependencyMode: "per-record-eligibility",
636
- capabilityKey: "lead-gen.company.website-extract",
637
- defaultBatchSize: 50,
638
- maxBatchSize: 100,
639
- recordColumns: DTC_RECORD_COLUMNS.extracted
640
- },
641
- scoreDtcFit: {
642
- id: "score-dtc-fit",
643
- label: "Companies qualified",
644
- description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
645
- primaryEntity: "company",
646
- outputs: ["company"],
647
- stageKey: "qualified",
648
- dependsOn: ["analyze-websites"],
649
- dependencyMode: "per-record-eligibility",
650
- capabilityKey: "lead-gen.company.dtc-subscription-qualify",
651
- defaultBatchSize: 100,
652
- maxBatchSize: 250,
653
- recordColumns: DTC_RECORD_COLUMNS.qualified
654
- },
655
- enrichDecisionMakers: {
656
- id: "enrich-decision-makers",
657
- label: "Decision-makers found",
658
- description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
659
- primaryEntity: "company",
660
- outputs: ["contact"],
661
- stageKey: "decision-makers-enriched",
662
- recordEntity: "contact",
663
- dependsOn: ["score-dtc-fit"],
664
- dependencyMode: "per-record-eligibility",
665
- capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
666
- defaultBatchSize: 100,
667
- maxBatchSize: 250,
668
- recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
669
- credentialRequirements: [
670
- {
671
- key: "apollo",
672
- provider: "apollo",
673
- credentialType: "api-key-secret",
674
- label: "Apollo API key",
675
- required: true,
676
- selectionMode: "single",
677
- inputPath: "credential"
678
- }
679
- ]
680
- },
681
- reviewAndExport: {
682
- id: "review-and-export",
683
- label: "Reviewed and exported",
684
- description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
685
- primaryEntity: "company",
686
- outputs: ["export"],
687
- stageKey: "uploaded",
688
- recordsStageKey: "uploaded",
689
- recordSourceStageKey: "qualified",
690
- dependsOn: ["enrich-decision-makers"],
691
- dependencyMode: "per-record-eligibility",
692
- capabilityKey: "lead-gen.export.list",
693
- defaultBatchSize: 100,
694
- maxBatchSize: 250,
695
- recordColumns: DTC_RECORD_COLUMNS.uploaded,
696
- credentialRequirements: [
697
- {
698
- key: "clickup",
699
- provider: "clickup",
700
- credentialType: "api-key-secret",
701
- label: "ClickUp API token",
702
- required: true,
703
- selectionMode: "single",
704
- inputPath: "clickupCredential",
705
- verifyOnRun: true
706
- }
707
- ]
708
- }
709
- }
710
- };
711
- var OrganizationModelProspectingSchema = z.object({
712
- listEntityId: ModelIdSchema,
713
- companyEntityId: ModelIdSchema,
714
- contactEntityId: ModelIdSchema,
715
- description: DescriptionSchema.optional(),
716
- companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
717
- contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
718
- defaultBuildTemplateId: ModelIdSchema,
719
- buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
720
- });
721
- function toProspectingLifecycleStage(stage) {
722
- return {
723
- id: stage.key,
724
- label: stage.label,
725
- order: stage.order
726
- };
727
- }
728
- function leadGenStagesForEntity(entity) {
729
- 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);
730
- }
731
- var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
732
- listEntityId: "leadgen.list",
733
- companyEntityId: "leadgen.company",
734
- contactEntityId: "leadgen.contact",
735
- companyStages: leadGenStagesForEntity("company"),
736
- contactStages: leadGenStagesForEntity("contact"),
737
- defaultBuildTemplateId: "local-services",
738
- buildTemplates: [
739
- {
740
- id: "local-services",
741
- label: "Local Services Prospecting",
742
- description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
743
- steps: [
744
- PROSPECTING_STEPS.localServices.sourceCompanies,
745
- PROSPECTING_STEPS.localServices.analyzeWebsites,
746
- PROSPECTING_STEPS.localServices.qualifyCompanies,
747
- PROSPECTING_STEPS.localServices.findContacts,
748
- PROSPECTING_STEPS.localServices.verifyEmails,
749
- PROSPECTING_STEPS.localServices.personalize,
750
- PROSPECTING_STEPS.localServices.review
751
- ]
752
- },
753
- {
754
- id: "dtc-subscription-apollo-clickup",
755
- label: "DTC Subscription Apollo Export",
756
- 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.",
757
- steps: [
758
- PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
759
- PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
760
- PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
761
- PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
762
- PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
763
- PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
764
- ]
765
- }
766
- ]
767
- };
768
-
769
- // src/organization-model/contracts.ts
770
- var KNOWLEDGE_FEATURE_ID = "knowledge";
771
- var PROJECTS_FEATURE_ID = "projects";
772
- var PROJECTS_INDEX_SURFACE_ID = "projects.index";
773
- var PROJECTS_VIEW_CAPABILITY_ID = "delivery.projects.view";
774
- var SALES_FEATURE_ID = "crm";
775
- var PROSPECTING_FEATURE_ID = "lead-gen";
776
- var OPERATIONS_FEATURE_ID = "operations";
777
- var MONITORING_FEATURE_ID = "monitoring";
778
- var SETTINGS_FEATURE_ID = "settings";
779
- var SEO_FEATURE_ID = "seo";
780
- var SALES_PIPELINE_SURFACE_ID = "crm.pipeline";
781
- var PROSPECTING_LISTS_SURFACE_ID = "lead-gen.lists";
782
- var OPERATIONS_COMMAND_VIEW_SURFACE_ID = "knowledge.command-view";
783
- var SETTINGS_ROLES_SURFACE_ID = "settings.roles";
784
-
785
- // src/organization-model/domains/navigation.ts
786
- 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" });
787
325
  var SurfaceDefinitionSchema = z.object({
788
326
  id: ModelIdSchema,
789
327
  label: LabelSchema,
@@ -793,23 +331,67 @@ var SurfaceDefinitionSchema = z.object({
793
331
  enabled: z.boolean().default(true),
794
332
  devOnly: z.boolean().optional(),
795
333
  icon: IconNameSchema.optional(),
796
- featureId: ModelIdSchema.optional(),
797
- featureIds: ReferenceIdsSchema,
798
- entityIds: ReferenceIdsSchema,
799
- resourceIds: ReferenceIdsSchema,
800
- capabilityIds: ReferenceIdsSchema,
801
- 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()
802
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
+ }
803
390
  var NavigationGroupSchema = z.object({
804
391
  id: ModelIdSchema,
805
392
  label: LabelSchema,
806
393
  placement: z.string().trim().min(1).max(50),
807
- surfaceIds: z.array(ModelIdSchema).default([])
808
- });
809
- var OrganizationModelNavigationSchema = z.object({
810
- defaultSurfaceId: ModelIdSchema.optional(),
811
- surfaces: z.array(SurfaceDefinitionSchema).default([]),
812
- groups: z.array(NavigationGroupSchema).default([])
394
+ surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
813
395
  });
814
396
  var BusinessHoursDaySchema = z.object({
815
397
  open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
@@ -894,6 +476,8 @@ var FirmographicsSchema = z.object({
894
476
  var CustomerSegmentSchema = z.object({
895
477
  /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
896
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(),
897
481
  /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
898
482
  name: z.string().trim().max(200).default(""),
899
483
  /** One or two sentences describing who this segment is. */
@@ -921,16 +505,16 @@ var CustomerSegmentSchema = z.object({
921
505
  */
922
506
  valueProp: z.string().trim().max(2e3).default("")
923
507
  });
924
- var CustomersDomainSchema = z.object({
925
- segments: z.array(CustomerSegmentSchema).default([])
926
- });
927
- var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {
928
- segments: []
929
- };
930
- 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" });
931
513
  var ProductSchema = z.object({
932
514
  /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
933
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(),
934
518
  /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
935
519
  name: z.string().trim().max(200).default(""),
936
520
  /** One or two sentences describing what this product/service delivers. */
@@ -957,49 +541,562 @@ var ProductSchema = z.object({
957
541
  */
958
542
  targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
959
543
  /**
960
- * Optional: ID of the platform feature responsible for delivering this product.
961
- * When present, must reference a declared `features[].id`.
544
+ * Optional: ID of the platform system responsible for delivering this product.
545
+ * When present, must reference a declared `systems.systems[].id`.
962
546
  * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
963
547
  */
964
548
  deliveryFeatureId: z.string().trim().min(1).optional()
965
549
  });
966
- var OfferingsDomainSchema = z.object({
967
- products: z.array(ProductSchema).default([])
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()
968
561
  });
969
- var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {
970
- products: []
971
- };
972
- var RoleSchema = z.object({
973
- /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
974
- id: z.string().trim().min(1).max(100),
975
- /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
976
- title: z.string().trim().min(1).max(200),
977
- /**
978
- * List of responsibilities this role owns — plain-language descriptions of
979
- * what the person in this role is accountable for delivering.
980
- * Defaults to empty array so minimal role definitions stay concise.
981
- */
982
- responsibilities: z.array(z.string().trim().max(500)).default([]),
983
- /**
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" });
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
+ });
889
+ var SystemEntrySchema = z.object({
890
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
891
+ id: SystemIdSchema,
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(),
896
+ /** One-paragraph purpose statement for the bounded context. */
897
+ description: DescriptionSchema.optional(),
898
+ /** Closed system shape enum; catalog values remain tenant-defined. */
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(),
906
+ /** Optional role responsible for this system. */
907
+ responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
908
+ /** Optional knowledge nodes that govern this system. */
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(),
914
+ /** Optional goals this system contributes to. */
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;
956
+ });
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 = {};
961
+
962
+ // src/organization-model/domains/resources.ts
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" });
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
+ });
984
+ var ResourceEntryBaseSchema = z.object({
985
+ /** Canonical resource id; runtime resourceId derives from this value. */
986
+ id: ResourceIdSchema,
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" }),
991
+ /** Optional role responsible for maintaining this resource. */
992
+ ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
993
+ status: ResourceGovernanceStatusSchema
994
+ });
995
+ var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
996
+ kind: z.literal("workflow"),
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()
1000
+ });
1001
+ var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
1002
+ kind: z.literal("agent"),
1003
+ /** Mirrors code-side AgentConfig.kind. */
1004
+ agentKind: AgentKindSchema,
1005
+ /** Role this agent embodies, if any. */
1006
+ actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
1007
+ /** Mirrors AgentConfig.sessionCapable. */
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()
1012
+ });
1013
+ var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
1014
+ kind: z.literal("integration"),
1015
+ provider: z.string().trim().min(1).max(100)
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
+ });
1028
+ var ResourceEntrySchema = z.discriminatedUnion("kind", [
1029
+ WorkflowResourceEntrySchema,
1030
+ AgentResourceEntrySchema,
1031
+ IntegrationResourceEntrySchema,
1032
+ ScriptResourceEntrySchema
1033
+ ]);
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 = {};
1038
+ function defineResource(resource) {
1039
+ return ResourceEntrySchema.parse(resource);
1040
+ }
1041
+ function defineResources(resources) {
1042
+ return Object.fromEntries(
1043
+ Object.entries(resources).map(([key, resource]) => [key, ResourceEntrySchema.parse(resource)])
1044
+ );
1045
+ }
1046
+
1047
+ // src/organization-model/domains/roles.ts
1048
+ var RoleIdSchema = ModelIdSchema;
1049
+ var HumanRoleHolderSchema = z.object({
1050
+ kind: z.literal("human"),
1051
+ userId: z.string().trim().min(1).max(200)
1052
+ });
1053
+ var AgentRoleHolderSchema = z.object({
1054
+ kind: z.literal("agent"),
1055
+ agentId: ResourceIdSchema.meta({ ref: "resource" })
1056
+ });
1057
+ var TeamRoleHolderSchema = z.object({
1058
+ kind: z.literal("team"),
1059
+ memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
1060
+ });
1061
+ var RoleHolderSchema = z.discriminatedUnion("kind", [
1062
+ HumanRoleHolderSchema,
1063
+ AgentRoleHolderSchema,
1064
+ TeamRoleHolderSchema
1065
+ ]);
1066
+ var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
1067
+ var RoleSchema = z.object({
1068
+ /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
1069
+ id: RoleIdSchema,
1070
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1071
+ order: z.number(),
1072
+ /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
1073
+ title: z.string().trim().min(1).max(200),
1074
+ /**
1075
+ * List of responsibilities this role owns - plain-language descriptions of
1076
+ * what the person in this role is accountable for delivering.
1077
+ * Defaults to empty array so minimal role definitions stay concise.
1078
+ */
1079
+ responsibilities: z.array(z.string().trim().max(500)).default([]),
1080
+ /**
984
1081
  * Optional: ID of another role this role reports to.
985
1082
  * When present, must reference another `roles[].id` in the same organization.
986
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
987
- * Absence indicates a top-level role (no reporting line).
988
1083
  */
989
- reportsToId: z.string().trim().min(1).max(100).optional(),
1084
+ reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
990
1085
  /**
991
- * Optional: name or email of the person currently holding this role.
992
- * Free-form string supports "Alice Johnson", "alice@example.com", or
993
- * any human-readable identifier. Not validated against any user registry.
1086
+ * Optional: human, agent, or team holder currently filling this role.
1087
+ * Agent holders reference OM Resource IDs and are validated at the model level.
994
1088
  */
995
- heldBy: z.string().trim().max(200).optional()
996
- });
997
- var RolesDomainSchema = z.object({
998
- roles: z.array(RoleSchema).default([])
1089
+ heldBy: RoleHoldersSchema.optional(),
1090
+ /**
1091
+ * Optional Systems this role is accountable for.
1092
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
1093
+ */
1094
+ responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
999
1095
  });
1000
- var DEFAULT_ORGANIZATION_MODEL_ROLES = {
1001
- roles: []
1002
- };
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 = {};
1003
1100
  var KeyResultSchema = z.object({
1004
1101
  /** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
1005
1102
  id: z.string().trim().min(1).max(100),
@@ -1023,6 +1120,8 @@ var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
1023
1120
  var ObjectiveSchema = z.object({
1024
1121
  /** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
1025
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(),
1026
1125
  /** Plain-language description of what the organization wants to achieve. */
1027
1126
  description: z.string().trim().min(1).max(1e3),
1028
1127
  /**
@@ -1042,180 +1141,63 @@ var ObjectiveSchema = z.object({
1042
1141
  */
1043
1142
  keyResults: z.array(KeyResultSchema).default([])
1044
1143
  });
1045
- var GoalsDomainSchema = z.object({
1046
- objectives: z.array(ObjectiveSchema).default([])
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)
1047
1168
  });
1048
- var DEFAULT_ORGANIZATION_MODEL_GOALS = {
1049
- objectives: []
1050
- };
1051
- var OperationSemanticClassSchema = z.enum(["queue", "executions", "sessions", "notifications", "schedules"]);
1052
- var OperationEntrySchema = z.object({
1053
- id: z.string().trim().min(1).max(100),
1054
- label: z.string().trim().min(1).max(120),
1055
- semanticClass: OperationSemanticClassSchema,
1056
- /** Optional reference to the feature that owns this runtime entity. */
1057
- featureId: z.string().trim().min(1).max(100).optional(),
1058
- /**
1059
- * Optional pointer to the status semanticClass values that apply to this
1060
- * entity — ties operations back to the statuses domain for vibe rendering.
1061
- */
1062
- supportedStatusSemanticClass: z.array(z.string().trim().min(1).max(80)).optional()
1063
- });
1064
- var OperationsDomainSchema = z.object({
1065
- entries: z.array(OperationEntrySchema).default([])
1066
- });
1067
- var DEFAULT_ORGANIZATION_MODEL_OPERATIONS = {
1068
- entries: [
1069
- // --- queue (HITL command queue) ---
1070
- {
1071
- id: "operations.queue",
1072
- label: "HITL Queue",
1073
- semanticClass: "queue",
1074
- featureId: "operations",
1075
- supportedStatusSemanticClass: ["queue"]
1076
- },
1077
- // --- executions (workflow / agent executions) ---
1078
- {
1079
- id: "operations.executions",
1080
- label: "Executions",
1081
- semanticClass: "executions",
1082
- featureId: "operations",
1083
- supportedStatusSemanticClass: ["execution"]
1084
- },
1085
- // --- sessions (agent conversation sessions) ---
1086
- {
1087
- id: "operations.sessions",
1088
- label: "Sessions",
1089
- semanticClass: "sessions",
1090
- featureId: "operations"
1091
- },
1092
- // --- notifications (platform in-app notifications) ---
1093
- {
1094
- id: "operations.notifications",
1095
- label: "Notifications",
1096
- semanticClass: "notifications",
1097
- featureId: "monitoring"
1098
- },
1099
- // --- schedules (task scheduler) ---
1100
- {
1101
- id: "operations.schedules",
1102
- label: "Schedules",
1103
- semanticClass: "schedules",
1104
- featureId: "operations",
1105
- supportedStatusSemanticClass: ["schedule", "schedule.run"]
1106
- }
1107
- ]
1108
- };
1109
- var StatusSemanticClassSchema = z.enum([
1110
- "delivery.task",
1111
- "delivery.project",
1112
- "delivery.milestone",
1113
- "queue",
1114
- "execution",
1115
- "schedule",
1116
- "schedule.run",
1117
- "request"
1118
- ]);
1119
- var StatusEntrySchema = z.object({
1120
- id: z.string().trim().min(1).max(100),
1121
- label: z.string().trim().min(1).max(120),
1122
- semanticClass: StatusSemanticClassSchema,
1123
- category: z.string().trim().min(1).max(80).optional()
1169
+ var LegacyKnowledgeLinkSchema = z.object({
1170
+ nodeId: NodeIdStringSchema
1124
1171
  });
1125
- var StatusesDomainSchema = z.object({
1126
- entries: z.array(StatusEntrySchema).default([])
1172
+ var CanonicalKnowledgeLinkSchema = z.object({
1173
+ target: KnowledgeTargetRefSchema
1127
1174
  });
1128
- var DEFAULT_ORGANIZATION_MODEL_STATUSES = {
1129
- entries: [
1130
- // --- delivery.task (TaskStatus — 9 values) ---
1131
- { id: "delivery.task.planned", label: "Planned", semanticClass: "delivery.task", category: "delivery" },
1132
- { id: "delivery.task.in_progress", label: "In Progress", semanticClass: "delivery.task", category: "delivery" },
1133
- { id: "delivery.task.blocked", label: "Blocked", semanticClass: "delivery.task", category: "delivery" },
1134
- { id: "delivery.task.submitted", label: "Submitted", semanticClass: "delivery.task", category: "delivery" },
1135
- { id: "delivery.task.approved", label: "Approved", semanticClass: "delivery.task", category: "delivery" },
1136
- {
1137
- id: "delivery.task.revision_requested",
1138
- label: "Revision Requested",
1139
- semanticClass: "delivery.task",
1140
- category: "delivery"
1141
- },
1142
- { id: "delivery.task.rejected", label: "Rejected", semanticClass: "delivery.task", category: "delivery" },
1143
- { id: "delivery.task.cancelled", label: "Cancelled", semanticClass: "delivery.task", category: "delivery" },
1144
- { id: "delivery.task.completed", label: "Completed", semanticClass: "delivery.task", category: "delivery" },
1145
- // --- delivery.project (ProjectStatus — 6 values) ---
1146
- { id: "delivery.project.active", label: "Active", semanticClass: "delivery.project", category: "delivery" },
1147
- { id: "delivery.project.on_track", label: "On Track", semanticClass: "delivery.project", category: "delivery" },
1148
- { id: "delivery.project.at_risk", label: "At Risk", semanticClass: "delivery.project", category: "delivery" },
1149
- { id: "delivery.project.blocked", label: "Blocked", semanticClass: "delivery.project", category: "delivery" },
1150
- { id: "delivery.project.paused", label: "Paused", semanticClass: "delivery.project", category: "delivery" },
1151
- { id: "delivery.project.completed", label: "Completed", semanticClass: "delivery.project", category: "delivery" },
1152
- // --- delivery.milestone (MilestoneStatus — 5 values) ---
1153
- {
1154
- id: "delivery.milestone.upcoming",
1155
- label: "Upcoming",
1156
- semanticClass: "delivery.milestone",
1157
- category: "delivery"
1158
- },
1159
- {
1160
- id: "delivery.milestone.in_progress",
1161
- label: "In Progress",
1162
- semanticClass: "delivery.milestone",
1163
- category: "delivery"
1164
- },
1165
- {
1166
- id: "delivery.milestone.blocked",
1167
- label: "Blocked",
1168
- semanticClass: "delivery.milestone",
1169
- category: "delivery"
1170
- },
1171
- { id: "delivery.milestone.overdue", label: "Overdue", semanticClass: "delivery.milestone", category: "delivery" },
1172
- {
1173
- id: "delivery.milestone.completed",
1174
- label: "Completed",
1175
- semanticClass: "delivery.milestone",
1176
- category: "delivery"
1177
- },
1178
- // --- queue (QueueTaskStatus — 5 values, maps hitl/command-queue tasks) ---
1179
- { id: "queue.pending", label: "Pending", semanticClass: "queue", category: "queue" },
1180
- { id: "queue.processing", label: "Processing", semanticClass: "queue", category: "queue" },
1181
- { id: "queue.completed", label: "Completed", semanticClass: "queue", category: "queue" },
1182
- { id: "queue.failed", label: "Failed", semanticClass: "queue", category: "queue" },
1183
- { id: "queue.expired", label: "Expired", semanticClass: "queue", category: "queue" },
1184
- // --- execution (ExecutionStatus — 5 values) ---
1185
- { id: "execution.pending", label: "Pending", semanticClass: "execution", category: "execution" },
1186
- { id: "execution.running", label: "Running", semanticClass: "execution", category: "execution" },
1187
- { id: "execution.completed", label: "Completed", semanticClass: "execution", category: "execution" },
1188
- { id: "execution.failed", label: "Failed", semanticClass: "execution", category: "execution" },
1189
- { id: "execution.warning", label: "Warning", semanticClass: "execution", category: "execution" },
1190
- // --- schedule (schedule status — 4 values) ---
1191
- { id: "schedule.active", label: "Active", semanticClass: "schedule", category: "schedule" },
1192
- { id: "schedule.paused", label: "Paused", semanticClass: "schedule", category: "schedule" },
1193
- { id: "schedule.completed", label: "Completed", semanticClass: "schedule", category: "schedule" },
1194
- { id: "schedule.cancelled", label: "Cancelled", semanticClass: "schedule", category: "schedule" },
1195
- // --- schedule.run (schedule run status — 4 values) ---
1196
- { id: "schedule.run.running", label: "Running", semanticClass: "schedule.run", category: "schedule" },
1197
- { id: "schedule.run.completed", label: "Completed", semanticClass: "schedule.run", category: "schedule" },
1198
- { id: "schedule.run.failed", label: "Failed", semanticClass: "schedule.run", category: "schedule" },
1199
- { id: "schedule.run.cancelled", label: "Cancelled", semanticClass: "schedule.run", category: "schedule" },
1200
- // --- request (RequestStatus — 4 values, maps reported_requests) ---
1201
- { id: "request.open", label: "Open", semanticClass: "request", category: "request" },
1202
- { id: "request.investigating", label: "Investigating", semanticClass: "request", category: "request" },
1203
- { id: "request.resolved", label: "Resolved", semanticClass: "request", category: "request" },
1204
- { id: "request.wont_fix", label: "Won't Fix", semanticClass: "request", category: "request" }
1205
- ]
1206
- };
1207
- var KnowledgeLinkSchema = z.object({
1208
- 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
+ };
1209
1191
  });
1210
- var KnowledgeSkillBindingSchema = z.string().trim().min(1).max(120);
1211
- var KnowledgeDomainBindingSchema = z.string().trim().min(1).max(80);
1212
- var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]);
1192
+ var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
1213
1193
  var OrgKnowledgeNodeSchema = z.object({
1214
1194
  id: ModelIdSchema,
1215
1195
  kind: OrgKnowledgeKindSchema,
1216
1196
  title: z.string().trim().min(1).max(200),
1217
1197
  summary: z.string().trim().min(1).max(1e3),
1218
1198
  icon: IconNameSchema.optional(),
1199
+ /** Canonical documentation URL when body content is a local summary. */
1200
+ externalUrl: z.string().trim().url().max(500).optional(),
1219
1201
  /** Raw MDX string. Phase 2 will introduce a structured block format. */
1220
1202
  body: z.string().trim().min(1),
1221
1203
  /**
@@ -1223,36 +1205,154 @@ var OrgKnowledgeNodeSchema = z.object({
1223
1205
  * Each link emits a `governs` edge: knowledge-node -> target node.
1224
1206
  */
1225
1207
  links: z.array(KnowledgeLinkSchema).default([]),
1226
- /** Operator skill or command bindings relevant to this node. */
1227
- skills: z.array(KnowledgeSkillBindingSchema).optional(),
1228
- /** Domain key used to derive fast graph->skill registries. */
1229
- domain: KnowledgeDomainBindingSchema.optional(),
1230
- /** Identifiers of the roles or members who own this knowledge node. */
1231
- ownerIds: z.array(ModelIdSchema).default([]),
1208
+ /** Role identifiers that own this knowledge node. */
1209
+ ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
1232
1210
  /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
1233
1211
  updatedAt: z.string().trim().min(1).max(50)
1234
1212
  });
1235
- var KnowledgeDomainSchema = z.object({
1236
- nodes: z.array(OrgKnowledgeNodeSchema).default([])
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([])
1237
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 = {};
1238
1291
 
1239
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 }));
1240
1339
  var OrganizationModelSchemaBase = z.object({
1241
1340
  version: z.literal(1).default(1),
1242
- features: z.array(FeatureSchema).default([]),
1341
+ domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
1243
1342
  branding: OrganizationModelBrandingSchema,
1244
- navigation: OrganizationModelNavigationSchema.default({ surfaces: [], groups: [] }),
1245
- sales: OrganizationModelSalesSchema,
1246
- prospecting: OrganizationModelProspectingSchema,
1247
- projects: OrganizationModelProjectsSchema,
1343
+ navigation: OrganizationModelNavigationSchema,
1248
1344
  identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
1249
1345
  customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
1250
1346
  offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
1251
1347
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
1252
1348
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
1253
- statuses: StatusesDomainSchema.default({ entries: [] }),
1254
- operations: OperationsDomainSchema.default({ entries: [] }),
1255
- knowledge: KnowledgeDomainSchema.default({ nodes: [] })
1349
+ systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
1350
+ resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
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({})
1256
1356
  });
1257
1357
  function addIssue(ctx, path, message) {
1258
1358
  ctx.addIssue({
@@ -1261,167 +1361,547 @@ function addIssue(ctx, path, message) {
1261
1361
  message
1262
1362
  });
1263
1363
  }
1264
- function collectIds(items, ctx, collectionPath, label) {
1265
- const itemsById = /* @__PURE__ */ new Map();
1266
- items.forEach((item, index) => {
1267
- if (itemsById.has(item.id)) {
1268
- addIssue(ctx, [...collectionPath, index, "id"], `${label} id "${item.id}" must be unique`);
1269
- return;
1270
- }
1271
- itemsById.set(item.id, item);
1272
- });
1273
- return itemsById;
1274
- }
1275
- var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
1276
- ["crm", "sales.crm"],
1277
- ["lead-gen", "sales.lead-gen"],
1278
- ["submitted-requests", "monitoring.submitted-requests"]
1279
- ]);
1280
- function hasFeature(featuresById, featureId) {
1281
- 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";
1282
1367
  }
1283
- function defaultFeaturePathFor(id) {
1368
+ function defaultSystemPathFor(id) {
1284
1369
  return `/${id.replaceAll(".", "/")}`;
1285
1370
  }
1371
+ function asRoleHolderArray(heldBy) {
1372
+ return Array.isArray(heldBy) ? heldBy : [heldBy];
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
+ }
1286
1384
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
1287
- const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
1288
- const featureIdsByEffectivePath = /* @__PURE__ */ new Map();
1289
- model.features.forEach((feature, featureIndex) => {
1290
- const segments = feature.id.split(".");
1291
- if (segments.length > 1) {
1292
- const parentId = segments.slice(0, -1).join(".");
1293
- if (!featuresById.has(parentId)) {
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"]));
1393
+ }
1394
+ }
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;
1414
+ if (contributesRoutePath) {
1415
+ const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
1416
+ const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
1417
+ if (existingSystemId !== void 0) {
1294
1418
  addIssue(
1295
1419
  ctx,
1296
- ["features", featureIndex, "id"],
1297
- `Feature "${feature.id}" references unknown parent "${parentId}"`
1420
+ [...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
1421
+ `System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
1298
1422
  );
1423
+ } else {
1424
+ systemIdsByEffectivePath.set(effectivePath, path);
1299
1425
  }
1300
1426
  }
1301
- const hasChildren = model.features.some(
1302
- (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.id !== feature.id
1303
- );
1304
- const contributesRoutePath = feature.path !== void 0 || !hasChildren;
1305
- if (contributesRoutePath) {
1306
- const effectivePath = feature.path ?? defaultFeaturePathFor(feature.id);
1307
- const existingFeatureId = featureIdsByEffectivePath.get(effectivePath);
1308
- if (existingFeatureId !== void 0) {
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)
1432
+ );
1433
+ if (!hasEnabledDescendant) {
1434
+ addIssue(
1435
+ ctx,
1436
+ [...schemaPath, "lifecycle"],
1437
+ `System "${path}" is active but has no active descendants`
1438
+ );
1439
+ }
1440
+ }
1441
+ });
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) {
1309
1477
  addIssue(
1310
1478
  ctx,
1311
- ["features", featureIndex, feature.path === void 0 ? "id" : "path"],
1312
- `Feature "${feature.id}" effective path "${effectivePath}" duplicates feature "${existingFeatureId}"`
1479
+ [...nodePath, "path"],
1480
+ `Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
1313
1481
  );
1314
1482
  } else {
1315
- featureIdsByEffectivePath.set(effectivePath, feature.id);
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
+ });
1495
+ }
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)) {
1502
+ addIssue(
1503
+ ctx,
1504
+ ["offerings", product.id, "targetSegmentIds", segmentIndex],
1505
+ `Product "${product.id}" references unknown customer segment "${segmentId}"`
1506
+ );
1507
+ }
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
+ }
1516
+ });
1517
+ Object.values(model.goals).forEach((objective) => {
1518
+ if (objective.periodEnd <= objective.periodStart) {
1519
+ addIssue(
1520
+ ctx,
1521
+ ["goals", objective.id, "periodEnd"],
1522
+ `Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
1523
+ );
1524
+ }
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)) {
1534
+ addIssue(
1535
+ ctx,
1536
+ [...path, "targets", "entities", entityIndex],
1537
+ `Sidebar surface "${id}" references unknown entity "${entityId}"`
1538
+ );
1539
+ }
1540
+ });
1541
+ node.targets?.actions?.forEach((actionId, actionIndex) => {
1542
+ if (!actionsById.has(actionId)) {
1543
+ addIssue(
1544
+ ctx,
1545
+ [...path, "targets", "actions", actionIndex],
1546
+ `Sidebar surface "${id}" references unknown action "${actionId}"`
1547
+ );
1316
1548
  }
1549
+ });
1550
+ });
1551
+ Object.values(model.entities).forEach((entity) => {
1552
+ if (!systemsById.has(entity.ownedBySystemId)) {
1553
+ addIssue(
1554
+ ctx,
1555
+ ["entities", entity.id, "ownedBySystemId"],
1556
+ `Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
1557
+ );
1317
1558
  }
1318
- if (hasChildren && feature.enabled) {
1319
- const hasEnabledDescendant = model.features.some(
1320
- (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.enabled
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
+ });
1568
+ });
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)) {
1572
+ addIssue(
1573
+ ctx,
1574
+ ["roles", role.id, "reportsToId"],
1575
+ `Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
1321
1576
  );
1322
- if (!hasEnabledDescendant) {
1577
+ }
1578
+ });
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)) {
1604
+ addIssue(
1605
+ ctx,
1606
+ [...schemaPath, "responsibleRoleId"],
1607
+ `System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
1608
+ );
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
+ });
1646
+ });
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) => {
1675
+ if (!systemsById.has(systemId)) {
1676
+ addIssue(
1677
+ ctx,
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)) {
1323
1685
  addIssue(
1324
1686
  ctx,
1325
- ["features", featureIndex, "enabled"],
1326
- `Feature "${feature.id}" is enabled but has no enabled descendants`
1687
+ ["policies", policy.id, "appliesTo", "actionIds", actionIndex],
1688
+ `Policy "${policy.id}" applies to unknown action "${actionId}"`
1327
1689
  );
1328
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}"`
1705
+ );
1706
+ }
1707
+ });
1708
+ if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
1709
+ addIssue(
1710
+ ctx,
1711
+ ["policies", policy.id, "trigger", "actionId"],
1712
+ `Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
1713
+ );
1329
1714
  }
1330
1715
  });
1331
- const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Navigation surface");
1332
- if (model.navigation.defaultSurfaceId !== void 0 && !surfacesById.has(model.navigation.defaultSurfaceId)) {
1333
- addIssue(
1334
- ctx,
1335
- ["navigation", "defaultSurfaceId"],
1336
- `Navigation defaultSurfaceId references unknown surface "${model.navigation.defaultSurfaceId}"`
1337
- );
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;
1338
1727
  }
1339
- model.navigation.groups.forEach((group, groupIndex) => {
1340
- group.surfaceIds.forEach((surfaceId, surfaceIndex) => {
1341
- if (!surfacesById.has(surfaceId)) {
1728
+ Object.entries(model.knowledge).forEach(([nodeId, node]) => {
1729
+ node.links.forEach((link, linkIndex) => {
1730
+ if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
1731
+ addIssue(
1732
+ ctx,
1733
+ ["knowledge", nodeId, "links", linkIndex, "target"],
1734
+ `Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
1735
+ );
1736
+ }
1737
+ if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
1342
1738
  addIssue(
1343
1739
  ctx,
1344
- ["navigation", "groups", groupIndex, "surfaceIds", surfaceIndex],
1345
- `Navigation group "${group.id}" references unknown surface "${surfaceId}"`
1740
+ ["knowledge", nodeId, "links", linkIndex, "target", "kind"],
1741
+ `Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
1346
1742
  );
1347
1743
  }
1348
1744
  });
1349
1745
  });
1350
- model.navigation.surfaces.forEach((surface, surfaceIndex) => {
1351
- if (surface.featureId !== void 0 && !hasFeature(featuresById, surface.featureId)) {
1746
+ Object.values(model.resources).forEach((resource) => {
1747
+ if (!systemsById.has(resource.systemPath)) {
1352
1748
  addIssue(
1353
1749
  ctx,
1354
- ["navigation", "surfaces", surfaceIndex, "featureId"],
1355
- `Navigation surface "${surface.id}" references unknown feature "${surface.featureId}"`
1750
+ ["resources", resource.id, "systemPath"],
1751
+ `Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
1356
1752
  );
1357
1753
  }
1358
- surface.featureIds.forEach((featureId, featureIndex) => {
1359
- if (!hasFeature(featuresById, featureId)) {
1754
+ if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
1755
+ addIssue(
1756
+ ctx,
1757
+ ["resources", resource.id, "ownerRoleId"],
1758
+ `Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
1759
+ );
1760
+ }
1761
+ if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
1762
+ addIssue(
1763
+ ctx,
1764
+ ["resources", resource.id, "actsAsRoleId"],
1765
+ `Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
1766
+ );
1767
+ }
1768
+ });
1769
+ Object.values(model.roles).forEach((role) => {
1770
+ if (role.heldBy === void 0) return;
1771
+ asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
1772
+ if (holder.kind !== "agent") return;
1773
+ const resource = resourcesById.get(holder.agentId);
1774
+ if (resource === void 0) {
1360
1775
  addIssue(
1361
1776
  ctx,
1362
- ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
1363
- `Navigation surface "${surface.id}" references unknown feature "${featureId}"`
1777
+ ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
1778
+ `Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
1779
+ );
1780
+ return;
1781
+ }
1782
+ if (resource.kind !== "agent") {
1783
+ addIssue(
1784
+ ctx,
1785
+ ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
1786
+ `Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
1364
1787
  );
1365
1788
  }
1366
1789
  });
1367
1790
  });
1368
- const segmentsById = new Map(model.customers.segments.map((seg) => [seg.id, seg]));
1369
- model.offerings.products.forEach((product, productIndex) => {
1370
- product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
1371
- if (!segmentsById.has(segmentId)) {
1791
+ Object.entries(model.knowledge).forEach(([nodeId, node]) => {
1792
+ node.ownerIds.forEach((roleId, ownerIndex) => {
1793
+ if (!rolesById.has(roleId)) {
1794
+ addIssue(
1795
+ ctx,
1796
+ ["knowledge", nodeId, "ownerIds", ownerIndex],
1797
+ `Knowledge node "${node.id}" references unknown owner role "${roleId}"`
1798
+ );
1799
+ }
1800
+ });
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)) {
1372
1814
  addIssue(
1373
1815
  ctx,
1374
- ["offerings", "products", productIndex, "targetSegmentIds", segmentIndex],
1375
- `Product "${product.id}" references unknown customer segment "${segmentId}"`
1816
+ [...systemPath, "content", localId, "parentContentId"],
1817
+ `Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
1376
1818
  );
1377
1819
  }
1378
1820
  });
1379
- if (product.deliveryFeatureId !== void 0 && !hasFeature(featuresById, product.deliveryFeatureId)) {
1380
- addIssue(
1381
- ctx,
1382
- ["offerings", "products", productIndex, "deliveryFeatureId"],
1383
- `Product "${product.id}" references unknown delivery feature "${product.deliveryFeatureId}"`
1384
- );
1385
- }
1386
- });
1387
- model.goals.objectives.forEach((objective, index) => {
1388
- if (objective.periodEnd <= objective.periodStart) {
1389
- addIssue(
1390
- ctx,
1391
- ["goals", "objectives", index, "periodEnd"],
1392
- `Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
1393
- );
1394
- }
1395
- });
1396
- const rolesById = new Map(model.roles.roles.map((role) => [role.id, role]));
1397
- model.roles.roles.forEach((role, roleIndex) => {
1398
- if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
1399
- addIssue(
1400
- ctx,
1401
- ["roles", "roles", roleIndex, "reportsToId"],
1402
- `Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
1403
- );
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
+ });
1404
1867
  }
1868
+ }
1869
+ Object.entries(model.systems).forEach(([systemKey, system]) => {
1870
+ validateSystemContent(system, ["systems", systemKey]);
1405
1871
  });
1406
1872
  });
1407
1873
  var OrganizationGraphNodeKindSchema = z.enum([
1408
1874
  "organization",
1409
- "feature",
1410
- "surface",
1875
+ "system",
1876
+ "role",
1877
+ "action",
1411
1878
  "entity",
1412
- "capability",
1879
+ "event",
1880
+ "policy",
1413
1881
  "stage",
1414
1882
  "resource",
1415
- "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"
1416
1891
  ]);
1417
1892
  var OrganizationGraphEdgeKindSchema = z.enum([
1418
1893
  "contains",
1419
1894
  "references",
1420
- "exposes",
1421
1895
  "maps_to",
1422
- "operates-on",
1423
1896
  "uses",
1424
- "governs"
1897
+ "governs",
1898
+ "links",
1899
+ "affects",
1900
+ "emits",
1901
+ "originates_from",
1902
+ "triggers",
1903
+ "applies_to",
1904
+ "effects"
1425
1905
  ]);
1426
1906
  var OrganizationGraphNodeSchema = z.object({
1427
1907
  id: z.string().trim().min(1).max(200),
@@ -1431,8 +1911,7 @@ var OrganizationGraphNodeSchema = z.object({
1431
1911
  description: DescriptionSchema.optional(),
1432
1912
  icon: IconNameSchema.optional(),
1433
1913
  enabled: z.boolean().optional(),
1434
- featureId: z.string().trim().min(1).max(100).optional(),
1435
- resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]).optional()
1914
+ resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint", "script"]).optional()
1436
1915
  });
1437
1916
  var OrganizationGraphEdgeSchema = z.object({
1438
1917
  id: z.string().trim().min(1).max(250),
@@ -1459,328 +1938,1173 @@ var LinkSchema = z.object({
1459
1938
  kind: OrganizationGraphEdgeKindSchema
1460
1939
  });
1461
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
+
1462
1965
  // src/organization-model/defaults.ts
1463
- var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {
1464
- nodes: []
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
+ }
1465
2290
  };
1466
2291
  var DEFAULT_ORGANIZATION_MODEL = {
1467
2292
  version: 1,
1468
- features: [
1469
- {
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: {
1470
2303
  id: "dashboard",
2304
+ order: 10,
1471
2305
  label: "Dashboard",
1472
2306
  enabled: true,
2307
+ lifecycle: "active",
1473
2308
  path: "/",
1474
- icon: "feature.dashboard",
1475
- uiPosition: "sidebar-primary"
1476
- },
1477
- {
1478
- id: "identity",
1479
- label: "Identity",
1480
- description: "Company identity, positioning, and market context",
1481
- enabled: true,
1482
- color: "indigo"
2309
+ icon: "feature.dashboard"
1483
2310
  },
1484
- {
2311
+ platform: {
1485
2312
  id: "platform",
2313
+ order: 30,
1486
2314
  label: "Platform",
1487
2315
  description: "Elevasis platform architecture, capabilities, and implementation patterns",
1488
2316
  enabled: true,
2317
+ lifecycle: "active",
1489
2318
  color: "cyan",
1490
2319
  icon: "feature.platform"
1491
2320
  },
1492
- {
2321
+ finance: {
1493
2322
  id: "finance",
2323
+ order: 40,
1494
2324
  label: "Finance",
1495
2325
  description: "Finance operations, accounting, billing, reconciliation, and tax prep",
1496
2326
  enabled: true,
2327
+ lifecycle: "active",
1497
2328
  color: "green",
1498
2329
  icon: "feature.finance"
1499
2330
  },
1500
- {
2331
+ sales: {
1501
2332
  id: "sales",
2333
+ order: 60,
1502
2334
  label: "Sales",
1503
2335
  description: "Revenue workflows and customer acquisition",
1504
2336
  enabled: true,
2337
+ lifecycle: "active",
1505
2338
  color: "blue",
1506
2339
  icon: "feature.sales",
1507
- uiPosition: "sidebar-primary"
2340
+ path: "/sales"
1508
2341
  },
1509
- {
2342
+ "sales.crm": {
1510
2343
  id: "sales.crm",
2344
+ order: 70,
1511
2345
  label: "CRM",
1512
2346
  description: "Relationship pipeline and deal management",
1513
2347
  enabled: true,
2348
+ lifecycle: "active",
1514
2349
  color: "blue",
1515
2350
  icon: "feature.crm",
1516
2351
  path: "/crm"
1517
2352
  },
1518
- {
2353
+ "sales.lead-gen": {
1519
2354
  id: "sales.lead-gen",
2355
+ order: 80,
1520
2356
  label: "Lead Gen",
1521
2357
  description: "Prospecting, qualification, and outreach preparation",
1522
2358
  enabled: true,
2359
+ lifecycle: "active",
2360
+ actions: Object.values(DEFAULT_ORGANIZATION_MODEL_ACTIONS).map((action) => ({
2361
+ actionId: action.id,
2362
+ intent: "exposes"
2363
+ })),
1523
2364
  color: "cyan",
1524
2365
  icon: "feature.lead-gen",
1525
2366
  path: "/lead-gen"
1526
2367
  },
1527
- {
2368
+ projects: {
1528
2369
  id: "projects",
2370
+ order: 90,
1529
2371
  label: "Projects",
1530
2372
  description: "Projects, milestones, and client work execution",
1531
2373
  enabled: true,
2374
+ lifecycle: "active",
2375
+ color: "orange",
2376
+ icon: "feature.projects",
2377
+ path: "/projects"
2378
+ },
2379
+ clients: {
2380
+ id: "clients",
2381
+ order: 100,
2382
+ label: "Clients",
2383
+ description: "Client relationships, accounts, and business context",
2384
+ enabled: true,
2385
+ lifecycle: "active",
1532
2386
  color: "orange",
1533
2387
  icon: "feature.projects",
1534
- path: "/projects",
1535
- uiPosition: "sidebar-primary"
2388
+ path: "/clients"
1536
2389
  },
1537
- {
2390
+ operations: {
1538
2391
  id: "operations",
2392
+ order: 110,
1539
2393
  label: "Operations",
1540
2394
  description: "Operational resources, topology, and orchestration visibility",
1541
2395
  enabled: true,
2396
+ lifecycle: "active",
1542
2397
  color: "violet",
1543
- icon: "feature.operations",
1544
- uiPosition: "sidebar-primary"
2398
+ icon: "feature.operations"
1545
2399
  },
1546
- {
2400
+ "knowledge.command-view": {
1547
2401
  id: "knowledge.command-view",
2402
+ order: 120,
1548
2403
  label: "Command View",
1549
2404
  enabled: true,
2405
+ lifecycle: "active",
1550
2406
  path: "/knowledge/command-view",
1551
2407
  devOnly: true
1552
2408
  },
1553
- {
2409
+ "operations.overview": {
1554
2410
  id: "operations.overview",
2411
+ order: 130,
1555
2412
  label: "Overview",
1556
2413
  enabled: true,
2414
+ lifecycle: "active",
1557
2415
  path: "/operations"
1558
2416
  },
1559
- {
2417
+ "operations.resources": {
1560
2418
  id: "operations.resources",
2419
+ order: 140,
1561
2420
  label: "Resources",
1562
2421
  enabled: true,
2422
+ lifecycle: "active",
1563
2423
  path: "/operations/resources"
1564
2424
  },
1565
- {
2425
+ "operations.command-queue": {
1566
2426
  id: "operations.command-queue",
2427
+ order: 150,
1567
2428
  label: "Command Queue",
1568
2429
  enabled: true,
2430
+ lifecycle: "active",
1569
2431
  path: "/operations/command-queue"
1570
2432
  },
1571
- {
2433
+ "operations.sessions": {
1572
2434
  id: "operations.sessions",
2435
+ order: 160,
1573
2436
  label: "Sessions",
1574
2437
  enabled: false,
2438
+ lifecycle: "deprecated",
1575
2439
  path: "/operations/sessions"
1576
2440
  },
1577
- {
2441
+ "operations.task-scheduler": {
1578
2442
  id: "operations.task-scheduler",
2443
+ order: 170,
1579
2444
  label: "Task Scheduler",
1580
2445
  enabled: true,
2446
+ lifecycle: "active",
1581
2447
  path: "/operations/task-scheduler"
1582
2448
  },
1583
- {
2449
+ monitoring: {
1584
2450
  id: "monitoring",
2451
+ order: 180,
1585
2452
  label: "Monitoring",
1586
2453
  enabled: true,
1587
- uiPosition: "sidebar-primary"
2454
+ lifecycle: "active"
1588
2455
  },
1589
- {
2456
+ "monitoring.calendar": {
1590
2457
  id: "monitoring.calendar",
2458
+ order: 190,
1591
2459
  label: "Calendar",
1592
2460
  description: "Google Calendar events and agenda views",
1593
2461
  enabled: true,
2462
+ lifecycle: "active",
1594
2463
  path: "/monitoring/calendar",
1595
2464
  icon: "feature.calendar"
1596
2465
  },
1597
- {
2466
+ "monitoring.activity-log": {
1598
2467
  id: "monitoring.activity-log",
2468
+ order: 200,
1599
2469
  label: "Activity Log",
1600
2470
  enabled: true,
2471
+ lifecycle: "active",
1601
2472
  path: "/monitoring/activity-log"
1602
2473
  },
1603
- {
2474
+ "monitoring.execution-logs": {
1604
2475
  id: "monitoring.execution-logs",
2476
+ order: 210,
1605
2477
  label: "Execution Logs",
1606
2478
  enabled: true,
2479
+ lifecycle: "active",
1607
2480
  path: "/monitoring/execution-logs"
1608
2481
  },
1609
- {
2482
+ "monitoring.execution-health": {
1610
2483
  id: "monitoring.execution-health",
2484
+ order: 220,
1611
2485
  label: "Execution Health",
1612
2486
  enabled: true,
2487
+ lifecycle: "active",
1613
2488
  path: "/monitoring/execution-health"
1614
2489
  },
1615
- {
2490
+ "monitoring.cost-analytics": {
1616
2491
  id: "monitoring.cost-analytics",
2492
+ order: 230,
1617
2493
  label: "Cost Analytics",
1618
2494
  enabled: false,
2495
+ lifecycle: "deprecated",
1619
2496
  path: "/monitoring/cost-analytics"
1620
2497
  },
1621
- {
2498
+ "monitoring.notifications": {
1622
2499
  id: "monitoring.notifications",
2500
+ order: 240,
1623
2501
  label: "Notifications",
1624
2502
  enabled: true,
2503
+ lifecycle: "active",
1625
2504
  path: "/monitoring/notifications"
1626
2505
  },
1627
- {
2506
+ "monitoring.submitted-requests": {
1628
2507
  id: "monitoring.submitted-requests",
2508
+ order: 250,
1629
2509
  label: "Submitted Requests",
1630
2510
  enabled: true,
2511
+ lifecycle: "active",
1631
2512
  path: "/monitoring/requests"
1632
2513
  },
1633
- {
2514
+ settings: {
1634
2515
  id: "settings",
2516
+ order: 260,
1635
2517
  label: "Settings",
1636
2518
  enabled: true,
1637
- icon: "feature.settings",
1638
- uiPosition: "sidebar-bottom"
2519
+ lifecycle: "active",
2520
+ icon: "feature.settings"
1639
2521
  },
1640
- {
2522
+ "settings.account": {
1641
2523
  id: "settings.account",
2524
+ order: 270,
1642
2525
  label: "Account",
1643
2526
  enabled: true,
2527
+ lifecycle: "active",
1644
2528
  path: "/settings/account"
1645
2529
  },
1646
- {
2530
+ "settings.appearance": {
1647
2531
  id: "settings.appearance",
2532
+ order: 280,
1648
2533
  label: "Appearance",
1649
2534
  enabled: true,
2535
+ lifecycle: "active",
1650
2536
  path: "/settings/appearance"
1651
2537
  },
1652
- {
2538
+ "settings.roles": {
1653
2539
  id: "settings.roles",
2540
+ order: 290,
1654
2541
  label: "My Roles",
1655
2542
  enabled: true,
2543
+ lifecycle: "active",
1656
2544
  path: "/settings/roles"
1657
2545
  },
1658
- {
2546
+ "settings.organization": {
1659
2547
  id: "settings.organization",
2548
+ order: 300,
1660
2549
  label: "Organization",
1661
2550
  enabled: true,
2551
+ lifecycle: "active",
1662
2552
  path: "/settings/organization"
1663
2553
  },
1664
- {
2554
+ "settings.credentials": {
1665
2555
  id: "settings.credentials",
2556
+ order: 310,
1666
2557
  label: "Credentials",
1667
2558
  enabled: true,
2559
+ lifecycle: "active",
1668
2560
  path: "/settings/credentials"
1669
2561
  },
1670
- {
2562
+ "settings.api-keys": {
1671
2563
  id: "settings.api-keys",
2564
+ order: 320,
1672
2565
  label: "API Keys",
1673
2566
  enabled: true,
2567
+ lifecycle: "active",
1674
2568
  path: "/settings/api-keys"
1675
2569
  },
1676
- {
2570
+ "settings.webhooks": {
1677
2571
  id: "settings.webhooks",
2572
+ order: 330,
1678
2573
  label: "Webhooks",
1679
2574
  enabled: true,
2575
+ lifecycle: "active",
1680
2576
  path: "/settings/webhooks"
1681
2577
  },
1682
- {
2578
+ "settings.deployments": {
1683
2579
  id: "settings.deployments",
2580
+ order: 340,
1684
2581
  label: "Deployments",
1685
2582
  enabled: true,
2583
+ lifecycle: "active",
1686
2584
  path: "/settings/deployments"
1687
2585
  },
1688
- {
2586
+ admin: {
1689
2587
  id: "admin",
2588
+ order: 350,
1690
2589
  label: "Admin",
1691
2590
  enabled: true,
2591
+ lifecycle: "active",
1692
2592
  path: "/admin",
1693
2593
  icon: "feature.admin",
1694
- uiPosition: "sidebar-bottom",
1695
2594
  requiresAdmin: true
1696
2595
  },
1697
- {
2596
+ "admin.system-health": {
1698
2597
  id: "admin.system-health",
2598
+ order: 360,
1699
2599
  label: "System Health",
1700
2600
  enabled: true,
2601
+ lifecycle: "active",
1701
2602
  path: "/admin/system-health"
1702
2603
  },
1703
- {
2604
+ "admin.organizations": {
1704
2605
  id: "admin.organizations",
2606
+ order: 370,
1705
2607
  label: "Organizations",
1706
2608
  enabled: true,
2609
+ lifecycle: "active",
1707
2610
  path: "/admin/organizations"
1708
2611
  },
1709
- {
2612
+ "admin.users": {
1710
2613
  id: "admin.users",
2614
+ order: 380,
1711
2615
  label: "Users",
1712
2616
  enabled: true,
2617
+ lifecycle: "active",
1713
2618
  path: "/admin/users"
1714
2619
  },
1715
- {
2620
+ "admin.design-showcase": {
1716
2621
  id: "admin.design-showcase",
2622
+ order: 390,
1717
2623
  label: "Design Showcase",
1718
2624
  enabled: true,
2625
+ lifecycle: "active",
1719
2626
  path: "/admin/design-showcase"
1720
2627
  },
1721
- {
2628
+ "admin.debug": {
1722
2629
  id: "admin.debug",
2630
+ order: 400,
1723
2631
  label: "Debug",
1724
2632
  enabled: true,
2633
+ lifecycle: "active",
1725
2634
  path: "/admin/debug"
1726
2635
  },
1727
- {
2636
+ archive: {
1728
2637
  id: "archive",
2638
+ order: 410,
1729
2639
  label: "Archive",
1730
2640
  enabled: true,
2641
+ lifecycle: "active",
1731
2642
  path: "/archive",
1732
2643
  icon: "feature.archive",
1733
- uiPosition: "sidebar-bottom",
1734
2644
  devOnly: true
1735
2645
  },
1736
- {
2646
+ "archive.agent-chat": {
1737
2647
  id: "archive.agent-chat",
2648
+ order: 420,
1738
2649
  label: "Agent Chat",
1739
2650
  enabled: true,
2651
+ lifecycle: "active",
1740
2652
  path: "/archive/agent-chat"
1741
2653
  },
1742
- {
2654
+ "archive.execution-runner": {
1743
2655
  id: "archive.execution-runner",
2656
+ order: 430,
1744
2657
  label: "Execution Runner",
1745
2658
  enabled: true,
2659
+ lifecycle: "active",
1746
2660
  path: "/archive/execution-runner"
1747
2661
  },
1748
- {
2662
+ seo: {
1749
2663
  id: "seo",
2664
+ order: 440,
1750
2665
  label: "SEO",
1751
2666
  enabled: false,
2667
+ lifecycle: "deprecated",
1752
2668
  path: "/seo"
1753
2669
  },
1754
- {
2670
+ knowledge: {
1755
2671
  id: "knowledge",
2672
+ order: 450,
1756
2673
  label: "Knowledge",
1757
2674
  description: "Operational knowledge, playbooks, and strategy docs",
1758
2675
  enabled: true,
2676
+ lifecycle: "active",
1759
2677
  color: "teal",
1760
- icon: "feature.knowledge",
1761
- uiPosition: "sidebar-primary"
2678
+ icon: "feature.knowledge"
1762
2679
  },
1763
- {
2680
+ "knowledge.base": {
1764
2681
  id: "knowledge.base",
2682
+ order: 460,
1765
2683
  label: "Knowledge Base",
1766
2684
  enabled: true,
2685
+ lifecycle: "active",
1767
2686
  path: "/knowledge"
1768
2687
  }
1769
- ],
1770
- branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
1771
- navigation: { surfaces: [], groups: [] },
1772
- sales: DEFAULT_ORGANIZATION_MODEL_SALES,
1773
- prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
1774
- projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
1775
- identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
1776
- customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
1777
- offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
1778
- roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
1779
- goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
1780
- statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
1781
- operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
2688
+ },
2689
+ resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
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.
1782
2694
  knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
1783
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
+ }
1784
3108
 
1785
3109
  // src/organization-model/resolve.ts
1786
3110
  function isPlainObject(value) {
@@ -1809,43 +3133,119 @@ function defineOrganizationModel(model) {
1809
3133
  }
1810
3134
  function resolveOrganizationModel(override, organizationId) {
1811
3135
  const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override);
1812
- const model = OrganizationModelSchema.parse(merged);
1813
- if (!model.sales?.pipelines || model.sales.pipelines.length === 0) {
1814
- const orgLabel = organizationId ? `Organization ${organizationId}` : "Organization";
1815
- throw new Error(
1816
- `${orgLabel} has no sales pipeline configuration. This indicates an incomplete provisioning state. Run org provisioning to seed defaults.`
1817
- );
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
+ }
1818
3148
  }
1819
- return model;
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
+ });
1820
3236
  }
1821
3237
 
1822
3238
  // src/organization-model/foundation.ts
1823
3239
  function createFoundationOrganizationModel(override) {
1824
3240
  const canonical = resolveOrganizationModel(override);
1825
- function requireCoreFeature(featureId) {
1826
- const feature = canonical.features.find((candidate) => candidate.id === featureId);
1827
- if (!feature) {
1828
- throw new Error(`Missing organization surface/feature: ${featureId}`);
1829
- }
1830
- return feature;
1831
- }
1832
- const operationsFeature = requireCoreFeature("operations");
1833
- const projectsFeature = requireCoreFeature("projects");
1834
- const leadGenFeature = requireCoreFeature("sales.lead-gen");
1835
- const crmFeature = requireCoreFeature("sales.crm");
1836
- const navigationSurfaces = [
1837
- { ...operationsFeature, id: "operations", path: "/operations", icon: "feature.operations", surfaceType: "dashboard" },
1838
- { ...projectsFeature, icon: "feature.projects", surfaceType: "list" },
1839
- { ...leadGenFeature, id: "lead-gen", icon: "feature.lead-gen", surfaceType: "list" },
1840
- { ...crmFeature, id: "crm", icon: "feature.crm", surfaceType: "graph" },
1841
- { ...requireCoreFeature("settings.account"), id: "settings", icon: "feature.settings", surfaceType: "settings" }
1842
- ];
1843
- const homeLabel = "Dashboard";
1844
- 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);
1845
3245
  const model = {
1846
3246
  ...canonical,
1847
3247
  navigation: {
1848
- defaultSurfaceId: "operations",
3248
+ defaultSurfaceId: defaultSurface?.id ?? "",
1849
3249
  homeLabel,
1850
3250
  quickAccessSurfaceIds: [...quickAccessSurfaceIds],
1851
3251
  surfaces: navigationSurfaces
@@ -1863,4 +3263,4 @@ function createFoundationOrganizationModel(override) {
1863
3263
  };
1864
3264
  }
1865
3265
 
1866
- export { CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_OPERATIONS, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, FeatureSchema, FirmographicsSchema, GoalsDomainSchema, IconNameSchema, KNOWLEDGE_FEATURE_ID, KeyResultSchema, KnowledgeDomainSchema, KnowledgeLinkSchema, LinkSchema, MONITORING_FEATURE_ID, NodeIdPathSchema, NodeIdStringSchema, OPERATIONS_COMMAND_VIEW_SURFACE_ID, OPERATIONS_FEATURE_ID, ORGANIZATION_MODEL_ICON_TOKENS, ObjectiveSchema, OfferingsDomainSchema, OperationEntrySchema, OperationSemanticClassSchema, OperationsDomainSchema, OrgKnowledgeKindSchema, OrgKnowledgeNodeSchema, OrganizationModelBuiltinIconTokenSchema, OrganizationModelIconTokenSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_VIEW_CAPABILITY_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PricingModelSchema, ProductSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SEO_FEATURE_ID, SETTINGS_FEATURE_ID, SETTINGS_ROLES_SURFACE_ID, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, TechStackEntrySchema, UiPositionSchema, createFoundationOrganizationModel, defineOrganizationModel, resolveOrganizationModel };
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 };