@elevasis/sdk 1.47.0 → 1.49.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 (54) hide show
  1. package/dist/cli.cjs +1034 -319
  2. package/dist/index.d.ts +687 -49
  3. package/dist/index.js +297 -47
  4. package/dist/node/index.d.ts +110 -26
  5. package/dist/test-utils/index.d.ts +649 -36
  6. package/dist/test-utils/index.js +275 -45
  7. package/dist/worker/index.d.ts +687 -53
  8. package/dist/worker/index.js +121 -6
  9. package/package.json +2 -2
  10. package/reference/_navigation.md +7 -6
  11. package/reference/_reference-manifest.json +12 -2
  12. package/reference/core/index.mdx +6 -4
  13. package/reference/index.mdx +11 -5
  14. package/reference/packages/core/src/README.md +46 -44
  15. package/reference/packages/core/src/content/README.md +13 -12
  16. package/reference/packages/core/src/organization-model/README.md +9 -6
  17. package/reference/rules/content.md +27 -0
  18. package/reference/rules/organization-model.md +9 -3
  19. package/reference/rules/organization-os.md +2 -2
  20. package/reference/rules/ui.md +1 -1
  21. package/reference/rules/vibe-intents.md +19 -16
  22. package/reference/rules/vibe.md +32 -12
  23. package/reference/scaffold/recipes/add-a-feature.md +1 -1
  24. package/reference/scaffold/recipes/customize-organization-model.md +2 -2
  25. package/reference/scaffold/recipes/extend-content.md +172 -30
  26. package/reference/scaffold/reference/glossary.md +2 -2
  27. package/reference/scaffold/reference/system-interface-capabilities.md +26 -6
  28. package/reference/sdk/cli-management.mdx +246 -41
  29. package/reference/sdk/cli.mdx +103 -64
  30. package/reference/sdk/define-builders.mdx +1 -1
  31. package/reference/sdk/deployment/command-center.mdx +2 -2
  32. package/reference/sdk/deployment/index.mdx +1 -1
  33. package/reference/sdk/exports.mdx +4 -4
  34. package/reference/sdk/framework/agent.mdx +4 -3
  35. package/reference/sdk/framework/index.mdx +1 -1
  36. package/reference/sdk/framework/project-structure.mdx +34 -23
  37. package/reference/sdk/framework/tutorial-system.mdx +1 -1
  38. package/reference/sdk/getting-started.mdx +25 -52
  39. package/reference/sdk/index.mdx +3 -3
  40. package/reference/sdk/platform-tools/adapters-integration.mdx +1 -1
  41. package/reference/sdk/platform-tools/adapters-platform.mdx +5 -5
  42. package/reference/sdk/platform-tools/type-safety.mdx +1 -1
  43. package/reference/sdk/resources/patterns.mdx +10 -11
  44. package/reference/sdk/resources/types.mdx +15 -9
  45. package/reference/sdk/templates/data-enrichment.mdx +1 -1
  46. package/reference/sdk/templates/email-sender.mdx +1 -1
  47. package/reference/sdk/templates/index.mdx +47 -47
  48. package/reference/sdk/templates/lead-scorer.mdx +1 -1
  49. package/reference/sdk/templates/pdf-generator.mdx +42 -24
  50. package/reference/sdk/templates/recurring-job.mdx +20 -15
  51. package/reference/sdk/templates/text-classifier.mdx +1 -1
  52. package/reference/sdk/templates/web-scraper.mdx +9 -5
  53. package/reference/ui/exports.mdx +1 -1
  54. package/reference/ui/index.mdx +2 -2
package/dist/index.js CHANGED
@@ -65,44 +65,64 @@ var OntologyRecordBaseSchema = z.object({
65
65
  }).passthrough();
66
66
  var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
67
67
  properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
68
- storage: z.record(z.string(), z.unknown()).optional()
69
- });
68
+ storage: z.record(z.string(), z.unknown()).optional(),
69
+ // Carried by the legacy entity projection (`addLegacyEntityProjections`); not
70
+ // authored directly, but a real key an authored record must not collide with.
71
+ rowSchema: z.string().trim().min(1).optional(),
72
+ stateCatalogId: z.string().trim().min(1).optional()
73
+ }).strict();
70
74
  var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
71
75
  from: OntologyIdSchema,
