agent-contracts 0.12.4 → 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;
51776
+ }
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;
51789
+ }
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;
51798
+ }
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
+ }
51816
+ }
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;
51563
52130
  }
51564
- const customPropDiagnostics = checkCustomPropsRecursive(data, DslSchema, "");
51565
- if (customPropDiagnostics.length > 0) {
51566
- return { success: false, diagnostics: customPropDiagnostics };
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;
51567
52141
  }
51568
- const decisionDiagnostics = checkDecisionStepRoutingKey(data);
51569
- if (decisionDiagnostics.length > 0) {
51570
- return { success: false, diagnostics: decisionDiagnostics };
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
+ }
51571
52159
  }
51572
- const xExtDiagnostics = checkXExtensionsKeys(data);
51573
- if (xExtDiagnostics.length > 0) {
51574
- return { success: false, diagnostics: xExtDiagnostics };
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
+ });
51575
52175
  }
51576
- return { success: true, data: result.data, diagnostics: [] };
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)) {
@@ -54838,7 +55470,7 @@ function resolveDslPath(dirArg, dirArgDefault, config) {
54838
55470
  }
54839
55471
 
54840
55472
  // src/config/binding-merger.ts
54841
- function isRecord3(v2) {
55473
+ function isRecord4(v2) {
54842
55474
  return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
54843
55475
  }
54844
55476
  var BINDING_MERGE_SECTIONS = ["guardrail_impl", "outputs"];
@@ -54851,7 +55483,7 @@ function mergeBinding(base, project) {
54851
55483
  if (projVal === void 0) {
54852
55484
  continue;
54853
55485
  }
54854
- const baseMap = isRecord3(baseVal) ? baseVal : {};
55486
+ const baseMap = isRecord4(baseVal) ? baseVal : {};
54855
55487
  result[section] = mergeEntityMaps(
54856
55488
  baseMap,
54857
55489
  projVal,
@@ -54859,7 +55491,7 @@ function mergeBinding(base, project) {
54859
55491
  hasExtends
54860
55492
  );
54861
55493
  }
54862
- if (project["reporting"] !== void 0 && isRecord3(base["reporting"]) && isRecord3(project["reporting"])) {
55494
+ if (project["reporting"] !== void 0 && isRecord4(base["reporting"]) && isRecord4(project["reporting"])) {
54863
55495
  result["reporting"] = deepMergeEntities(
54864
55496
  base["reporting"],
54865
55497
  project["reporting"],
@@ -55664,6 +56296,8 @@ export {
55664
56296
  ReplaceOperatorSchema,
55665
56297
  ReportingSchema,
55666
56298
  RuleSchema,
56299
+ SCOPE_NODE_TYPES,
56300
+ ScopeNodeTypeSchema,
55667
56301
  SoftwareBindingSchema,
55668
56302
  SystemSchema,
55669
56303
  TaskSchema,