@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
@@ -19416,6 +19416,190 @@ function makeTask(overrides = {}) {
19416
19416
  ...overrides
19417
19417
  });
19418
19418
  }
19419
+
19420
+ // src/organization-model/content-kinds/registry.ts
19421
+ function defineContentType(def) {
19422
+ return def;
19423
+ }
19424
+ var ContentNodeBaseSchema = z.object({
19425
+ /** Human-readable label for the content node. */
19426
+ label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
19427
+ /** Optional one-paragraph description. */
19428
+ description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
19429
+ /** Optional display order within the system content map. */
19430
+ order: z.number().int().optional().meta({ label: "Order" }),
19431
+ /**
19432
+ * Local NodeId of the parent content node within the SAME system.
19433
+ * Per B4/L9: MUST resolve to a sibling in the same `system.content` map.
19434
+ * Per L19: parent and child MUST share the same `kind` (meta-category).
19435
+ */
19436
+ parentContentId: z.string().trim().min(1).max(200).optional().meta({ label: "Parent content id" })
19437
+ });
19438
+ var ContentNodeSchema = ContentNodeBaseSchema.extend({
19439
+ /** Meta-category (e.g. 'schema', 'config', 'knowledge', tenant-defined). */
19440
+ kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
19441
+ /** Specific family within the meta-category (e.g. 'pipeline', 'kv'). */
19442
+ type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
19443
+ /** Payload data; validated against registered payloadSchema when (kind, type) is known. */
19444
+ data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
19445
+ });
19446
+ z.object({
19447
+ /** Meta-category (tenant-defined or registry-shipped). */
19448
+ kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
19449
+ /** Specific family within the meta-category. */
19450
+ type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
19451
+ /** Human-readable label shown in the KB tree and describe views. */
19452
+ label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
19453
+ /** Optional description. */
19454
+ description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
19455
+ /**
19456
+ * Which KB tree group this extension renders in.
19457
+ * Per L6: 'business-model' places it alongside Customers / Offerings / Goals.
19458
+ */
19459
+ treeGroup: z.union([z.enum(["profile", "business-model", "systems", "graph", "governance-wiring"]), z.string().min(1).max(100)]).meta({ label: "Tree group" }),
19460
+ /** Untyped payload; shape governed by the registered payloadSchema when available. */
19461
+ data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
19462
+ });
19463
+ var PipelinePayloadSchema = z.object({
19464
+ /**
19465
+ * Local NodeId of the entity this pipeline applies to (e.g. 'crm.deal').
19466
+ * `.meta({ ref: 'entity' })` enables SchemaDrivenFieldList to render a
19467
+ * clickable graph link to the referenced entity node.
19468
+ */
19469
+ entityId: z.string().trim().min(1).max(200).meta({ label: "Entity", ref: "entity", hint: "The entity type this pipeline tracks" }),
19470
+ /**
19471
+ * Optional Kanban column color token for UI rendering.
19472
+ */
19473
+ kanbanColor: z.string().trim().min(1).max(40).optional().meta({ label: "Kanban color", hint: "UI color token" })
19474
+ });
19475
+ var pipelineKind = defineContentType({
19476
+ kind: "schema",
19477
+ type: "pipeline",
19478
+ label: "Pipeline",
19479
+ description: "A named progression pipeline that applies to a specific entity type.",
19480
+ payloadSchema: PipelinePayloadSchema,
19481
+ parentTypes: []
19482
+ });
19483
+ var StagePayloadSchema = z.object({
19484
+ /**
19485
+ * Semantic classification for this stage.
19486
+ * Drives color, icon, and CRM-priority logic in consuming views.
19487
+ * Optional — prospecting stages use data.entityKind instead.
19488
+ * Enum aligned with SalesStageSemanticClassSchema (sales.ts).
19489
+ */
19490
+ 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" })
19491
+ });
19492
+ var stageKind = defineContentType({
19493
+ kind: "schema",
19494
+ type: "stage",
19495
+ label: "Stage",
19496
+ description: "A stage within a pipeline. Must be parented under a schema:pipeline content node.",
19497
+ payloadSchema: StagePayloadSchema,
19498
+ parentTypes: ["schema:pipeline"]
19499
+ });
19500
+ var TemplatePayloadSchema = z.object({
19501
+ /**
19502
+ * Optional description surfaced in the KB describe view and tooling.
19503
+ */
19504
+ description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description", hint: "What this template is used for" })
19505
+ });
19506
+ var templateKind = defineContentType({
19507
+ kind: "schema",
19508
+ type: "template",
19509
+ label: "Template",
19510
+ description: "A named build template (e.g. a prospecting pipeline sequence).",
19511
+ payloadSchema: TemplatePayloadSchema,
19512
+ parentTypes: []
19513
+ });
19514
+ var TemplateStepPayloadSchema = z.object({
19515
+ /**
19516
+ * Which entity type this step primarily operates on.
19517
+ */
19518
+ primaryEntity: z.enum(["company", "contact"]).meta({ label: "Primary entity", hint: "Entity type this step processes", color: "blue" }),
19519
+ /**
19520
+ * Action key identifying the workflow action executed by this step.
19521
+ * `.meta({ ref: 'action' })` enables SchemaDrivenFieldList to render a
19522
+ * clickable graph link.
19523
+ */
19524
+ actionKey: z.string().trim().min(1).max(200).meta({ label: "Action", ref: "action", hint: "Workflow action executed by this step" }),
19525
+ /**
19526
+ * IDs of sibling step local NodeIds this step depends on.
19527
+ */
19528
+ dependsOn: z.array(z.string().trim().min(1).max(200)).optional().meta({ label: "Depends on", hint: "Local NodeIds of prerequisite steps" })
19529
+ });
19530
+ var templateStepKind = defineContentType({
19531
+ kind: "schema",
19532
+ type: "template-step",
19533
+ label: "Template Step",
19534
+ description: "A step within a build template. Must be parented under a schema:template content node.",
19535
+ payloadSchema: TemplateStepPayloadSchema,
19536
+ parentTypes: ["schema:template"]
19537
+ });
19538
+ var StatusFlowPayloadSchema = z.object({
19539
+ /**
19540
+ * Which entity scope this status flow governs.
19541
+ */
19542
+ appliesTo: z.enum(["project", "milestone", "task"]).meta({ label: "Applies to", hint: "Entity scope governed by this status flow", color: "blue" })
19543
+ });
19544
+ var statusFlowKind = defineContentType({
19545
+ kind: "schema",
19546
+ type: "status-flow",
19547
+ label: "Status Flow",
19548
+ description: "A named set of statuses governing a project, milestone, or task entity.",
19549
+ payloadSchema: StatusFlowPayloadSchema,
19550
+ parentTypes: []
19551
+ });
19552
+ var StatusPayloadSchema = z.object({
19553
+ /**
19554
+ * Semantic classification string for this status.
19555
+ * Free-form to allow tenant-defined classifications (e.g. 'active', 'blocked',
19556
+ * 'completed'). Used by UI to apply color and icon fallbacks.
19557
+ * Optional — status nodes may omit this when the label is self-descriptive.
19558
+ */
19559
+ semanticClass: z.string().trim().min(1).max(100).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this status (e.g. active, blocked, completed)" }),
19560
+ /**
19561
+ * Optional UI color token override for this status.
19562
+ */
19563
+ color: z.string().trim().min(1).max(40).optional().meta({ label: "Color", hint: "UI color token" })
19564
+ });
19565
+ var statusKind = defineContentType({
19566
+ kind: "schema",
19567
+ type: "status",
19568
+ label: "Status",
19569
+ description: "A single status within a status flow. Must be parented under a schema:status-flow content node.",
19570
+ payloadSchema: StatusPayloadSchema,
19571
+ parentTypes: ["schema:status-flow"]
19572
+ });
19573
+ var ConfigKvPayloadSchema = z.object({
19574
+ /**
19575
+ * Flat key-value entries. Values are JSON primitives.
19576
+ * Keys are short identifiers (e.g. 'maxBatchSize', 'featureEnabled').
19577
+ */
19578
+ 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)" })
19579
+ });
19580
+ var configKvKind = defineContentType({
19581
+ kind: "config",
19582
+ type: "kv",
19583
+ label: "Key-Value Config",
19584
+ description: "A flat key-value configuration store co-located with a system. Values are JSON primitives.",
19585
+ payloadSchema: ConfigKvPayloadSchema,
19586
+ parentTypes: []
19587
+ });
19588
+
19589
+ // src/organization-model/content-kinds/index.ts
19590
+ var CONTENT_KIND_REGISTRY = {
19591
+ "schema:pipeline": pipelineKind,
19592
+ "schema:stage": stageKind,
19593
+ "schema:template": templateKind,
19594
+ "schema:template-step": templateStepKind,
19595
+ "schema:status-flow": statusFlowKind,
19596
+ "schema:status": statusKind,
19597
+ "config:kv": configKvKind
19598
+ };
19599
+ function lookupContentType(kind, type3) {
19600
+ const key = `${kind}:${type3}`;
19601
+ return CONTENT_KIND_REGISTRY[key];
19602
+ }
19419
19603
  var ORGANIZATION_MODEL_ICON_TOKENS = [
19420
19604
  "nav.dashboard",
19421
19605
  "nav.calendar",
@@ -19527,10 +19711,10 @@ DisplayMetadataSchema.extend({
19527
19711
  id: ModelIdSchema,
19528
19712
  resourceId: z.string().trim().min(1).max(255),
19529
19713
  resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
19530
- featureIds: ReferenceIdsSchema,
19714
+ systemIds: ReferenceIdsSchema,
19531
19715
  entityIds: ReferenceIdsSchema,
19532
19716
  surfaceIds: ReferenceIdsSchema,
19533
- capabilityIds: ReferenceIdsSchema,
19717
+ actionIds: ReferenceIdsSchema,
19534
19718
  /** Optional tech-stack metadata for external-SaaS integrations. */
19535
19719
  techStack: TechStackEntrySchema.optional()
19536
19720
  });
@@ -19552,637 +19736,8 @@ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
19552
19736
  shortName: "Elevasis",
19553
19737
  logos: {}
19554
19738
  };
