agent-contracts 0.12.3 → 0.13.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.
package/dist/index.js CHANGED
@@ -49863,7 +49863,7 @@ var require_dist12 = __commonJS({
49863
49863
  var draft4MetaSchema = require_json_schema_draft_04();
49864
49864
  var META_SUPPORT_DATA = ["/properties"];
49865
49865
  var META_SCHEMA_ID = "http://json-schema.org/draft-04/schema";
49866
- var Ajv2 = class extends core_1.default {
49866
+ var Ajv3 = class extends core_1.default {
49867
49867
  constructor(opts = {}) {
49868
49868
  super({
49869
49869
  ...opts,
@@ -49888,9 +49888,9 @@ var require_dist12 = __commonJS({
49888
49888
  return this.opts.defaultMeta = super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : void 0);
49889
49889
  }
49890
49890
  };
49891
- module.exports = exports = Ajv2;
49891
+ module.exports = exports = Ajv3;
49892
49892
  Object.defineProperty(exports, "__esModule", { value: true });
49893
- exports.default = Ajv2;
49893
+ exports.default = Ajv3;
49894
49894
  var core_2 = __require("ajv/dist/core");
49895
49895
  Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function() {
49896
49896
  return core_2.KeywordCxt;
@@ -50087,8 +50087,8 @@ var require_ajv2 = __commonJS({
50087
50087
  log: console.log,
50088
50088
  error: console.error
50089
50089
  };
50090
- function createAjvInstance(Ajv2, allErrors) {
50091
- const ajv2 = new Ajv2({
50090
+ function createAjvInstance(Ajv3, allErrors) {
50091
+ const ajv2 = new Ajv3({
50092
50092
  allErrors,
50093
50093
  meta: true,
50094
50094
  messages: true,
@@ -50101,22 +50101,22 @@ var require_ajv2 = __commonJS({
50101
50101
  if (allErrors) {
50102
50102
  (0, ajv_errors_1.default)(ajv2);
50103
50103
  }
50104
- if (Ajv2 === ajv_1.default) {
50104
+ if (Ajv3 === ajv_1.default) {
50105
50105
  ajv2.addSchema(draft4MetaSchema);
50106
50106
  ajv2.addSchema(draft6MetaSchema);
50107
50107
  }
50108
50108
  return ajv2;
50109
50109
  }
50110
- function _createAjvInstances(Ajv2) {
50110
+ function _createAjvInstances(Ajv3) {
50111
50111
  let _default;
50112
50112
  let _allErrors;
50113
50113
  return {
50114
50114
  get default() {
50115
- _default !== null && _default !== void 0 ? _default : _default = createAjvInstance(Ajv2, false);
50115
+ _default !== null && _default !== void 0 ? _default : _default = createAjvInstance(Ajv3, false);
50116
50116
  return _default;
50117
50117
  },
50118
50118
  get allErrors() {
50119
- _allErrors !== null && _allErrors !== void 0 ? _allErrors : _allErrors = createAjvInstance(Ajv2, true);
50119
+ _allErrors !== null && _allErrors !== void 0 ? _allErrors : _allErrors = createAjvInstance(Ajv3, true);
50120
50120
  return _allErrors;
50121
50121
  }
50122
50122
  };
@@ -50748,10 +50748,34 @@ var WorkflowSchema = z11.object({
50748
50748
  var ComponentsSchema = z12.object({
50749
50749
  schemas: z12.record(z12.string(), z12.record(z12.string(), z12.any())).default({})
50750
50750
  }).passthrough();
50751
+ var SCOPE_NODE_TYPES = [
50752
+ "root",
50753
+ "system",
50754
+ "agent",
50755
+ "task",
50756
+ "execution_step",
50757
+ "artifact",
50758
+ "tool",
50759
+ "tool_command",
50760
+ "validation",
50761
+ "handoff_type",
50762
+ "workflow",
50763
+ "workflow_step",
50764
+ "policy",
50765
+ "guardrail",
50766
+ "guardrail_policy",
50767
+ "rule",
50768
+ "escalation_criterion",
50769
+ "prerequisite"
50770
+ ];
50771
+ var ScopeNodeTypeSchema = z12.enum(SCOPE_NODE_TYPES);
50751
50772
  var XExtensionDeclSchema = z12.object({
50752
50773
  type: z12.string(),
50753
50774
  items: z12.string().optional(),
50754
- description: z12.string().optional()
50775
+ description: z12.string().optional(),
50776
+ scope: z12.array(ScopeNodeTypeSchema).optional(),
50777
+ schema: z12.record(z12.string(), z12.any()).optional(),
50778
+ required: z12.boolean().default(false)
50755
50779
  });
50756
50780
  var DslSchema = z12.object({
50757
50781
  version: z12.literal(1),
@@ -50768,7 +50792,8 @@ var DslSchema = z12.object({
50768
50792
  guardrails: z12.record(z12.string(), GuardrailSchema).default({}),
50769
50793
  guardrail_policies: z12.record(z12.string(), GuardrailPolicySchema).default({}),
50770
50794
  components: ComponentsSchema.default({ schemas: {} }),
50771
- "x-extensions": z12.record(z12.string(), XExtensionDeclSchema).optional()
50795
+ extensions: z12.record(z12.string(), XExtensionDeclSchema).default({}),
50796
+ extensions_strict: z12.boolean().default(false)
50772
50797
  }).passthrough();
50773
50798
 
50774
50799
  // src/schema/json-schema-utils.ts
@@ -51387,7 +51412,8 @@ var MERGE_SECTIONS = [
51387
51412
  "policies",
51388
51413
  "guardrails",
51389
51414
  "guardrail_policies",
51390
- "components"
51415
+ "components",
51416
+ "extensions"
51391
51417
  ];
51392
51418
  function mergeDsl(base, project) {
51393
51419
  const hasExtends = typeof project["extends"] === "string";
@@ -51449,6 +51475,7 @@ function expandDefaults(data) {
51449
51475
  }
51450
51476
 
51451
51477
  // src/validator/schema-validator.ts
51478
+ import Ajv from "ajv";
51452
51479
  import { z as z14 } from "zod";
51453
51480
  function unwrap(schema) {
51454
51481
  if (schema instanceof z14.ZodOptional) return unwrap(schema.unwrap());
@@ -51510,14 +51537,14 @@ function checkCustomPropsRecursive(data, schema, path) {
51510
51537
  }
51511
51538
  return [];
51512
51539
  }
51513
- function checkXExtensionsKeys(data) {
51514
- const extensions = data["x-extensions"];
51540
+ function checkExtensionsKeys(data) {
51541
+ const extensions = data["extensions"];
51515
51542
  if (typeof extensions !== "object" || extensions === null) return [];
51516
51543
  const diagnostics = [];
51517
51544
  for (const key of Object.keys(extensions)) {
51518
51545
  if (!key.startsWith("x-")) {
51519
51546
  diagnostics.push({
51520
- path: `x-extensions.${key}`,
51547
+ path: `extensions.${key}`,
51521
51548
  message: `Extension key "${key}" must start with "x-" prefix.`,
51522
51549
  code: "x-extension-key-prefix"
51523
51550
  });
@@ -51551,29 +51578,634 @@ function checkDecisionStepRoutingKey(data) {
51551
51578
  }
51552
51579
  return diagnostics;
51553
51580
  }
51554
- function validateSchema(data) {
51555
- const result = DslSchema.safeParse(data);
51556
- if (!result.success) {
51557
- const diagnostics = result.error.issues.map((issue) => ({
51558
- path: issue.path.join("."),
51559
- message: issue.message,
51560
- code: "schema-validation"
51561
- }));
51562
- return { success: false, diagnostics };
51581
+ function isRecord3(v2) {
51582
+ return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
51583
+ }
51584
+ function* enumerateEntitiesByType(data, nodeType) {
51585
+ switch (nodeType) {
51586
+ case "root":
51587
+ yield { path: "", obj: data };
51588
+ return;
51589
+ case "system": {
51590
+ const sys = data["system"];
51591
+ if (isRecord3(sys)) yield { path: "system", obj: sys };
51592
+ return;
51593
+ }
51594
+ case "agent": {
51595
+ const agents = data["agents"];
51596
+ if (!isRecord3(agents)) return;
51597
+ for (const [id, a3] of Object.entries(agents)) {
51598
+ if (isRecord3(a3)) yield { path: `agents.${id}`, obj: a3 };
51599
+ }
51600
+ return;
51601
+ }
51602
+ case "rule": {
51603
+ const agents = data["agents"];
51604
+ if (!isRecord3(agents)) return;
51605
+ for (const [aid, a3] of Object.entries(agents)) {
51606
+ if (!isRecord3(a3)) continue;
51607
+ const rules = a3["rules"];
51608
+ if (!Array.isArray(rules)) continue;
51609
+ for (let i3 = 0; i3 < rules.length; i3++) {
51610
+ const r3 = rules[i3];
51611
+ if (isRecord3(r3)) yield { path: `agents.${aid}.rules[${i3}]`, obj: r3 };
51612
+ }
51613
+ }
51614
+ return;
51615
+ }
51616
+ case "escalation_criterion": {
51617
+ const agents = data["agents"];
51618
+ if (!isRecord3(agents)) return;
51619
+ for (const [aid, a3] of Object.entries(agents)) {
51620
+ if (!isRecord3(a3)) continue;
51621
+ const esc = a3["escalation_criteria"];
51622
+ if (!Array.isArray(esc)) continue;
51623
+ for (let i3 = 0; i3 < esc.length; i3++) {
51624
+ const e3 = esc[i3];
51625
+ if (isRecord3(e3)) {
51626
+ yield {
51627
+ path: `agents.${aid}.escalation_criteria[${i3}]`,
51628
+ obj: e3
51629
+ };
51630
+ }
51631
+ }
51632
+ }
51633
+ return;
51634
+ }
51635
+ case "prerequisite": {
51636
+ const agents = data["agents"];
51637
+ if (!isRecord3(agents)) return;
51638
+ for (const [aid, a3] of Object.entries(agents)) {
51639
+ if (!isRecord3(a3)) continue;
51640
+ const pre = a3["prerequisites"];
51641
+ if (!Array.isArray(pre)) continue;
51642
+ for (let i3 = 0; i3 < pre.length; i3++) {
51643
+ const p2 = pre[i3];
51644
+ if (isRecord3(p2)) {
51645
+ yield { path: `agents.${aid}.prerequisites[${i3}]`, obj: p2 };
51646
+ }
51647
+ }
51648
+ }
51649
+ return;
51650
+ }
51651
+ case "task": {
51652
+ const tasks = data["tasks"];
51653
+ if (!isRecord3(tasks)) return;
51654
+ for (const [id, t3] of Object.entries(tasks)) {
51655
+ if (isRecord3(t3)) yield { path: `tasks.${id}`, obj: t3 };
51656
+ }
51657
+ return;
51658
+ }
51659
+ case "execution_step": {
51660
+ const tasks = data["tasks"];
51661
+ if (!isRecord3(tasks)) return;
51662
+ for (const [tid, t3] of Object.entries(tasks)) {
51663
+ if (!isRecord3(t3)) continue;
51664
+ const steps = t3["execution_steps"];
51665
+ if (!Array.isArray(steps)) continue;
51666
+ for (let i3 = 0; i3 < steps.length; i3++) {
51667
+ const s2 = steps[i3];
51668
+ if (isRecord3(s2)) {
51669
+ yield {
51670
+ path: `tasks.${tid}.execution_steps[${i3}]`,
51671
+ obj: s2
51672
+ };
51673
+ }
51674
+ }
51675
+ }
51676
+ return;
51677
+ }
51678
+ case "artifact": {
51679
+ const arts = data["artifacts"];
51680
+ if (!isRecord3(arts)) return;
51681
+ for (const [id, a3] of Object.entries(arts)) {
51682
+ if (isRecord3(a3)) yield { path: `artifacts.${id}`, obj: a3 };
51683
+ }
51684
+ return;
51685
+ }
51686
+ case "tool": {
51687
+ const tools = data["tools"];
51688
+ if (!isRecord3(tools)) return;
51689
+ for (const [id, t3] of Object.entries(tools)) {
51690
+ if (isRecord3(t3)) yield { path: `tools.${id}`, obj: t3 };
51691
+ }
51692
+ return;
51693
+ }
51694
+ case "tool_command": {
51695
+ const tools = data["tools"];
51696
+ if (!isRecord3(tools)) return;
51697
+ for (const [tid, t3] of Object.entries(tools)) {
51698
+ if (!isRecord3(t3)) continue;
51699
+ const cmds = t3["commands"];
51700
+ if (!Array.isArray(cmds)) continue;
51701
+ for (let i3 = 0; i3 < cmds.length; i3++) {
51702
+ const c2 = cmds[i3];
51703
+ if (isRecord3(c2)) {
51704
+ yield { path: `tools.${tid}.commands[${i3}]`, obj: c2 };
51705
+ }
51706
+ }
51707
+ }
51708
+ return;
51709
+ }
51710
+ case "validation": {
51711
+ const vals = data["validations"];
51712
+ if (!isRecord3(vals)) return;
51713
+ for (const [id, v2] of Object.entries(vals)) {
51714
+ if (isRecord3(v2)) yield { path: `validations.${id}`, obj: v2 };
51715
+ }
51716
+ return;
51717
+ }
51718
+ case "handoff_type": {
51719
+ const ht = data["handoff_types"];
51720
+ if (!isRecord3(ht)) return;
51721
+ for (const [id, h2] of Object.entries(ht)) {
51722
+ if (isRecord3(h2)) yield { path: `handoff_types.${id}`, obj: h2 };
51723
+ }
51724
+ return;
51725
+ }
51726
+ case "workflow": {
51727
+ const wf = data["workflow"];
51728
+ if (!isRecord3(wf)) return;
51729
+ for (const [id, w2] of Object.entries(wf)) {
51730
+ if (isRecord3(w2)) yield { path: `workflow.${id}`, obj: w2 };
51731
+ }
51732
+ return;
51733
+ }
51734
+ case "workflow_step": {
51735
+ const wf = data["workflow"];
51736
+ if (!isRecord3(wf)) return;
51737
+ for (const [wid, w2] of Object.entries(wf)) {
51738
+ if (!isRecord3(w2)) continue;
51739
+ const steps = w2["steps"];
51740
+ if (!Array.isArray(steps)) continue;
51741
+ for (let i3 = 0; i3 < steps.length; i3++) {
51742
+ const s2 = steps[i3];
51743
+ if (isRecord3(s2)) {
51744
+ yield { path: `workflow.${wid}.steps[${i3}]`, obj: s2 };
51745
+ }
51746
+ }
51747
+ }
51748
+ return;
51749
+ }
51750
+ case "policy": {
51751
+ const pol = data["policies"];
51752
+ if (!isRecord3(pol)) return;
51753
+ for (const [id, p2] of Object.entries(pol)) {
51754
+ if (isRecord3(p2)) yield { path: `policies.${id}`, obj: p2 };
51755
+ }
51756
+ return;
51757
+ }
51758
+ case "guardrail": {
51759
+ const gr = data["guardrails"];
51760
+ if (!isRecord3(gr)) return;
51761
+ for (const [id, g2] of Object.entries(gr)) {
51762
+ if (isRecord3(g2)) yield { path: `guardrails.${id}`, obj: g2 };
51763
+ }
51764
+ return;
51765
+ }
51766
+ case "guardrail_policy": {
51767
+ const gp = data["guardrail_policies"];
51768
+ if (!isRecord3(gp)) return;
51769
+ for (const [id, p2] of Object.entries(gp)) {
51770
+ if (isRecord3(p2)) yield { path: `guardrail_policies.${id}`, obj: p2 };
51771
+ }
51772
+ return;
51773
+ }
51774
+ default:
51775
+ return;
51563
51776
  }
51564
- const customPropDiagnostics = checkCustomPropsRecursive(data, DslSchema, "");
51565
- if (customPropDiagnostics.length > 0) {
51566
- return { success: false, diagnostics: customPropDiagnostics };
51777
+ }
51778
+ function validateDeclaredExtension(parentPath, nodeType, key, val, declMap, diagnostics, ajvInstance, strict) {
51779
+ const path = parentPath ? `${parentPath}.${key}` : key;
51780
+ const decl = declMap[key];
51781
+ if (decl === void 0) {
51782
+ diagnostics.push({
51783
+ path,
51784
+ message: `Extension "${key}" is not declared in extensions.`,
51785
+ code: "undeclared-extension",
51786
+ ...!strict ? { severity: "warning" } : {}
51787
+ });
51788
+ return;
51567
51789
  }
51568
- const decisionDiagnostics = checkDecisionStepRoutingKey(data);
51569
- if (decisionDiagnostics.length > 0) {
51570
- return { success: false, diagnostics: decisionDiagnostics };
51790
+ const scope = decl.scope;
51791
+ if (scope && scope.length > 0 && !scope.includes(nodeType)) {
51792
+ diagnostics.push({
51793
+ path,
51794
+ message: `Extension "${key}" is not allowed on ${nodeType} (declared scope: ${scope.join(", ")}).`,
51795
+ code: "extension-scope-mismatch"
51796
+ });
51797
+ return;
51571
51798
  }
51572
- const xExtDiagnostics = checkXExtensionsKeys(data);
51573
- if (xExtDiagnostics.length > 0) {
51574
- return { success: false, diagnostics: xExtDiagnostics };
51799
+ if (decl.schema && typeof decl.schema === "object" && decl.schema !== null && Object.keys(decl.schema).length > 0) {
51800
+ try {
51801
+ const validate = ajvInstance.compile(decl.schema);
51802
+ if (!validate(val)) {
51803
+ diagnostics.push({
51804
+ path,
51805
+ message: `Extension "${key}" value does not match declared schema: ${ajvInstance.errorsText(validate.errors)}`,
51806
+ code: "extension-schema-violation"
51807
+ });
51808
+ }
51809
+ } catch (e3) {
51810
+ diagnostics.push({
51811
+ path,
51812
+ message: `Extension "${key}" has invalid JSON Schema in declaration: ${e3 instanceof Error ? e3.message : String(e3)}`,
51813
+ code: "extension-schema-violation"
51814
+ });
51815
+ }
51575
51816
  }
51576
- return { success: true, data: result.data, diagnostics: [] };
51817
+ }
51818
+ function walkExtensionNodes(value, path, nodeType, declMap, diagnostics, ajvInstance, strict) {
51819
+ if (!isRecord3(value)) return;
51820
+ const obj = value;
51821
+ for (const key of Object.keys(obj)) {
51822
+ if (key === "extensions" || key === "extensions_strict" || key === "x-extensions" || key === "x-extensions-strict") {
51823
+ continue;
51824
+ }
51825
+ if (key.startsWith("x-")) {
51826
+ validateDeclaredExtension(
51827
+ path,
51828
+ nodeType,
51829
+ key,
51830
+ obj[key],
51831
+ declMap,
51832
+ diagnostics,
51833
+ ajvInstance,
51834
+ strict
51835
+ );
51836
+ }
51837
+ }
51838
+ switch (nodeType) {
51839
+ case "root": {
51840
+ const sys = obj["system"];
51841
+ if (isRecord3(sys)) {
51842
+ walkExtensionNodes(
51843
+ sys,
51844
+ "system",
51845
+ "system",
51846
+ declMap,
51847
+ diagnostics,
51848
+ ajvInstance,
51849
+ strict
51850
+ );
51851
+ }
51852
+ const agents = obj["agents"];
51853
+ if (isRecord3(agents)) {
51854
+ for (const [id, a3] of Object.entries(agents)) {
51855
+ if (isRecord3(a3)) {
51856
+ walkExtensionNodes(
51857
+ a3,
51858
+ `agents.${id}`,
51859
+ "agent",
51860
+ declMap,
51861
+ diagnostics,
51862
+ ajvInstance,
51863
+ strict
51864
+ );
51865
+ }
51866
+ }
51867
+ }
51868
+ const tasks = obj["tasks"];
51869
+ if (isRecord3(tasks)) {
51870
+ for (const [id, t3] of Object.entries(tasks)) {
51871
+ if (isRecord3(t3)) {
51872
+ walkExtensionNodes(
51873
+ t3,
51874
+ `tasks.${id}`,
51875
+ "task",
51876
+ declMap,
51877
+ diagnostics,
51878
+ ajvInstance,
51879
+ strict
51880
+ );
51881
+ }
51882
+ }
51883
+ }
51884
+ const artifacts = obj["artifacts"];
51885
+ if (isRecord3(artifacts)) {
51886
+ for (const [id, a3] of Object.entries(artifacts)) {
51887
+ if (isRecord3(a3)) {
51888
+ walkExtensionNodes(
51889
+ a3,
51890
+ `artifacts.${id}`,
51891
+ "artifact",
51892
+ declMap,
51893
+ diagnostics,
51894
+ ajvInstance,
51895
+ strict
51896
+ );
51897
+ }
51898
+ }
51899
+ }
51900
+ const tools = obj["tools"];
51901
+ if (isRecord3(tools)) {
51902
+ for (const [id, t3] of Object.entries(tools)) {
51903
+ if (isRecord3(t3)) {
51904
+ walkExtensionNodes(
51905
+ t3,
51906
+ `tools.${id}`,
51907
+ "tool",
51908
+ declMap,
51909
+ diagnostics,
51910
+ ajvInstance,
51911
+ strict
51912
+ );
51913
+ }
51914
+ }
51915
+ }
51916
+ const validations = obj["validations"];
51917
+ if (isRecord3(validations)) {
51918
+ for (const [id, v2] of Object.entries(validations)) {
51919
+ if (isRecord3(v2)) {
51920
+ walkExtensionNodes(
51921
+ v2,
51922
+ `validations.${id}`,
51923
+ "validation",
51924
+ declMap,
51925
+ diagnostics,
51926
+ ajvInstance,
51927
+ strict
51928
+ );
51929
+ }
51930
+ }
51931
+ }
51932
+ const handoffTypes = obj["handoff_types"];
51933
+ if (isRecord3(handoffTypes)) {
51934
+ for (const [id, h2] of Object.entries(handoffTypes)) {
51935
+ if (isRecord3(h2)) {
51936
+ walkExtensionNodes(
51937
+ h2,
51938
+ `handoff_types.${id}`,
51939
+ "handoff_type",
51940
+ declMap,
51941
+ diagnostics,
51942
+ ajvInstance,
51943
+ strict
51944
+ );
51945
+ }
51946
+ }
51947
+ }
51948
+ const workflow = obj["workflow"];
51949
+ if (isRecord3(workflow)) {
51950
+ for (const [id, w2] of Object.entries(workflow)) {
51951
+ if (isRecord3(w2)) {
51952
+ walkExtensionNodes(
51953
+ w2,
51954
+ `workflow.${id}`,
51955
+ "workflow",
51956
+ declMap,
51957
+ diagnostics,
51958
+ ajvInstance,
51959
+ strict
51960
+ );
51961
+ }
51962
+ }
51963
+ }
51964
+ const policies = obj["policies"];
51965
+ if (isRecord3(policies)) {
51966
+ for (const [id, p2] of Object.entries(policies)) {
51967
+ if (isRecord3(p2)) {
51968
+ walkExtensionNodes(
51969
+ p2,
51970
+ `policies.${id}`,
51971
+ "policy",
51972
+ declMap,
51973
+ diagnostics,
51974
+ ajvInstance,
51975
+ strict
51976
+ );
51977
+ }
51978
+ }
51979
+ }
51980
+ const guardrails = obj["guardrails"];
51981
+ if (isRecord3(guardrails)) {
51982
+ for (const [id, g2] of Object.entries(guardrails)) {
51983
+ if (isRecord3(g2)) {
51984
+ walkExtensionNodes(
51985
+ g2,
51986
+ `guardrails.${id}`,
51987
+ "guardrail",
51988
+ declMap,
51989
+ diagnostics,
51990
+ ajvInstance,
51991
+ strict
51992
+ );
51993
+ }
51994
+ }
51995
+ }
51996
+ const guardrailPolicies = obj["guardrail_policies"];
51997
+ if (isRecord3(guardrailPolicies)) {
51998
+ for (const [id, p2] of Object.entries(guardrailPolicies)) {
51999
+ if (isRecord3(p2)) {
52000
+ walkExtensionNodes(
52001
+ p2,
52002
+ `guardrail_policies.${id}`,
52003
+ "guardrail_policy",
52004
+ declMap,
52005
+ diagnostics,
52006
+ ajvInstance,
52007
+ strict
52008
+ );
52009
+ }
52010
+ }
52011
+ }
52012
+ break;
52013
+ }
52014
+ case "agent": {
52015
+ const rules = obj["rules"];
52016
+ if (Array.isArray(rules)) {
52017
+ for (let i3 = 0; i3 < rules.length; i3++) {
52018
+ const r3 = rules[i3];
52019
+ if (isRecord3(r3)) {
52020
+ walkExtensionNodes(
52021
+ r3,
52022
+ `${path}.rules[${i3}]`,
52023
+ "rule",
52024
+ declMap,
52025
+ diagnostics,
52026
+ ajvInstance,
52027
+ strict
52028
+ );
52029
+ }
52030
+ }
52031
+ }
52032
+ const esc = obj["escalation_criteria"];
52033
+ if (Array.isArray(esc)) {
52034
+ for (let i3 = 0; i3 < esc.length; i3++) {
52035
+ const e3 = esc[i3];
52036
+ if (isRecord3(e3)) {
52037
+ walkExtensionNodes(
52038
+ e3,
52039
+ `${path}.escalation_criteria[${i3}]`,
52040
+ "escalation_criterion",
52041
+ declMap,
52042
+ diagnostics,
52043
+ ajvInstance,
52044
+ strict
52045
+ );
52046
+ }
52047
+ }
52048
+ }
52049
+ const pre = obj["prerequisites"];
52050
+ if (Array.isArray(pre)) {
52051
+ for (let i3 = 0; i3 < pre.length; i3++) {
52052
+ const p2 = pre[i3];
52053
+ if (isRecord3(p2)) {
52054
+ walkExtensionNodes(
52055
+ p2,
52056
+ `${path}.prerequisites[${i3}]`,
52057
+ "prerequisite",
52058
+ declMap,
52059
+ diagnostics,
52060
+ ajvInstance,
52061
+ strict
52062
+ );
52063
+ }
52064
+ }
52065
+ }
52066
+ break;
52067
+ }
52068
+ case "task": {
52069
+ const steps = obj["execution_steps"];
52070
+ if (Array.isArray(steps)) {
52071
+ for (let i3 = 0; i3 < steps.length; i3++) {
52072
+ const s2 = steps[i3];
52073
+ if (isRecord3(s2)) {
52074
+ walkExtensionNodes(
52075
+ s2,
52076
+ `${path}.execution_steps[${i3}]`,
52077
+ "execution_step",
52078
+ declMap,
52079
+ diagnostics,
52080
+ ajvInstance,
52081
+ strict
52082
+ );
52083
+ }
52084
+ }
52085
+ }
52086
+ break;
52087
+ }
52088
+ case "tool": {
52089
+ const cmds = obj["commands"];
52090
+ if (Array.isArray(cmds)) {
52091
+ for (let i3 = 0; i3 < cmds.length; i3++) {
52092
+ const c2 = cmds[i3];
52093
+ if (isRecord3(c2)) {
52094
+ walkExtensionNodes(
52095
+ c2,
52096
+ `${path}.commands[${i3}]`,
52097
+ "tool_command",
52098
+ declMap,
52099
+ diagnostics,
52100
+ ajvInstance,
52101
+ strict
52102
+ );
52103
+ }
52104
+ }
52105
+ }
52106
+ break;
52107
+ }
52108
+ case "workflow": {
52109
+ const steps = obj["steps"];
52110
+ if (Array.isArray(steps)) {
52111
+ for (let i3 = 0; i3 < steps.length; i3++) {
52112
+ const s2 = steps[i3];
52113
+ if (isRecord3(s2)) {
52114
+ walkExtensionNodes(
52115
+ s2,
52116
+ `${path}.steps[${i3}]`,
52117
+ "workflow_step",
52118
+ declMap,
52119
+ diagnostics,
52120
+ ajvInstance,
52121
+ strict
52122
+ );
52123
+ }
52124
+ }
52125
+ }
52126
+ break;
52127
+ }
52128
+ default:
52129
+ break;
52130
+ }
52131
+ }
52132
+ function checkExtensionValidation(data) {
52133
+ const strict = data["extensions_strict"] === true;
52134
+ const raw = data["extensions"];
52135
+ let declMap;
52136
+ if (!isRecord3(raw) || Object.keys(raw).length === 0) {
52137
+ if (!strict) return [];
52138
+ declMap = {};
52139
+ } else {
52140
+ declMap = raw;
52141
+ }
52142
+ const diagnostics = [];
52143
+ const ajvInstance = new Ajv({ allErrors: true, strict: false });
52144
+ walkExtensionNodes(data, "", "root", declMap, diagnostics, ajvInstance, strict);
52145
+ for (const [extKey, decl] of Object.entries(declMap)) {
52146
+ if (!decl.required) continue;
52147
+ const applicableTypes = decl.scope && decl.scope.length > 0 ? decl.scope : [...SCOPE_NODE_TYPES];
52148
+ for (const t3 of applicableTypes) {
52149
+ for (const { path, obj } of enumerateEntitiesByType(data, t3)) {
52150
+ if (!(extKey in obj)) {
52151
+ diagnostics.push({
52152
+ path,
52153
+ message: `Required extension "${extKey}" is missing on ${t3}.`,
52154
+ code: "extension-required-missing"
52155
+ });
52156
+ }
52157
+ }
52158
+ }
52159
+ }
52160
+ return diagnostics;
52161
+ }
52162
+ function hasBlockingDiagnostic(diagnostics) {
52163
+ return diagnostics.some((d2) => d2.severity !== "warning");
52164
+ }
52165
+ function validateSchema(data) {
52166
+ const deprecationWarnings = [];
52167
+ if ("x-extensions" in data && !("extensions" in data)) {
52168
+ data["extensions"] = data["x-extensions"];
52169
+ deprecationWarnings.push({
52170
+ path: "x-extensions",
52171
+ message: '"x-extensions" is deprecated. Use "extensions" instead.',
52172
+ code: "deprecated-property",
52173
+ severity: "warning"
52174
+ });
52175
+ }
52176
+ if ("x-extensions-strict" in data && !("extensions_strict" in data)) {
52177
+ data["extensions_strict"] = data["x-extensions-strict"];
52178
+ deprecationWarnings.push({
52179
+ path: "x-extensions-strict",
52180
+ message: '"x-extensions-strict" is deprecated. Use "extensions_strict" instead.',
52181
+ code: "deprecated-property",
52182
+ severity: "warning"
52183
+ });
52184
+ }
52185
+ const result = DslSchema.safeParse(data);
52186
+ if (!result.success) {
52187
+ const diagnostics2 = [
52188
+ ...deprecationWarnings,
52189
+ ...result.error.issues.map((issue) => ({
52190
+ path: issue.path.join("."),
52191
+ message: issue.message,
52192
+ code: "schema-validation"
52193
+ }))
52194
+ ];
52195
+ return { success: false, diagnostics: diagnostics2 };
52196
+ }
52197
+ const diagnostics = [
52198
+ ...deprecationWarnings,
52199
+ ...checkCustomPropsRecursive(data, DslSchema, ""),
52200
+ ...checkDecisionStepRoutingKey(data),
52201
+ ...checkExtensionsKeys(data),
52202
+ ...checkExtensionValidation(data)
52203
+ ];
52204
+ return {
52205
+ success: !hasBlockingDiagnostic(diagnostics),
52206
+ data: result.data,
52207
+ diagnostics
52208
+ };
51577
52209
  }
51578
52210
 
51579
52211
  // src/validator/reference-resolver.ts
@@ -51881,8 +52513,8 @@ function checkReferences(dsl) {
51881
52513
  }
51882
52514
 
51883
52515
  // src/validator/handoff-schema-validator.ts
51884
- import Ajv from "ajv";
51885
- var ajv = new Ajv({ allErrors: true, strict: false });
52516
+ import Ajv2 from "ajv";
52517
+ var ajv = new Ajv2({ allErrors: true, strict: false });
51886
52518
  function validateHandoffSchemas(dsl) {
51887
52519
  const diagnostics = [];
51888
52520
  for (const [kind, ht] of Object.entries(dsl.handoff_types)) {
@@ -52597,6 +53229,40 @@ var guardrailOrphanedRule = {
52597
53229
  }
52598
53230
  };
52599
53231
 
53232
+ // src/linter/rules/validation-executor-no-context.ts
53233
+ var validationExecutorNoContextRule = {
53234
+ id: "validation-executor-no-context",
53235
+ description: "Validation executor is not wired so the validation appears in the executor's rendered context",
53236
+ run(dsl) {
53237
+ const diagnostics = [];
53238
+ for (const [validationId, val] of Object.entries(dsl.validations)) {
53239
+ if (val.executor_type === "agent") {
53240
+ const agent = dsl.agents[val.executor];
53241
+ if (!agent) continue;
53242
+ const allowed = new Set(agent.can_perform_validations ?? []);
53243
+ if (!allowed.has(validationId)) {
53244
+ diagnostics.push({
53245
+ ruleId: "validation-executor-no-context",
53246
+ severity: "warning",
53247
+ path: `agents.${val.executor}.can_perform_validations`,
53248
+ message: `Validation "${validationId}" is executed by agent "${val.executor}" but is not listed in can_perform_validations, so it will be missing from that agent's prompt context`
53249
+ });
53250
+ }
53251
+ } else if (val.executor_type === "tool") {
53252
+ if (!dsl.tools[val.executor]) {
53253
+ diagnostics.push({
53254
+ ruleId: "validation-executor-no-context",
53255
+ severity: "warning",
53256
+ path: `validations.${validationId}.executor`,
53257
+ message: `Validation "${validationId}" references tool executor "${val.executor}" which is not defined in tools`
53258
+ });
53259
+ }
53260
+ }
53261
+ }
53262
+ return diagnostics;
53263
+ }
53264
+ };
53265
+
52600
53266
  // src/linter/linter.ts
52601
53267
  var builtinRules = [
52602
53268
  validationCoverageRule,
@@ -52612,7 +53278,8 @@ var builtinRules = [
52612
53278
  semanticValidationPhaseCoverageRule,
52613
53279
  entityGuardrailUndefinedRule,
52614
53280
  entityNoGuardrailsRule,
52615
- guardrailOrphanedRule
53281
+ guardrailOrphanedRule,
53282
+ validationExecutorNoContextRule
52616
53283
  ];
52617
53284
  function lint(dsl, rules = builtinRules) {
52618
53285
  const diagnostics = [];
@@ -53368,13 +54035,54 @@ function resolveEffectiveGuardrails(dsl, entityType, entityId) {
53368
54035
  }
53369
54036
  return entries;
53370
54037
  }
54038
+ function validationToEntityEntry(validationId, validation) {
54039
+ return {
54040
+ validation_id: validationId,
54041
+ kind: validation.kind,
54042
+ target_artifact: validation.target_artifact,
54043
+ executor_type: validation.executor_type,
54044
+ blocking: validation.blocking,
54045
+ produces_evidence: validation.produces_evidence
54046
+ };
54047
+ }
54048
+ function resolveEntityValidations(dsl, entityType, entityId) {
54049
+ if (entityType === "agents") {
54050
+ const agent = dsl.agents[entityId];
54051
+ if (!agent) return [];
54052
+ const entries2 = [];
54053
+ for (const vid of agent.can_perform_validations ?? []) {
54054
+ const v2 = dsl.validations[vid];
54055
+ if (v2) entries2.push(validationToEntityEntry(vid, v2));
54056
+ }
54057
+ return entries2;
54058
+ }
54059
+ if (entityType === "tasks") {
54060
+ const task = dsl.tasks[entityId];
54061
+ if (!task) return [];
54062
+ const entries2 = [];
54063
+ for (const vid of task.validations ?? []) {
54064
+ const v2 = dsl.validations[vid];
54065
+ if (v2) entries2.push(validationToEntityEntry(vid, v2));
54066
+ }
54067
+ return entries2;
54068
+ }
54069
+ const entries = [];
54070
+ for (const [vid, v2] of Object.entries(dsl.validations)) {
54071
+ if (v2.executor_type === "tool" && v2.executor === entityId) {
54072
+ entries.push(validationToEntityEntry(vid, v2));
54073
+ }
54074
+ }
54075
+ entries.sort((a3, b3) => a3.validation_id.localeCompare(b3.validation_id));
54076
+ return entries;
54077
+ }
53371
54078
  function buildTaskContext(dsl, taskId) {
53372
54079
  const taskDef = dsl.tasks[taskId];
53373
54080
  const task = { ...taskDef, id: taskId };
53374
54081
  const agentDef = dsl.agents[taskDef.target_agent];
53375
54082
  const targetAgent = agentDef ? { ...agentDef, id: taskDef.target_agent } : null;
53376
54083
  const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tasks", taskId);
53377
- return { task, targetAgent, relatedGuardrails, dsl };
54084
+ const relatedValidations = resolveEntityValidations(dsl, "tasks", taskId);
54085
+ return { task, targetAgent, relatedGuardrails, relatedValidations, dsl };
53378
54086
  }
53379
54087
  function buildArtifactContext(dsl, artifactId) {
53380
54088
  const artifactDef = dsl.artifacts[artifactId];
@@ -53445,12 +54153,14 @@ function buildToolContext(dsl, toolId) {
53445
54153
  return result;
53446
54154
  };
53447
54155
  const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tools", toolId);
54156
+ const relatedValidations = resolveEntityValidations(dsl, "tools", toolId);
53448
54157
  return {
53449
54158
  tool,
53450
54159
  invokableAgents,
53451
54160
  inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
53452
54161
  outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
53453
54162
  relatedGuardrails,
54163
+ relatedValidations,
53454
54164
  dsl
53455
54165
  };
53456
54166
  }
@@ -53683,6 +54393,7 @@ function buildPerAgentContext(dsl, agent) {
53683
54393
  const rawReceivableTasks = receivableTasks.map(({ id: _id, ...rest }) => rest);
53684
54394
  const mergedBehavior = mergeBehavioralSpec(agent, rawReceivableTasks);
53685
54395
  const relatedGuardrails = resolveEffectiveGuardrails(dsl, "agents", agentId);
54396
+ const relatedValidations = resolveEntityValidations(dsl, "agents", agentId);
53686
54397
  return {
53687
54398
  agent,
53688
54399
  tasks: receivableTasks,
@@ -53693,6 +54404,7 @@ function buildPerAgentContext(dsl, agent) {
53693
54404
  relatedHandoffTypes,
53694
54405
  mergedBehavior,
53695
54406
  relatedGuardrails,
54407
+ relatedValidations,
53696
54408
  dsl
53697
54409
  };
53698
54410
  }
@@ -54758,7 +55470,7 @@ function resolveDslPath(dirArg, dirArgDefault, config) {
54758
55470
  }
54759
55471
 
54760
55472
  // src/config/binding-merger.ts
54761
- function isRecord3(v2) {
55473
+ function isRecord4(v2) {
54762
55474
  return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
54763
55475
  }
54764
55476
  var BINDING_MERGE_SECTIONS = ["guardrail_impl", "outputs"];
@@ -54771,7 +55483,7 @@ function mergeBinding(base, project) {
54771
55483
  if (projVal === void 0) {
54772
55484
  continue;
54773
55485
  }
54774
- const baseMap = isRecord3(baseVal) ? baseVal : {};
55486
+ const baseMap = isRecord4(baseVal) ? baseVal : {};
54775
55487
  result[section] = mergeEntityMaps(
54776
55488
  baseMap,
54777
55489
  projVal,
@@ -54779,7 +55491,7 @@ function mergeBinding(base, project) {
54779
55491
  hasExtends
54780
55492
  );
54781
55493
  }
54782
- if (project["reporting"] !== void 0 && isRecord3(base["reporting"]) && isRecord3(project["reporting"])) {
55494
+ if (project["reporting"] !== void 0 && isRecord4(base["reporting"]) && isRecord4(project["reporting"])) {
54783
55495
  result["reporting"] = deepMergeEntities(
54784
55496
  base["reporting"],
54785
55497
  project["reporting"],
@@ -55584,6 +56296,8 @@ export {
55584
56296
  ReplaceOperatorSchema,
55585
56297
  ReportingSchema,
55586
56298
  RuleSchema,
56299
+ SCOPE_NODE_TYPES,
56300
+ ScopeNodeTypeSchema,
55587
56301
  SoftwareBindingSchema,
55588
56302
  SystemSchema,
55589
56303
  TaskSchema,
@@ -55623,6 +56337,7 @@ export {
55623
56337
  resolveChecks,
55624
56338
  resolveDslPath,
55625
56339
  resolveEffectiveGuardrails,
56340
+ resolveEntityValidations,
55626
56341
  score,
55627
56342
  spectralLint,
55628
56343
  validateHandoffSchemas,