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/cli.js CHANGED
@@ -49864,7 +49864,7 @@ var require_dist12 = __commonJS({
49864
49864
  var draft4MetaSchema = require_json_schema_draft_04();
49865
49865
  var META_SUPPORT_DATA = ["/properties"];
49866
49866
  var META_SCHEMA_ID = "http://json-schema.org/draft-04/schema";
49867
- var Ajv2 = class extends core_1.default {
49867
+ var Ajv3 = class extends core_1.default {
49868
49868
  constructor(opts = {}) {
49869
49869
  super({
49870
49870
  ...opts,
@@ -49889,9 +49889,9 @@ var require_dist12 = __commonJS({
49889
49889
  return this.opts.defaultMeta = super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : void 0);
49890
49890
  }
49891
49891
  };
49892
- module.exports = exports = Ajv2;
49892
+ module.exports = exports = Ajv3;
49893
49893
  Object.defineProperty(exports, "__esModule", { value: true });
49894
- exports.default = Ajv2;
49894
+ exports.default = Ajv3;
49895
49895
  var core_2 = __require("ajv/dist/core");
49896
49896
  Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function() {
49897
49897
  return core_2.KeywordCxt;
@@ -50088,8 +50088,8 @@ var require_ajv2 = __commonJS({
50088
50088
  log: console.log,
50089
50089
  error: console.error
50090
50090
  };
50091
- function createAjvInstance(Ajv2, allErrors) {
50092
- const ajv2 = new Ajv2({
50091
+ function createAjvInstance(Ajv3, allErrors) {
50092
+ const ajv2 = new Ajv3({
50093
50093
  allErrors,
50094
50094
  meta: true,
50095
50095
  messages: true,
@@ -50102,22 +50102,22 @@ var require_ajv2 = __commonJS({
50102
50102
  if (allErrors) {
50103
50103
  (0, ajv_errors_1.default)(ajv2);
50104
50104
  }
50105
- if (Ajv2 === ajv_1.default) {
50105
+ if (Ajv3 === ajv_1.default) {
50106
50106
  ajv2.addSchema(draft4MetaSchema);
50107
50107
  ajv2.addSchema(draft6MetaSchema);
50108
50108
  }
50109
50109
  return ajv2;
50110
50110
  }
50111
- function _createAjvInstances(Ajv2) {
50111
+ function _createAjvInstances(Ajv3) {
50112
50112
  let _default;
50113
50113
  let _allErrors;
50114
50114
  return {
50115
50115
  get default() {
50116
- _default !== null && _default !== void 0 ? _default : _default = createAjvInstance(Ajv2, false);
50116
+ _default !== null && _default !== void 0 ? _default : _default = createAjvInstance(Ajv3, false);
50117
50117
  return _default;
50118
50118
  },
50119
50119
  get allErrors() {
50120
- _allErrors !== null && _allErrors !== void 0 ? _allErrors : _allErrors = createAjvInstance(Ajv2, true);
50120
+ _allErrors !== null && _allErrors !== void 0 ? _allErrors : _allErrors = createAjvInstance(Ajv3, true);
50121
50121
  return _allErrors;
50122
50122
  }
50123
50123
  };
@@ -50764,10 +50764,34 @@ var WorkflowSchema = z11.object({
50764
50764
  var ComponentsSchema = z12.object({
50765
50765
  schemas: z12.record(z12.string(), z12.record(z12.string(), z12.any())).default({})
50766
50766
  }).passthrough();
50767
+ var SCOPE_NODE_TYPES = [
50768
+ "root",
50769
+ "system",
50770
+ "agent",
50771
+ "task",
50772
+ "execution_step",
50773
+ "artifact",
50774
+ "tool",
50775
+ "tool_command",
50776
+ "validation",
50777
+ "handoff_type",
50778
+ "workflow",
50779
+ "workflow_step",
50780
+ "policy",
50781
+ "guardrail",
50782
+ "guardrail_policy",
50783
+ "rule",
50784
+ "escalation_criterion",
50785
+ "prerequisite"
50786
+ ];
50787
+ var ScopeNodeTypeSchema = z12.enum(SCOPE_NODE_TYPES);
50767
50788
  var XExtensionDeclSchema = z12.object({
50768
50789
  type: z12.string(),
50769
50790
  items: z12.string().optional(),
50770
- description: z12.string().optional()
50791
+ description: z12.string().optional(),
50792
+ scope: z12.array(ScopeNodeTypeSchema).optional(),
50793
+ schema: z12.record(z12.string(), z12.any()).optional(),
50794
+ required: z12.boolean().default(false)
50771
50795
  });
50772
50796
  var DslSchema = z12.object({
50773
50797
  version: z12.literal(1),
@@ -50784,7 +50808,8 @@ var DslSchema = z12.object({
50784
50808
  guardrails: z12.record(z12.string(), GuardrailSchema).default({}),
50785
50809
  guardrail_policies: z12.record(z12.string(), GuardrailPolicySchema).default({}),
50786
50810
  components: ComponentsSchema.default({ schemas: {} }),
50787
- "x-extensions": z12.record(z12.string(), XExtensionDeclSchema).optional()
50811
+ extensions: z12.record(z12.string(), XExtensionDeclSchema).default({}),
50812
+ extensions_strict: z12.boolean().default(false)
50788
50813
  }).passthrough();
50789
50814
 
50790
50815
  // src/schema/json-schema-utils.ts
@@ -51541,7 +51566,8 @@ var MERGE_SECTIONS = [
51541
51566
  "policies",
51542
51567
  "guardrails",
51543
51568
  "guardrail_policies",
51544
- "components"
51569
+ "components",
51570
+ "extensions"
51545
51571
  ];
51546
51572
  function mergeDsl(base, project) {
51547
51573
  const hasExtends = typeof project["extends"] === "string";
@@ -51812,6 +51838,7 @@ var resolveCommand = new Command("resolve").description("Resolve DSL (load + mer
51812
51838
  import { Command as Command2 } from "commander";
51813
51839
 
51814
51840
  // src/validator/schema-validator.ts
51841
+ import Ajv from "ajv";
51815
51842
  import { z as z15 } from "zod";
51816
51843
  function unwrap(schema) {
51817
51844
  if (schema instanceof z15.ZodOptional) return unwrap(schema.unwrap());
@@ -51873,14 +51900,14 @@ function checkCustomPropsRecursive(data, schema, path) {
51873
51900
  }
51874
51901
  return [];
51875
51902
  }
51876
- function checkXExtensionsKeys(data) {
51877
- const extensions = data["x-extensions"];
51903
+ function checkExtensionsKeys(data) {
51904
+ const extensions = data["extensions"];
51878
51905
  if (typeof extensions !== "object" || extensions === null) return [];
51879
51906
  const diagnostics = [];
51880
51907
  for (const key of Object.keys(extensions)) {
51881
51908
  if (!key.startsWith("x-")) {
51882
51909
  diagnostics.push({
51883
- path: `x-extensions.${key}`,
51910
+ path: `extensions.${key}`,
51884
51911
  message: `Extension key "${key}" must start with "x-" prefix.`,
51885
51912
  code: "x-extension-key-prefix"
51886
51913
  });
@@ -51914,29 +51941,634 @@ function checkDecisionStepRoutingKey(data) {
51914
51941
  }
51915
51942
  return diagnostics;
51916
51943
  }
51917
- function validateSchema(data) {
51918
- const result = DslSchema.safeParse(data);
51919
- if (!result.success) {
51920
- const diagnostics = result.error.issues.map((issue) => ({
51921
- path: issue.path.join("."),
51922
- message: issue.message,
51923
- code: "schema-validation"
51924
- }));
51925
- return { success: false, diagnostics };
51944
+ function isRecord4(v2) {
51945
+ return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
51946
+ }
51947
+ function* enumerateEntitiesByType(data, nodeType) {
51948
+ switch (nodeType) {
51949
+ case "root":
51950
+ yield { path: "", obj: data };
51951
+ return;
51952
+ case "system": {
51953
+ const sys = data["system"];
51954
+ if (isRecord4(sys)) yield { path: "system", obj: sys };
51955
+ return;
51956
+ }
51957
+ case "agent": {
51958
+ const agents = data["agents"];
51959
+ if (!isRecord4(agents)) return;
51960
+ for (const [id, a3] of Object.entries(agents)) {
51961
+ if (isRecord4(a3)) yield { path: `agents.${id}`, obj: a3 };
51962
+ }
51963
+ return;
51964
+ }
51965
+ case "rule": {
51966
+ const agents = data["agents"];
51967
+ if (!isRecord4(agents)) return;
51968
+ for (const [aid, a3] of Object.entries(agents)) {
51969
+ if (!isRecord4(a3)) continue;
51970
+ const rules = a3["rules"];
51971
+ if (!Array.isArray(rules)) continue;
51972
+ for (let i3 = 0; i3 < rules.length; i3++) {
51973
+ const r3 = rules[i3];
51974
+ if (isRecord4(r3)) yield { path: `agents.${aid}.rules[${i3}]`, obj: r3 };
51975
+ }
51976
+ }
51977
+ return;
51978
+ }
51979
+ case "escalation_criterion": {
51980
+ const agents = data["agents"];
51981
+ if (!isRecord4(agents)) return;
51982
+ for (const [aid, a3] of Object.entries(agents)) {
51983
+ if (!isRecord4(a3)) continue;
51984
+ const esc = a3["escalation_criteria"];
51985
+ if (!Array.isArray(esc)) continue;
51986
+ for (let i3 = 0; i3 < esc.length; i3++) {
51987
+ const e3 = esc[i3];
51988
+ if (isRecord4(e3)) {
51989
+ yield {
51990
+ path: `agents.${aid}.escalation_criteria[${i3}]`,
51991
+ obj: e3
51992
+ };
51993
+ }
51994
+ }
51995
+ }
51996
+ return;
51997
+ }
51998
+ case "prerequisite": {
51999
+ const agents = data["agents"];
52000
+ if (!isRecord4(agents)) return;
52001
+ for (const [aid, a3] of Object.entries(agents)) {
52002
+ if (!isRecord4(a3)) continue;
52003
+ const pre = a3["prerequisites"];
52004
+ if (!Array.isArray(pre)) continue;
52005
+ for (let i3 = 0; i3 < pre.length; i3++) {
52006
+ const p2 = pre[i3];
52007
+ if (isRecord4(p2)) {
52008
+ yield { path: `agents.${aid}.prerequisites[${i3}]`, obj: p2 };
52009
+ }
52010
+ }
52011
+ }
52012
+ return;
52013
+ }
52014
+ case "task": {
52015
+ const tasks = data["tasks"];
52016
+ if (!isRecord4(tasks)) return;
52017
+ for (const [id, t3] of Object.entries(tasks)) {
52018
+ if (isRecord4(t3)) yield { path: `tasks.${id}`, obj: t3 };
52019
+ }
52020
+ return;
52021
+ }
52022
+ case "execution_step": {
52023
+ const tasks = data["tasks"];
52024
+ if (!isRecord4(tasks)) return;
52025
+ for (const [tid, t3] of Object.entries(tasks)) {
52026
+ if (!isRecord4(t3)) continue;
52027
+ const steps = t3["execution_steps"];
52028
+ if (!Array.isArray(steps)) continue;
52029
+ for (let i3 = 0; i3 < steps.length; i3++) {
52030
+ const s2 = steps[i3];
52031
+ if (isRecord4(s2)) {
52032
+ yield {
52033
+ path: `tasks.${tid}.execution_steps[${i3}]`,
52034
+ obj: s2
52035
+ };
52036
+ }
52037
+ }
52038
+ }
52039
+ return;
52040
+ }
52041
+ case "artifact": {
52042
+ const arts = data["artifacts"];
52043
+ if (!isRecord4(arts)) return;
52044
+ for (const [id, a3] of Object.entries(arts)) {
52045
+ if (isRecord4(a3)) yield { path: `artifacts.${id}`, obj: a3 };
52046
+ }
52047
+ return;
52048
+ }
52049
+ case "tool": {
52050
+ const tools = data["tools"];
52051
+ if (!isRecord4(tools)) return;
52052
+ for (const [id, t3] of Object.entries(tools)) {
52053
+ if (isRecord4(t3)) yield { path: `tools.${id}`, obj: t3 };
52054
+ }
52055
+ return;
52056
+ }
52057
+ case "tool_command": {
52058
+ const tools = data["tools"];
52059
+ if (!isRecord4(tools)) return;
52060
+ for (const [tid, t3] of Object.entries(tools)) {
52061
+ if (!isRecord4(t3)) continue;
52062
+ const cmds = t3["commands"];
52063
+ if (!Array.isArray(cmds)) continue;
52064
+ for (let i3 = 0; i3 < cmds.length; i3++) {
52065
+ const c2 = cmds[i3];
52066
+ if (isRecord4(c2)) {
52067
+ yield { path: `tools.${tid}.commands[${i3}]`, obj: c2 };
52068
+ }
52069
+ }
52070
+ }
52071
+ return;
52072
+ }
52073
+ case "validation": {
52074
+ const vals = data["validations"];
52075
+ if (!isRecord4(vals)) return;
52076
+ for (const [id, v2] of Object.entries(vals)) {
52077
+ if (isRecord4(v2)) yield { path: `validations.${id}`, obj: v2 };
52078
+ }
52079
+ return;
52080
+ }
52081
+ case "handoff_type": {
52082
+ const ht = data["handoff_types"];
52083
+ if (!isRecord4(ht)) return;
52084
+ for (const [id, h2] of Object.entries(ht)) {
52085
+ if (isRecord4(h2)) yield { path: `handoff_types.${id}`, obj: h2 };
52086
+ }
52087
+ return;
52088
+ }
52089
+ case "workflow": {
52090
+ const wf = data["workflow"];
52091
+ if (!isRecord4(wf)) return;
52092
+ for (const [id, w2] of Object.entries(wf)) {
52093
+ if (isRecord4(w2)) yield { path: `workflow.${id}`, obj: w2 };
52094
+ }
52095
+ return;
52096
+ }
52097
+ case "workflow_step": {
52098
+ const wf = data["workflow"];
52099
+ if (!isRecord4(wf)) return;
52100
+ for (const [wid, w2] of Object.entries(wf)) {
52101
+ if (!isRecord4(w2)) continue;
52102
+ const steps = w2["steps"];
52103
+ if (!Array.isArray(steps)) continue;
52104
+ for (let i3 = 0; i3 < steps.length; i3++) {
52105
+ const s2 = steps[i3];
52106
+ if (isRecord4(s2)) {
52107
+ yield { path: `workflow.${wid}.steps[${i3}]`, obj: s2 };
52108
+ }
52109
+ }
52110
+ }
52111
+ return;
52112
+ }
52113
+ case "policy": {
52114
+ const pol = data["policies"];
52115
+ if (!isRecord4(pol)) return;
52116
+ for (const [id, p2] of Object.entries(pol)) {
52117
+ if (isRecord4(p2)) yield { path: `policies.${id}`, obj: p2 };
52118
+ }
52119
+ return;
52120
+ }
52121
+ case "guardrail": {
52122
+ const gr = data["guardrails"];
52123
+ if (!isRecord4(gr)) return;
52124
+ for (const [id, g2] of Object.entries(gr)) {
52125
+ if (isRecord4(g2)) yield { path: `guardrails.${id}`, obj: g2 };
52126
+ }
52127
+ return;
52128
+ }
52129
+ case "guardrail_policy": {
52130
+ const gp = data["guardrail_policies"];
52131
+ if (!isRecord4(gp)) return;
52132
+ for (const [id, p2] of Object.entries(gp)) {
52133
+ if (isRecord4(p2)) yield { path: `guardrail_policies.${id}`, obj: p2 };
52134
+ }
52135
+ return;
52136
+ }
52137
+ default:
52138
+ return;
52139
+ }
52140
+ }
52141
+ function validateDeclaredExtension(parentPath, nodeType, key, val, declMap, diagnostics, ajvInstance, strict) {
52142
+ const path = parentPath ? `${parentPath}.${key}` : key;
52143
+ const decl = declMap[key];
52144
+ if (decl === void 0) {
52145
+ diagnostics.push({
52146
+ path,
52147
+ message: `Extension "${key}" is not declared in extensions.`,
52148
+ code: "undeclared-extension",
52149
+ ...!strict ? { severity: "warning" } : {}
52150
+ });
52151
+ return;
52152
+ }
52153
+ const scope = decl.scope;
52154
+ if (scope && scope.length > 0 && !scope.includes(nodeType)) {
52155
+ diagnostics.push({
52156
+ path,
52157
+ message: `Extension "${key}" is not allowed on ${nodeType} (declared scope: ${scope.join(", ")}).`,
52158
+ code: "extension-scope-mismatch"
52159
+ });
52160
+ return;
52161
+ }
52162
+ if (decl.schema && typeof decl.schema === "object" && decl.schema !== null && Object.keys(decl.schema).length > 0) {
52163
+ try {
52164
+ const validate = ajvInstance.compile(decl.schema);
52165
+ if (!validate(val)) {
52166
+ diagnostics.push({
52167
+ path,
52168
+ message: `Extension "${key}" value does not match declared schema: ${ajvInstance.errorsText(validate.errors)}`,
52169
+ code: "extension-schema-violation"
52170
+ });
52171
+ }
52172
+ } catch (e3) {
52173
+ diagnostics.push({
52174
+ path,
52175
+ message: `Extension "${key}" has invalid JSON Schema in declaration: ${e3 instanceof Error ? e3.message : String(e3)}`,
52176
+ code: "extension-schema-violation"
52177
+ });
52178
+ }
52179
+ }
52180
+ }
52181
+ function walkExtensionNodes(value, path, nodeType, declMap, diagnostics, ajvInstance, strict) {
52182
+ if (!isRecord4(value)) return;
52183
+ const obj = value;
52184
+ for (const key of Object.keys(obj)) {
52185
+ if (key === "extensions" || key === "extensions_strict" || key === "x-extensions" || key === "x-extensions-strict") {
52186
+ continue;
52187
+ }
52188
+ if (key.startsWith("x-")) {
52189
+ validateDeclaredExtension(
52190
+ path,
52191
+ nodeType,
52192
+ key,
52193
+ obj[key],
52194
+ declMap,
52195
+ diagnostics,
52196
+ ajvInstance,
52197
+ strict
52198
+ );
52199
+ }
52200
+ }
52201
+ switch (nodeType) {
52202
+ case "root": {
52203
+ const sys = obj["system"];
52204
+ if (isRecord4(sys)) {
52205
+ walkExtensionNodes(
52206
+ sys,
52207
+ "system",
52208
+ "system",
52209
+ declMap,
52210
+ diagnostics,
52211
+ ajvInstance,
52212
+ strict
52213
+ );
52214
+ }
52215
+ const agents = obj["agents"];
52216
+ if (isRecord4(agents)) {
52217
+ for (const [id, a3] of Object.entries(agents)) {
52218
+ if (isRecord4(a3)) {
52219
+ walkExtensionNodes(
52220
+ a3,
52221
+ `agents.${id}`,
52222
+ "agent",
52223
+ declMap,
52224
+ diagnostics,
52225
+ ajvInstance,
52226
+ strict
52227
+ );
52228
+ }
52229
+ }
52230
+ }
52231
+ const tasks = obj["tasks"];
52232
+ if (isRecord4(tasks)) {
52233
+ for (const [id, t3] of Object.entries(tasks)) {
52234
+ if (isRecord4(t3)) {
52235
+ walkExtensionNodes(
52236
+ t3,
52237
+ `tasks.${id}`,
52238
+ "task",
52239
+ declMap,
52240
+ diagnostics,
52241
+ ajvInstance,
52242
+ strict
52243
+ );
52244
+ }
52245
+ }
52246
+ }
52247
+ const artifacts = obj["artifacts"];
52248
+ if (isRecord4(artifacts)) {
52249
+ for (const [id, a3] of Object.entries(artifacts)) {
52250
+ if (isRecord4(a3)) {
52251
+ walkExtensionNodes(
52252
+ a3,
52253
+ `artifacts.${id}`,
52254
+ "artifact",
52255
+ declMap,
52256
+ diagnostics,
52257
+ ajvInstance,
52258
+ strict
52259
+ );
52260
+ }
52261
+ }
52262
+ }
52263
+ const tools = obj["tools"];
52264
+ if (isRecord4(tools)) {
52265
+ for (const [id, t3] of Object.entries(tools)) {
52266
+ if (isRecord4(t3)) {
52267
+ walkExtensionNodes(
52268
+ t3,
52269
+ `tools.${id}`,
52270
+ "tool",
52271
+ declMap,
52272
+ diagnostics,
52273
+ ajvInstance,
52274
+ strict
52275
+ );
52276
+ }
52277
+ }
52278
+ }
52279
+ const validations = obj["validations"];
52280
+ if (isRecord4(validations)) {
52281
+ for (const [id, v2] of Object.entries(validations)) {
52282
+ if (isRecord4(v2)) {
52283
+ walkExtensionNodes(
52284
+ v2,
52285
+ `validations.${id}`,
52286
+ "validation",
52287
+ declMap,
52288
+ diagnostics,
52289
+ ajvInstance,
52290
+ strict
52291
+ );
52292
+ }
52293
+ }
52294
+ }
52295
+ const handoffTypes = obj["handoff_types"];
52296
+ if (isRecord4(handoffTypes)) {
52297
+ for (const [id, h2] of Object.entries(handoffTypes)) {
52298
+ if (isRecord4(h2)) {
52299
+ walkExtensionNodes(
52300
+ h2,
52301
+ `handoff_types.${id}`,
52302
+ "handoff_type",
52303
+ declMap,
52304
+ diagnostics,
52305
+ ajvInstance,
52306
+ strict
52307
+ );
52308
+ }
52309
+ }
52310
+ }
52311
+ const workflow = obj["workflow"];
52312
+ if (isRecord4(workflow)) {
52313
+ for (const [id, w2] of Object.entries(workflow)) {
52314
+ if (isRecord4(w2)) {
52315
+ walkExtensionNodes(
52316
+ w2,
52317
+ `workflow.${id}`,
52318
+ "workflow",
52319
+ declMap,
52320
+ diagnostics,
52321
+ ajvInstance,
52322
+ strict
52323
+ );
52324
+ }
52325
+ }
52326
+ }
52327
+ const policies = obj["policies"];
52328
+ if (isRecord4(policies)) {
52329
+ for (const [id, p2] of Object.entries(policies)) {
52330
+ if (isRecord4(p2)) {
52331
+ walkExtensionNodes(
52332
+ p2,
52333
+ `policies.${id}`,
52334
+ "policy",
52335
+ declMap,
52336
+ diagnostics,
52337
+ ajvInstance,
52338
+ strict
52339
+ );
52340
+ }
52341
+ }
52342
+ }
52343
+ const guardrails = obj["guardrails"];
52344
+ if (isRecord4(guardrails)) {
52345
+ for (const [id, g2] of Object.entries(guardrails)) {
52346
+ if (isRecord4(g2)) {
52347
+ walkExtensionNodes(
52348
+ g2,
52349
+ `guardrails.${id}`,
52350
+ "guardrail",
52351
+ declMap,
52352
+ diagnostics,
52353
+ ajvInstance,
52354
+ strict
52355
+ );
52356
+ }
52357
+ }
52358
+ }
52359
+ const guardrailPolicies = obj["guardrail_policies"];
52360
+ if (isRecord4(guardrailPolicies)) {
52361
+ for (const [id, p2] of Object.entries(guardrailPolicies)) {
52362
+ if (isRecord4(p2)) {
52363
+ walkExtensionNodes(
52364
+ p2,
52365
+ `guardrail_policies.${id}`,
52366
+ "guardrail_policy",
52367
+ declMap,
52368
+ diagnostics,
52369
+ ajvInstance,
52370
+ strict
52371
+ );
52372
+ }
52373
+ }
52374
+ }
52375
+ break;
52376
+ }
52377
+ case "agent": {
52378
+ const rules = obj["rules"];
52379
+ if (Array.isArray(rules)) {
52380
+ for (let i3 = 0; i3 < rules.length; i3++) {
52381
+ const r3 = rules[i3];
52382
+ if (isRecord4(r3)) {
52383
+ walkExtensionNodes(
52384
+ r3,
52385
+ `${path}.rules[${i3}]`,
52386
+ "rule",
52387
+ declMap,
52388
+ diagnostics,
52389
+ ajvInstance,
52390
+ strict
52391
+ );
52392
+ }
52393
+ }
52394
+ }
52395
+ const esc = obj["escalation_criteria"];
52396
+ if (Array.isArray(esc)) {
52397
+ for (let i3 = 0; i3 < esc.length; i3++) {
52398
+ const e3 = esc[i3];
52399
+ if (isRecord4(e3)) {
52400
+ walkExtensionNodes(
52401
+ e3,
52402
+ `${path}.escalation_criteria[${i3}]`,
52403
+ "escalation_criterion",
52404
+ declMap,
52405
+ diagnostics,
52406
+ ajvInstance,
52407
+ strict
52408
+ );
52409
+ }
52410
+ }
52411
+ }
52412
+ const pre = obj["prerequisites"];
52413
+ if (Array.isArray(pre)) {
52414
+ for (let i3 = 0; i3 < pre.length; i3++) {
52415
+ const p2 = pre[i3];
52416
+ if (isRecord4(p2)) {
52417
+ walkExtensionNodes(
52418
+ p2,
52419
+ `${path}.prerequisites[${i3}]`,
52420
+ "prerequisite",
52421
+ declMap,
52422
+ diagnostics,
52423
+ ajvInstance,
52424
+ strict
52425
+ );
52426
+ }
52427
+ }
52428
+ }
52429
+ break;
52430
+ }
52431
+ case "task": {
52432
+ const steps = obj["execution_steps"];
52433
+ if (Array.isArray(steps)) {
52434
+ for (let i3 = 0; i3 < steps.length; i3++) {
52435
+ const s2 = steps[i3];
52436
+ if (isRecord4(s2)) {
52437
+ walkExtensionNodes(
52438
+ s2,
52439
+ `${path}.execution_steps[${i3}]`,
52440
+ "execution_step",
52441
+ declMap,
52442
+ diagnostics,
52443
+ ajvInstance,
52444
+ strict
52445
+ );
52446
+ }
52447
+ }
52448
+ }
52449
+ break;
52450
+ }
52451
+ case "tool": {
52452
+ const cmds = obj["commands"];
52453
+ if (Array.isArray(cmds)) {
52454
+ for (let i3 = 0; i3 < cmds.length; i3++) {
52455
+ const c2 = cmds[i3];
52456
+ if (isRecord4(c2)) {
52457
+ walkExtensionNodes(
52458
+ c2,
52459
+ `${path}.commands[${i3}]`,
52460
+ "tool_command",
52461
+ declMap,
52462
+ diagnostics,
52463
+ ajvInstance,
52464
+ strict
52465
+ );
52466
+ }
52467
+ }
52468
+ }
52469
+ break;
52470
+ }
52471
+ case "workflow": {
52472
+ const steps = obj["steps"];
52473
+ if (Array.isArray(steps)) {
52474
+ for (let i3 = 0; i3 < steps.length; i3++) {
52475
+ const s2 = steps[i3];
52476
+ if (isRecord4(s2)) {
52477
+ walkExtensionNodes(
52478
+ s2,
52479
+ `${path}.steps[${i3}]`,
52480
+ "workflow_step",
52481
+ declMap,
52482
+ diagnostics,
52483
+ ajvInstance,
52484
+ strict
52485
+ );
52486
+ }
52487
+ }
52488
+ }
52489
+ break;
52490
+ }
52491
+ default:
52492
+ break;
51926
52493
  }
51927
- const customPropDiagnostics = checkCustomPropsRecursive(data, DslSchema, "");
51928
- if (customPropDiagnostics.length > 0) {
51929
- return { success: false, diagnostics: customPropDiagnostics };
52494
+ }
52495
+ function checkExtensionValidation(data) {
52496
+ const strict = data["extensions_strict"] === true;
52497
+ const raw = data["extensions"];
52498
+ let declMap;
52499
+ if (!isRecord4(raw) || Object.keys(raw).length === 0) {
52500
+ if (!strict) return [];
52501
+ declMap = {};
52502
+ } else {
52503
+ declMap = raw;
52504
+ }
52505
+ const diagnostics = [];
52506
+ const ajvInstance = new Ajv({ allErrors: true, strict: false });
52507
+ walkExtensionNodes(data, "", "root", declMap, diagnostics, ajvInstance, strict);
52508
+ for (const [extKey, decl] of Object.entries(declMap)) {
52509
+ if (!decl.required) continue;
52510
+ const applicableTypes = decl.scope && decl.scope.length > 0 ? decl.scope : [...SCOPE_NODE_TYPES];
52511
+ for (const t3 of applicableTypes) {
52512
+ for (const { path, obj } of enumerateEntitiesByType(data, t3)) {
52513
+ if (!(extKey in obj)) {
52514
+ diagnostics.push({
52515
+ path,
52516
+ message: `Required extension "${extKey}" is missing on ${t3}.`,
52517
+ code: "extension-required-missing"
52518
+ });
52519
+ }
52520
+ }
52521
+ }
51930
52522
  }
51931
- const decisionDiagnostics = checkDecisionStepRoutingKey(data);
51932
- if (decisionDiagnostics.length > 0) {
51933
- return { success: false, diagnostics: decisionDiagnostics };
52523
+ return diagnostics;
52524
+ }
52525
+ function hasBlockingDiagnostic(diagnostics) {
52526
+ return diagnostics.some((d2) => d2.severity !== "warning");
52527
+ }
52528
+ function validateSchema(data) {
52529
+ const deprecationWarnings = [];
52530
+ if ("x-extensions" in data && !("extensions" in data)) {
52531
+ data["extensions"] = data["x-extensions"];
52532
+ deprecationWarnings.push({
52533
+ path: "x-extensions",
52534
+ message: '"x-extensions" is deprecated. Use "extensions" instead.',
52535
+ code: "deprecated-property",
52536
+ severity: "warning"
52537
+ });
51934
52538
  }
51935
- const xExtDiagnostics = checkXExtensionsKeys(data);
51936
- if (xExtDiagnostics.length > 0) {
51937
- return { success: false, diagnostics: xExtDiagnostics };
52539
+ if ("x-extensions-strict" in data && !("extensions_strict" in data)) {
52540
+ data["extensions_strict"] = data["x-extensions-strict"];
52541
+ deprecationWarnings.push({
52542
+ path: "x-extensions-strict",
52543
+ message: '"x-extensions-strict" is deprecated. Use "extensions_strict" instead.',
52544
+ code: "deprecated-property",
52545
+ severity: "warning"
52546
+ });
51938
52547
  }
51939
- return { success: true, data: result.data, diagnostics: [] };
52548
+ const result = DslSchema.safeParse(data);
52549
+ if (!result.success) {
52550
+ const diagnostics2 = [
52551
+ ...deprecationWarnings,
52552
+ ...result.error.issues.map((issue) => ({
52553
+ path: issue.path.join("."),
52554
+ message: issue.message,
52555
+ code: "schema-validation"
52556
+ }))
52557
+ ];
52558
+ return { success: false, diagnostics: diagnostics2 };
52559
+ }
52560
+ const diagnostics = [
52561
+ ...deprecationWarnings,
52562
+ ...checkCustomPropsRecursive(data, DslSchema, ""),
52563
+ ...checkDecisionStepRoutingKey(data),
52564
+ ...checkExtensionsKeys(data),
52565
+ ...checkExtensionValidation(data)
52566
+ ];
52567
+ return {
52568
+ success: !hasBlockingDiagnostic(diagnostics),
52569
+ data: result.data,
52570
+ diagnostics
52571
+ };
51940
52572
  }
51941
52573
 
51942
52574
  // src/validator/reference-resolver.ts
@@ -52244,8 +52876,8 @@ function checkReferences(dsl) {
52244
52876
  }
52245
52877
 
52246
52878
  // src/validator/handoff-schema-validator.ts
52247
- import Ajv from "ajv";
52248
- var ajv = new Ajv({ allErrors: true, strict: false });
52879
+ import Ajv2 from "ajv";
52880
+ var ajv = new Ajv2({ allErrors: true, strict: false });
52249
52881
  function validateHandoffSchemas(dsl) {
52250
52882
  const diagnostics = [];
52251
52883
  for (const [kind, ht] of Object.entries(dsl.handoff_types)) {
@@ -52280,13 +52912,16 @@ function formatDiagnostics(diagnostics, options) {
52280
52912
 
52281
52913
  // src/cli/commands/validate.ts
52282
52914
  var DIR_DEFAULT2 = "agent-contracts.yaml";
52283
- var validateCommand = new Command2("validate").description("Validate DSL against schema and check references").argument("[dir]", "Path to agent-contracts.yaml", DIR_DEFAULT2).option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--format <format>", "Output format (text|json)", "text").option("--quiet", "Suppress output on success", false).action(async (dir, opts) => {
52915
+ var validateCommand = new Command2("validate").description("Validate DSL against schema and check references").argument("[dir]", "Path to agent-contracts.yaml", DIR_DEFAULT2).option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--format <format>", "Output format (text|json)", "text").option("--quiet", "Suppress output on success", false).option("--strict", "Treat warnings as errors", false).action(async (dir, opts) => {
52284
52916
  try {
52285
52917
  const config = await loadConfig(opts.config);
52286
52918
  const dslPath = resolveDslPath(dir, DIR_DEFAULT2, config);
52287
52919
  const resolved = await resolve4(dslPath);
52288
52920
  const data = config?.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
52289
52921
  const schemaResult = validateSchema(data);
52922
+ const schemaWarnings = schemaResult.diagnostics.filter(
52923
+ (d2) => d2.severity === "warning"
52924
+ );
52290
52925
  if (!schemaResult.success) {
52291
52926
  const output = formatDiagnostics(schemaResult.diagnostics, opts);
52292
52927
  if (output) process.stderr.write(output + "\n");
@@ -52294,13 +52929,18 @@ var validateCommand = new Command2("validate").description("Validate DSL against
52294
52929
  }
52295
52930
  const refDiags = checkReferences(schemaResult.data);
52296
52931
  const handoffDiags = validateHandoffSchemas(schemaResult.data);
52297
- const allDiags = [...refDiags, ...handoffDiags];
52932
+ const allDiags = [...refDiags, ...handoffDiags, ...schemaWarnings];
52933
+ const hasWarnings = allDiags.some(
52934
+ (d2) => "severity" in d2 && d2.severity === "warning"
52935
+ );
52298
52936
  if (allDiags.length > 0) {
52299
52937
  const output = formatDiagnostics(allDiags, opts);
52300
52938
  if (output) process.stderr.write(output + "\n");
52301
- process.exit(1);
52939
+ if (refDiags.length > 0 || handoffDiags.length > 0 || opts.strict && hasWarnings) {
52940
+ process.exit(1);
52941
+ }
52302
52942
  }
52303
- if (!opts.quiet) {
52943
+ if (!opts.quiet && allDiags.length === 0) {
52304
52944
  process.stdout.write("Validation passed.\n");
52305
52945
  }
52306
52946
  } catch (err) {
@@ -53009,6 +53649,40 @@ var guardrailOrphanedRule = {
53009
53649
  }
53010
53650
  };
53011
53651
 
53652
+ // src/linter/rules/validation-executor-no-context.ts
53653
+ var validationExecutorNoContextRule = {
53654
+ id: "validation-executor-no-context",
53655
+ description: "Validation executor is not wired so the validation appears in the executor's rendered context",
53656
+ run(dsl) {
53657
+ const diagnostics = [];
53658
+ for (const [validationId, val] of Object.entries(dsl.validations)) {
53659
+ if (val.executor_type === "agent") {
53660
+ const agent = dsl.agents[val.executor];
53661
+ if (!agent) continue;
53662
+ const allowed = new Set(agent.can_perform_validations ?? []);
53663
+ if (!allowed.has(validationId)) {
53664
+ diagnostics.push({
53665
+ ruleId: "validation-executor-no-context",
53666
+ severity: "warning",
53667
+ path: `agents.${val.executor}.can_perform_validations`,
53668
+ 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`
53669
+ });
53670
+ }
53671
+ } else if (val.executor_type === "tool") {
53672
+ if (!dsl.tools[val.executor]) {
53673
+ diagnostics.push({
53674
+ ruleId: "validation-executor-no-context",
53675
+ severity: "warning",
53676
+ path: `validations.${validationId}.executor`,
53677
+ message: `Validation "${validationId}" references tool executor "${val.executor}" which is not defined in tools`
53678
+ });
53679
+ }
53680
+ }
53681
+ }
53682
+ return diagnostics;
53683
+ }
53684
+ };
53685
+
53012
53686
  // src/linter/linter.ts
53013
53687
  var builtinRules = [
53014
53688
  validationCoverageRule,
@@ -53024,7 +53698,8 @@ var builtinRules = [
53024
53698
  semanticValidationPhaseCoverageRule,
53025
53699
  entityGuardrailUndefinedRule,
53026
53700
  entityNoGuardrailsRule,
53027
- guardrailOrphanedRule
53701
+ guardrailOrphanedRule,
53702
+ validationExecutorNoContextRule
53028
53703
  ];
53029
53704
  function lint(dsl, rules = builtinRules) {
53030
53705
  const diagnostics = [];
@@ -53680,6 +54355,9 @@ var lintCommand = new Command3("lint").description("Run semantic lint rules on r
53680
54355
  const resolved = await resolve4(dslPath);
53681
54356
  const data = config?.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
53682
54357
  const schemaResult = validateSchema(data);
54358
+ const schemaWarnings = schemaResult.diagnostics.filter(
54359
+ (d2) => d2.severity === "warning"
54360
+ );
53683
54361
  if (!schemaResult.success) {
53684
54362
  const output = formatDiagnostics(schemaResult.diagnostics, {
53685
54363
  format: opts.format,
@@ -53690,7 +54368,7 @@ var lintCommand = new Command3("lint").description("Run semantic lint rules on r
53690
54368
  }
53691
54369
  const tsDiagnostics = lint(schemaResult.data);
53692
54370
  const spectralDiagnostics = await spectralLint(schemaResult.data);
53693
- const diagnostics = [...tsDiagnostics, ...spectralDiagnostics];
54371
+ const diagnostics = [...tsDiagnostics, ...spectralDiagnostics, ...schemaWarnings];
53694
54372
  if (diagnostics.length > 0) {
53695
54373
  const output = formatDiagnostics(diagnostics, {
53696
54374
  format: opts.format,
@@ -53813,13 +54491,54 @@ function resolveEffectiveGuardrails(dsl, entityType, entityId) {
53813
54491
  }
53814
54492
  return entries;
53815
54493
  }
54494
+ function validationToEntityEntry(validationId, validation) {
54495
+ return {
54496
+ validation_id: validationId,
54497
+ kind: validation.kind,
54498
+ target_artifact: validation.target_artifact,
54499
+ executor_type: validation.executor_type,
54500
+ blocking: validation.blocking,
54501
+ produces_evidence: validation.produces_evidence
54502
+ };
54503
+ }
54504
+ function resolveEntityValidations(dsl, entityType, entityId) {
54505
+ if (entityType === "agents") {
54506
+ const agent = dsl.agents[entityId];
54507
+ if (!agent) return [];
54508
+ const entries2 = [];
54509
+ for (const vid of agent.can_perform_validations ?? []) {
54510
+ const v2 = dsl.validations[vid];
54511
+ if (v2) entries2.push(validationToEntityEntry(vid, v2));
54512
+ }
54513
+ return entries2;
54514
+ }
54515
+ if (entityType === "tasks") {
54516
+ const task = dsl.tasks[entityId];
54517
+ if (!task) return [];
54518
+ const entries2 = [];
54519
+ for (const vid of task.validations ?? []) {
54520
+ const v2 = dsl.validations[vid];
54521
+ if (v2) entries2.push(validationToEntityEntry(vid, v2));
54522
+ }
54523
+ return entries2;
54524
+ }
54525
+ const entries = [];
54526
+ for (const [vid, v2] of Object.entries(dsl.validations)) {
54527
+ if (v2.executor_type === "tool" && v2.executor === entityId) {
54528
+ entries.push(validationToEntityEntry(vid, v2));
54529
+ }
54530
+ }
54531
+ entries.sort((a3, b3) => a3.validation_id.localeCompare(b3.validation_id));
54532
+ return entries;
54533
+ }
53816
54534
  function buildTaskContext(dsl, taskId) {
53817
54535
  const taskDef = dsl.tasks[taskId];
53818
54536
  const task = { ...taskDef, id: taskId };
53819
54537
  const agentDef = dsl.agents[taskDef.target_agent];
53820
54538
  const targetAgent = agentDef ? { ...agentDef, id: taskDef.target_agent } : null;
53821
54539
  const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tasks", taskId);
53822
- return { task, targetAgent, relatedGuardrails, dsl };
54540
+ const relatedValidations = resolveEntityValidations(dsl, "tasks", taskId);
54541
+ return { task, targetAgent, relatedGuardrails, relatedValidations, dsl };
53823
54542
  }
53824
54543
  function buildArtifactContext(dsl, artifactId) {
53825
54544
  const artifactDef = dsl.artifacts[artifactId];
@@ -53890,12 +54609,14 @@ function buildToolContext(dsl, toolId) {
53890
54609
  return result;
53891
54610
  };
53892
54611
  const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tools", toolId);
54612
+ const relatedValidations = resolveEntityValidations(dsl, "tools", toolId);
53893
54613
  return {
53894
54614
  tool,
53895
54615
  invokableAgents,
53896
54616
  inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
53897
54617
  outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
53898
54618
  relatedGuardrails,
54619
+ relatedValidations,
53899
54620
  dsl
53900
54621
  };
53901
54622
  }
@@ -54128,6 +54849,7 @@ function buildPerAgentContext(dsl, agent) {
54128
54849
  const rawReceivableTasks = receivableTasks.map(({ id: _id, ...rest }) => rest);
54129
54850
  const mergedBehavior = mergeBehavioralSpec(agent, rawReceivableTasks);
54130
54851
  const relatedGuardrails = resolveEffectiveGuardrails(dsl, "agents", agentId);
54852
+ const relatedValidations = resolveEntityValidations(dsl, "agents", agentId);
54131
54853
  return {
54132
54854
  agent,
54133
54855
  tasks: receivableTasks,
@@ -54138,6 +54860,7 @@ function buildPerAgentContext(dsl, agent) {
54138
54860
  relatedHandoffTypes,
54139
54861
  mergedBehavior,
54140
54862
  relatedGuardrails,
54863
+ relatedValidations,
54141
54864
  dsl
54142
54865
  };
54143
54866
  }
@@ -55150,6 +55873,9 @@ var checkCommand = new Command5("check").description("Run full pipeline: resolve
55150
55873
  const resolved = await resolve4(config.dsl);
55151
55874
  const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
55152
55875
  const schemaResult = validateSchema(data);
55876
+ const schemaWarnings = schemaResult.diagnostics.filter(
55877
+ (d2) => d2.severity === "warning"
55878
+ );
55153
55879
  if (!schemaResult.success) {
55154
55880
  const output = formatDiagnostics(schemaResult.diagnostics, {
55155
55881
  format: opts.format,
@@ -55160,7 +55886,7 @@ var checkCommand = new Command5("check").description("Run full pipeline: resolve
55160
55886
  }
55161
55887
  const refDiags = checkReferences(schemaResult.data);
55162
55888
  const handoffDiags = validateHandoffSchemas(schemaResult.data);
55163
- const allRefDiags = [...refDiags, ...handoffDiags];
55889
+ const allRefDiags = [...refDiags, ...handoffDiags, ...schemaWarnings];
55164
55890
  if (allRefDiags.length > 0) {
55165
55891
  const output = formatDiagnostics(allRefDiags, {
55166
55892
  format: opts.format,