@sweny-ai/core 0.1.102 → 0.1.103

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schema.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * parsing untrusted input (JSON/YAML import, Studio editor).
8
8
  */
9
9
  import { z } from "zod";
10
- import type { Workflow } from "./types.js";
10
+ import type { Workflow, WorkflowType } from "./types.js";
11
11
  import { sourceZ } from "./sources.js";
12
12
  import { workflowInputsZ } from "./inputs.js";
13
13
  export { sourceZ };
@@ -239,7 +239,7 @@ export declare const skillZ: z.ZodEffects<z.ZodObject<{
239
239
  args?: string[] | undefined;
240
240
  }>>;
241
241
  mcpAliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
242
- }, "strip", z.ZodTypeAny, {
242
+ }, "strict", z.ZodTypeAny, {
243
243
  description: string;
244
244
  name: string;
245
245
  id: string;
@@ -1089,6 +1089,7 @@ export declare const nodeZ: z.ZodObject<{
1089
1089
  }>, "many">>;
1090
1090
  eval_policy: z.ZodOptional<z.ZodEnum<["all_pass", "any_pass", "weighted"]>>;
1091
1091
  judge_model: z.ZodOptional<z.ZodString>;
1092
+ model: z.ZodOptional<z.ZodString>;
1092
1093
  requires: z.ZodOptional<z.ZodEffects<z.ZodObject<{
1093
1094
  output_required: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1094
1095
  output_matches: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
@@ -1196,6 +1197,7 @@ export declare const nodeZ: z.ZodObject<{
1196
1197
  type?: string | undefined;
1197
1198
  };
1198
1199
  skills: string[];
1200
+ model?: string | undefined;
1199
1201
  output?: Record<string, unknown> | undefined;
1200
1202
  max_turns?: number | undefined;
1201
1203
  disallowed_tools?: string[] | undefined;
@@ -1284,6 +1286,7 @@ export declare const nodeZ: z.ZodObject<{
1284
1286
  url: string;
1285
1287
  type?: string | undefined;
1286
1288
  };
1289
+ model?: string | undefined;
1287
1290
  skills?: string[] | undefined;
1288
1291
  output?: Record<string, unknown> | undefined;
1289
1292
  max_turns?: number | undefined;
@@ -1393,7 +1396,7 @@ export declare const edgeZ: z.ZodObject<{
1393
1396
  * cloud renderer + metric schema. Don't extend casually.
1394
1397
  */
1395
1398
  export declare const workflowTypeZ: z.ZodEnum<["pr_review", "e2e_test", "content_generation", "monitor", "data_sync", "generic"]>;
1396
- export type WorkflowType = z.infer<typeof workflowTypeZ>;
1399
+ export type { WorkflowType };
1397
1400
  export declare const workflowZ: z.ZodObject<{
1398
1401
  id: z.ZodString;
1399
1402
  name: z.ZodString;
@@ -1716,6 +1719,7 @@ export declare const workflowZ: z.ZodObject<{
1716
1719
  }>, "many">>;
1717
1720
  eval_policy: z.ZodOptional<z.ZodEnum<["all_pass", "any_pass", "weighted"]>>;
1718
1721
  judge_model: z.ZodOptional<z.ZodString>;
1722
+ model: z.ZodOptional<z.ZodString>;
1719
1723
  requires: z.ZodOptional<z.ZodEffects<z.ZodObject<{
1720
1724
  output_required: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1721
1725
  output_matches: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
@@ -1823,6 +1827,7 @@ export declare const workflowZ: z.ZodObject<{
1823
1827
  type?: string | undefined;
1824
1828
  };
1825
1829
  skills: string[];
1830
+ model?: string | undefined;
1826
1831
  output?: Record<string, unknown> | undefined;
1827
1832
  max_turns?: number | undefined;
1828
1833
  disallowed_tools?: string[] | undefined;
@@ -1911,6 +1916,7 @@ export declare const workflowZ: z.ZodObject<{
1911
1916
  url: string;
1912
1917
  type?: string | undefined;
1913
1918
  };
1919
+ model?: string | undefined;
1914
1920
  skills?: string[] | undefined;
1915
1921
  output?: Record<string, unknown> | undefined;
1916
1922
  max_turns?: number | undefined;
@@ -2142,6 +2148,7 @@ export declare const workflowZ: z.ZodObject<{
2142
2148
  type?: string | undefined;
2143
2149
  }>]>, "many">>;
2144
2150
  judge_model: z.ZodOptional<z.ZodString>;
2151
+ model: z.ZodOptional<z.ZodString>;
2145
2152
  judge_budget: z.ZodOptional<z.ZodNumber>;
2146
2153
  inputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodObject<{
2147
2154
  type: z.ZodEnum<["string", "number", "boolean", "string[]"]>;
@@ -2202,6 +2209,7 @@ export declare const workflowZ: z.ZodObject<{
2202
2209
  type?: string | undefined;
2203
2210
  };
2204
2211
  skills: string[];
2212
+ model?: string | undefined;
2205
2213
  output?: Record<string, unknown> | undefined;
2206
2214
  max_turns?: number | undefined;
2207
2215
  disallowed_tools?: string[] | undefined;
@@ -2288,6 +2296,7 @@ export declare const workflowZ: z.ZodObject<{
2288
2296
  max_iterations?: number | undefined;
2289
2297
  }[];
2290
2298
  entry: string;
2299
+ model?: string | undefined;
2291
2300
  rules?: (string | {
2292
2301
  inline: string;
2293
2302
  } | {
@@ -2327,6 +2336,7 @@ export declare const workflowZ: z.ZodObject<{
2327
2336
  url: string;
2328
2337
  type?: string | undefined;
2329
2338
  };
2339
+ model?: string | undefined;
2330
2340
  skills?: string[] | undefined;
2331
2341
  output?: Record<string, unknown> | undefined;
2332
2342
  max_turns?: number | undefined;
@@ -2415,6 +2425,7 @@ export declare const workflowZ: z.ZodObject<{
2415
2425
  }[];
2416
2426
  entry: string;
2417
2427
  description?: string | undefined;
2428
+ model?: string | undefined;
2418
2429
  skills?: Record<string, {
2419
2430
  description?: string | undefined;
2420
2431
  name?: string | undefined;
@@ -2455,6 +2466,18 @@ export declare const workflowZ: z.ZodObject<{
2455
2466
  enum?: unknown[] | undefined;
2456
2467
  }> | undefined;
2457
2468
  }>;
2469
+ /**
2470
+ * Detect legacy `verify:` blocks before parse and throw a clear migration
2471
+ * error. Without this preflight, the user gets Zod's generic "Unrecognized
2472
+ * key(s)" message at the node level (and silent passthrough at the
2473
+ * workflow level, since workflowZ allows extra top-level fields for
2474
+ * marketplace metadata).
2475
+ *
2476
+ * Catches:
2477
+ * - Top-level `workflow.verify` (typo / wrong scope).
2478
+ * - Per-node `nodes[*].verify` (the most common shape pre-rename).
2479
+ */
2480
+ export declare function preflightLegacyVerify(raw: unknown): void;
2458
2481
  /** Parse + validate a raw object as a Workflow. Throws on invalid input. */
2459
2482
  export declare function parseWorkflow(raw: unknown): {
2460
2483
  description: string;
@@ -2484,6 +2507,7 @@ export declare function parseWorkflow(raw: unknown): {
2484
2507
  type?: string | undefined;
2485
2508
  };
2486
2509
  skills: string[];
2510
+ model?: string | undefined;
2487
2511
  output?: Record<string, unknown> | undefined;
2488
2512
  max_turns?: number | undefined;
2489
2513
  disallowed_tools?: string[] | undefined;
@@ -2570,6 +2594,7 @@ export declare function parseWorkflow(raw: unknown): {
2570
2594
  max_iterations?: number | undefined;
2571
2595
  }[];
2572
2596
  entry: string;
2597
+ model?: string | undefined;
2573
2598
  rules?: (string | {
2574
2599
  inline: string;
2575
2600
  } | {
@@ -2802,6 +2827,15 @@ export declare const workflowJsonSchema: {
2802
2827
  };
2803
2828
  readonly then: {
2804
2829
  readonly required: readonly ["rule"];
2830
+ readonly not: {
2831
+ readonly anyOf: readonly [{
2832
+ readonly required: readonly ["rubric"];
2833
+ }, {
2834
+ readonly required: readonly ["pass_when"];
2835
+ }, {
2836
+ readonly required: readonly ["model"];
2837
+ }];
2838
+ };
2805
2839
  };
2806
2840
  }, {
2807
2841
  readonly if: {
@@ -2813,6 +2847,9 @@ export declare const workflowJsonSchema: {
2813
2847
  };
2814
2848
  readonly then: {
2815
2849
  readonly required: readonly ["rubric"];
2850
+ readonly not: {
2851
+ readonly required: readonly ["rule"];
2852
+ };
2816
2853
  };
2817
2854
  }];
2818
2855
  };
@@ -2856,13 +2893,16 @@ export declare const workflowJsonSchema: {
2856
2893
  readonly judge_model: {
2857
2894
  readonly type: "string";
2858
2895
  readonly minLength: 1;
2859
- readonly default: "claude-haiku-4-5";
2860
2896
  readonly description: "Default model for judge evaluators across the workflow. Overridable per-node and per-evaluator.";
2861
2897
  };
2898
+ readonly model: {
2899
+ readonly type: "string";
2900
+ readonly minLength: 1;
2901
+ readonly description: "Default execution model for every node. Overridable per-node. Free-text passthrough (no registry); resolved as node.model ?? workflow.model ?? executor default.";
2902
+ };
2862
2903
  readonly judge_budget: {
2863
2904
  readonly type: "integer";
2864
2905
  readonly minimum: 0;
2865
- readonly default: 50;
2866
2906
  readonly description: "Soft cap on expected judge calls per workflow run. Executor warns at load time if exceeded; not a hard runtime cap in v1.";
2867
2907
  };
2868
2908
  readonly inputs: {
@@ -2896,6 +2936,102 @@ export declare const workflowJsonSchema: {
2896
2936
  readonly description: "Optional set of allowed values. Validated after the type check.";
2897
2937
  };
2898
2938
  };
2939
+ readonly not: {
2940
+ readonly type: "object";
2941
+ readonly required: readonly ["required", "default"];
2942
+ readonly properties: {
2943
+ readonly required: {
2944
+ readonly const: true;
2945
+ };
2946
+ };
2947
+ };
2948
+ readonly allOf: readonly [{
2949
+ readonly if: {
2950
+ readonly properties: {
2951
+ readonly type: {
2952
+ readonly const: "string";
2953
+ };
2954
+ };
2955
+ };
2956
+ readonly then: {
2957
+ readonly properties: {
2958
+ readonly default: {
2959
+ readonly type: "string";
2960
+ };
2961
+ readonly enum: {
2962
+ readonly items: {
2963
+ readonly type: "string";
2964
+ };
2965
+ };
2966
+ };
2967
+ };
2968
+ }, {
2969
+ readonly if: {
2970
+ readonly properties: {
2971
+ readonly type: {
2972
+ readonly const: "number";
2973
+ };
2974
+ };
2975
+ };
2976
+ readonly then: {
2977
+ readonly properties: {
2978
+ readonly default: {
2979
+ readonly type: "number";
2980
+ };
2981
+ readonly enum: {
2982
+ readonly items: {
2983
+ readonly type: "number";
2984
+ };
2985
+ };
2986
+ };
2987
+ };
2988
+ }, {
2989
+ readonly if: {
2990
+ readonly properties: {
2991
+ readonly type: {
2992
+ readonly const: "boolean";
2993
+ };
2994
+ };
2995
+ };
2996
+ readonly then: {
2997
+ readonly properties: {
2998
+ readonly default: {
2999
+ readonly type: "boolean";
3000
+ };
3001
+ readonly enum: {
3002
+ readonly items: {
3003
+ readonly type: "boolean";
3004
+ };
3005
+ };
3006
+ };
3007
+ };
3008
+ }, {
3009
+ readonly if: {
3010
+ readonly properties: {
3011
+ readonly type: {
3012
+ readonly const: "string[]";
3013
+ };
3014
+ };
3015
+ };
3016
+ readonly then: {
3017
+ readonly properties: {
3018
+ readonly default: {
3019
+ readonly type: "array";
3020
+ readonly items: {
3021
+ readonly type: "string";
3022
+ };
3023
+ };
3024
+ readonly enum: {
3025
+ readonly items: {
3026
+ readonly type: "array";
3027
+ readonly items: {
3028
+ readonly type: "string";
3029
+ };
3030
+ };
3031
+ };
3032
+ };
3033
+ };
3034
+ }];
2899
3035
  };
2900
3036
  };
2901
3037
  readonly nodes: {
@@ -2956,7 +3092,6 @@ export declare const workflowJsonSchema: {
2956
3092
  readonly eval_policy: {
2957
3093
  readonly type: "string";
2958
3094
  readonly enum: readonly ["all_pass", "any_pass", "weighted"];
2959
- readonly default: "all_pass";
2960
3095
  readonly description: "How evaluator results aggregate. v1 implements all_pass; the others are reserved.";
2961
3096
  };
2962
3097
  readonly judge_model: {
@@ -2964,6 +3099,11 @@ export declare const workflowJsonSchema: {
2964
3099
  readonly minLength: 1;
2965
3100
  readonly description: "Default model for judge evaluators on this node. Overrides workflow-level judge_model.";
2966
3101
  };
3102
+ readonly model: {
3103
+ readonly type: "string";
3104
+ readonly minLength: 1;
3105
+ readonly description: "Execution model for this node's AI invocation. Overrides the workflow-level model. Free-text passthrough (no registry).";
3106
+ };
2967
3107
  readonly requires: {
2968
3108
  readonly type: "object";
2969
3109
  readonly description: "Pre-condition checks evaluated before the LLM runs.";
@@ -3151,6 +3291,11 @@ export declare const skillJsonSchema: {
3151
3291
  readonly required: readonly ["id", "name", "description", "category", "config"];
3152
3292
  readonly anyOf: readonly [{
3153
3293
  readonly required: readonly ["tools"];
3294
+ readonly properties: {
3295
+ readonly tools: {
3296
+ readonly minItems: 1;
3297
+ };
3298
+ };
3154
3299
  }, {
3155
3300
  readonly required: readonly ["instruction"];
3156
3301
  }, {
@@ -3201,6 +3346,18 @@ export declare const skillJsonSchema: {
3201
3346
  readonly $ref: "#/$defs/McpServerConfig";
3202
3347
  readonly description: "External MCP server definition wired for nodes referencing this skill.";
3203
3348
  };
3349
+ readonly mcpAliases: {
3350
+ readonly type: "object";
3351
+ readonly description: "Maps a logical MCP server name to the tool-name aliases nodes use to reference it. Each entry is a non-empty list of non-empty strings.";
3352
+ readonly additionalProperties: {
3353
+ readonly type: "array";
3354
+ readonly minItems: 1;
3355
+ readonly items: {
3356
+ readonly type: "string";
3357
+ readonly minLength: 1;
3358
+ };
3359
+ };
3360
+ };
3204
3361
  };
3205
3362
  readonly $defs: {
3206
3363
  readonly ConfigField: {
package/dist/schema.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * parsing untrusted input (JSON/YAML import, Studio editor).
8
8
  */
9
9
  import { z } from "zod";
10
- import { EVALUATOR_KINDS, EVAL_POLICIES, MCP_TRANSPORTS, REQUIRES_ON_FAIL, SKILL_CATEGORIES, SKILL_ID_MAX_LENGTH, SKILL_ID_PATTERN, } from "./types.js";
10
+ import { EVALUATOR_KINDS, EVAL_POLICIES, MCP_TRANSPORTS, REQUIRES_ON_FAIL, SKILL_CATEGORIES, SKILL_ID_MAX_LENGTH, SKILL_ID_PATTERN, WORKFLOW_TYPES, } from "./types.js";
11
11
  import { sourceZ } from "./sources.js";
12
12
  import { workflowInputsZ, WORKFLOW_INPUT_TYPES } from "./inputs.js";
13
13
  export { sourceZ };
@@ -66,6 +66,13 @@ export const skillZ = z
66
66
  mcp: mcpServerConfigZ.optional(),
67
67
  mcpAliases: z.record(z.array(z.string().min(1)).min(1)).optional(),
68
68
  })
69
+ // Strict to match the published skill JSON Schema's
70
+ // `additionalProperties: false`. Without this an unknown top-level key was
71
+ // silently STRIPPED by Zod but REJECTED by ajv (the one remaining
72
+ // Zod<->ajv skill divergence #214 flagged). custom-loader.ts builds Skill
73
+ // objects from frontmatter directly and never runs skillZ, so nothing
74
+ // downstream relies on extra keys passing through.
75
+ .strict()
69
76
  .refine((s) => s.tools.length > 0 || s.instruction || s.mcp, {
70
77
  message: "Skill must provide at least one of: tools, instruction, or mcp",
71
78
  });
@@ -200,6 +207,7 @@ export const nodeZ = z
200
207
  eval: z.array(evaluatorZ).min(1).optional(),
201
208
  eval_policy: evalPolicyZ.optional(),
202
209
  judge_model: z.string().min(1).optional(),
210
+ model: z.string().min(1).optional(),
203
211
  requires: nodeRequiresZ.optional(),
204
212
  retry: nodeRetryZ.optional(),
205
213
  })
@@ -224,7 +232,7 @@ export const edgeZ = z
224
232
  * Adding a new value here is a deliberate spec change: it requires a new
225
233
  * cloud renderer + metric schema. Don't extend casually.
226
234
  */
227
- export const workflowTypeZ = z.enum(["pr_review", "e2e_test", "content_generation", "monitor", "data_sync", "generic"]);
235
+ export const workflowTypeZ = z.enum(WORKFLOW_TYPES);
228
236
  // Fix #4 gap — workflowZ is intentionally NOT .strict(). The published
229
237
  // JSON Schema's `additionalProperties: false` only scopes the properties
230
238
  // block, but marketplace workflows routinely carry top-level metadata
@@ -243,6 +251,7 @@ export const workflowZ = z.object({
243
251
  rules: z.array(sourceZ).optional(),
244
252
  context: z.array(sourceZ).optional(),
245
253
  judge_model: z.string().min(1).optional(),
254
+ model: z.string().min(1).optional(),
246
255
  judge_budget: z.number().int().min(0).optional(),
247
256
  inputs: workflowInputsZ.optional(),
248
257
  });
@@ -259,7 +268,7 @@ const LEGACY_VERIFY_MESSAGE = "uses the legacy 'verify:' field. It was renamed t
259
268
  * - Top-level `workflow.verify` (typo / wrong scope).
260
269
  * - Per-node `nodes[*].verify` (the most common shape pre-rename).
261
270
  */
262
- function preflightLegacyVerify(raw) {
271
+ export function preflightLegacyVerify(raw) {
263
272
  if (!raw || typeof raw !== "object")
264
273
  return;
265
274
  const wf = raw;
@@ -532,14 +541,28 @@ export const workflowJsonSchema = {
532
541
  description: "judge only. Override the judge model for this evaluator.",
533
542
  },
534
543
  },
544
+ // The `then` branches mirror evaluatorZ.superRefine exactly: each kind
545
+ // requires its own field AND forbids the other kind's fields. Without
546
+ // the `not` clauses ajv only checked presence, so a `value` evaluator
547
+ // carrying a `rubric` passed ajv but threw under Zod (cross-kind drift).
535
548
  allOf: [
536
549
  {
537
550
  if: { properties: { kind: { enum: ["value", "function"] } } },
538
- then: { required: ["rule"] },
551
+ then: {
552
+ required: ["rule"],
553
+ // judge-only fields are illegal on value / function evaluators.
554
+ not: {
555
+ anyOf: [{ required: ["rubric"] }, { required: ["pass_when"] }, { required: ["model"] }],
556
+ },
557
+ },
539
558
  },
540
559
  {
541
560
  if: { properties: { kind: { const: "judge" } } },
542
- then: { required: ["rubric"] },
561
+ then: {
562
+ required: ["rubric"],
563
+ // `rule` is value / function only.
564
+ not: { required: ["rule"] },
565
+ },
543
566
  },
544
567
  ],
545
568
  },
@@ -561,19 +584,27 @@ export const workflowJsonSchema = {
561
584
  },
562
585
  workflow_type: {
563
586
  type: "string",
564
- enum: ["pr_review", "e2e_test", "content_generation", "monitor", "data_sync", "generic"],
587
+ enum: [...WORKFLOW_TYPES],
565
588
  description: "Workflow type discriminator. Cloud uses this to route runs to a type-specific renderer. Optional; absence defaults to 'generic'.",
566
589
  },
567
590
  judge_model: {
568
591
  type: "string",
569
592
  minLength: 1,
570
- default: "claude-haiku-4-5",
593
+ // No JSON `default` here: the Zod parser leaves this undefined and the
594
+ // executor applies the effective judge-model default at use-time. A
595
+ // documented JSON default that Zod never writes back is misleading.
571
596
  description: "Default model for judge evaluators across the workflow. Overridable per-node and per-evaluator.",
572
597
  },
598
+ model: {
599
+ type: "string",
600
+ minLength: 1,
601
+ description: "Default execution model for every node. Overridable per-node. Free-text passthrough (no registry); resolved as node.model ?? workflow.model ?? executor default.",
602
+ },
573
603
  judge_budget: {
574
604
  type: "integer",
575
605
  minimum: 0,
576
- default: 50,
606
+ // No JSON `default` here: Zod leaves this undefined; the executor
607
+ // applies the soft-cap default at use-time. See judge_model above.
577
608
  description: "Soft cap on expected judge calls per workflow run. Executor warns at load time if exceeded; not a hard runtime cap in v1.",
578
609
  },
579
610
  inputs: {
@@ -607,6 +638,61 @@ export const workflowJsonSchema = {
607
638
  description: "Optional set of allowed values. Validated after the type check.",
608
639
  },
609
640
  },
641
+ // The combination `required: true` together with a `default` is incoherent:
642
+ // a default would either silently satisfy the required check (making it
643
+ // vestigial) or never fire (making the default dead code). Reject the
644
+ // combination at JSON-Schema validation time so external validators agree
645
+ // with the Zod parser. See workflowInputFieldZ.superRefine in inputs.ts.
646
+ not: {
647
+ type: "object",
648
+ required: ["required", "default"],
649
+ properties: {
650
+ required: { const: true },
651
+ },
652
+ },
653
+ // Per-type checks on `default` and each `enum` element, mirroring
654
+ // workflowInputFieldZ.superRefine -> checkValueType in inputs.ts.
655
+ // Without these, a `type: number` field with `default: "x"` passed
656
+ // ajv but threw under Zod (default/enum type drift). One if/then per
657
+ // primitive in WORKFLOW_INPUT_TYPES.
658
+ allOf: [
659
+ {
660
+ if: { properties: { type: { const: "string" } } },
661
+ then: {
662
+ properties: {
663
+ default: { type: "string" },
664
+ enum: { items: { type: "string" } },
665
+ },
666
+ },
667
+ },
668
+ {
669
+ if: { properties: { type: { const: "number" } } },
670
+ then: {
671
+ properties: {
672
+ default: { type: "number" },
673
+ enum: { items: { type: "number" } },
674
+ },
675
+ },
676
+ },
677
+ {
678
+ if: { properties: { type: { const: "boolean" } } },
679
+ then: {
680
+ properties: {
681
+ default: { type: "boolean" },
682
+ enum: { items: { type: "boolean" } },
683
+ },
684
+ },
685
+ },
686
+ {
687
+ if: { properties: { type: { const: "string[]" } } },
688
+ then: {
689
+ properties: {
690
+ default: { type: "array", items: { type: "string" } },
691
+ enum: { items: { type: "array", items: { type: "string" } } },
692
+ },
693
+ },
694
+ },
695
+ ],
610
696
  },
611
697
  },
612
698
  nodes: {
@@ -654,7 +740,10 @@ export const workflowJsonSchema = {
654
740
  eval_policy: {
655
741
  type: "string",
656
742
  enum: [...EVAL_POLICIES],
657
- default: "all_pass",
743
+ // No JSON `default` here: evalPolicyZ is `.optional()` with no
744
+ // `.default()`, so Zod leaves this undefined and the executor
745
+ // applies `?? "all_pass"` at use-time (executor.ts aggregateEval).
746
+ // Matches the judge_model / judge_budget treatment (issue #214 #6).
658
747
  description: "How evaluator results aggregate. v1 implements all_pass; the others are reserved.",
659
748
  },
660
749
  judge_model: {
@@ -662,6 +751,11 @@ export const workflowJsonSchema = {
662
751
  minLength: 1,
663
752
  description: "Default model for judge evaluators on this node. Overrides workflow-level judge_model.",
664
753
  },
754
+ model: {
755
+ type: "string",
756
+ minLength: 1,
757
+ description: "Execution model for this node's AI invocation. Overrides the workflow-level model. Free-text passthrough (no registry).",
758
+ },
665
759
  requires: {
666
760
  type: "object",
667
761
  description: "Pre-condition checks evaluated before the LLM runs.",
@@ -784,7 +878,15 @@ export const skillJsonSchema = {
784
878
  description: "A composable tool bundle that provides capabilities to workflow nodes.",
785
879
  type: "object",
786
880
  required: ["id", "name", "description", "category", "config"],
787
- anyOf: [{ required: ["tools"] }, { required: ["instruction"] }, { required: ["mcp"] }],
881
+ // Mirror skillZ.refine: a skill must provide at least one of NON-EMPTY
882
+ // tools, instruction, or mcp. `required: ["tools"]` alone is satisfied by
883
+ // `tools: []` (presence, not non-emptiness), so the tools branch pins
884
+ // minItems: 1 to match Zod (which checks `s.tools.length > 0`).
885
+ anyOf: [
886
+ { required: ["tools"], properties: { tools: { minItems: 1 } } },
887
+ { required: ["instruction"] },
888
+ { required: ["mcp"] },
889
+ ],
788
890
  additionalProperties: false,
789
891
  properties: {
790
892
  id: {
@@ -826,6 +928,19 @@ export const skillJsonSchema = {
826
928
  $ref: "#/$defs/McpServerConfig",
827
929
  description: "External MCP server definition wired for nodes referencing this skill.",
828
930
  },
931
+ // Mirror skillZ.mcpAliases: a record mapping a logical MCP server name
932
+ // to a non-empty list of non-empty tool-name aliases. Omitting this from
933
+ // the published schema (which is additionalProperties: false) caused ajv
934
+ // to REJECT valid skills that Zod accepts.
935
+ mcpAliases: {
936
+ type: "object",
937
+ description: "Maps a logical MCP server name to the tool-name aliases nodes use to reference it. Each entry is a non-empty list of non-empty strings.",
938
+ additionalProperties: {
939
+ type: "array",
940
+ minItems: 1,
941
+ items: { type: "string", minLength: 1 },
942
+ },
943
+ },
829
944
  },
830
945
  $defs: {
831
946
  ConfigField: {
@@ -15,7 +15,7 @@ import type { Skill } from "../types.js";
15
15
  * can inspect `kind` to decide whether to surface, ignore, or fail.
16
16
  */
17
17
  export interface SkillDiagnostic {
18
- kind: "invalid-frontmatter" | "missing-name" | "invalid-id" | "unreadable-file" | "duplicate-id";
18
+ kind: "invalid-frontmatter" | "missing-name" | "invalid-id" | "unreadable-file" | "duplicate-id" | "stdio-command-declared";
19
19
  path: string;
20
20
  message: string;
21
21
  }
@@ -30,14 +30,14 @@ export interface SkillDiscoveryResult {
30
30
  * to users. `discoverSkills` stays as a backward-compatible wrapper for
31
31
  * callers that only want the happy-path skill list.
32
32
  */
33
- export declare function discoverSkillsWithDiagnostics(cwd?: string): SkillDiscoveryResult;
33
+ export declare function discoverSkillsWithDiagnostics(cwd?: string, env?: Record<string, string | undefined>): SkillDiscoveryResult;
34
34
  /**
35
35
  * Discover custom skills from all known harness directories.
36
36
  *
37
37
  * Backwards-compatible wrapper that drops diagnostics. Use
38
38
  * `discoverSkillsWithDiagnostics` when you want to surface warnings.
39
39
  */
40
- export declare function discoverSkills(cwd?: string): Skill[];
40
+ export declare function discoverSkills(cwd?: string, env?: Record<string, string | undefined>): Skill[];
41
41
  /**
42
42
  * Legacy API — load custom skills from `.claude/skills/` only.
43
43
  * @deprecated Use `discoverSkills` for multi-directory support.