72
76
  to: OntologyIdSchema,
73
77
  cardinality: z.string().trim().min(1).max(80).optional(),
74
78
  via: z.string().trim().min(1).max(255).optional()
75
- });
79
+ }).strict();
76
80
  var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
77
81
  actsOn: OntologyReferenceListSchema,
78
82
  input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
79
- effects: z.array(z.record(z.string(), z.unknown())).optional()
80
- });
83
+ effects: z.array(z.record(z.string(), z.unknown())).optional(),
84
+ resourceId: z.string().trim().min(1).optional(),
85
+ invocations: z.array(z.unknown()).optional(),
86
+ lifecycle: z.string().trim().min(1).optional(),
87
+ // Carried by the legacy action projection (`addLegacyActionProjections`); not
88
+ // authored directly, but a real key an authored record must not collide with.
89
+ legacyActionId: z.string().trim().min(1).optional()
90
+ }).strict();
81
91
  var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
82
92
  kind: z.string().trim().min(1).max(120).optional(),
83
93
  appliesTo: OntologyIdSchema.optional(),
84
- entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
85
- });
94
+ entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
95
+ // Carried by lead-gen's legacy stage-catalog projection
96
+ // (`createLeadGenStageCatalog`); not authored directly, but a real key an
97
+ // authored record must not collide with.
98
+ legacyCatalogKey: z.string().trim().min(1).optional(),
99
+ // Carried in live tenant configs (Elevasis, `nirvana-marketing`, and the
100
+ // `_template` scaffold all author these on `sales.crm:catalog/crm.pipeline`)
101
+ // as a cross-reference to the pre-ontology CRM pipeline key/entity id. No
102
+ // code currently reads them back — do not silently normalize them away.
103
+ legacyPipelineKey: z.string().trim().min(1).optional(),
104
+ legacyEntityKey: z.string().trim().min(1).optional()
105
+ }).strict();
86
106
  var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
87
107
  payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
88
- });
108
+ }).strict();
89
109
  var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
90
110
  properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
91
- });
111
+ }).strict();
92
112
  var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
93
113
  primitive: z.string().trim().min(1).max(120).optional()
94
- });
114
+ }).strict();
95
115
  var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
96
116
  valueType: OntologyIdSchema.optional(),
97
117
  searchable: z.boolean().optional(),
98
118
  pii: z.boolean().optional()
99
- });
119
+ }).strict();
100
120
  var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
101
121
  members: OntologyReferenceListSchema
102
- });
122
+ }).strict();
103
123
  var OntologyEndpointTypeSchema = OntologyRecordBaseSchema.extend({
104
124
  route: z.string().trim().min(1).max(500).optional()
105
- });
125
+ }).strict();
106
126
  var OntologyScopeSchema = z.object({
107
127
  objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
108
128
  linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
@@ -114,7 +134,7 @@ var OntologyScopeSchema = z.object({
114
134
  sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
115
135
  groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
116
136
  endpoints: z.record(OntologyIdSchema, OntologyEndpointTypeSchema).default({}).optional()
117
- }).default({});
137
+ }).strict().default({});
118
138
  var SCOPE_KIND = {
119
139
  objectTypes: "object",
120
140
  linkTypes: "link",
@@ -612,29 +632,45 @@ var SystemUiSchema = z.object({
612
632
  path: PathSchema,
613
633
  surfaces: ReferenceIdsSchema,
614
634
  icon: IconNameSchema.optional()
615
- });
635
+ }).strict();
616
636
  var SystemInterfaceKeySchema = ModelIdSchema;
617
637
  var SystemInterfaceLifecycleSchema = z.enum(["draft", "active", "disabled", "deprecated", "archived"]).meta({ label: "System interface lifecycle", color: "teal" });
