@elevasis/core 0.22.0 → 0.23.0

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