19555
- var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
19556
- var SalesStageSchema = DisplayMetadataSchema.extend({
19557
- id: ModelIdSchema,
19558
- order: z.number().int().min(0),
19559
- semanticClass: SalesStageSemanticClassSchema,
19560
- surfaceIds: ReferenceIdsSchema,
19561
- resourceIds: ReferenceIdsSchema
19562
- });
19563
- var SalesPipelineSchema = z.object({
19564
- id: ModelIdSchema,
19565
- label: z.string().trim().min(1).max(120),
19566
- description: DescriptionSchema.optional(),
19567
- entityId: ModelIdSchema,
19568
- stages: z.array(SalesStageSchema).min(1)
19569
- });
19570
- var OrganizationModelSalesSchema = z.object({
19571
- entityId: ModelIdSchema,
19572
- defaultPipelineId: ModelIdSchema,
19573
- pipelines: z.array(SalesPipelineSchema).min(1)
19574
- });
19575
- var DEFAULT_ORGANIZATION_MODEL_SALES = {
19576
- entityId: "crm.deal",
19577
- defaultPipelineId: "default",
19578
- pipelines: [
19579
- {
19580
- id: "default",
19581
- label: "Default Pipeline",
19582
- entityId: "crm.deal",
19583
- stages: [
19584
- {
19585
- id: "interested",
19586
- label: "Interested",
19587
- color: "blue",
19588
- order: 1,
19589
- semanticClass: "open",
19590
- surfaceIds: ["crm.pipeline"],
19591
- resourceIds: []
19592
- },
19593
- {
19594
- id: "proposal",
19595
- label: "Proposal",
19596
- color: "yellow",
19597
- order: 2,
19598
- semanticClass: "active",
19599
- surfaceIds: ["crm.pipeline"],
19600
- resourceIds: []
19601
- },
19602
- {
19603
- id: "closing",
19604
- label: "Closing",
19605
- color: "lime",
19606
- order: 3,
19607
- semanticClass: "active",
19608
- surfaceIds: ["crm.pipeline"],
19609
- resourceIds: []
19610
- },
19611
- {
19612
- id: "closed_won",
19613
- label: "Closed Won",
19614
- color: "green",
19615
- order: 4,
19616
- semanticClass: "closed_won",
19617
- surfaceIds: ["crm.pipeline"],
19618
- resourceIds: []
19619
- },
19620
- {
19621
- id: "closed_lost",
19622
- label: "Closed Lost",
19623
- color: "red",
19624
- order: 5,
19625
- semanticClass: "closed_lost",
19626
- surfaceIds: ["crm.pipeline"],
19627
- resourceIds: []
19628
- },
19629
- {
19630
- id: "nurturing",
19631
- label: "Nurturing",
19632
- color: "grape",
19633
- order: 6,
19634
- semanticClass: "nurturing",
19635
- surfaceIds: ["crm.pipeline"],
19636
- resourceIds: []
19637
- }
19638
- ]
19639
- }
19640
- ]
19641
- };
19642
- var LEAD_GEN_STAGE_CATALOG = {
19643
- // Prospecting — company population
19644
- scraped: {
19645
- key: "scraped",
19646
- label: "Scraped",
19647
- description: "Company was scraped from a source directory (Apify actor run).",
19648
- order: 1,
19649
- entity: "company"
19650
- },
19651
- populated: {
19652
- key: "populated",
19653
- label: "Companies found",
19654
- description: "Companies have been found and added to the lead-gen list.",
19655
- order: 2,
19656
- entity: "company"
19657
- },
19658
- crawled: {
19659
- key: "crawled",
19660
- label: "Websites crawled",
19661
- description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
19662
- order: 2.5,
19663
- entity: "company"
19664
- },
19665
- extracted: {
19666
- key: "extracted",
19667
- label: "Websites analyzed",
19668
- description: "Company websites have been analyzed for business signals.",
19669
- order: 3,
19670
- entity: "company"
19671
- },
19672
- enriched: {
19673
- key: "enriched",
19674
- label: "Enriched",
19675
- description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
19676
- order: 4,
19677
- entity: "company"
19678
- },
19679
- "decision-makers-enriched": {
19680
- key: "decision-makers-enriched",
19681
- label: "Decision-makers found",
19682
- description: "Decision-maker contacts discovered and attached to a qualified company.",
19683
- order: 6,
19684
- entity: "company",
19685
- recordEntity: "contact",
19686
- recordStageKey: "discovered"
19687
- },
19688
- // Prospecting — contact discovery
19689
- discovered: {
19690
- key: "discovered",
19691
- label: "Decision-makers found",
19692
- description: "Decision-maker contact details have been found.",
19693
- order: 5,
19694
- entity: "contact"
19695
- },
19696
- verified: {
19697
- key: "verified",
19698
- label: "Emails verified",
19699
- description: "Contact email addresses have been checked for deliverability.",
19700
- order: 7,
19701
- entity: "contact"
19702
- },
19703
- // Qualification
19704
- qualified: {
19705
- key: "qualified",
19706
- label: "Companies qualified",
19707
- description: "Companies have been scored against the qualification criteria.",
19708
- order: 8,
19709
- entity: "company"
19710
- },
19711
- // Outreach
19712
- personalized: {
19713
- key: "personalized",
19714
- label: "Personalized",
19715
- description: "Outreach message personalized for the contact (Instantly personalization workflow).",
19716
- order: 9,
19717
- entity: "contact"
19718
- },
19719
- uploaded: {
19720
- key: "uploaded",
19721
- label: "Reviewed and exported",
19722
- description: "Approved records have been reviewed and exported for handoff.",
19723
- order: 10,
19724
- entity: "company",
19725
- additionalEntities: ["contact"]
19726
- },
19727
- interested: {
19728
- key: "interested",
19729
- label: "Interested",
19730
- description: "Contact replied with a positive signal (Instantly reply-handler transition).",
19731
- order: 11,
19732
- entity: "contact"
19733
- }
19734
- };
19735
- var ProjectsDomainStateSchema = DisplayMetadataSchema.extend({
19736
- id: ModelIdSchema,
19737
- order: z.number().int().min(0)
19738
- });
19739
- var OrganizationModelProjectsSchema = z.object({
19740
- projectEntityId: ModelIdSchema,
19741
- milestoneEntityId: ModelIdSchema,
19742
- taskEntityId: ModelIdSchema,
19743
- projectStatuses: z.array(ProjectsDomainStateSchema).min(1),
19744
- milestoneStatuses: z.array(ProjectsDomainStateSchema).min(1),
19745
- taskStatuses: z.array(ProjectsDomainStateSchema).min(1)
19746
- });
19747
- var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
19748
- projectEntityId: "delivery.project",
19749
- milestoneEntityId: "delivery.milestone",
19750
- taskEntityId: "delivery.task",
19751
- projectStatuses: [
19752
- { id: "active", label: "Active", order: 1 },
19753
- { id: "on_track", label: "On Track", order: 2 },
19754
- { id: "at_risk", label: "At Risk", order: 3 },
19755
- { id: "blocked", label: "Blocked", order: 4 },
19756
- { id: "paused", label: "Paused", order: 5 },
19757
- { id: "completed", label: "Completed", order: 6 }
19758
- ],
19759
- milestoneStatuses: [
19760
- { id: "upcoming", label: "Upcoming", order: 1 },
19761
- { id: "in_progress", label: "In Progress", order: 2 },
19762
- { id: "blocked", label: "Blocked", order: 3 },
19763
- { id: "overdue", label: "Overdue", order: 4 },
19764
- { id: "completed", label: "Completed", order: 5 }
19765
- ],
19766
- taskStatuses: [
19767
- { id: "planned", label: "Planned", order: 1 },
19768
- { id: "in_progress", label: "In Progress", order: 2 },
19769
- { id: "blocked", label: "Blocked", order: 3 },
19770
- { id: "submitted", label: "Submitted", order: 4 },
19771
- { id: "approved", label: "Approved", order: 5 },
19772
- { id: "revision_requested", label: "Revision Requested", order: 6 },
19773
- { id: "rejected", label: "Rejected", order: 7 },
19774
- { id: "cancelled", label: "Cancelled", order: 8 },
19775
- { id: "completed", label: "Completed", order: 9 }
19776
- ]
19777
- };
19778
- var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
19779
- 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");
19780
- var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
19781
- var FeatureSchema = z.object({
19782
- id: NodeIdPathSchema,
19783
- label: LabelSchema,
19784
- description: DescriptionSchema.optional(),
19785
- enabled: z.boolean().default(true),
19786
- path: PathSchema.optional(),
19787
- icon: IconNameSchema.optional(),
19788
- color: ColorTokenSchema.optional(),
19789
- uiPosition: UiPositionSchema.optional(),
19790
- requiresAdmin: z.boolean().optional(),
19791
- devOnly: z.boolean().optional()
19792
- });
19793
- var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
19794
- id: ModelIdSchema,
19795
- order: z.number().min(0)
19796
- });
19797
- var RecordColumnConfigSchema = z.object({
19798
- key: ModelIdSchema,
19799
- label: z.string().trim().min(1).max(120),
19800
- path: z.string().trim().min(1).max(500),
19801
- width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
19802
- renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
19803
- badgeColor: z.string().trim().min(1).max(40).optional()
19804
- });
19805
- var RecordColumnsConfigSchema = z.object({
19806
- company: z.array(RecordColumnConfigSchema).optional(),
19807
- contact: z.array(RecordColumnConfigSchema).optional()
19808
- }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
19809
- message: "recordColumns must include at least one entity column set"
19810
- });
19811
- var CredentialRequirementSchema = z.object({
19812
- key: ModelIdSchema,
19813
- provider: ModelIdSchema,
19814
- credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
19815
- label: z.string().trim().min(1).max(120),
19816
- required: z.boolean(),
19817
- selectionMode: z.enum(["single", "multiple"]).optional(),
19818
- inputPath: z.string().trim().min(1).max(500),
19819
- verifyOnRun: z.boolean().optional()
19820
- });
19821
- var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
19822
- id: ModelIdSchema,
19823
- primaryEntity: z.enum(["company", "contact"]),
19824
- outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
19825
- stageKey: ModelIdSchema,
19826
- recordEntity: z.enum(["company", "contact"]).optional(),
19827
- recordsStageKey: ModelIdSchema.optional(),
19828
- recordSourceStageKey: ModelIdSchema.optional(),
19829
- dependsOn: z.array(ModelIdSchema).optional(),
19830
- dependencyMode: z.literal("per-record-eligibility"),
19831
- capabilityKey: ModelIdSchema,
19832
- defaultBatchSize: z.number().int().positive(),
19833
- maxBatchSize: z.number().int().positive(),
19834
- recordColumns: RecordColumnsConfigSchema.optional(),
19835
- credentialRequirements: z.array(CredentialRequirementSchema).optional()
19836
- }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
19837
- message: "defaultBatchSize must be less than or equal to maxBatchSize",
19838
- path: ["defaultBatchSize"]
19839
- });
19840
- var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
19841
- id: ModelIdSchema,
19842
- steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
19843
- });
19844
- var DTC_RECORD_COLUMNS = {
19845
- populated: {
19846
- company: [
19847
- { key: "name", label: "Company", path: "company.name" },
19848
- { key: "domain", label: "Domain", path: "company.domain" },
19849
- { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
19850
- { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
19851
- { key: "location", label: "Location", path: "company.locationState" }
19852
- ]
19853
- },
19854
- crawled: {
19855
- company: [
19856
- { key: "name", label: "Company", path: "company.name" },
19857
- { key: "domain", label: "Domain", path: "company.domain" },
19858
- { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
19859
- { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
19860
- ]
19861
- },
19862
- extracted: {
19863
- company: [
19864
- { key: "name", label: "Company", path: "company.name" },
19865
- { key: "domain", label: "Domain", path: "company.domain" },
19866
- { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
19867
- { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
19868
- { key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
19869
- { key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
19870
- ]
19871
- },
19872
- qualified: {
19873
- company: [
19874
- { key: "name", label: "Company", path: "company.name" },
19875
- { key: "domain", label: "Domain", path: "company.domain" },
19876
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
19877
- { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
19878
- { key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
19879
- ]
19880
- },
19881
- decisionMakers: {
19882
- contact: [
19883
- { key: "name", label: "Name", path: "contact.name" },
19884
- { key: "title", label: "Title", path: "contact.title" },
19885
- { key: "email", label: "Email", path: "contact.email" },
19886
- { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
19887
- { key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
19888
- ]
19889
- },
19890
- uploaded: {
19891
- company: [
19892
- { key: "name", label: "Company", path: "company.name" },
19893
- { key: "domain", label: "Domain", path: "company.domain" },
19894
- { key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
19895
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
19896
- { key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
19897
- ]
19898
- }
19899
- };
19739
+ var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
19900
19740
  z.object({
19901
- id: ModelIdSchema,
19902
- label: z.string(),
19903
- description: z.string(),
19904
- resourceId: ModelIdSchema
19905
- });
19906
- var PROSPECTING_STEPS = {
19907
- localServices: {
19908
- sourceCompanies: {
19909
- id: "source-companies",
19910
- label: "Companies found",
19911
- primaryEntity: "company",
19912
- outputs: ["company"],
19913
- stageKey: "populated",
19914
- dependencyMode: "per-record-eligibility",
19915
- capabilityKey: "lead-gen.company.source",
19916
- defaultBatchSize: 100,
19917
- maxBatchSize: 250
19918
- },
19919
- analyzeWebsites: {
19920
- id: "analyze-websites",
19921
- label: "Websites analyzed",
19922
- primaryEntity: "company",
19923
- outputs: ["company"],
19924
- stageKey: "extracted",
19925
- dependsOn: ["source-companies"],
19926
- dependencyMode: "per-record-eligibility",
19927
- capabilityKey: "lead-gen.company.website-extract",
19928
- defaultBatchSize: 50,
19929
- maxBatchSize: 100
19930
- },
19931
- qualifyCompanies: {
19932
- id: "qualify-companies",
19933
- label: "Companies qualified",
19934
- primaryEntity: "company",
19935
- outputs: ["company"],
19936
- stageKey: "qualified",
19937
- dependsOn: ["analyze-websites"],
19938
- dependencyMode: "per-record-eligibility",
19939
- capabilityKey: "lead-gen.company.qualify",
19940
- defaultBatchSize: 100,
19941
- maxBatchSize: 250
19942
- },
19943
- findContacts: {
19944
- id: "find-contacts",
19945
- label: "Decision-makers found",
19946
- primaryEntity: "contact",
19947
- outputs: ["contact"],
19948
- stageKey: "discovered",
19949
- dependsOn: ["qualify-companies"],
19950
- dependencyMode: "per-record-eligibility",
19951
- capabilityKey: "lead-gen.contact.discover",
19952
- defaultBatchSize: 50,
19953
- maxBatchSize: 100
19954
- },
19955
- verifyEmails: {
19956
- id: "verify-emails",
19957
- label: "Emails verified",
19958
- primaryEntity: "contact",
19959
- outputs: ["contact"],
19960
- stageKey: "verified",
19961
- dependsOn: ["find-contacts"],
19962
- dependencyMode: "per-record-eligibility",
19963
- capabilityKey: "lead-gen.contact.verify-email",
19964
- defaultBatchSize: 100,
19965
- maxBatchSize: 500
19966
- },
19967
- personalize: {
19968
- id: "personalize",
19969
- label: "Personalize",
19970
- primaryEntity: "contact",
19971
- outputs: ["contact"],
19972
- stageKey: "personalized",
19973
- dependsOn: ["verify-emails"],
19974
- dependencyMode: "per-record-eligibility",
19975
- capabilityKey: "lead-gen.contact.personalize",
19976
- defaultBatchSize: 25,
19977
- maxBatchSize: 100
19978
- },
19979
- review: {
19980
- id: "review",
19981
- label: "Reviewed and exported",
19982
- primaryEntity: "contact",
19983
- outputs: ["export"],
19984
- stageKey: "uploaded",
19985
- dependsOn: ["personalize"],
19986
- dependencyMode: "per-record-eligibility",
19987
- capabilityKey: "lead-gen.review.outreach-ready",
19988
- defaultBatchSize: 25,
19989
- maxBatchSize: 100
19990
- }
19991
- },
19992
- dtcApolloClickup: {
19993
- importApolloSearch: {
19994
- id: "import-apollo-search",
19995
- label: "Companies found",
19996
- description: "Pull companies and seed contact data from a predefined Apollo search or list.",
19997
- primaryEntity: "company",
19998
- outputs: ["company", "contact"],
19999
- stageKey: "populated",
20000
- dependencyMode: "per-record-eligibility",
20001
- capabilityKey: "lead-gen.company.apollo-import",
20002
- defaultBatchSize: 250,
20003
- maxBatchSize: 1e3,
20004
- recordColumns: DTC_RECORD_COLUMNS.populated,
20005
- credentialRequirements: [
20006
- {
20007
- key: "apollo",
20008
- provider: "apollo",
20009
- credentialType: "api-key-secret",
20010
- label: "Apollo API key",
20011
- required: true,
20012
- selectionMode: "single",
20013
- inputPath: "credential"
20014
- }
20015
- ]
20016
- },
20017
- apifyCrawl: {
20018
- id: "apify-crawl",
20019
- label: "Websites crawled",
20020
- 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.",
20021
- primaryEntity: "company",
20022
- outputs: ["company"],
20023
- stageKey: "crawled",
20024
- dependsOn: ["import-apollo-search"],
20025
- dependencyMode: "per-record-eligibility",
20026
- capabilityKey: "lead-gen.company.apify-crawl",
20027
- defaultBatchSize: 50,
20028
- maxBatchSize: 100,
20029
- recordColumns: DTC_RECORD_COLUMNS.crawled,
20030
- credentialRequirements: [
20031
- {
20032
- key: "apify",
20033
- provider: "apify",
20034
- credentialType: "api-key-secret",
20035
- label: "Apify API token",
20036
- required: true,
20037
- selectionMode: "single",
20038
- inputPath: "credential",
20039
- verifyOnRun: true
20040
- }
20041
- ]
20042
- },
20043
- analyzeWebsites: {
20044
- id: "analyze-websites",
20045
- label: "Websites analyzed",
20046
- description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
20047
- primaryEntity: "company",
20048
- outputs: ["company"],
20049
- stageKey: "extracted",
20050
- dependsOn: ["apify-crawl"],
20051
- dependencyMode: "per-record-eligibility",
20052
- capabilityKey: "lead-gen.company.website-extract",
20053
- defaultBatchSize: 50,
20054
- maxBatchSize: 100,
20055
- recordColumns: DTC_RECORD_COLUMNS.extracted
20056
- },
20057
- scoreDtcFit: {
20058
- id: "score-dtc-fit",
20059
- label: "Companies qualified",
20060
- description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
20061
- primaryEntity: "company",
20062
- outputs: ["company"],
20063
- stageKey: "qualified",
20064
- dependsOn: ["analyze-websites"],
20065
- dependencyMode: "per-record-eligibility",
20066
- capabilityKey: "lead-gen.company.dtc-subscription-qualify",
20067
- defaultBatchSize: 100,
20068
- maxBatchSize: 250,
20069
- recordColumns: DTC_RECORD_COLUMNS.qualified
20070
- },
20071
- enrichDecisionMakers: {
20072
- id: "enrich-decision-makers",
20073
- label: "Decision-makers found",
20074
- description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
20075
- primaryEntity: "company",
20076
- outputs: ["contact"],
20077
- stageKey: "decision-makers-enriched",
20078
- recordEntity: "contact",
20079
- dependsOn: ["score-dtc-fit"],
20080
- dependencyMode: "per-record-eligibility",
20081
- capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
20082
- defaultBatchSize: 100,
20083
- maxBatchSize: 250,
20084
- recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
20085
- credentialRequirements: [
20086
- {
20087
- key: "apollo",
20088
- provider: "apollo",
20089
- credentialType: "api-key-secret",
20090
- label: "Apollo API key",
20091
- required: true,
20092
- selectionMode: "single",
20093
- inputPath: "credential"
20094
- }
20095
- ]
20096
- },
20097
- reviewAndExport: {
20098
- id: "review-and-export",
20099
- label: "Reviewed and exported",
20100
- description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
20101
- primaryEntity: "company",
20102
- outputs: ["export"],
20103
- stageKey: "uploaded",
20104
- recordsStageKey: "uploaded",
20105
- recordSourceStageKey: "qualified",
20106
- dependsOn: ["enrich-decision-makers"],
20107
- dependencyMode: "per-record-eligibility",
20108
- capabilityKey: "lead-gen.export.list",
20109
- defaultBatchSize: 100,
20110
- maxBatchSize: 250,
20111
- recordColumns: DTC_RECORD_COLUMNS.uploaded,
20112
- credentialRequirements: [
20113
- {
20114
- key: "clickup",
20115
- provider: "clickup",
20116
- credentialType: "api-key-secret",
20117
- label: "ClickUp API token",
20118
- required: true,
20119
- selectionMode: "single",
20120
- inputPath: "clickupCredential",
20121
- verifyOnRun: true
20122
- }
20123
- ]
20124
- }
20125
- }
20126
- };
20127
- var OrganizationModelProspectingSchema = z.object({
20128
- listEntityId: ModelIdSchema,
20129
- companyEntityId: ModelIdSchema,
20130
- contactEntityId: ModelIdSchema,
20131
- description: DescriptionSchema.optional(),
20132
- companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
20133
- contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
20134
- defaultBuildTemplateId: ModelIdSchema,
20135
- buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
20136
- });
20137
- function toProspectingLifecycleStage(stage) {
20138
- return {
20139
- id: stage.key,
20140
- label: stage.label,
20141
- order: stage.order
20142
- };
20143
- }
20144
- function leadGenStagesForEntity(entity) {
20145
- return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity)).sort((a3, b2) => a3.order - b2.order).map(toProspectingLifecycleStage);
20146
- }
20147
- var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
20148
- listEntityId: "leadgen.list",
20149
- companyEntityId: "leadgen.company",
20150
- contactEntityId: "leadgen.contact",
20151
- companyStages: leadGenStagesForEntity("company"),
20152
- contactStages: leadGenStagesForEntity("contact"),
20153
- defaultBuildTemplateId: "local-services",
20154
- buildTemplates: [
20155
- {
20156
- id: "local-services",
20157
- label: "Local Services Prospecting",
20158
- description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
20159
- steps: [
20160
- PROSPECTING_STEPS.localServices.sourceCompanies,
20161
- PROSPECTING_STEPS.localServices.analyzeWebsites,
20162
- PROSPECTING_STEPS.localServices.qualifyCompanies,
20163
- PROSPECTING_STEPS.localServices.findContacts,
20164
- PROSPECTING_STEPS.localServices.verifyEmails,
20165
- PROSPECTING_STEPS.localServices.personalize,
20166
- PROSPECTING_STEPS.localServices.review
20167
- ]
20168
- },
20169
- {
20170
- id: "dtc-subscription-apollo-clickup",
20171
- label: "DTC Subscription Apollo Export",
20172
- 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.",
20173
- steps: [
20174
- PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
20175
- PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
20176
- PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
20177
- PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
20178
- PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
20179
- PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
20180
- ]
20181
- }
20182
- ]
20183
- };
20184
- var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]);
20185
- var SurfaceDefinitionSchema = z.object({
20186
19741
  id: ModelIdSchema,
20187
19742
  label: LabelSchema,
20188
19743
  path: PathSchema,
@@ -20191,23 +19746,55 @@ var SurfaceDefinitionSchema = z.object({
20191
19746
  enabled: z.boolean().default(true),
20192
19747
  devOnly: z.boolean().optional(),
20193
19748
  icon: IconNameSchema.optional(),
20194
- featureId: ModelIdSchema.optional(),
20195
- featureIds: ReferenceIdsSchema,
20196
- entityIds: ReferenceIdsSchema,
20197
- resourceIds: ReferenceIdsSchema,
20198
- capabilityIds: ReferenceIdsSchema,
20199
- parentId: ModelIdSchema.optional()
19749
+ systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
19750
+ entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
19751
+ resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
19752
+ actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
19753
+ parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
20200
19754
  });
20201
- var NavigationGroupSchema = z.object({
19755
+ var SidebarSurfaceTargetsSchema = z.object({
19756
+ systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
19757
+ entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
19758
+ resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
19759
+ actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
19760
+ }).default({});
19761
+ var SidebarNodeSchema = z.lazy(
19762
+ () => z.discriminatedUnion("type", [
19763
+ z.object({
19764
+ type: z.literal("group"),
19765
+ label: LabelSchema,
19766
+ description: DescriptionSchema.optional(),
19767
+ icon: IconNameSchema.optional(),
19768
+ order: z.number().int().optional(),
19769
+ children: z.record(z.string(), SidebarNodeSchema).default({})
19770
+ }),
19771
+ z.object({
19772
+ type: z.literal("surface"),
19773
+ label: LabelSchema,
19774
+ path: PathSchema,
19775
+ surfaceType: SurfaceTypeSchema,
19776
+ description: DescriptionSchema.optional(),
19777
+ icon: IconNameSchema.optional(),
19778
+ order: z.number().int().optional(),
19779
+ targets: SidebarSurfaceTargetsSchema.optional(),
19780
+ devOnly: z.boolean().optional(),
19781
+ requiresAdmin: z.boolean().optional()
19782
+ })
19783
+ ])
19784
+ );
19785
+ var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
19786
+ var SidebarNavigationSchema = z.object({
19787
+ primary: SidebarSectionSchema,
19788
+ bottom: SidebarSectionSchema
19789
+ }).default({ primary: {}, bottom: {} });
19790
+ var OrganizationModelNavigationSchema = z.object({
19791
+ sidebar: SidebarNavigationSchema
19792
+ }).default({ sidebar: { primary: {}, bottom: {} } });
19793
+ z.object({
20202
19794
  id: ModelIdSchema,
20203
19795
  label: LabelSchema,
20204
19796
  placement: z.string().trim().min(1).max(50),
20205
- surfaceIds: z.array(ModelIdSchema).default([])
20206
- });
20207
- var OrganizationModelNavigationSchema = z.object({
20208
- defaultSurfaceId: ModelIdSchema.optional(),
20209
- surfaces: z.array(SurfaceDefinitionSchema).default([]),
20210
- groups: z.array(NavigationGroupSchema).default([])
19797
+ surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
20211
19798
  });
20212
19799
  var BusinessHoursDaySchema = z.object({
20213
19800
  open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
@@ -20292,6 +19879,8 @@ var FirmographicsSchema = z.object({
20292
19879
  var CustomerSegmentSchema = z.object({
20293
19880
  /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
20294
19881
  id: z.string().trim().min(1).max(100),
19882
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
19883
+ order: z.number(),
20295
19884
  /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
20296
19885
  name: z.string().trim().max(200).default(""),
20297
19886
  /** One or two sentences describing who this segment is. */
@@ -20319,16 +19908,16 @@ var CustomerSegmentSchema = z.object({
20319
19908
  */
20320
19909
  valueProp: z.string().trim().max(2e3).default("")
20321
19910
  });
20322
- var CustomersDomainSchema = z.object({
20323
- segments: z.array(CustomerSegmentSchema).default([])
20324
- });
20325
- var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {
20326
- segments: []
20327
- };
20328
- var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]);
19911
+ var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
19912
+ message: "Each segment entry id must match its map key"
19913
+ }).default({});
19914
+ var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
19915
+ var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
20329
19916
  var ProductSchema = z.object({
20330
19917
  /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
20331
19918
  id: z.string().trim().min(1).max(100),
19919
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
19920
+ order: z.number(),
20332
19921
  /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
20333
19922
  name: z.string().trim().max(200).default(""),
20334
19923
  /** One or two sentences describing what this product/service delivers. */
@@ -20355,88 +19944,496 @@ var ProductSchema = z.object({
20355
19944
  */
20356
19945
  targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
20357
19946
  /**
20358
- * Optional: ID of the platform feature responsible for delivering this product.
20359
- * When present, must reference a declared `features[].id`.
19947
+ * Optional: ID of the platform system responsible for delivering this product.
19948
+ * When present, must reference a declared `systems.systems[].id`.
20360
19949
  * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
20361
19950
  */
20362
19951
  deliveryFeatureId: z.string().trim().min(1).optional()
20363
19952
  });
20364
- var OfferingsDomainSchema = z.object({
20365
- products: z.array(ProductSchema).default([])
19953
+ var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
19954
+ message: "Each product entry id must match its map key"
19955
+ }).default({});
19956
+ var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
19957
+ var EntityIdSchema = ModelIdSchema;
19958
+ var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
19959
+ var EntityLinkSchema = z.object({
19960
+ toEntity: EntityIdSchema.meta({ ref: "entity" }),
19961
+ kind: EntityLinkKindSchema,
19962
+ via: z.string().trim().min(1).max(255).optional(),
19963
+ label: LabelSchema.optional()
20366
19964
  });
20367
- var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {
20368
- products: []
20369
- };
20370
- var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]);
20371
- var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]);
19965
+ var EntitySchema = z.object({
19966
+ id: EntityIdSchema,
19967
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
19968
+ order: z.number(),
19969
+ label: LabelSchema,
19970
+ description: DescriptionSchema.optional(),
19971
+ ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
19972
+ table: z.string().trim().min(1).max(255).optional(),
19973
+ rowSchema: ModelIdSchema.optional(),
19974
+ stateCatalogId: ModelIdSchema.optional(),
19975
+ links: z.array(EntityLinkSchema).optional()
19976
+ });
19977
+ var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
19978
+ message: "Each entity entry id must match its map key"
19979
+ }).default({});
19980
+ var ENTITY_ENTRY_INPUTS = [
19981
+ {
19982
+ id: "crm.deal",
19983
+ order: 10,
19984
+ label: "Deal",
19985
+ description: "A CRM opportunity or sales pipeline record.",
19986
+ ownedBySystemId: "sales.crm",
19987
+ table: "crm_deals",
19988
+ stateCatalogId: "crm.pipeline",
19989
+ links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
19990
+ },
19991
+ {
19992
+ id: "crm.contact",
19993
+ order: 20,
19994
+ label: "CRM Contact",
19995
+ description: "A person associated with a CRM relationship or deal.",
19996
+ ownedBySystemId: "sales.crm",
19997
+ table: "crm_contacts"
19998
+ },
19999
+ {
20000
+ id: "leadgen.list",
20001
+ order: 30,
20002
+ label: "Lead List",
20003
+ description: "A prospecting list that groups companies and contacts for acquisition workflows.",
20004
+ ownedBySystemId: "sales.lead-gen",
20005
+ table: "acq_lists",
20006
+ links: [
20007
+ { toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
20008
+ { toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
20009
+ ]
20010
+ },
20011
+ {
20012
+ id: "leadgen.company",
20013
+ order: 40,
20014
+ label: "Lead Company",
20015
+ description: "A company record sourced, enriched, and qualified during prospecting.",
20016
+ ownedBySystemId: "sales.lead-gen",
20017
+ table: "acq_list_companies",
20018
+ stateCatalogId: "lead-gen.company",
20019
+ links: [
20020
+ { toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
20021
+ { toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
20022
+ ]
20023
+ },
20024
+ {
20025
+ id: "leadgen.contact",
20026
+ order: 50,
20027
+ label: "Lead Contact",
20028
+ description: "A prospect contact discovered or enriched during lead generation.",
20029
+ ownedBySystemId: "sales.lead-gen",
20030
+ table: "acq_list_members",
20031
+ stateCatalogId: "lead-gen.contact",
20032
+ links: [
20033
+ { toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
20034
+ { toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
20035
+ ]
20036
+ },
20037
+ {
20038
+ id: "delivery.project",
20039
+ order: 60,
20040
+ label: "Project",
20041
+ description: "A client delivery project.",
20042
+ ownedBySystemId: "projects",
20043
+ table: "projects",
20044
+ links: [
20045
+ { toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
20046
+ { toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
20047
+ ]
20048
+ },
20049
+ {
20050
+ id: "delivery.milestone",
20051
+ order: 70,
20052
+ label: "Milestone",
20053
+ description: "A delivery checkpoint within a project.",
20054
+ ownedBySystemId: "projects",
20055
+ table: "project_milestones",
20056
+ links: [
20057
+ { toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
20058
+ { toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
20059
+ ]
20060
+ },
20061
+ {
20062
+ id: "delivery.task",
20063
+ order: 80,
20064
+ label: "Task",
20065
+ description: "A delivery task that can move through the task status catalog.",
20066
+ ownedBySystemId: "projects",
20067
+ table: "project_tasks",
20068
+ stateCatalogId: "delivery.task",
20069
+ links: [
20070
+ { toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
20071
+ { toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
20072
+ ]
20073
+ }
20074
+ ];
20075
+ var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
20076
+ ENTITY_ENTRY_INPUTS.map((entity) => {
20077
+ const parsed = EntitySchema.parse(entity);
20078
+ return [parsed.id, parsed];
20079
+ })
20080
+ );
20081
+
20082
+ // src/organization-model/domains/actions.ts
20083
+ 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");
20084
+ z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
20085
+ var ActionIdSchema = ModelIdSchema;
20086
+ var ActionScopeSchema = z.union([
20087
+ z.literal("global"),
20088
+ z.object({
20089
+ domain: ModelIdSchema
20090
+ })
20091
+ ]);
20092
+ var ActionRefSchema = z.object({
20093
+ actionId: ActionIdSchema.meta({ ref: "action" }),
20094
+ intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
20095
+ });
20096
+ var SlashCommandInvocationSchema = z.object({
20097
+ kind: z.literal("slash-command"),
20098
+ command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
20099
+ toolFactory: ModelIdSchema.optional()
20100
+ });
20101
+ var McpToolInvocationSchema = z.object({
20102
+ kind: z.literal("mcp-tool"),
20103
+ server: ModelIdSchema,
20104
+ name: ModelIdSchema
20105
+ });
20106
+ var ApiEndpointInvocationSchema = z.object({
20107
+ kind: z.literal("api-endpoint"),
20108
+ method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
20109
+ path: z.string().trim().startsWith("/").max(500),
20110
+ requestSchema: ModelIdSchema.optional(),
20111
+ responseSchema: ModelIdSchema.optional()
20112
+ });
20113
+ var ScriptExecutionInvocationSchema = z.object({
20114
+ kind: z.literal("script-execution"),
20115
+ resourceId: ActionResourceIdSchema
20116
+ });
20117
+ var ActionInvocationSchema = z.discriminatedUnion("kind", [
20118
+ SlashCommandInvocationSchema,
20119
+ McpToolInvocationSchema,
20120
+ ApiEndpointInvocationSchema,
20121
+ ScriptExecutionInvocationSchema
20122
+ ]);
20123
+ var ActionSchema = z.object({
20124
+ id: ActionIdSchema,
20125
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
20126
+ order: z.number(),
20127
+ label: LabelSchema,
20128
+ description: DescriptionSchema.optional(),
20129
+ scope: ActionScopeSchema.default("global"),
20130
+ resourceId: ActionResourceIdSchema.optional(),
20131
+ affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
20132
+ invocations: z.array(ActionInvocationSchema).default([]),
20133
+ knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
20134
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
20135
+ });
20136
+ var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
20137
+ message: "Each action entry id must match its map key"
20138
+ }).default({});
20139
+ var LEAD_GEN_ACTION_ENTRY_INPUTS = [
20140
+ {
20141
+ id: "lead-gen.company.source",
20142
+ order: 10,
20143
+ label: "Source companies",
20144
+ description: "Import source companies from a list provider.",
20145
+ scope: { domain: "sales" },
20146
+ resourceId: "lgn-import-workflow",
20147
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/source" }]
20148
+ },
20149
+ {
20150
+ id: "lead-gen.company.apollo-import",
20151
+ order: 20,
20152
+ label: "Import from Apollo",
20153
+ description: "Pull companies and seed contact data from an Apollo search or list.",
20154
+ scope: { domain: "sales" },
20155
+ resourceId: "lgn-01c-apollo-import-workflow",
20156
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apollo-import" }]
20157
+ },
20158
+ {
20159
+ id: "lead-gen.contact.discover",
20160
+ order: 30,
20161
+ label: "Discover contact emails",
20162
+ description: "Find email addresses for contacts at qualified companies.",
20163
+ scope: { domain: "sales" },
20164
+ resourceId: "lgn-04-email-discovery-workflow",
20165
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/discover" }]
20166
+ },
20167
+ {
20168
+ id: "lead-gen.contact.verify-email",
20169
+ order: 40,
20170
+ label: "Verify emails",
20171
+ description: "Check email deliverability before outreach.",
20172
+ scope: { domain: "sales" },
20173
+ resourceId: "lgn-05-email-verification-workflow",
20174
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/verify-email" }]
20175
+ },
20176
+ {
20177
+ id: "lead-gen.company.apify-crawl",
20178
+ order: 50,
20179
+ label: "Crawl websites",
20180
+ description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
20181
+ scope: { domain: "sales" },
20182
+ resourceId: "lgn-02a-apify-website-crawl-workflow",
20183
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apify-crawl" }]
20184
+ },
20185
+ {
20186
+ id: "lead-gen.company.website-extract",
20187
+ order: 60,
20188
+ label: "Extract website signals",
20189
+ description: "Scrape and analyze company websites for qualification signals.",
20190
+ scope: { domain: "sales" },
20191
+ resourceId: "lgn-02-website-extract-workflow",
20192
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/website-extract" }]
20193
+ },
20194
+ {
20195
+ id: "lead-gen.company.qualify",
20196
+ order: 70,
20197
+ label: "Qualify companies",
20198
+ description: "Score and filter companies against the ICP rubric.",
20199
+ scope: { domain: "sales" },
20200
+ resourceId: "lgn-03-company-qualification-workflow",
20201
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/qualify" }]
20202
+ },
20203
+ {
20204
+ id: "lead-gen.company.dtc-subscription-qualify",
20205
+ order: 80,
20206
+ label: "Qualify DTC subscription fit",
20207
+ description: "Classify subscription potential and consumable-product fit for DTC brands.",
20208
+ scope: { domain: "sales" },
20209
+ resourceId: "lgn-03b-dtc-subscription-score-workflow",
20210
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/dtc-subscription-qualify" }]
20211
+ },
20212
+ {
20213
+ id: "lead-gen.contact.apollo-decision-maker-enrich",
20214
+ order: 90,
20215
+ label: "Enrich decision-makers",
20216
+ description: "Find and enrich qualified contacts at qualified companies via Apollo.",
20217
+ scope: { domain: "sales" },
20218
+ resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow",
20219
+ invocations: [
20220
+ { kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/apollo-decision-maker-enrich" }
20221
+ ]
20222
+ },
20223
+ {
20224
+ id: "lead-gen.contact.personalize",
20225
+ order: 100,
20226
+ label: "Personalize outreach",
20227
+ description: "Generate personalized opening lines for each contact.",
20228
+ scope: { domain: "sales" },
20229
+ resourceId: "ist-personalization-workflow",
20230
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/personalize" }]
20231
+ },
20232
+ {
20233
+ id: "lead-gen.review.outreach-ready",
20234
+ order: 110,
20235
+ label: "Upload to outreach",
20236
+ description: "Upload approved contacts to the outreach sequence after QC review.",
20237
+ scope: { domain: "sales" },
20238
+ resourceId: "ist-upload-contacts-workflow",
20239
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/review/outreach-ready" }]
20240
+ },
20241
+ {
20242
+ id: "lead-gen.export.list",
20243
+ order: 120,
20244
+ label: "Export lead list",
20245
+ description: "Export approved leads as a downloadable lead list.",
20246
+ scope: { domain: "sales" },
20247
+ resourceId: "lgn-06-export-list-workflow",
20248
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/export/list" }]
20249
+ },
20250
+ {
20251
+ id: "lead-gen.company.cleanup",
20252
+ order: 130,
20253
+ label: "Clean up companies",
20254
+ description: "Remove disqualified or duplicate companies from the list.",
20255
+ scope: { domain: "sales" },
20256
+ resourceId: "lgn-company-cleanup-workflow",
20257
+ invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
20258
+ }
20259
+ ];
20260
+ var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
20261
+ LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
20262
+ const parsed = ActionSchema.parse(action);
20263
+ return [parsed.id, parsed];
20264
+ })
20265
+ );
20266
+ var DEFAULT_ORGANIZATION_MODEL_ACTIONS = LEAD_GEN_ACTION_ENTRIES;
20267
+
20268
+ // src/organization-model/domains/systems.ts
20269
+ var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
20270
+ var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
20271
+ var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
20372
20272
  var SystemIdSchema = ModelIdSchema;
20273
+ var SystemPathSchema = z.string().trim().min(1).regex(
20274
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
20275
+ 'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
20276
+ );
20277
+ var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
20278
+ var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
20279
+ /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
20280
+ "Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)"
20281
+ );
20282
+ var SystemUiSchema = z.object({
20283
+ path: PathSchema,
20284
+ surfaces: ReferenceIdsSchema,
20285
+ icon: IconNameSchema.optional(),
20286
+ order: z.number().int().optional()
20287
+ });
20373
20288
  var SystemEntrySchema = z.object({
20374
- /** Stable tenant-defined system id (e.g. "sys.lead-gen"). */
20289
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
20375
20290
  id: SystemIdSchema,
20376
- /** Human-readable system title shown in governance and operations UI. */
20377
- title: LabelSchema,
20291
+ /** Human-readable system label shown in UI, governance, and operations surfaces. */
20292
+ label: LabelSchema.optional(),
20293
+ /** @deprecated Use label. Accepted for pre-consolidation System declarations. */
20294
+ title: LabelSchema.optional(),
20378
20295
  /** One-paragraph purpose statement for the bounded context. */
20379
- description: DescriptionSchema,
20296
+ description: DescriptionSchema.optional(),
20380
20297
  /** Closed system shape enum; catalog values remain tenant-defined. */
20381
- kind: SystemKindSchema,
20298
+ kind: SystemKindSchema.optional(),
20299
+ /** Optional self-reference for System hierarchy. */
20300
+ parentSystemId: SystemIdSchema.optional(),
20301
+ /** Optional UI presence. Systems without UI omit this. */
20302
+ ui: SystemUiSchema.optional(),
20303
+ /** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
20304
+ lifecycle: SystemLifecycleSchema.optional(),
20382
20305
  /** Optional role responsible for this system. */
20383
- responsibleRoleId: ModelIdSchema.optional(),
20306
+ responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
20384
20307
  /** Optional knowledge nodes that govern this system. */
20385
- governedByKnowledge: ReferenceIdsSchema,
20308
+ governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
20309
+ /** Optional actions this system exposes or consumes. */
20310
+ actions: z.array(ActionRefSchema).optional(),
20311
+ /** Optional operational policies that apply to this system. */
20312
+ policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
20386
20313
  /** Optional goals this system contributes to. */
20387
- drivesGoals: ReferenceIdsSchema,
20388
- status: SystemStatusSchema
20389
- });
20390
- var SystemsDomainSchema = z.object({
20391
- systems: z.array(SystemEntrySchema).default([])
20314
+ drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
20315
+ /** @deprecated Use lifecycle. Accepted for one publish cycle. */
20316
+ status: SystemStatusSchema.optional(),
20317
+ /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
20318
+ path: PathSchema.optional(),
20319
+ /** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
20320
+ icon: IconNameSchema.optional(),
20321
+ /** @deprecated Feature color token, retained for one-cycle compatibility. */
20322
+ color: ColorTokenSchema.optional(),
20323
+ /** @deprecated UI placement hint, retained for one-cycle compatibility. */
20324
+ uiPosition: UiPositionSchema.optional(),
20325
+ /** @deprecated Use lifecycle. */
20326
+ enabled: z.boolean().optional(),
20327
+ /** @deprecated Use lifecycle: "beta". */
20328
+ devOnly: z.boolean().optional(),
20329
+ requiresAdmin: z.boolean().optional(),
20330
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
20331
+ order: z.number(),
20332
+ /**
20333
+ * System-scoped operational data, co-located with the owning system.
20334
+ * Per L1, L3, L13: keyed by local NodeId (the key is the local id; qualified
20335
+ * id is `<system-path>:<local-id>`, computed by graph projection).
20336
+ * Per L14: every ContentNode carries both `kind` and `type`.
20337
+ * Per D2: unregistered (kind, type) pairs parse successfully.
20338
+ */
20339
+ content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
20340
+ /**
20341
+ * Recursive child systems, authored via nesting (per L11).
20342
+ * The key is the local system id; the full path is computed by joining
20343
+ * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
20344
+ * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
20345
+ * position-derived paths. Both still exist on this schema for backward compat.
20346
+ */
20347
+ subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
20348
+ }).refine((system) => system.label !== void 0 || system.title !== void 0, {
20349
+ path: ["label"],
20350
+ message: "System must provide label or title"
20351
+ }).transform((system) => {
20352
+ if (system.status === void 0) return system;
20353
+ console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
20354
+ return system.lifecycle === void 0 ? { ...system, lifecycle: system.status } : system;
20392
20355
  });
20393
- var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {
20394
- systems: []
20395
- };
20356
+ var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
20357
+ message: "Each system entry id must match its map key"
20358
+ }).default({});
20359
+ var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
20396
20360
 
20397
20361
  // src/organization-model/domains/resources.ts
20398
- z.enum(["workflow", "agent", "integration"]);
20399
- var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]);
20400
- var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "system"]);
20362
+ z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
20363
+ var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
20364
+ var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
20365
+ var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
20401
20366
  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");
20367
+ var EventIdSchema = z.string().trim().min(1).max(300).regex(
20368
+ /^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
20369
+ "Event IDs must use <owner-id>:<event-key>"
20370
+ );
20371
+ var EventKeySchema = ModelIdSchema;
20372
+ var EventEmissionDescriptorSchema = z.object({
20373
+ eventKey: EventKeySchema,
20374
+ label: z.string().trim().min(1).max(120),
20375
+ payloadSchema: ModelIdSchema.optional(),
20376
+ lifecycle: SystemLifecycleSchema.optional()
20377
+ });
20378
+ EventEmissionDescriptorSchema.extend({
20379
+ id: EventIdSchema,
20380
+ ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
20381
+ ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
20382
+ });
20402
20383
  var ResourceEntryBaseSchema = z.object({
20403
20384
  /** Canonical resource id; runtime resourceId derives from this value. */
20404
20385
  id: ResourceIdSchema,
20405
- /** Required single System membership. */
20406
- systemId: SystemIdSchema,
20386
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
20387
+ order: z.number().default(0),
20388
+ /** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
20389
+ systemPath: SystemPathSchema.meta({ ref: "system" }),
20407
20390
  /** Optional role responsible for maintaining this resource. */
20408
- ownerRoleId: ModelIdSchema.optional(),
20391
+ ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
20409
20392
  status: ResourceGovernanceStatusSchema
20410
20393
  });
20411
20394
  var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
20412
20395
  kind: z.literal("workflow"),
20413
- /** Mirrors WorkflowConfig.capabilityKey when the runtime workflow has one. */
20414
- capabilityKey: z.string().trim().min(1).max(255).optional()
20396
+ /** Mirrors WorkflowConfig.actionKey when the runtime workflow has one. */
20397
+ actionKey: z.string().trim().min(1).max(255).optional(),
20398
+ emits: z.array(EventEmissionDescriptorSchema).optional()
20415
20399
  });
20416
20400
  var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
20417
20401
  kind: z.literal("agent"),
20418
20402
  /** Mirrors code-side AgentConfig.kind. */
20419
20403
  agentKind: AgentKindSchema,
20420
20404
  /** Role this agent embodies, if any. */
20421
- actsAsRoleId: ModelIdSchema.optional(),
20405
+ actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
20422
20406
  /** Mirrors AgentConfig.sessionCapable. */
20423
- sessionCapable: z.boolean()
20407
+ sessionCapable: z.boolean(),
20408
+ /** Broad/composite callable entry points orchestrated by this agent. */
20409
+ invocations: z.array(ActionInvocationSchema).default([]),
20410
+ emits: z.array(EventEmissionDescriptorSchema).optional()
20424
20411
  });
20425
20412
  var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
20426
20413
  kind: z.literal("integration"),
20427
20414
  provider: z.string().trim().min(1).max(100)
20428
20415
  });
20416
+ var ScriptResourceSourceSchema = z.union([
20417
+ z.string().trim().min(1).max(5e4),
20418
+ z.object({
20419
+ file: z.string().trim().min(1).max(500)
20420
+ })
20421
+ ]);
20422
+ var ScriptResourceEntrySchema = ResourceEntryBaseSchema.extend({
20423
+ kind: z.literal("script"),
20424
+ language: ScriptResourceLanguageSchema,
20425
+ source: ScriptResourceSourceSchema
20426
+ });
20429
20427
  var ResourceEntrySchema = z.discriminatedUnion("kind", [
20430
20428
  WorkflowResourceEntrySchema,
20431
20429
  AgentResourceEntrySchema,
20432
- IntegrationResourceEntrySchema
20430
+ IntegrationResourceEntrySchema,
20431
+ ScriptResourceEntrySchema
20433
20432
  ]);
20434
- var ResourcesDomainSchema = z.object({
20435
- entries: z.array(ResourceEntrySchema).default([])
20436
- });
20437
- var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {
20438
- entries: []
20439
- };
20433
+ var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
20434
+ message: "Each resource entry id must match its map key"
20435
+ }).default({});
20436
+ var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
20440
20437
 
20441
20438
  // src/organization-model/domains/roles.ts
20442
20439
  var RoleIdSchema = ModelIdSchema;
@@ -20446,7 +20443,7 @@ var HumanRoleHolderSchema = z.object({
20446
20443
  });
20447
20444
  var AgentRoleHolderSchema = z.object({
20448
20445
  kind: z.literal("agent"),
20449
- agentId: ResourceIdSchema
20446
+ agentId: ResourceIdSchema.meta({ ref: "resource" })
20450
20447
  });
20451
20448
  var TeamRoleHolderSchema = z.object({
20452
20449
  kind: z.literal("team"),
@@ -20461,6 +20458,8 @@ var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min
20461
20458
  var RoleSchema = z.object({
20462
20459
  /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
20463
20460
  id: RoleIdSchema,
20461
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
20462
+ order: z.number(),
20464
20463
  /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
20465
20464
  title: z.string().trim().min(1).max(200),
20466
20465
  /**
@@ -20473,7 +20472,7 @@ var RoleSchema = z.object({
20473
20472
  * Optional: ID of another role this role reports to.
20474
20473
  * When present, must reference another `roles[].id` in the same organization.
20475
20474
  */
20476
- reportsToId: RoleIdSchema.optional(),
20475
+ reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
20477
20476
  /**
20478
20477
  * Optional: human, agent, or team holder currently filling this role.
20479
20478
  * Agent holders reference OM Resource IDs and are validated at the model level.
@@ -20483,14 +20482,12 @@ var RoleSchema = z.object({
20483
20482
  * Optional Systems this role is accountable for.
20484
20483
  * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
20485
20484
  */
20486
- responsibleFor: z.array(SystemIdSchema).optional()
20487
- });
20488
- var RolesDomainSchema = z.object({
20489
- roles: z.array(RoleSchema).default([])
20485
+ responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
20490
20486
  });
20491
- var DEFAULT_ORGANIZATION_MODEL_ROLES = {
20492
- roles: []
20493
- };
20487
+ var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
20488
+ message: "Each role entry id must match its map key"
20489
+ }).default({});
20490
+ var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
20494
20491
  var KeyResultSchema = z.object({
20495
20492
  /** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
20496
20493
  id: z.string().trim().min(1).max(100),
@@ -20514,6 +20511,8 @@ var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
20514
20511
  var ObjectiveSchema = z.object({
20515
20512
  /** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
20516
20513
  id: z.string().trim().min(1).max(100),
20514
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
20515
+ order: z.number(),
20517
20516
  /** Plain-language description of what the organization wants to achieve. */
20518
20517
  description: z.string().trim().min(1).max(1e3),
20519
20518
  /**
@@ -20533,180 +20532,63 @@ var ObjectiveSchema = z.object({
20533
20532
  */
20534
20533
  keyResults: z.array(KeyResultSchema).default([])
20535
20534
  });
20536
- var GoalsDomainSchema = z.object({
20537
- objectives: z.array(ObjectiveSchema).default([])
20538
- });
20539
- var DEFAULT_ORGANIZATION_MODEL_GOALS = {
20540
- objectives: []
20541
- };
20542
- var OperationSemanticClassSchema = z.enum(["queue", "executions", "sessions", "notifications", "schedules"]);
20543
- var OperationEntrySchema = z.object({
20544
- id: z.string().trim().min(1).max(100),
20545
- label: z.string().trim().min(1).max(120),
20546
- semanticClass: OperationSemanticClassSchema,
20547
- /** Optional reference to the feature that owns this runtime entity. */
20548
- featureId: z.string().trim().min(1).max(100).optional(),
20549
- /**
20550
- * Optional pointer to the status semanticClass values that apply to this
20551
- * entity — ties operations back to the statuses domain for vibe rendering.
20552
- */
20553
- supportedStatusSemanticClass: z.array(z.string().trim().min(1).max(80)).optional()
20554
- });
20555
- var OperationsDomainSchema = z.object({
20556
- entries: z.array(OperationEntrySchema).default([])
20535
+ var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
20536
+ message: "Each objective entry id must match its map key"
20537
+ }).default({});
20538
+ var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
20539
+ var KnowledgeTargetKindSchema = z.enum([
20540
+ "system",
20541
+ "resource",
20542
+ "knowledge",
20543
+ "stage",
20544
+ "action",
20545
+ "role",
20546
+ "goal",
20547
+ "customer-segment",
20548
+ "offering",
20549
+ // D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
20550
+ "content-node"
20551
+ ]).meta({ label: "Target kind" });
20552
+ var KnowledgeTargetRefSchema = z.object({
20553
+ kind: KnowledgeTargetKindSchema,
20554
+ // D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'
20555
+ // which contains a colon separator and cannot satisfy ModelIdSchema. Use a permissive
20556
+ // string schema here; business-logic validation of target existence is done in
20557
+ // OrganizationModelSchema.superRefine (knowledgeTargetExists).
20558
+ id: z.string().trim().min(1).max(300)
20557
20559
  });
20558
- var DEFAULT_ORGANIZATION_MODEL_OPERATIONS = {
20559
- entries: [
20560
- // --- queue (HITL command queue) ---
20561
- {
20562
- id: "operations.queue",
20563
- label: "HITL Queue",
20564
- semanticClass: "queue",
20565
- featureId: "operations",
20566
- supportedStatusSemanticClass: ["queue"]
20567
- },
20568
- // --- executions (workflow / agent executions) ---
20569
- {
20570
- id: "operations.executions",
20571
- label: "Executions",
20572
- semanticClass: "executions",
20573
- featureId: "operations",
20574
- supportedStatusSemanticClass: ["execution"]
20575
- },
20576
- // --- sessions (agent conversation sessions) ---
20577
- {
20578
- id: "operations.sessions",
20579
- label: "Sessions",
20580
- semanticClass: "sessions",
20581
- featureId: "operations"
20582
- },
20583
- // --- notifications (platform in-app notifications) ---
20584
- {
20585
- id: "operations.notifications",
20586
- label: "Notifications",
20587
- semanticClass: "notifications",
20588
- featureId: "monitoring"
20589
- },
20590
- // --- schedules (task scheduler) ---
20591
- {
20592
- id: "operations.schedules",
20593
- label: "Schedules",
20594
- semanticClass: "schedules",
20595
- featureId: "operations",
20596
- supportedStatusSemanticClass: ["schedule", "schedule.run"]
20597
- }
20598
- ]
20599
- };
20600
- var StatusSemanticClassSchema = z.enum([
20601
- "delivery.task",
20602
- "delivery.project",
20603
- "delivery.milestone",
20604
- "queue",
20605
- "execution",
20606
- "schedule",
20607
- "schedule.run",
20608
- "request"
20609
- ]);
20610
- var StatusEntrySchema = z.object({
20611
- id: z.string().trim().min(1).max(100),
20612
- label: z.string().trim().min(1).max(120),
20613
- semanticClass: StatusSemanticClassSchema,
20614
- category: z.string().trim().min(1).max(80).optional()
20560
+ var LegacyKnowledgeLinkSchema = z.object({
20561
+ nodeId: NodeIdStringSchema
20615
20562
  });
20616
- var StatusesDomainSchema = z.object({
20617
- entries: z.array(StatusEntrySchema).default([])
20563
+ var CanonicalKnowledgeLinkSchema = z.object({
20564
+ target: KnowledgeTargetRefSchema
20618
20565
  });
20619
- var DEFAULT_ORGANIZATION_MODEL_STATUSES = {
20620
- entries: [
20621
- // --- delivery.task (TaskStatus — 9 values) ---
20622
- { id: "delivery.task.planned", label: "Planned", semanticClass: "delivery.task", category: "delivery" },
20623
- { id: "delivery.task.in_progress", label: "In Progress", semanticClass: "delivery.task", category: "delivery" },
20624
- { id: "delivery.task.blocked", label: "Blocked", semanticClass: "delivery.task", category: "delivery" },
20625
- { id: "delivery.task.submitted", label: "Submitted", semanticClass: "delivery.task", category: "delivery" },
20626
- { id: "delivery.task.approved", label: "Approved", semanticClass: "delivery.task", category: "delivery" },
20627
- {
20628
- id: "delivery.task.revision_requested",
20629
- label: "Revision Requested",
20630
- semanticClass: "delivery.task",
20631
- category: "delivery"
20632
- },
20633
- { id: "delivery.task.rejected", label: "Rejected", semanticClass: "delivery.task", category: "delivery" },
20634
- { id: "delivery.task.cancelled", label: "Cancelled", semanticClass: "delivery.task", category: "delivery" },
20635
- { id: "delivery.task.completed", label: "Completed", semanticClass: "delivery.task", category: "delivery" },
20636
- // --- delivery.project (ProjectStatus — 6 values) ---
20637
- { id: "delivery.project.active", label: "Active", semanticClass: "delivery.project", category: "delivery" },
20638
- { id: "delivery.project.on_track", label: "On Track", semanticClass: "delivery.project", category: "delivery" },
20639
- { id: "delivery.project.at_risk", label: "At Risk", semanticClass: "delivery.project", category: "delivery" },
20640
- { id: "delivery.project.blocked", label: "Blocked", semanticClass: "delivery.project", category: "delivery" },
20641
- { id: "delivery.project.paused", label: "Paused", semanticClass: "delivery.project", category: "delivery" },
20642
- { id: "delivery.project.completed", label: "Completed", semanticClass: "delivery.project", category: "delivery" },
20643
- // --- delivery.milestone (MilestoneStatus — 5 values) ---
20644
- {
20645
- id: "delivery.milestone.upcoming",
20646
- label: "Upcoming",
20647
- semanticClass: "delivery.milestone",
20648
- category: "delivery"
20649
- },
20650
- {
20651
- id: "delivery.milestone.in_progress",
20652
- label: "In Progress",
20653
- semanticClass: "delivery.milestone",
20654
- category: "delivery"
20655
- },
20656
- {
20657
- id: "delivery.milestone.blocked",
20658
- label: "Blocked",
20659
- semanticClass: "delivery.milestone",
20660
- category: "delivery"
20661
- },
20662
- { id: "delivery.milestone.overdue", label: "Overdue", semanticClass: "delivery.milestone", category: "delivery" },
20663
- {
20664
- id: "delivery.milestone.completed",
20665
- label: "Completed",
20666
- semanticClass: "delivery.milestone",
20667
- category: "delivery"
20668
- },
20669
- // --- queue (QueueTaskStatus — 5 values, maps hitl/command-queue tasks) ---
20670
- { id: "queue.pending", label: "Pending", semanticClass: "queue", category: "queue" },
20671
- { id: "queue.processing", label: "Processing", semanticClass: "queue", category: "queue" },
20672
- { id: "queue.completed", label: "Completed", semanticClass: "queue", category: "queue" },
20673
- { id: "queue.failed", label: "Failed", semanticClass: "queue", category: "queue" },
20674
- { id: "queue.expired", label: "Expired", semanticClass: "queue", category: "queue" },
20675
- // --- execution (ExecutionStatus — 5 values) ---
20676
- { id: "execution.pending", label: "Pending", semanticClass: "execution", category: "execution" },
20677
- { id: "execution.running", label: "Running", semanticClass: "execution", category: "execution" },
20678
- { id: "execution.completed", label: "Completed", semanticClass: "execution", category: "execution" },
20679
- { id: "execution.failed", label: "Failed", semanticClass: "execution", category: "execution" },
20680
- { id: "execution.warning", label: "Warning", semanticClass: "execution", category: "execution" },
20681
- // --- schedule (schedule status — 4 values) ---
20682
- { id: "schedule.active", label: "Active", semanticClass: "schedule", category: "schedule" },
20683
- { id: "schedule.paused", label: "Paused", semanticClass: "schedule", category: "schedule" },
20684
- { id: "schedule.completed", label: "Completed", semanticClass: "schedule", category: "schedule" },
20685
- { id: "schedule.cancelled", label: "Cancelled", semanticClass: "schedule", category: "schedule" },
20686
- // --- schedule.run (schedule run status — 4 values) ---
20687
- { id: "schedule.run.running", label: "Running", semanticClass: "schedule.run", category: "schedule" },
20688
- { id: "schedule.run.completed", label: "Completed", semanticClass: "schedule.run", category: "schedule" },
20689
- { id: "schedule.run.failed", label: "Failed", semanticClass: "schedule.run", category: "schedule" },
20690
- { id: "schedule.run.cancelled", label: "Cancelled", semanticClass: "schedule.run", category: "schedule" },
20691
- // --- request (RequestStatus — 4 values, maps reported_requests) ---
20692
- { id: "request.open", label: "Open", semanticClass: "request", category: "request" },
20693
- { id: "request.investigating", label: "Investigating", semanticClass: "request", category: "request" },
20694
- { id: "request.resolved", label: "Resolved", semanticClass: "request", category: "request" },
20695
- { id: "request.wont_fix", label: "Won't Fix", semanticClass: "request", category: "request" }
20696
- ]
20697
- };
20698
- var KnowledgeLinkSchema = z.object({
20699
- nodeId: NodeIdStringSchema
20566
+ function nodeIdFromTarget(target) {
20567
+ return `${target.kind}:${target.id}`;
20568
+ }
20569
+ function targetFromNodeId(nodeId) {
20570
+ const [kind, ...idParts] = nodeId.split(":");
20571
+ return {
20572
+ kind: KnowledgeTargetKindSchema.parse(kind),
20573
+ id: idParts.join(":")
20574
+ };
20575
+ }
20576
+ var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
20577
+ const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
20578
+ return {
20579
+ target,
20580
+ nodeId: nodeIdFromTarget(target)
20581
+ };
20700
20582
  });
20701
- var KnowledgeSkillBindingSchema = z.string().trim().min(1).max(120);
20702
- var KnowledgeDomainBindingSchema = z.string().trim().min(1).max(80);
20703
- var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]);
20583
+ var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
20704
20584
  var OrgKnowledgeNodeSchema = z.object({
20705
20585
  id: ModelIdSchema,
20706
20586
  kind: OrgKnowledgeKindSchema,
20707
20587
  title: z.string().trim().min(1).max(200),
20708
20588
  summary: z.string().trim().min(1).max(1e3),
20709
20589
  icon: IconNameSchema.optional(),
20590
+ /** Canonical documentation URL when body content is a local summary. */
20591
+ externalUrl: z.string().trim().url().max(500).optional(),
20710
20592
  /** Raw MDX string. Phase 2 will introduce a structured block format. */
20711
20593
  body: z.string().trim().min(1),
20712
20594
  /**
@@ -20714,28 +20596,142 @@ var OrgKnowledgeNodeSchema = z.object({
20714
20596
  * Each link emits a `governs` edge: knowledge-node -> target node.
20715
20597
  */
20716
20598
  links: z.array(KnowledgeLinkSchema).default([]),
20717
- /** Operator skill or command bindings relevant to this node. */
20718
- skills: z.array(KnowledgeSkillBindingSchema).optional(),
20719
- /** Domain key used to derive fast graph->skill registries. */
20720
- domain: KnowledgeDomainBindingSchema.optional(),
20721
20599
  /** Role identifiers that own this knowledge node. */
20722
- ownerIds: z.array(RoleIdSchema).default([]),
20600
+ ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
20723
20601
  /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
20724
20602
  updatedAt: z.string().trim().min(1).max(50)
20725
20603
  });
20726
- var KnowledgeDomainSchema = z.object({
20727
- nodes: z.array(OrgKnowledgeNodeSchema).default([])
20604
+ var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
20605
+ var PolicyIdSchema = ModelIdSchema;
20606
+ var PolicyApplicabilitySchema = z.object({
20607
+ systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
20608
+ actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
20609
+ resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
20610
+ roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
20611
+ });
20612
+ var PolicyTriggerSchema = z.discriminatedUnion("kind", [
20613
+ z.object({
20614
+ kind: z.literal("event"),
20615
+ eventId: EventIdSchema.meta({ ref: "event" })
20616
+ }),
20617
+ z.object({
20618
+ kind: z.literal("action-invocation"),
20619
+ actionId: ModelIdSchema.meta({ ref: "action" })
20620
+ }),
20621
+ z.object({
20622
+ kind: z.literal("schedule"),
20623
+ cron: z.string().trim().min(1).max(120)
20624
+ }),
20625
+ z.object({
20626
+ kind: z.literal("manual")
20627
+ })
20628
+ ]);
20629
+ var PolicyPredicateSchema = z.discriminatedUnion("kind", [
20630
+ z.object({
20631
+ kind: z.literal("always")
20632
+ }),
20633
+ z.object({
20634
+ kind: z.literal("expression"),
20635
+ expression: z.string().trim().min(1).max(2e3)
20636
+ }),
20637
+ z.object({
20638
+ kind: z.literal("threshold"),
20639
+ metric: ModelIdSchema,
20640
+ operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
20641
+ value: z.number()
20642
+ })
20643
+ ]);
20644
+ var PolicyEffectSchema = z.discriminatedUnion("kind", [
20645
+ z.object({
20646
+ kind: z.literal("require-approval"),
20647
+ roleId: ModelIdSchema.meta({ ref: "role" }).optional()
20648
+ }),
20649
+ z.object({
20650
+ kind: z.literal("invoke-action"),
20651
+ actionId: ModelIdSchema.meta({ ref: "action" })
20652
+ }),
20653
+ z.object({
20654
+ kind: z.literal("notify-role"),
20655
+ roleId: ModelIdSchema.meta({ ref: "role" })
20656
+ }),
20657
+ z.object({
20658
+ kind: z.literal("block")
20659
+ })
20660
+ ]);
20661
+ var PolicySchema = z.object({
20662
+ id: PolicyIdSchema,
20663
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
20664
+ order: z.number(),
20665
+ label: LabelSchema,
20666
+ description: DescriptionSchema.optional(),
20667
+ trigger: PolicyTriggerSchema,
20668
+ predicate: PolicyPredicateSchema.default({ kind: "always" }),
20669
+ actions: z.array(PolicyEffectSchema).min(1),
20670
+ appliesTo: PolicyApplicabilitySchema.default({
20671
+ systemIds: [],
20672
+ actionIds: [],
20673
+ resourceIds: [],
20674
+ roleIds: []
20675
+ }),
20676
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
20728
20677
  });
20678
+ var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
20679
+ message: "Each policy entry id must match its map key"
20680
+ }).default({});
20681
+ var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
20729
20682
 
20730
20683
  // src/organization-model/schema.ts
20684
+ z.enum([
20685
+ "branding",
20686
+ "identity",
20687
+ "customers",
20688
+ "offerings",
20689
+ "roles",
20690
+ "goals",
20691
+ "systems",
20692
+ "resources",
20693
+ "actions",
20694
+ "entities",
20695
+ "policies",
20696
+ "knowledge"
20697
+ ]);
20698
+ var OrganizationModelDomainMetadataSchema = z.object({
20699
+ version: z.literal(1).default(1),
20700
+ lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
20701
+ });
20702
+ var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
20703
+ branding: { version: 1, lastModified: "2026-05-10" },
20704
+ identity: { version: 1, lastModified: "2026-05-10" },
20705
+ customers: { version: 1, lastModified: "2026-05-10" },
20706
+ offerings: { version: 1, lastModified: "2026-05-10" },
20707
+ roles: { version: 1, lastModified: "2026-05-10" },
20708
+ goals: { version: 1, lastModified: "2026-05-10" },
20709
+ systems: { version: 1, lastModified: "2026-05-10" },
20710
+ resources: { version: 1, lastModified: "2026-05-10" },
20711
+ actions: { version: 1, lastModified: "2026-05-10" },
20712
+ entities: { version: 1, lastModified: "2026-05-10" },
20713
+ policies: { version: 1, lastModified: "2026-05-10" },
20714
+ knowledge: { version: 1, lastModified: "2026-05-10" }
20715
+ };
20716
+ var OrganizationModelDomainMetadataByDomainSchema = z.object({
20717
+ branding: OrganizationModelDomainMetadataSchema,
20718
+ identity: OrganizationModelDomainMetadataSchema,
20719
+ customers: OrganizationModelDomainMetadataSchema,
20720
+ offerings: OrganizationModelDomainMetadataSchema,
20721
+ roles: OrganizationModelDomainMetadataSchema,
20722
+ goals: OrganizationModelDomainMetadataSchema,
20723
+ systems: OrganizationModelDomainMetadataSchema,
20724
+ resources: OrganizationModelDomainMetadataSchema,
20725
+ actions: OrganizationModelDomainMetadataSchema,
20726
+ entities: OrganizationModelDomainMetadataSchema,
20727
+ policies: OrganizationModelDomainMetadataSchema,
20728
+ knowledge: OrganizationModelDomainMetadataSchema
20729
+ }).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
20731
20730
  var OrganizationModelSchemaBase = z.object({
20732
20731
  version: z.literal(1).default(1),
20733
- features: z.array(FeatureSchema).default([]),
20732
+ domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
20734
20733
  branding: OrganizationModelBrandingSchema,
20735
- navigation: OrganizationModelNavigationSchema.default({ surfaces: [], groups: [] }),
20736
- sales: OrganizationModelSalesSchema,
20737
- prospecting: OrganizationModelProspectingSchema,
20738
- projects: OrganizationModelProjectsSchema,
20734
+ navigation: OrganizationModelNavigationSchema,
20739
20735
  identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
20740
20736
  customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
20741
20737
  offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
@@ -20743,9 +20739,11 @@ var OrganizationModelSchemaBase = z.object({
20743
20739
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
20744
20740
  systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
20745
20741
  resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
20746
- statuses: StatusesDomainSchema.default({ entries: [] }),
20747
- operations: OperationsDomainSchema.default({ entries: [] }),
20748
- knowledge: KnowledgeDomainSchema.default({ nodes: [] })
20742
+ actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
20743
+ entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
20744
+ policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
20745
+ // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
20746
+ knowledge: KnowledgeDomainSchema.default({})
20749
20747
  });
20750
20748
  function addIssue(ctx, path, message) {
20751
20749
  ctx.addIssue({
@@ -20754,217 +20752,412 @@ function addIssue(ctx, path, message) {
20754
20752
  message
20755
20753
  });
20756
20754
  }
20757
- function collectIds(items, ctx, collectionPath, label) {
20758
- const itemsById = /* @__PURE__ */ new Map();
20759
- items.forEach((item, index2) => {
20760
- if (itemsById.has(item.id)) {
20761
- addIssue(ctx, [...collectionPath, index2, "id"], `${label} id "${item.id}" must be unique`);
20762
- return;
20763
- }
20764
- itemsById.set(item.id, item);
20765
- });
20766
- return itemsById;
20767
- }
20768
- var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
20769
- ["crm", "sales.crm"],
20770
- ["lead-gen", "sales.lead-gen"],
20771
- ["submitted-requests", "monitoring.submitted-requests"]
20772
- ]);
20773
- function hasFeature(featuresById, featureId) {
20774
- return featuresById.has(featureId) || featuresById.has(LEGACY_FEATURE_ALIASES.get(featureId) ?? "");
20755
+ function isLifecycleEnabled(lifecycle, enabled) {
20756
+ if (enabled === false) return false;
20757
+ return lifecycle !== "deprecated" && lifecycle !== "archived";
20775
20758
  }
20776
- function defaultFeaturePathFor(id) {
20759
+ function defaultSystemPathFor(id) {
20777
20760
  return `/${id.replaceAll(".", "/")}`;
20778
20761
  }
20779
20762
  function asRoleHolderArray(heldBy) {
20780
20763
  return Array.isArray(heldBy) ? heldBy : [heldBy];
20781
20764
  }
20782
- var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
20783
- const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
20784
- const featureIdsByEffectivePath = /* @__PURE__ */ new Map();
20785
- model.features.forEach((feature, featureIndex) => {
20786
- const segments = feature.id.split(".");
20787
- if (segments.length > 1) {
20788
- const parentId = segments.slice(0, -1).join(".");
20789
- if (!featuresById.has(parentId)) {
20790
- addIssue(
20791
- ctx,
20792
- ["features", featureIndex, "id"],
20793
- `Feature "${feature.id}" references unknown parent "${parentId}"`
20794
- );
20765
+ function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
20766
+ if (knowledgeKind === "reference") return true;
20767
+ if (knowledgeKind === "playbook") {
20768
+ return ["system", "resource", "stage", "action"].includes(targetKind);
20769
+ }
20770
+ if (knowledgeKind === "strategy") {
20771
+ return ["system", "goal", "offering", "customer-segment"].includes(targetKind);
20772
+ }
20773
+ return false;
20774
+ }
20775
+ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
20776
+ function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
20777
+ const result = [];
20778
+ for (const [key, system] of Object.entries(systems)) {
20779
+ const path = prefix ? `${prefix}.${key}` : key;
20780
+ const currentSchemaPath = [...schemaPath, key];
20781
+ result.push({ path, schemaPath: currentSchemaPath, system });
20782
+ if (system.subsystems !== void 0) {
20783
+ result.push(...collectAllSystems(system.subsystems, path, [...currentSchemaPath, "subsystems"]));
20795
20784
  }
20796
20785
  }
20797
- const hasChildren = model.features.some(
20798
- (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.id !== feature.id
20799
- );
20800
- const contributesRoutePath = feature.path !== void 0 || !hasChildren;
20786
+ return result;
20787
+ }
20788
+ const allSystems = collectAllSystems(model.systems);
20789
+ const systemsById = /* @__PURE__ */ new Map();
20790
+ for (const { path, system } of allSystems) {
20791
+ systemsById.set(path, system);
20792
+ systemsById.set(system.id, system);
20793
+ }
20794
+ const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
20795
+ allSystems.forEach(({ path, schemaPath, system }) => {
20796
+ if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
20797
+ addIssue(
20798
+ ctx,
20799
+ [...schemaPath, "parentSystemId"],
20800
+ `System "${system.id}" references unknown parent "${system.parentSystemId}"`
20801
+ );
20802
+ }
20803
+ const hasChildren = Object.keys(system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
20804
+ const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
20801
20805
  if (contributesRoutePath) {
20802
- const effectivePath = feature.path ?? defaultFeaturePathFor(feature.id);
20803
- const existingFeatureId = featureIdsByEffectivePath.get(effectivePath);
20804
- if (existingFeatureId !== void 0) {
20806
+ const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
20807
+ const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
20808
+ if (existingSystemId !== void 0) {
20805
20809
  addIssue(
20806
20810
  ctx,
20807
- ["features", featureIndex, feature.path === void 0 ? "id" : "path"],
20808
- `Feature "${feature.id}" effective path "${effectivePath}" duplicates feature "${existingFeatureId}"`
20811
+ [...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
20812
+ `System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
20809
20813
  );
20810
20814
  } else {
20811
- featureIdsByEffectivePath.set(effectivePath, feature.id);
20815
+ systemIdsByEffectivePath.set(effectivePath, path);
20812
20816
  }
20813
20817
  }
20814
- if (hasChildren && feature.enabled) {
20815
- const hasEnabledDescendant = model.features.some(
20816
- (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.enabled
20818
+ if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
20819
+ const hasEnabledDescendant = Object.values(system.subsystems ?? {}).some(
20820
+ (candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
20821
+ ) || allSystems.some(
20822
+ (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
20817
20823
  );
20818
20824
  if (!hasEnabledDescendant) {
20819
20825
  addIssue(
20820
20826
  ctx,
20821
- ["features", featureIndex, "enabled"],
20822
- `Feature "${feature.id}" is enabled but has no enabled descendants`
20827
+ [...schemaPath, "lifecycle"],
20828
+ `System "${path}" is active but has no active descendants`
20823
20829
  );
20824
20830
  }
20825
20831
  }
20826
20832
  });
20827
- const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Navigation surface");
20828
- if (model.navigation.defaultSurfaceId !== void 0 && !surfacesById.has(model.navigation.defaultSurfaceId)) {
20829
- addIssue(
20830
- ctx,
20831
- ["navigation", "defaultSurfaceId"],
20832
- `Navigation defaultSurfaceId references unknown surface "${model.navigation.defaultSurfaceId}"`
20833
- );
20833
+ allSystems.forEach(({ schemaPath, system }) => {
20834
+ const visited = /* @__PURE__ */ new Set();
20835
+ let currentParentId = system.parentSystemId;
20836
+ while (currentParentId !== void 0) {
20837
+ if (currentParentId === system.id || visited.has(currentParentId)) {
20838
+ addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
20839
+ return;
20840
+ }
20841
+ visited.add(currentParentId);
20842
+ currentParentId = systemsById.get(currentParentId)?.parentSystemId;
20843
+ }
20844
+ });
20845
+ function normalizeRoutePath(path) {
20846
+ return path.length > 1 ? path.replace(/\/+$/, "") : path;
20847
+ }
20848
+ const sidebarNodeIds = /* @__PURE__ */ new Map();
20849
+ const sidebarSurfacePaths = /* @__PURE__ */ new Map();
20850
+ const sidebarSurfaces = [];
20851
+ function collectSidebarNodes(nodes, schemaPath) {
20852
+ Object.entries(nodes).forEach(([nodeId, node]) => {
20853
+ const nodePath = [...schemaPath, nodeId];
20854
+ const existingNodePath = sidebarNodeIds.get(nodeId);
20855
+ if (existingNodePath !== void 0) {
20856
+ addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
20857
+ } else {
20858
+ sidebarNodeIds.set(nodeId, nodePath);
20859
+ }
20860
+ if (node.type === "group") {
20861
+ collectSidebarNodes(node.children, [...nodePath, "children"]);
20862
+ return;
20863
+ }
20864
+ sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
20865
+ const normalizedPath = normalizeRoutePath(node.path);
20866
+ const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
20867
+ if (existingSurfaceId !== void 0) {
20868
+ addIssue(
20869
+ ctx,
20870
+ [...nodePath, "path"],
20871
+ `Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
20872
+ );
20873
+ } else {
20874
+ sidebarSurfacePaths.set(normalizedPath, nodeId);
20875
+ }
20876
+ node.targets?.systems?.forEach((systemId, systemIndex) => {
20877
+ if (!systemsById.has(systemId)) {
20878
+ addIssue(
20879
+ ctx,
20880
+ [...nodePath, "targets", "systems", systemIndex],
20881
+ `Sidebar surface "${nodeId}" references unknown system "${systemId}"`
20882
+ );
20883
+ }
20884
+ });
20885
+ });
20834
20886
  }
20835
- model.navigation.groups.forEach((group, groupIndex) => {
20836
- group.surfaceIds.forEach((surfaceId, surfaceIndex) => {
20837
- if (!surfacesById.has(surfaceId)) {
20887
+ collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
20888
+ collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
20889
+ const segmentsById = new Map(Object.entries(model.customers));
20890
+ Object.values(model.offerings).forEach((product) => {
20891
+ product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
20892
+ if (!segmentsById.has(segmentId)) {
20838
20893
  addIssue(
20839
20894
  ctx,
20840
- ["navigation", "groups", groupIndex, "surfaceIds", surfaceIndex],
20841
- `Navigation group "${group.id}" references unknown surface "${surfaceId}"`
20895
+ ["offerings", product.id, "targetSegmentIds", segmentIndex],
20896
+ `Product "${product.id}" references unknown customer segment "${segmentId}"`
20842
20897
  );
20843
20898
  }
20844
20899
  });
20900
+ if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
20901
+ addIssue(
20902
+ ctx,
20903
+ ["offerings", product.id, "deliveryFeatureId"],
20904
+ `Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
20905
+ );
20906
+ }
20845
20907
  });
20846
- model.navigation.surfaces.forEach((surface, surfaceIndex) => {
20847
- if (surface.featureId !== void 0 && !hasFeature(featuresById, surface.featureId)) {
20908
+ Object.values(model.goals).forEach((objective) => {
20909
+ if (objective.periodEnd <= objective.periodStart) {
20848
20910
  addIssue(
20849
20911
  ctx,
20850
- ["navigation", "surfaces", surfaceIndex, "featureId"],
20851
- `Navigation surface "${surface.id}" references unknown feature "${surface.featureId}"`
20912
+ ["goals", objective.id, "periodEnd"],
20913
+ `Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
20852
20914
  );
20853
20915
  }
20854
- surface.featureIds.forEach((featureId, featureIndex) => {
20855
- if (!hasFeature(featuresById, featureId)) {
20916
+ });
20917
+ const goalsById = new Map(Object.entries(model.goals));
20918
+ const knowledgeById = new Map(Object.entries(model.knowledge));
20919
+ const actionsById = new Map(Object.entries(model.actions));
20920
+ const entitiesById = new Map(Object.entries(model.entities));
20921
+ const policiesById = new Map(Object.entries(model.policies));
20922
+ sidebarSurfaces.forEach(({ id, node, path }) => {
20923
+ node.targets?.entities?.forEach((entityId, entityIndex) => {
20924
+ if (!entitiesById.has(entityId)) {
20856
20925
  addIssue(
20857
20926
  ctx,
20858
- ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
20859
- `Navigation surface "${surface.id}" references unknown feature "${featureId}"`
20927
+ [...path, "targets", "entities", entityIndex],
20928
+ `Sidebar surface "${id}" references unknown entity "${entityId}"`
20860
20929
  );
20861
20930
  }
20862
20931
  });
20863
- });
20864
- const segmentsById = new Map(model.customers.segments.map((seg) => [seg.id, seg]));
20865
- model.offerings.products.forEach((product, productIndex) => {
20866
- product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
20867
- if (!segmentsById.has(segmentId)) {
20932
+ node.targets?.actions?.forEach((actionId, actionIndex) => {
20933
+ if (!actionsById.has(actionId)) {
20868
20934
  addIssue(
20869
20935
  ctx,
20870
- ["offerings", "products", productIndex, "targetSegmentIds", segmentIndex],
20871
- `Product "${product.id}" references unknown customer segment "${segmentId}"`
20936
+ [...path, "targets", "actions", actionIndex],
20937
+ `Sidebar surface "${id}" references unknown action "${actionId}"`
20872
20938
  );
20873
20939
  }
20874
20940
  });
20875
- if (product.deliveryFeatureId !== void 0 && !hasFeature(featuresById, product.deliveryFeatureId)) {
20876
- addIssue(
20877
- ctx,
20878
- ["offerings", "products", productIndex, "deliveryFeatureId"],
20879
- `Product "${product.id}" references unknown delivery feature "${product.deliveryFeatureId}"`
20880
- );
20881
- }
20882
20941
  });
20883
- model.goals.objectives.forEach((objective, index2) => {
20884
- if (objective.periodEnd <= objective.periodStart) {
20942
+ Object.values(model.entities).forEach((entity) => {
20943
+ if (!systemsById.has(entity.ownedBySystemId)) {
20885
20944
  addIssue(
20886
20945
  ctx,
20887
- ["goals", "objectives", index2, "periodEnd"],
20888
- `Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
20946
+ ["entities", entity.id, "ownedBySystemId"],
20947
+ `Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
20889
20948
  );
20890
20949
  }
20950
+ entity.links?.forEach((link, linkIndex) => {
20951
+ if (!entitiesById.has(link.toEntity)) {
20952
+ addIssue(
20953
+ ctx,
20954
+ ["entities", entity.id, "links", linkIndex, "toEntity"],
20955
+ `Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
20956
+ );
20957
+ }
20958
+ });
20891
20959
  });
20892
- const goalsById = new Map(model.goals.objectives.map((objective) => [objective.id, objective]));
20893
- const knowledgeById = new Map(model.knowledge.nodes.map((node) => [node.id, node]));
20894
- const rolesById = new Map(model.roles.roles.map((role) => [role.id, role]));
20895
- model.roles.roles.forEach((role, roleIndex) => {
20960
+ const rolesById = new Map(Object.entries(model.roles));
20961
+ Object.values(model.roles).forEach((role) => {
20896
20962
  if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
20897
20963
  addIssue(
20898
20964
  ctx,
20899
- ["roles", "roles", roleIndex, "reportsToId"],
20965
+ ["roles", role.id, "reportsToId"],
20900
20966
  `Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
20901
20967
  );
20902
20968
  }
20903
20969
  });
20904
- const systemsById = collectIds(model.systems.systems, ctx, ["systems", "systems"], "System");
20905
- model.roles.roles.forEach((role, roleIndex) => {
20970
+ Object.values(model.roles).forEach((role) => {
20971
+ const visited = /* @__PURE__ */ new Set();
20972
+ let currentReportsToId = role.reportsToId;
20973
+ while (currentReportsToId !== void 0) {
20974
+ if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
20975
+ addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
20976
+ return;
20977
+ }
20978
+ visited.add(currentReportsToId);
20979
+ currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
20980
+ }
20981
+ });
20982
+ Object.values(model.roles).forEach((role) => {
20906
20983
  role.responsibleFor?.forEach((systemId, systemIndex) => {
20907
20984
  if (!systemsById.has(systemId)) {
20908
20985
  addIssue(
20909
20986
  ctx,
20910
- ["roles", "roles", roleIndex, "responsibleFor", systemIndex],
20987
+ ["roles", role.id, "responsibleFor", systemIndex],
20911
20988
  `Role "${role.id}" references unknown responsibleFor system "${systemId}"`
20912
20989
  );
20913
20990
  }
20914
20991
  });
20915
20992
  });
20916
- model.systems.systems.forEach((system, systemIndex) => {
20993
+ allSystems.forEach(({ schemaPath, system }) => {
20917
20994
  if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
20918
20995
  addIssue(
20919
20996
  ctx,
20920
- ["systems", "systems", systemIndex, "responsibleRoleId"],
20997
+ [...schemaPath, "responsibleRoleId"],
20921
20998
  `System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
20922
20999
  );
20923
21000
  }
20924
- system.governedByKnowledge.forEach((nodeId, nodeIndex) => {
21001
+ system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
20925
21002
  if (!knowledgeById.has(nodeId)) {
20926
21003
  addIssue(
20927
21004
  ctx,
20928
- ["systems", "systems", systemIndex, "governedByKnowledge", nodeIndex],
21005
+ [...schemaPath, "governedByKnowledge", nodeIndex],
20929
21006
  `System "${system.id}" references unknown knowledge node "${nodeId}"`
20930
21007
  );
20931
21008
  }
20932
21009
  });
20933
- system.drivesGoals.forEach((goalId, goalIndex) => {
21010
+ system.drivesGoals?.forEach((goalId, goalIndex) => {
20934
21011
  if (!goalsById.has(goalId)) {
20935
21012
  addIssue(
20936
21013
  ctx,
20937
- ["systems", "systems", systemIndex, "drivesGoals", goalIndex],
21014
+ [...schemaPath, "drivesGoals", goalIndex],
20938
21015
  `System "${system.id}" references unknown goal "${goalId}"`
20939
21016
  );
20940
21017
  }
20941
21018
  });
21019
+ system.actions?.forEach((actionRef, actionIndex) => {
21020
+ if (!actionsById.has(actionRef.actionId)) {
21021
+ addIssue(
21022
+ ctx,
21023
+ [...schemaPath, "actions", actionIndex, "actionId"],
21024
+ `System "${system.id}" references unknown action "${actionRef.actionId}"`
21025
+ );
21026
+ }
21027
+ });
21028
+ system.policies?.forEach((policyId, policyIndex) => {
21029
+ if (!policiesById.has(policyId)) {
21030
+ addIssue(
21031
+ ctx,
21032
+ [...schemaPath, "policies", policyIndex],
21033
+ `System "${system.id}" references unknown policy "${policyId}"`
21034
+ );
21035
+ }
21036
+ });
21037
+ });
21038
+ Object.values(model.actions).forEach((action) => {
21039
+ action.affects?.forEach((entityId, entityIndex) => {
21040
+ if (!entitiesById.has(entityId)) {
21041
+ addIssue(
21042
+ ctx,
21043
+ ["actions", action.id, "affects", entityIndex],
21044
+ `Action "${action.id}" affects unknown entity "${entityId}"`
21045
+ );
21046
+ }
21047
+ });
21048
+ });
21049
+ const resourcesById = new Map(Object.entries(model.resources));
21050
+ sidebarSurfaces.forEach(({ id, node, path }) => {
21051
+ node.targets?.resources?.forEach((resourceId, resourceIndex) => {
21052
+ if (!resourcesById.has(resourceId)) {
21053
+ addIssue(
21054
+ ctx,
21055
+ [...path, "targets", "resources", resourceIndex],
21056
+ `Sidebar surface "${id}" references unknown resource "${resourceId}"`
21057
+ );
21058
+ }
21059
+ });
21060
+ });
21061
+ const stageIds = /* @__PURE__ */ new Set();
21062
+ const actionIds = new Set(Object.keys(model.actions));
21063
+ const offeringsById = new Map(Object.entries(model.offerings));
21064
+ Object.values(model.policies).forEach((policy) => {
21065
+ policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
21066
+ if (!systemsById.has(systemId)) {
21067
+ addIssue(
21068
+ ctx,
21069
+ ["policies", policy.id, "appliesTo", "systemIds", systemIndex],
21070
+ `Policy "${policy.id}" applies to unknown system "${systemId}"`
21071
+ );
21072
+ }
21073
+ });
21074
+ policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
21075
+ if (!actionsById.has(actionId)) {
21076
+ addIssue(
21077
+ ctx,
21078
+ ["policies", policy.id, "appliesTo", "actionIds", actionIndex],
21079
+ `Policy "${policy.id}" applies to unknown action "${actionId}"`
21080
+ );
21081
+ }
21082
+ });
21083
+ policy.actions.forEach((action, actionIndex) => {
21084
+ if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
21085
+ addIssue(
21086
+ ctx,
21087
+ ["policies", policy.id, "actions", actionIndex, "actionId"],
21088
+ `Policy "${policy.id}" invokes unknown action "${action.actionId}"`
21089
+ );
21090
+ }
21091
+ if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
21092
+ addIssue(
21093
+ ctx,
21094
+ ["policies", policy.id, "actions", actionIndex, "roleId"],
21095
+ `Policy "${policy.id}" references unknown role "${action.roleId}"`
21096
+ );
21097
+ }
21098
+ });
21099
+ if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
21100
+ addIssue(
21101
+ ctx,
21102
+ ["policies", policy.id, "trigger", "actionId"],
21103
+ `Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
21104
+ );
21105
+ }
21106
+ });
21107
+ function knowledgeTargetExists(kind, id) {
21108
+ if (kind === "system") return systemsById.has(id);
21109
+ if (kind === "resource") return resourcesById.has(id);
21110
+ if (kind === "knowledge") return knowledgeById.has(id);
21111
+ if (kind === "stage") return stageIds.has(id);
21112
+ if (kind === "action") return actionIds.has(id);
21113
+ if (kind === "role") return rolesById.has(id);
21114
+ if (kind === "goal") return goalsById.has(id);
21115
+ if (kind === "customer-segment") return segmentsById.has(id);
21116
+ if (kind === "offering") return offeringsById.has(id);
21117
+ return false;
21118
+ }
21119
+ Object.entries(model.knowledge).forEach(([nodeId, node]) => {
21120
+ node.links.forEach((link, linkIndex) => {
21121
+ if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
21122
+ addIssue(
21123
+ ctx,
21124
+ ["knowledge", nodeId, "links", linkIndex, "target"],
21125
+ `Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
21126
+ );
21127
+ }
21128
+ if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
21129
+ addIssue(
21130
+ ctx,
21131
+ ["knowledge", nodeId, "links", linkIndex, "target", "kind"],
21132
+ `Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
21133
+ );
21134
+ }
21135
+ });
20942
21136
  });
20943
- const resourcesById = collectIds(model.resources.entries, ctx, ["resources", "entries"], "Resource");
20944
- model.resources.entries.forEach((resource, resourceIndex) => {
20945
- if (!systemsById.has(resource.systemId)) {
21137
+ Object.values(model.resources).forEach((resource) => {
21138
+ if (!systemsById.has(resource.systemPath)) {
20946
21139
  addIssue(
20947
21140
  ctx,
20948
- ["resources", "entries", resourceIndex, "systemId"],
20949
- `Resource "${resource.id}" references unknown systemId "${resource.systemId}"`
21141
+ ["resources", resource.id, "systemPath"],
21142
+ `Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
20950
21143
  );
20951
21144
  }
20952
21145
  if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
20953
21146
  addIssue(
20954
21147
  ctx,
20955
- ["resources", "entries", resourceIndex, "ownerRoleId"],
21148
+ ["resources", resource.id, "ownerRoleId"],
20956
21149
  `Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
20957
21150
  );
20958
21151
  }
20959
21152
  if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
20960
21153
  addIssue(
20961
21154
  ctx,
20962
- ["resources", "entries", resourceIndex, "actsAsRoleId"],
21155
+ ["resources", resource.id, "actsAsRoleId"],
20963
21156
  `Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
20964
21157
  );
20965
21158
  }
20966
21159
  });
20967
- model.roles.roles.forEach((role, roleIndex) => {
21160
+ Object.values(model.roles).forEach((role) => {
20968
21161
  if (role.heldBy === void 0) return;
20969
21162
  asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
20970
21163
  if (holder.kind !== "agent") return;
@@ -20972,7 +21165,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20972
21165
  if (resource === void 0) {
20973
21166
  addIssue(
20974
21167
  ctx,
20975
- ["roles", "roles", roleIndex, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
21168
+ ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
20976
21169
  `Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
20977
21170
  );
20978
21171
  return;
@@ -20980,364 +21173,824 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20980
21173
  if (resource.kind !== "agent") {
20981
21174
  addIssue(
20982
21175
  ctx,
20983
- ["roles", "roles", roleIndex, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
21176
+ ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
20984
21177
  `Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
20985
21178
  );
20986
21179
  }
20987
21180
  });
20988
21181
  });
20989
- model.knowledge.nodes.forEach((node, nodeIndex) => {
21182
+ Object.entries(model.knowledge).forEach(([nodeId, node]) => {
20990
21183
  node.ownerIds.forEach((roleId, ownerIndex) => {
20991
21184
  if (!rolesById.has(roleId)) {
20992
21185
  addIssue(
20993
21186
  ctx,
20994
- ["knowledge", "nodes", nodeIndex, "ownerIds", ownerIndex],
21187
+ ["knowledge", nodeId, "ownerIds", ownerIndex],
20995
21188
  `Knowledge node "${node.id}" references unknown owner role "${roleId}"`
20996
21189
  );
20997
21190
  }
20998
21191
  });
20999
21192
  });
21193
+ function validateSystemContent(system, systemPath) {
21194
+ const content = system.content;
21195
+ if (content === void 0 || Object.keys(content).length === 0) {
21196
+ if (system.subsystems !== void 0) {
21197
+ Object.entries(system.subsystems).forEach(([childKey, child]) => {
21198
+ validateSystemContent(child, [...systemPath, "subsystems", childKey]);
21199
+ });
21200
+ }
21201
+ return;
21202
+ }
21203
+ Object.entries(content).forEach(([localId, node]) => {
21204
+ if (node.parentContentId !== void 0 && !(node.parentContentId in content)) {
21205
+ addIssue(
21206
+ ctx,
21207
+ [...systemPath, "content", localId, "parentContentId"],
21208
+ `Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
21209
+ );
21210
+ }
21211
+ });
21212
+ Object.entries(content).forEach(([localId, node]) => {
21213
+ const visited = /* @__PURE__ */ new Set();
21214
+ let currentId = node.parentContentId;
21215
+ while (currentId !== void 0) {
21216
+ if (currentId === localId || visited.has(currentId)) {
21217
+ addIssue(
21218
+ ctx,
21219
+ [...systemPath, "content", localId, "parentContentId"],
21220
+ `Content node "${localId}" has a parentContentId cycle`
21221
+ );
21222
+ break;
21223
+ }
21224
+ visited.add(currentId);
21225
+ currentId = content[currentId]?.parentContentId;
21226
+ }
21227
+ });
21228
+ Object.entries(content).forEach(([localId, node]) => {
21229
+ const childDef = lookupContentType(node.kind, node.type);
21230
+ if (childDef !== void 0 && node.data !== void 0) {
21231
+ const result = childDef.payloadSchema.safeParse(node.data);
21232
+ if (!result.success) {
21233
+ addIssue(
21234
+ ctx,
21235
+ [...systemPath, "content", localId, "data"],
21236
+ `Content node "${localId}" (${node.kind}:${node.type}) data failed payload validation: ${result.error.message}`
21237
+ );
21238
+ }
21239
+ }
21240
+ if (node.parentContentId !== void 0 && childDef !== void 0) {
21241
+ const parentNode = content[node.parentContentId];
21242
+ if (parentNode !== void 0) {
21243
+ const parentDef = lookupContentType(parentNode.kind, parentNode.type);
21244
+ if (parentDef !== void 0 && childDef.kind !== parentDef.kind) {
21245
+ addIssue(
21246
+ ctx,
21247
+ [...systemPath, "content", localId, "parentContentId"],
21248
+ `Content node "${localId}" kind "${childDef.kind}" cannot parent under "${node.parentContentId}" kind "${parentDef.kind}": parentContentId must be same-meta-kind (per L19)`
21249
+ );
21250
+ }
21251
+ }
21252
+ }
21253
+ });
21254
+ if (system.subsystems !== void 0) {
21255
+ Object.entries(system.subsystems).forEach(([childKey, child]) => {
21256
+ validateSystemContent(child, [...systemPath, "subsystems", childKey]);
21257
+ });
21258
+ }
21259
+ }
21260
+ Object.entries(model.systems).forEach(([systemKey, system]) => {
21261
+ validateSystemContent(system, ["systems", systemKey]);
21262
+ });
21000
21263
  });
21001
21264
 
21002
21265
  // src/organization-model/defaults.ts
21003
- var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {
21004
- nodes: []
21266
+ var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
21267
+ var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = DEFAULT_ORGANIZATION_MODEL_ENTITIES;
21268
+ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
21269
+ sidebar: {
21270
+ primary: {
21271
+ dashboard: {
21272
+ type: "surface",
21273
+ label: "Dashboard",
21274
+ path: "/",
21275
+ surfaceType: "dashboard",
21276
+ icon: "feature.dashboard",
21277
+ order: 10,
21278
+ targets: { systems: ["dashboard"] }
21279
+ },
21280
+ business: {
21281
+ type: "group",
21282
+ label: "Business",
21283
+ icon: "feature.business",
21284
+ order: 20,
21285
+ children: {
21286
+ sales: {
21287
+ type: "surface",
21288
+ label: "Sales",
21289
+ path: "/sales",
21290
+ surfaceType: "page",
21291
+ icon: "feature.sales",
21292
+ order: 10,
21293
+ targets: { systems: ["sales"] }
21294
+ },
21295
+ clients: {
21296
+ type: "surface",
21297
+ label: "Clients",
21298
+ path: "/clients",
21299
+ surfaceType: "list",
21300
+ icon: "feature.projects",
21301
+ order: 20,
21302
+ targets: { systems: ["clients"] }
21303
+ },
21304
+ projects: {
21305
+ type: "surface",
21306
+ label: "Projects",
21307
+ path: "/projects",
21308
+ surfaceType: "page",
21309
+ icon: "feature.projects",
21310
+ order: 30,
21311
+ targets: { systems: ["projects"] }
21312
+ }
21313
+ }
21314
+ },
21315
+ operations: {
21316
+ type: "group",
21317
+ label: "Operations",
21318
+ icon: "feature.operations",
21319
+ order: 30,
21320
+ children: {
21321
+ "operations-overview": {
21322
+ type: "surface",
21323
+ label: "Overview",
21324
+ path: "/operations",
21325
+ surfaceType: "page",
21326
+ order: 10,
21327
+ targets: { systems: ["operations.overview"] }
21328
+ },
21329
+ "operations-systems": {
21330
+ type: "surface",
21331
+ label: "Systems",
21332
+ path: "/operations/systems",
21333
+ surfaceType: "page",
21334
+ order: 20,
21335
+ targets: { systems: ["operations"] }
21336
+ },
21337
+ "operations-resources": {
21338
+ type: "surface",
21339
+ label: "Resources",
21340
+ path: "/operations/resources",
21341
+ surfaceType: "list",
21342
+ order: 30,
21343
+ targets: { systems: ["operations.resources"] }
21344
+ },
21345
+ "operations-command-queue": {
21346
+ type: "surface",
21347
+ label: "Command Queue",
21348
+ path: "/operations/command-queue",
21349
+ surfaceType: "list",
21350
+ order: 40,
21351
+ targets: { systems: ["operations.command-queue"] }
21352
+ },
21353
+ "operations-task-scheduler": {
21354
+ type: "surface",
21355
+ label: "Task Scheduler",
21356
+ path: "/operations/task-scheduler",
21357
+ surfaceType: "list",
21358
+ order: 50,
21359
+ targets: { systems: ["operations.task-scheduler"] }
21360
+ }
21361
+ }
21362
+ },
21363
+ monitoring: {
21364
+ type: "group",
21365
+ label: "Monitoring",
21366
+ icon: "feature.monitoring",
21367
+ order: 40,
21368
+ children: {
21369
+ "monitoring-overview": {
21370
+ type: "surface",
21371
+ label: "Overview",
21372
+ path: "/monitoring",
21373
+ surfaceType: "page",
21374
+ order: 10,
21375
+ targets: { systems: ["monitoring"] }
21376
+ },
21377
+ "monitoring-calendar": {
21378
+ type: "surface",
21379
+ label: "Calendar",
21380
+ path: "/monitoring/calendar",
21381
+ surfaceType: "page",
21382
+ order: 20,
21383
+ targets: { systems: ["monitoring.calendar"] }
21384
+ },
21385
+ "monitoring-activity-log": {
21386
+ type: "surface",
21387
+ label: "Activity Log",
21388
+ path: "/monitoring/activity-log",
21389
+ surfaceType: "list",
21390
+ order: 30,
21391
+ targets: { systems: ["monitoring.activity-log"] }
21392
+ },
21393
+ "monitoring-execution-logs": {
21394
+ type: "surface",
21395
+ label: "Execution Logs",
21396
+ path: "/monitoring/execution-logs",
21397
+ surfaceType: "list",
21398
+ order: 40,
21399
+ targets: { systems: ["monitoring.execution-logs"] }
21400
+ },
21401
+ "monitoring-execution-health": {
21402
+ type: "surface",
21403
+ label: "Execution Health",
21404
+ path: "/monitoring/execution-health",
21405
+ surfaceType: "dashboard",
21406
+ order: 50,
21407
+ targets: { systems: ["monitoring.execution-health"] }
21408
+ },
21409
+ "monitoring-notifications": {
21410
+ type: "surface",
21411
+ label: "Notifications",
21412
+ path: "/monitoring/notifications",
21413
+ surfaceType: "list",
21414
+ order: 60,
21415
+ targets: { systems: ["monitoring.notifications"] }
21416
+ },
21417
+ "monitoring-requests": {
21418
+ type: "surface",
21419
+ label: "Requests",
21420
+ path: "/monitoring/requests",
21421
+ surfaceType: "list",
21422
+ order: 70,
21423
+ targets: { systems: ["monitoring.submitted-requests"] }
21424
+ }
21425
+ }
21426
+ },
21427
+ knowledge: {
21428
+ type: "group",
21429
+ label: "Knowledge",
21430
+ icon: "feature.knowledge",
21431
+ order: 50,
21432
+ children: {
21433
+ "knowledge-base": {
21434
+ type: "surface",
21435
+ label: "Knowledge Base",
21436
+ path: "/knowledge",
21437
+ surfaceType: "page",
21438
+ order: 10,
21439
+ targets: { systems: ["knowledge.base"] }
21440
+ },
21441
+ "knowledge-command-view": {
21442
+ type: "surface",
21443
+ label: "Command View",
21444
+ path: "/knowledge/command-view",
21445
+ surfaceType: "graph",
21446
+ order: 20,
21447
+ targets: { systems: ["knowledge.command-view"] },
21448
+ devOnly: true
21449
+ }
21450
+ }
21451
+ }
21452
+ },
21453
+ bottom: {
21454
+ settings: {
21455
+ type: "group",
21456
+ label: "Settings",
21457
+ icon: "feature.settings",
21458
+ order: 10,
21459
+ children: {
21460
+ "settings-account": {
21461
+ type: "surface",
21462
+ label: "Account",
21463
+ path: "/settings/account",
21464
+ surfaceType: "settings",
21465
+ order: 10,
21466
+ targets: { systems: ["settings.account"] }
21467
+ },
21468
+ "settings-appearance": {
21469
+ type: "surface",
21470
+ label: "Appearance",
21471
+ path: "/settings/appearance",
21472
+ surfaceType: "settings",
21473
+ order: 20,
21474
+ targets: { systems: ["settings.appearance"] }
21475
+ },
21476
+ "settings-roles": {
21477
+ type: "surface",
21478
+ label: "My Roles",
21479
+ path: "/settings/roles",
21480
+ surfaceType: "settings",
21481
+ order: 30,
21482
+ targets: { systems: ["settings.roles"] }
21483
+ },
21484
+ "settings-organization": {
21485
+ type: "surface",
21486
+ label: "Organization",
21487
+ path: "/settings/organization",
21488
+ surfaceType: "settings",
21489
+ order: 40,
21490
+ targets: { systems: ["settings.organization"] }
21491
+ },
21492
+ "settings-credentials": {
21493
+ type: "surface",
21494
+ label: "Credentials",
21495
+ path: "/settings/credentials",
21496
+ surfaceType: "settings",
21497
+ order: 50,
21498
+ targets: { systems: ["settings.credentials"] }
21499
+ },
21500
+ "settings-api-keys": {
21501
+ type: "surface",
21502
+ label: "API Keys",
21503
+ path: "/settings/api-keys",
21504
+ surfaceType: "settings",
21505
+ order: 60,
21506
+ targets: { systems: ["settings.api-keys"] }
21507
+ },
21508
+ "settings-webhooks": {
21509
+ type: "surface",
21510
+ label: "Webhooks",
21511
+ path: "/settings/webhooks",
21512
+ surfaceType: "settings",
21513
+ order: 70,
21514
+ targets: { systems: ["settings.webhooks"] }
21515
+ },
21516
+ "settings-deployments": {
21517
+ type: "surface",
21518
+ label: "Deployments",
21519
+ path: "/settings/deployments",
21520
+ surfaceType: "settings",
21521
+ order: 80,
21522
+ targets: { systems: ["settings.deployments"] }
21523
+ }
21524
+ }
21525
+ },
21526
+ admin: {
21527
+ type: "group",
21528
+ label: "Admin",
21529
+ icon: "feature.admin",
21530
+ order: 20,
21531
+ children: {
21532
+ "admin-dashboard": {
21533
+ type: "surface",
21534
+ label: "Dashboard",
21535
+ path: "/admin/dashboard",
21536
+ surfaceType: "dashboard",
21537
+ order: 10,
21538
+ targets: { systems: ["admin"] },
21539
+ requiresAdmin: true
21540
+ },
21541
+ "admin-system-health": {
21542
+ type: "surface",
21543
+ label: "System Health",
21544
+ path: "/admin/system-health",
21545
+ surfaceType: "dashboard",
21546
+ order: 20,
21547
+ targets: { systems: ["admin.system-health"] },
21548
+ requiresAdmin: true
21549
+ },
21550
+ "admin-organizations": {
21551
+ type: "surface",
21552
+ label: "Organizations",
21553
+ path: "/admin/organizations",
21554
+ surfaceType: "list",
21555
+ order: 30,
21556
+ targets: { systems: ["admin.organizations"] },
21557
+ requiresAdmin: true
21558
+ },
21559
+ "admin-users": {
21560
+ type: "surface",
21561
+ label: "Users",
21562
+ path: "/admin/users",
21563
+ surfaceType: "list",
21564
+ order: 40,
21565
+ targets: { systems: ["admin.users"] },
21566
+ requiresAdmin: true
21567
+ },
21568
+ "admin-design-showcase": {
21569
+ type: "surface",
21570
+ label: "Design Showcase",
21571
+ path: "/admin/design-showcase",
21572
+ surfaceType: "page",
21573
+ order: 50,
21574
+ targets: { systems: ["admin.design-showcase"] },
21575
+ requiresAdmin: true
21576
+ },
21577
+ "admin-debug": {
21578
+ type: "surface",
21579
+ label: "Debug",
21580
+ path: "/admin/debug",
21581
+ surfaceType: "page",
21582
+ order: 60,
21583
+ targets: { systems: ["admin.debug"] },
21584
+ requiresAdmin: true
21585
+ }
21586
+ }
21587
+ }
21588
+ }
21589
+ }
21005
21590
  };
21006
21591
  var DEFAULT_ORGANIZATION_MODEL = {
21007
21592
  version: 1,
21008
- features: [
21009
- {
21593
+ domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
21594
+ branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
21595
+ navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
21596
+ identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
21597
+ customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
21598
+ offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
21599
+ roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
21600
+ goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
21601
+ systems: {
21602
+ dashboard: {
21010
21603
  id: "dashboard",
21604
+ order: 10,
21011
21605
  label: "Dashboard",
21012
21606
  enabled: true,
21607
+ lifecycle: "active",
21013
21608
  path: "/",
21014
- icon: "feature.dashboard",
21015
- uiPosition: "sidebar-primary"
21016
- },
21017
- {
21018
- id: "identity",
21019
- label: "Identity",
21020
- description: "Company identity, positioning, and market context",
21021
- enabled: true,
21022
- color: "indigo"
21609
+ icon: "feature.dashboard"
21023
21610
  },
21024
- {
21611
+ platform: {
21025
21612
  id: "platform",
21613
+ order: 30,
21026
21614
  label: "Platform",
21027
21615
  description: "Elevasis platform architecture, capabilities, and implementation patterns",
21028
21616
  enabled: true,
21617
+ lifecycle: "active",
21029
21618
  color: "cyan",
21030
21619
  icon: "feature.platform"
21031
21620
  },
21032
- {
21621
+ finance: {
21033
21622
  id: "finance",
21623
+ order: 40,
21034
21624
  label: "Finance",
21035
21625
  description: "Finance operations, accounting, billing, reconciliation, and tax prep",
21036
21626
  enabled: true,
21627
+ lifecycle: "active",
21037
21628
  color: "green",
21038
21629
  icon: "feature.finance"
21039
21630
  },
21040
- {
21041
- id: "business",
21042
- label: "Business",
21043
- description: "Revenue, client relationships, and project delivery",
21044
- enabled: true,
21045
- color: "blue",
21046
- icon: "feature.business",
21047
- uiPosition: "sidebar-primary"
21048
- },
21049
- {
21631
+ sales: {
21050
21632
  id: "sales",
21633
+ order: 60,
21051
21634
  label: "Sales",
21052
21635
  description: "Revenue workflows and customer acquisition",
21053
21636
  enabled: true,
21637
+ lifecycle: "active",
21054
21638
  color: "blue",
21055
21639
  icon: "feature.sales",
21056
21640
  path: "/sales"
21057
21641
  },
21058
- {
21642
+ "sales.crm": {
21059
21643
  id: "sales.crm",
21644
+ order: 70,
21060
21645
  label: "CRM",
21061
21646
  description: "Relationship pipeline and deal management",
21062
21647
  enabled: true,
21648
+ lifecycle: "active",
21063
21649
  color: "blue",
21064
21650
  icon: "feature.crm",
21065
21651
  path: "/crm"
21066
21652
  },
21067
- {
21653
+ "sales.lead-gen": {
21068
21654
  id: "sales.lead-gen",
21655
+ order: 80,
21069
21656
  label: "Lead Gen",
21070
21657
  description: "Prospecting, qualification, and outreach preparation",
21071
21658
  enabled: true,
21659
+ lifecycle: "active",
21660
+ actions: Object.values(DEFAULT_ORGANIZATION_MODEL_ACTIONS).map((action) => ({
21661
+ actionId: action.id,
21662
+ intent: "exposes"
21663
+ })),
21072
21664
  color: "cyan",
21073
21665
  icon: "feature.lead-gen",
21074
21666
  path: "/lead-gen"
21075
21667
  },
21076
- {
21668
+ projects: {
21077
21669
  id: "projects",
21670
+ order: 90,
21078
21671
  label: "Projects",
21079
21672
  description: "Projects, milestones, and client work execution",
21080
21673
  enabled: true,
21674
+ lifecycle: "active",
21081
21675
  color: "orange",
21082
21676
  icon: "feature.projects",
21083
21677
  path: "/projects"
21084
21678
  },
21085
- {
21679
+ clients: {
21086
21680
  id: "clients",
21681
+ order: 100,
21087
21682
  label: "Clients",
21088
21683
  description: "Client relationships, accounts, and business context",
21089
21684
  enabled: true,
21685
+ lifecycle: "active",
21090
21686
  color: "orange",
21091
21687
  icon: "feature.projects",
21092
- path: "/business/clients"
21688
+ path: "/clients"
21093
21689
  },
21094
- {
21690
+ operations: {
21095
21691
  id: "operations",
21692
+ order: 110,
21096
21693
  label: "Operations",
21097
21694
  description: "Operational resources, topology, and orchestration visibility",
21098
21695
  enabled: true,
21696
+ lifecycle: "active",
21099
21697
  color: "violet",
21100
- icon: "feature.operations",
21101
- uiPosition: "sidebar-primary"
21698
+ icon: "feature.operations"
21102
21699
  },
21103
- {
21700
+ "knowledge.command-view": {
21104
21701
  id: "knowledge.command-view",
21702
+ order: 120,
21105
21703
  label: "Command View",
21106
21704
  enabled: true,
21705
+ lifecycle: "active",
21107
21706
  path: "/knowledge/command-view",
21108
21707
  devOnly: true
21109
21708
  },
21110
- {
21709
+ "operations.overview": {
21111
21710
  id: "operations.overview",
21711
+ order: 130,
21112
21712
  label: "Overview",
21113
21713
  enabled: true,
21714
+ lifecycle: "active",
21114
21715
  path: "/operations"
21115
21716
  },
21116
- {
21717
+ "operations.resources": {
21117
21718
  id: "operations.resources",
21719
+ order: 140,
21118
21720
  label: "Resources",
21119
21721
  enabled: true,
21722
+ lifecycle: "active",
21120
21723
  path: "/operations/resources"
21121
21724
  },
21122
- {
21725
+ "operations.command-queue": {
21123
21726
  id: "operations.command-queue",
21727
+ order: 150,
21124
21728
  label: "Command Queue",
21125
21729
  enabled: true,
21730
+ lifecycle: "active",
21126
21731
  path: "/operations/command-queue"
21127
21732
  },
21128
- {
21733
+ "operations.sessions": {
21129
21734
  id: "operations.sessions",
21735
+ order: 160,
21130
21736
  label: "Sessions",
21131
21737
  enabled: false,
21738
+ lifecycle: "deprecated",
21132
21739
  path: "/operations/sessions"
21133
21740
  },
21134
- {
21741
+ "operations.task-scheduler": {
21135
21742
  id: "operations.task-scheduler",
21743
+ order: 170,
21136
21744
  label: "Task Scheduler",
21137
21745
  enabled: true,
21746
+ lifecycle: "active",
21138
21747
  path: "/operations/task-scheduler"
21139
21748
  },
21140
- {
21749
+ monitoring: {
21141
21750
  id: "monitoring",
21751
+ order: 180,
21142
21752
  label: "Monitoring",
21143
21753
  enabled: true,
21144
- uiPosition: "sidebar-primary"
21754
+ lifecycle: "active"
21145
21755
  },
21146
- {
21756
+ "monitoring.calendar": {
21147
21757
  id: "monitoring.calendar",
21758
+ order: 190,
21148
21759
  label: "Calendar",
21149
21760
  description: "Google Calendar events and agenda views",
21150
21761
  enabled: true,
21762
+ lifecycle: "active",
21151
21763
  path: "/monitoring/calendar",
21152
21764
  icon: "feature.calendar"
21153
21765
  },
21154
- {
21766
+ "monitoring.activity-log": {
21155
21767
  id: "monitoring.activity-log",
21768
+ order: 200,
21156
21769
  label: "Activity Log",
21157
21770
  enabled: true,
21771
+ lifecycle: "active",
21158
21772
  path: "/monitoring/activity-log"
21159
21773
  },
21160
- {
21774
+ "monitoring.execution-logs": {
21161
21775
  id: "monitoring.execution-logs",
21776
+ order: 210,
21162
21777
  label: "Execution Logs",
21163
21778
  enabled: true,
21779
+ lifecycle: "active",
21164
21780
  path: "/monitoring/execution-logs"
21165
21781
  },
21166
- {
21782
+ "monitoring.execution-health": {
21167
21783
  id: "monitoring.execution-health",
21784
+ order: 220,
21168
21785
  label: "Execution Health",
21169
21786
  enabled: true,
21787
+ lifecycle: "active",
21170
21788
  path: "/monitoring/execution-health"
21171
21789
  },
21172
- {
21790
+ "monitoring.cost-analytics": {
21173
21791
  id: "monitoring.cost-analytics",
21792
+ order: 230,
21174
21793
  label: "Cost Analytics",
21175
21794
  enabled: false,
21795
+ lifecycle: "deprecated",
21176
21796
  path: "/monitoring/cost-analytics"
21177
21797
  },
21178
- {
21798
+ "monitoring.notifications": {
21179
21799
  id: "monitoring.notifications",
21800
+ order: 240,
21180
21801
  label: "Notifications",
21181
21802
  enabled: true,
21803
+ lifecycle: "active",
21182
21804
  path: "/monitoring/notifications"
21183
21805
  },
21184
- {
21806
+ "monitoring.submitted-requests": {
21185
21807
  id: "monitoring.submitted-requests",
21808
+ order: 250,
21186
21809
  label: "Submitted Requests",
21187
21810
  enabled: true,
21811
+ lifecycle: "active",
21188
21812
  path: "/monitoring/requests"
21189
21813
  },
21190
- {
21814
+ settings: {
21191
21815
  id: "settings",
21816
+ order: 260,
21192
21817
  label: "Settings",
21193
21818
  enabled: true,
21194
- icon: "feature.settings",
21195
- uiPosition: "sidebar-bottom"
21819
+ lifecycle: "active",
21820
+ icon: "feature.settings"
21196
21821
  },
21197
- {
21822
+ "settings.account": {
21198
21823
  id: "settings.account",
21824
+ order: 270,
21199
21825
  label: "Account",
21200
21826
  enabled: true,
21827
+ lifecycle: "active",
21201
21828
  path: "/settings/account"
21202
21829
  },
21203
- {
21830
+ "settings.appearance": {
21204
21831
  id: "settings.appearance",
21832
+ order: 280,
21205
21833
  label: "Appearance",
21206
21834
  enabled: true,
21835
+ lifecycle: "active",
21207
21836
  path: "/settings/appearance"
21208
21837
  },
21209
- {
21838
+ "settings.roles": {
21210
21839
  id: "settings.roles",
21840
+ order: 290,
21211
21841
  label: "My Roles",
21212
21842
  enabled: true,
21843
+ lifecycle: "active",
21213
21844
  path: "/settings/roles"
21214
21845
  },
21215
- {
21846
+ "settings.organization": {
21216
21847
  id: "settings.organization",
21848
+ order: 300,
21217
21849
  label: "Organization",
21218
21850
  enabled: true,
21851
+ lifecycle: "active",
21219
21852
  path: "/settings/organization"
21220
21853
  },
21221
- {
21854
+ "settings.credentials": {
21222
21855
  id: "settings.credentials",
21856
+ order: 310,
21223
21857
  label: "Credentials",
21224
21858
  enabled: true,
21859
+ lifecycle: "active",
21225
21860
  path: "/settings/credentials"
21226
21861
  },
21227
- {
21862
+ "settings.api-keys": {
21228
21863
  id: "settings.api-keys",
21864
+ order: 320,
21229
21865
  label: "API Keys",
21230
21866
  enabled: true,
21867
+ lifecycle: "active",
21231
21868
  path: "/settings/api-keys"
21232
21869
  },
21233
- {
21870
+ "settings.webhooks": {
21234
21871
  id: "settings.webhooks",
21872
+ order: 330,
21235
21873
  label: "Webhooks",
21236
21874
  enabled: true,
21875
+ lifecycle: "active",
21237
21876
  path: "/settings/webhooks"
21238
21877
  },
21239
- {
21878
+ "settings.deployments": {
21240
21879
  id: "settings.deployments",
21880
+ order: 340,
21241
21881
  label: "Deployments",
21242
21882
  enabled: true,
21883
+ lifecycle: "active",
21243
21884
  path: "/settings/deployments"
21244
21885
  },
21245
- {
21886
+ admin: {
21246
21887
  id: "admin",
21888
+ order: 350,
21247
21889
  label: "Admin",
21248
21890
  enabled: true,
21891
+ lifecycle: "active",
21249
21892
  path: "/admin",
21250
21893
  icon: "feature.admin",
21251
- uiPosition: "sidebar-bottom",
21252
21894
  requiresAdmin: true
21253
21895
  },
21254
- {
21896
+ "admin.system-health": {
21255
21897
  id: "admin.system-health",
21898
+ order: 360,
21256
21899
  label: "System Health",
21257
21900
  enabled: true,
21901
+ lifecycle: "active",
21258
21902
  path: "/admin/system-health"
21259
21903
  },
21260
- {
21904
+ "admin.organizations": {
21261
21905
  id: "admin.organizations",
21906
+ order: 370,
21262
21907
  label: "Organizations",
21263
21908
  enabled: true,
21909
+ lifecycle: "active",
21264
21910
  path: "/admin/organizations"
21265
21911
  },
21266
- {
21912
+ "admin.users": {
21267
21913
  id: "admin.users",
21914
+ order: 380,
21268
21915
  label: "Users",
21269
21916
  enabled: true,
21917
+ lifecycle: "active",
21270
21918
  path: "/admin/users"
21271
21919
  },
21272
- {
21920
+ "admin.design-showcase": {
21273
21921
  id: "admin.design-showcase",
21922
+ order: 390,
21274
21923
  label: "Design Showcase",
21275
21924
  enabled: true,
21925
+ lifecycle: "active",
21276
21926
  path: "/admin/design-showcase"
21277
21927
  },
21278
- {
21928
+ "admin.debug": {
21279
21929
  id: "admin.debug",
21930
+ order: 400,
21280
21931
  label: "Debug",
21281
21932
  enabled: true,
21933
+ lifecycle: "active",
21282
21934
  path: "/admin/debug"
21283
21935
  },
21284
- {
21936
+ archive: {
21285
21937
  id: "archive",
21938
+ order: 410,
21286
21939
  label: "Archive",
21287
21940
  enabled: true,
21941
+ lifecycle: "active",
21288
21942
  path: "/archive",
21289
21943
  icon: "feature.archive",
21290
- uiPosition: "sidebar-bottom",
21291
21944
  devOnly: true
21292
21945
  },
21293
- {
21946
+ "archive.agent-chat": {
21294
21947
  id: "archive.agent-chat",
21948
+ order: 420,
21295
21949
  label: "Agent Chat",
21296
21950
  enabled: true,
21951
+ lifecycle: "active",
21297
21952
  path: "/archive/agent-chat"
21298
21953
  },
21299
- {
21954
+ "archive.execution-runner": {
21300
21955
  id: "archive.execution-runner",
21956
+ order: 430,
21301
21957
  label: "Execution Runner",
21302
21958
  enabled: true,
21959
+ lifecycle: "active",
21303
21960
  path: "/archive/execution-runner"
21304
21961
  },
21305
- {
21962
+ seo: {
21306
21963
  id: "seo",
21964
+ order: 440,
21307
21965
  label: "SEO",
21308
21966
  enabled: false,
21967
+ lifecycle: "deprecated",
21309
21968
  path: "/seo"
21310
21969
  },
21311
- {
21970
+ knowledge: {
21312
21971
  id: "knowledge",
21972
+ order: 450,
21313
21973
  label: "Knowledge",
21314
21974
  description: "Operational knowledge, playbooks, and strategy docs",
21315
21975
  enabled: true,
21976
+ lifecycle: "active",
21316
21977
  color: "teal",
21317
- icon: "feature.knowledge",
21318
- uiPosition: "sidebar-primary"
21978
+ icon: "feature.knowledge"
21319
21979
  },
21320
- {
21980
+ "knowledge.base": {
21321
21981
  id: "knowledge.base",
21982
+ order: 460,
21322
21983
  label: "Knowledge Base",
21323
21984
  enabled: true,
21985
+ lifecycle: "active",
21324
21986
  path: "/knowledge"
21325
21987
  }
21326
- ],
21327
- branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
21328
- navigation: { surfaces: [], groups: [] },
21329
- sales: DEFAULT_ORGANIZATION_MODEL_SALES,
21330
- prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
21331
- projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
21332
- identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
21333
- customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
21334
- offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
21335
- roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
21336
- goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
21337
- systems: DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
21988
+ },
21338
21989
  resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
21339
- statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
21340
- operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
21990
+ actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
21991
+ entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
21992
+ policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
21993
+ // Phase 4 (D1): statuses top-level field removed; status data lives in system.content.
21341
21994
  knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
21342
21995
  };
21343
21996
 
@@ -21365,14 +22018,7 @@ function deepMerge2(base, override) {
21365
22018
  }
21366
22019
  function resolveOrganizationModel(override, organizationId) {
21367
22020
  const merged = deepMerge2(DEFAULT_ORGANIZATION_MODEL, override);
21368
- const model = OrganizationModelSchema.parse(merged);
21369
- if (!model.sales?.pipelines || model.sales.pipelines.length === 0) {
21370
- const orgLabel = "Organization";
21371
- throw new Error(
21372
- `${orgLabel} has no sales pipeline configuration. This indicates an incomplete provisioning state. Run org provisioning to seed defaults.`
21373
- );
21374
- }
21375
- return model;
22021
+ return OrganizationModelSchema.parse(merged);
21376
22022
  }
21377
22023
 
21378
22024
  // src/test-utils/organization-model.ts