618
638
  var SYSTEM_INTERFACE_PROFILES = [
619
639
  {
620
640
  systemPath: "sales.lead-gen",
621
641
  interfaceKey: "api",
622
- readinessProfile: "sales.lead-gen.api"
642
+ readinessProfile: "sales.lead-gen.api",
643
+ validation: "built-in"
623
644
  },
624
645
  {
625
646
  systemPath: "sales.crm",
626
647
  interfaceKey: "api",
627
- readinessProfile: "sales.crm.api"
648
+ readinessProfile: "sales.crm.api",
649
+ validation: "built-in"
628
650
  },
629
651
  {
630
652
  systemPath: "sales.lead-gen",
631
653
  interfaceKey: "crm-handoff",
632
- readinessProfile: "sales.lead-gen.crm-handoff"
654
+ readinessProfile: "sales.lead-gen.crm-handoff",
655
+ validation: "built-in"
656
+ },
657
+ {
658
+ // Gated by `CONTENT_API_INTERFACE` in `apps/api/src/business/content/organization-model.ts`,
659
+ // which every `/api/content/*` and `/api/external/content/*` route asserts. Contract-validated
660
+ // rather than built-in because the required step catalog is per-adopter: Elevasis declares
661
+ // `content:catalog/long-form-to-shorts-steps`, a tenant declares its own.
662
+ systemPath: "content",
663
+ interfaceKey: "api",
664
+ readinessProfile: "content.api",
665
+ validation: "contract"
633
666
  }
634
667
  ];
635
- var SYSTEM_INTERFACE_READINESS_PROFILES = SYSTEM_INTERFACE_PROFILES.map(
668
+ SYSTEM_INTERFACE_PROFILES.map(
636
669
  (profile) => profile.readinessProfile
637
670
  );
671
+ var BUILT_IN_VALIDATED_PROFILE_IDS = SYSTEM_INTERFACE_PROFILES.filter(
672
+ (profile) => profile.validation === "built-in"
673
+ ).map((profile) => profile.readinessProfile);
638
674
  var SystemInterfaceReadinessProfileSchema = z.string().trim().min(1);
639
675
  var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
640
676
  var SystemApiInterfaceReadinessContractSchema = z.object({
@@ -673,7 +709,7 @@ var SystemApiInterfaceSchema = z.object({
673
709
  }).strict();
674
710
  var _customProfileIds = /* @__PURE__ */ new Set();
675
711
  function isReservedPlatformProfileId(profileId) {
676
- return SYSTEM_INTERFACE_READINESS_PROFILES.includes(profileId);
712
+ return BUILT_IN_VALIDATED_PROFILE_IDS.includes(profileId);
677
713
  }
678
714
  function lookupReadinessProfile(profileId) {
679
715
  if (isReservedPlatformProfileId(profileId) || getBuiltInReadinessProfile(profileId) !== void 0) {
@@ -3852,6 +3888,19 @@ var GPT5ConfigSchema = z.object({
3852
3888
  topP: z.number().min(0).max(1).optional(),
3853
3889
  modelOptions: GPT5OptionsSchema.optional()
3854
3890
  });
3891
+ var GPT56OptionsSchema = z.object({
3892
+ reasoning_effort: z.enum(["none", "low", "medium", "high", "xhigh", "max"]).optional(),
3893
+ verbosity: z.enum(["low", "medium", "high"]).optional()
3894
+ });
3895
+ var GPT56ConfigSchema = z.object({
3896
+ model: z.enum(["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]),
3897
+ provider: z.enum(["openai"]),
3898
+ apiKey: z.string(),
3899
+ temperature: z.literal(1).optional(),
3900
+ maxOutputTokens: z.number().min(4e3).optional(),
3901
+ topP: z.number().min(0).max(1).optional(),
3902
+ modelOptions: GPT56OptionsSchema.optional()
3903
+ });
3855
3904
  var MockConfigSchema = z.object({
3856
3905
  model: z.enum(["mock"]),
3857
3906
  provider: z.enum(["mock"]),
@@ -3904,9 +3953,12 @@ var AnthropicConfigSchema = z.discriminatedUnion("model", [
3904
3953
  AnthropicClaude5ConfigSchema,
3905
3954
  AnthropicStandardConfigSchema
3906
3955
  ]);
3956
+ var GPT56_CACHE_READ_RATE_MULTIPLIER = 0.1;
3957
+ var CACHE_CREATION_RATE_MULTIPLIER = 1.25;
3907
3958
  var MODEL_INFO = {
3908
3959
  // OpenAI GPT-5 (Reasoning Models)
3909
3960
  "gpt-5": {
3961
+ provider: "openai",
3910
3962
  inputCostPer1M: 125,
3911
3963
  // $1.25 per 1M tokens
3912
3964
  outputCostPer1M: 1e3,
@@ -3920,6 +3972,7 @@ var MODEL_INFO = {
3920
3972
  configSchema: GPT5ConfigSchema
3921
3973
  },
3922
3974
  "gpt-5.4-mini": {
3975
+ provider: "openai",
3923
3976
  inputCostPer1M: 75,
3924
3977
  // $0.75 per 1M tokens
3925
3978
  outputCostPer1M: 450,
@@ -3933,6 +3986,7 @@ var MODEL_INFO = {
3933
3986
  configSchema: GPT5ConfigSchema
3934
3987
  },
3935
3988
  "gpt-5.4-nano": {
3989
+ provider: "openai",
3936
3990
  inputCostPer1M: 20,
3937
3991
  // $0.20 per 1M tokens
3938
3992
  outputCostPer1M: 125,
@@ -3944,8 +3998,60 @@ var MODEL_INFO = {
3944
3998
  category: "standard",
3945
3999
  configSchema: GPT5ConfigSchema
3946
4000
  },
4001
+ // OpenAI GPT-5.6 family (GA 2026-07-09). All three tiers share 1.05M context, 128K max output,
4002
+ // image input, tool use, structured outputs, and prompt caching -- they differ in reasoning depth
4003
+ // and price, not capability. The bare `gpt-5.6` alias is deliberately unregistered; see OpenAIModel.
4004
+ "gpt-5.6-sol": {
4005
+ provider: "openai",
4006
+ inputCostPer1M: 500,
4007
+ // $5.00 per 1M tokens
4008
+ outputCostPer1M: 3e3,
4009
+ // $30.00 per 1M tokens
4010
+ minTokens: 4e3,
4011
+ recommendedTokens: 8e3,
4012
+ maxTokens: 105e4,
4013
+ // 1.05M context window
4014
+ maxOutputTokens: 128e3,
4015
+ category: "reasoning",
4016
+ configSchema: GPT56ConfigSchema,
4017
+ cacheReadRateMultiplier: GPT56_CACHE_READ_RATE_MULTIPLIER,
4018
+ cacheCreationRateMultiplier: CACHE_CREATION_RATE_MULTIPLIER
4019
+ },
4020
+ "gpt-5.6-terra": {
4021
+ provider: "openai",
4022
+ inputCostPer1M: 250,
4023
+ // $2.50 per 1M tokens
4024
+ outputCostPer1M: 1500,
4025
+ // $15.00 per 1M tokens
4026
+ minTokens: 4e3,
4027
+ recommendedTokens: 8e3,
4028
+ maxTokens: 105e4,
4029
+ // 1.05M context window
4030
+ maxOutputTokens: 128e3,
4031
+ category: "standard",
4032
+ configSchema: GPT56ConfigSchema,
4033
+ cacheReadRateMultiplier: GPT56_CACHE_READ_RATE_MULTIPLIER,
4034
+ cacheCreationRateMultiplier: CACHE_CREATION_RATE_MULTIPLIER
4035
+ },
4036
+ "gpt-5.6-luna": {
4037
+ provider: "openai",
4038
+ inputCostPer1M: 100,
4039
+ // $1.00 per 1M tokens
4040
+ outputCostPer1M: 600,
4041
+ // $6.00 per 1M tokens
4042
+ minTokens: 4e3,
4043
+ recommendedTokens: 8e3,
4044
+ maxTokens: 105e4,
4045
+ // 1.05M context window
4046
+ maxOutputTokens: 128e3,
4047
+ category: "standard",
4048
+ configSchema: GPT56ConfigSchema,
4049
+ cacheReadRateMultiplier: GPT56_CACHE_READ_RATE_MULTIPLIER,
4050
+ cacheCreationRateMultiplier: CACHE_CREATION_RATE_MULTIPLIER
4051
+ },
3947
4052
  // Mock model for testing
3948
4053
  mock: {
4054
+ provider: "mock",
3949
4055
  inputCostPer1M: 0,
3950
4056
  // Free for tests
3951
4057
  outputCostPer1M: 0,
@@ -3959,6 +4065,7 @@ var MODEL_INFO = {
3959
4065
  },
3960
4066
  // OpenRouter Models (via openrouter.ai)
3961
4067
  "openrouter/z-ai/glm-5": {
4068
+ provider: "openrouter",
3962
4069
  inputCostPer1M: 72,
3963
4070
  // $0.72 per 1M tokens
3964
4071
  outputCostPer1M: 230,
@@ -3972,6 +4079,7 @@ var MODEL_INFO = {
3972
4079
  },
3973
4080
  // Anthropic Claude Models (direct SDK access via @anthropic-ai/sdk)
3974
4081
  "claude-opus-5": {
4082
+ provider: "anthropic",
3975
4083
  inputCostPer1M: 500,
3976
4084
  // $5.00 per 1M tokens
3977
4085
  outputCostPer1M: 2500,
@@ -3985,6 +4093,7 @@ var MODEL_INFO = {
3985
4093
  configSchema: AnthropicConfigSchema
3986
4094
  },
3987
4095
  "claude-sonnet-5": {
4096
+ provider: "anthropic",
3988
4097
  // List pricing. An introductory rate of $2.00/$10.00 runs through 2026-08-31; encoding the
3989
4098
  // temporary rate would make historical cost analytics wrong once it lapses.
3990
4099
  inputCostPer1M: 300,
@@ -4000,6 +4109,7 @@ var MODEL_INFO = {
4000
4109
  configSchema: AnthropicConfigSchema
4001
4110
  },
4002
4111
  "claude-haiku-4-5-20251001": {
4112
+ provider: "anthropic",
4003
4113
  inputCostPer1M: 100,
4004
4114
  // $1.00 per 1M tokens
4005
4115
  outputCostPer1M: 500,
@@ -4013,6 +4123,7 @@ var MODEL_INFO = {
4013
4123
  configSchema: AnthropicConfigSchema
4014
4124
  },
4015
4125
  "claude-haiku-4-5": {
4126
+ provider: "anthropic",
4016
4127
  inputCostPer1M: 100,
4017
4128
  // $1.00 per 1M tokens
4018
4129
  outputCostPer1M: 500,
@@ -4032,7 +4143,7 @@ function getModelInfo(model) {
4032
4143
  return MODEL_INFO[model];
4033
4144
  }
4034
4145
  for (const knownModel of MODEL_KEYS_BY_SPECIFICITY) {
4035
- if (model.startsWith(knownModel)) {
4146
+ if (model.startsWith(`${knownModel}-`)) {
4036
4147
  return MODEL_INFO[knownModel];
4037
4148
  }
4038
4149
  }
@@ -4404,13 +4515,126 @@ function buildIterationResponseSchemaUncached(tools, capabilities) {
4404
4515
  };
4405
4516
  }
4406
4517
 
4518
+ // ../core/src/execution/engine/workflow/types.ts
4519
+ var StepType2 = {
4520
+ LINEAR: "linear",
4521
+ CONDITIONAL: "conditional"
4522
+ };
4523
+
4524
+ // ../core/src/execution/engine/workflow/errors.ts
4525
+ var WorkflowStepError = class extends ExecutionError2 {
4526
+ type = "workflow_step_error";
4527
+ severity = "critical";
4528
+ category = "workflow";
4529
+ /**
4530
+ * @param cause - The error the step actually threw. Kept so the original stack and any
4531
+ * non-`ExecutionError` throw survive the wrap; its classification is additionally copied into
4532
+ * `context` by the caller, because `type`/`severity`/`category` are fixed on this class.
4533
+ */
4534
+ constructor(message, context, cause) {
4535
+ super(message, context);
4536
+ if (cause !== void 0) this.cause = cause;
4537
+ }
4538
+ };
4539
+ var WorkflowValidationError = class extends ExecutionError2 {
4540
+ type = "workflow_validation_error";
4541
+ severity = "info";
4542
+ category = "validation";
4543
+ constructor(message, context) {
4544
+ super(message, context);
4545
+ }
4546
+ };
4547
+
4548
+ // ../core/src/execution/engine/workflow/utils.ts
4549
+ function validateEntryPoint(steps, entryPoint) {
4550
+ if (!(entryPoint in steps)) {
4551
+ throw new WorkflowValidationError(`Entry point step '${entryPoint}' not found in workflow`, {
4552
+ entryPoint
4553
+ });
4554
+ }
4555
+ }
4556
+ function findTerminalSteps(steps) {
4557
+ return Object.values(steps).filter((step) => step.next === null);
4558
+ }
4559
+ function validateTerminalSteps(steps, workflowId) {
4560
+ const terminalSteps = findTerminalSteps(steps);
4561
+ if (terminalSteps.length === 0) {
4562
+ throw new WorkflowValidationError(`Workflow '${workflowId}' must have at least one terminal step (next: null)`, {
4563
+ workflowId
4564
+ });
4565
+ }
4566
+ }
4567
+ function validateStepReferences(steps) {
4568
+ for (const [id, step] of Object.entries(steps)) {
4569
+ if (step.next === null) {
4570
+ continue;
4571
+ }
4572
+ if (step.next.type === StepType2.LINEAR) {
4573
+ if (!(step.next.target in steps)) {
4574
+ throw new WorkflowValidationError(`Step '${id}' references non-existent target '${step.next.target}'`, {
4575
+ stepId: id,
4576
+ target: step.next.target
4577
+ });
4578
+ }
4579
+ } else if (step.next.type === StepType2.CONDITIONAL) {
4580
+ const targets = [...step.next.routes.map((r) => r.target), step.next.default];
4581
+ for (const target of targets) {
4582
+ if (!(target in steps)) {
4583
+ throw new WorkflowValidationError(`Step '${id}' references non-existent target '${target}'`, {
4584
+ stepId: id,
4585
+ target
4586
+ });
4587
+ }
4588
+ }
4589
+ }
4590
+ }
4591
+ }
4592
+ function detectCycle(visited, executionPath, currentStepId) {
4593
+ if (visited.has(currentStepId)) {
4594
+ const cycle = executionPath.slice(executionPath.indexOf(currentStepId));
4595
+ throw new WorkflowStepError(`Cycle detected in workflow: ${cycle.join(" -> ")} -> ${currentStepId}`, {
4596
+ stepId: currentStepId,
4597
+ cycle: [...cycle, currentStepId]
4598
+ });
4599
+ }
4600
+ }
4601
+ function validateWorkflowGraph(steps, entryPoint, workflowId) {
4602
+ const onPath = /* @__PURE__ */ new Set();
4603
+ const executionPath = [];
4604
+ const reached = /* @__PURE__ */ new Set();
4605
+ const walk = (stepId) => {
4606
+ detectCycle(onPath, executionPath, stepId);
4607
+ onPath.add(stepId);
4608
+ executionPath.push(stepId);
4609
+ reached.add(stepId);
4610
+ const step = steps[stepId];
4611
+ if (step && step.next !== null) {
4612
+ const targets = step.next.type === StepType2.LINEAR ? [step.next.target] : [...step.next.routes.map((route) => route.target), step.next.default];
4613
+ for (const target of targets) {
4614
+ if (target in steps) walk(target);
4615
+ }
4616
+ }
4617
+ executionPath.pop();
4618
+ onPath.delete(stepId);
4619
+ };
4620
+ if (entryPoint in steps) walk(entryPoint);
4621
+ const orphanIds = Object.keys(steps).filter((id) => !reached.has(id));
4622
+ if (orphanIds.length > 0) {
4623
+ throw new WorkflowValidationError(
4624
+ `Workflow '${workflowId}' has step(s) unreachable from entry point '${entryPoint}': ${orphanIds.join(", ")}`,
4625
+ { workflowId, entryPoint, orphanIds }
4626
+ );
4627
+ }
4628
+ }
4629
+
4407
4630
  // ../core/src/platform/registry/validation.ts
4408
4631
  var RegistryValidationError = class extends Error {
4409
- constructor(orgName, resourceId, field, message) {
4632
+ constructor(orgName, resourceId, field, message, issues) {
4410
4633
  super(message);
4411
4634
  this.orgName = orgName;
4412
4635
  this.resourceId = resourceId;
4413
4636
  this.field = field;
4637
+ this.issues = issues;
4414
4638
  this.name = "RegistryValidationError";
4415
4639
  }
4416
4640
  };
@@ -4431,7 +4655,14 @@ function emitGovernanceIssues(issues, mode, onWarning) {
4431
4655
  if (issues.length === 0) return;
4432
4656
  if (mode === "strict") {
4433
4657
  const first = issues[0];
4434
- throw new RegistryValidationError(first.orgName, first.resourceId, "organizationModel.resources", first.message);
4658
+ const messages = issues.map((issue) => issue.message);
4659
+ throw new RegistryValidationError(
4660
+ first.orgName,
4661
+ first.resourceId,
4662
+ "organizationModel.resources",
4663
+ messages.join("\n"),
4664
+ messages
4665
+ );
4435
4666
  }
4436
4667
  const warn = onWarning ?? ((issue) => console.warn(issue.message));
4437
4668
  for (const issue of issues) {
@@ -4592,7 +4823,7 @@ function addTopologyIssues(issues, orgName, deployment, organizationModel, syste
4592
4823
  if (ref.kind === "humanCheckpoint") return humanCheckpointIds.has(ref.id);
4593
4824
  if (ref.kind === "externalResource") return externalResourceIds.has(ref.id);
4594
4825
  if (ref.kind === "ontology") {
4595
- if (ontologyIndex === void 0) return true;
4826
+ if (ontologyIndex === void 0) return false;
4596
4827
  return Object.values(ontologyIndex).some((records) => records[ref.id] !== void 0);
4597
4828
  }
4598
4829
  return false;
@@ -4750,7 +4981,8 @@ function addSystemInterfaceIssue(issues, orgName, systemPath, interfaceKey, issu
4750
4981
  message: `[${orgName}] ${issue.family}:${issue.code}: ${issue.message}`
4751
4982
  });
4752
4983
  }
4753
- function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel) {
4984
+ function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel, options = {}) {
4985
+ const mode = getResourceValidatorMode(options.mode);
4754
4986
  const issues = [];
4755
4987
  if (organizationModel === void 0) return { valid: true, issues };
4756
4988
  const model = organizationModel;
@@ -4776,17 +5008,27 @@ function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel) {
4776
5008
  }
4777
5009
  }
4778
5010
  if (issues.length > 0) {
4779
- const first = issues[0];
4780
- throw new RegistryValidationError(
4781
- first.orgName,
4782
- `${first.systemPath}/${first.interfaceKey}`,
4783
- first.path ?? "organizationModel.systems.apiInterface",
4784
- first.message
4785
- );
5011
+ if (mode === "strict") {
5012
+ const first = issues[0];
5013
+ const messages = issues.map((issue) => issue.message);
5014
+ throw new RegistryValidationError(
5015
+ first.orgName,
5016
+ `${first.systemPath}/${first.interfaceKey}`,
5017
+ first.path ?? "organizationModel.systems.apiInterface",
5018
+ messages.join("\n"),
5019
+ messages
5020
+ );
5021
+ }
5022
+ const warn = options.onWarning ?? ((issue) => console.warn(issue.message));
5023
+ for (const issue of issues) {
5024
+ warn(issue);
5025
+ }
5026
+ return { valid: false, issues };
4786
5027
  }
4787
5028
  return { valid: true, issues };
4788
5029
  }
4789
- function validateDeploymentSpec(orgName, resources) {
5030
+ function validateDeploymentSpec(orgName, resources, options = {}) {
5031
+ const warn = options.onWarning ?? ((message) => console.warn(message));
4790
5032
  const seenIds = /* @__PURE__ */ new Set();
4791
5033
  resources.workflows?.forEach((workflow) => {
4792
5034
  const id = workflow.config.resourceId;
@@ -4805,6 +5047,14 @@ function validateDeploymentSpec(orgName, resources) {
4805
5047
  if (workflow.interface) {
4806
5048
  validateExecutionInterface(orgName, id, workflow.interface, workflow.contract.inputSchema);
4807
5049
  }
5050
+ try {
5051
+ validateEntryPoint(workflow.steps, workflow.entryPoint);
5052
+ validateTerminalSteps(workflow.steps, id);
5053
+ validateStepReferences(workflow.steps);
5054
+ validateWorkflowGraph(workflow.steps, workflow.entryPoint, id);
5055
+ } catch (error) {
5056
+ warn(`[${orgName}] Workflow '${id}' graph validation: ${error instanceof Error ? error.message : String(error)}`);
5057
+ }
4808
5058
  });
4809
5059
  resources.agents?.forEach((agent) => {
4810
5060
  const id = agent.config.resourceId;
@@ -4818,14 +5068,20 @@ function validateDeploymentSpec(orgName, resources) {
4818
5068
  }
4819
5069
  seenIds.add(id);
4820
5070
  validateResourceModelConfig(orgName, id, agent.modelConfig);
4821
- validateAgentGrammar(orgName, id, agent);
4822
- validateAgentCheapAssertions(orgName, id, agent);
5071
+ validateAgentGrammar(orgName, id, agent, options.mode);
5072
+ validateAgentCheapAssertions(orgName, id, agent, options.mode);
4823
5073
  if (agent.interface) {
4824
5074
  validateExecutionInterface(orgName, id, agent.interface, agent.contract.inputSchema);
4825
5075
  }
4826
5076
  });
4827
- validateResourceGovernance(orgName, resources);
4828
- validateDeclaredSystemInterfaceReadiness(orgName, resources.organizationModel);
5077
+ validateResourceGovernance(orgName, resources, void 0, {
5078
+ mode: options.mode,
5079
+ onWarning: (issue) => warn(issue.message)
5080
+ });
5081
+ validateDeclaredSystemInterfaceReadiness(orgName, resources.organizationModel, {
5082
+ mode: options.mode,
5083
+ onWarning: (issue) => warn(issue.message)
5084
+ });
4829
5085
  }
4830
5086
  function validateResourceModelConfig(orgName, resourceId, modelConfig) {
4831
5087
  try {
@@ -4900,7 +5156,7 @@ function describeGrammarRefusal(reasons, toolInputSchema) {
4900
5156
  }
4901
5157
  return `refused strict mode: ${reasons.join(", ")}`;
4902
5158
  }
4903
- function validateAgentGrammar(orgName, agentId, agent) {
5159
+ function validateAgentGrammar(orgName, agentId, agent, mode) {
4904
5160
  const dialect = dialectForProvider(agent.modelConfig.provider);
4905
5161
  if (!dialect) return;
4906
5162
  const capabilities = agentCapabilitiesForGrammarCheck(agent.config);
@@ -4921,12 +5177,12 @@ function validateAgentGrammar(orgName, agentId, agent) {
4921
5177
  compileSchema(offending.inputSchema, dialect).refusalReasons,
4922
5178
  offending.inputSchema
4923
5179
  )}. This silently drops strict-mode enforcement for the agent's ENTIRE iteration schema on every call, not just this tool -- compileSchema refuses whole-schema, never per-tool.` : `[${orgName}] Agent '${agentId}' iteration schema refused strict mode for provider '${agent.modelConfig.provider}': ${compiled.refusalReasons.join(", ")}. No single tool is independently responsible -- this is a whole-schema limit (e.g. total optional properties across every tool exceeding the provider's cap).`;
4924
- if (getResourceValidatorMode() === "strict") {
5180
+ if (getResourceValidatorMode(mode) === "strict") {
4925
5181
  throw new RegistryValidationError(orgName, agentId, "tools", message);
4926
5182
  }
4927
5183
  console.warn(message);
4928
5184
  }
4929
- function validateAgentCheapAssertions(orgName, agentId, agent) {
5185
+ function validateAgentCheapAssertions(orgName, agentId, agent, mode) {
4930
5186
  const issues = [];
4931
5187
  const config = agent.config;
4932
5188
  if (config.sessionCapable && config.securityLevel === "none") {
@@ -4956,7 +5212,7 @@ function validateAgentCheapAssertions(orgName, agentId, agent) {
4956
5212
  }
4957
5213
  if (issues.length === 0) return;
4958
5214
  const message = `[${orgName}] Agent '${agentId}': ${issues.join(" ")}`;
4959
- if (getResourceValidatorMode() === "strict") {
5215
+ if (getResourceValidatorMode(mode) === "strict") {
4960
5216
  throw new RegistryValidationError(orgName, agentId, "config", message);
4961
5217
  }
4962
5218
  console.warn(message);
@@ -5212,12 +5468,6 @@ function validateHumanCheckpoints(orgName, humanCheckpoints, allInternalIds, val
5212
5468
  });
5213
5469
  }
5214
5470
 
5215
- // ../core/src/execution/engine/workflow/types.ts
5216
- var StepType2 = {
5217
- LINEAR: "linear",
5218
- CONDITIONAL: "conditional"
5219
- };
5220
-
5221
5471
  // ../core/src/execution/engine/base/serialization.ts
5222
5472
  function serializeDefinition(definition, options) {
5223
5473
  const opts = {