agent-contracts 0.19.5 → 0.21.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
@@ -40457,9 +40457,9 @@ var require_errors = __commonJS({
40457
40457
  }
40458
40458
  });
40459
40459
 
40460
- // node_modules/ajv-formats/dist/formats.js
40460
+ // node_modules/@stoplight/spectral-core/node_modules/ajv-formats/dist/formats.js
40461
40461
  var require_formats2 = __commonJS({
40462
- "node_modules/ajv-formats/dist/formats.js"(exports) {
40462
+ "node_modules/@stoplight/spectral-core/node_modules/ajv-formats/dist/formats.js"(exports) {
40463
40463
  "use strict";
40464
40464
  Object.defineProperty(exports, "__esModule", { value: true });
40465
40465
  exports.formatNames = exports.fastFormats = exports.fullFormats = void 0;
@@ -40624,9 +40624,9 @@ var require_formats2 = __commonJS({
40624
40624
  }
40625
40625
  });
40626
40626
 
40627
- // node_modules/ajv-formats/dist/limit.js
40627
+ // node_modules/@stoplight/spectral-core/node_modules/ajv-formats/dist/limit.js
40628
40628
  var require_limit = __commonJS({
40629
- "node_modules/ajv-formats/dist/limit.js"(exports) {
40629
+ "node_modules/@stoplight/spectral-core/node_modules/ajv-formats/dist/limit.js"(exports) {
40630
40630
  "use strict";
40631
40631
  Object.defineProperty(exports, "__esModule", { value: true });
40632
40632
  exports.formatLimitDefinition = void 0;
@@ -40696,9 +40696,9 @@ var require_limit = __commonJS({
40696
40696
  }
40697
40697
  });
40698
40698
 
40699
- // node_modules/ajv-formats/dist/index.js
40699
+ // node_modules/@stoplight/spectral-core/node_modules/ajv-formats/dist/index.js
40700
40700
  var require_dist7 = __commonJS({
40701
- "node_modules/ajv-formats/dist/index.js"(exports, module) {
40701
+ "node_modules/@stoplight/spectral-core/node_modules/ajv-formats/dist/index.js"(exports, module) {
40702
40702
  "use strict";
40703
40703
  Object.defineProperty(exports, "__esModule", { value: true });
40704
40704
  var formats_1 = require_formats2();
@@ -48101,6 +48101,287 @@ var require_dist12 = __commonJS({
48101
48101
  }
48102
48102
  });
48103
48103
 
48104
+ // node_modules/@stoplight/spectral-functions/node_modules/ajv-formats/dist/formats.js
48105
+ var require_formats3 = __commonJS({
48106
+ "node_modules/@stoplight/spectral-functions/node_modules/ajv-formats/dist/formats.js"(exports) {
48107
+ "use strict";
48108
+ Object.defineProperty(exports, "__esModule", { value: true });
48109
+ exports.formatNames = exports.fastFormats = exports.fullFormats = void 0;
48110
+ function fmtDef(validate, compare) {
48111
+ return { validate, compare };
48112
+ }
48113
+ exports.fullFormats = {
48114
+ // date: http://tools.ietf.org/html/rfc3339#section-5.6
48115
+ date: fmtDef(date, compareDate),
48116
+ // date-time: http://tools.ietf.org/html/rfc3339#section-5.6
48117
+ time: fmtDef(time, compareTime),
48118
+ "date-time": fmtDef(date_time, compareDateTime),
48119
+ // duration: https://tools.ietf.org/html/rfc3339#appendix-A
48120
+ duration: /^P(?!$)((\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?|(\d+W)?)$/,
48121
+ uri,
48122
+ "uri-reference": /^(?:[a-z][a-z0-9+\-.]*:)?(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'"()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'"()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'"()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i,
48123
+ // uri-template: https://tools.ietf.org/html/rfc6570
48124
+ "uri-template": /^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$/i,
48125
+ // For the source: https://gist.github.com/dperini/729294
48126
+ // For test cases: https://mathiasbynens.be/demo/url-regex
48127
+ url: /^(?:https?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu,
48128
+ email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
48129
+ hostname: /^(?=.{1,253}\.?$)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[-0-9a-z]{0,61}[0-9a-z])?)*\.?$/i,
48130
+ // optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
48131
+ ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
48132
+ ipv6: /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i,
48133
+ regex,
48134
+ // uuid: http://tools.ietf.org/html/rfc4122
48135
+ uuid: /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i,
48136
+ // JSON-pointer: https://tools.ietf.org/html/rfc6901
48137
+ // uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
48138
+ "json-pointer": /^(?:\/(?:[^~/]|~0|~1)*)*$/,
48139
+ "json-pointer-uri-fragment": /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i,
48140
+ // relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
48141
+ "relative-json-pointer": /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/,
48142
+ // the following formats are used by the openapi specification: https://spec.openapis.org/oas/v3.0.0#data-types
48143
+ // byte: https://github.com/miguelmota/is-base64
48144
+ byte,
48145
+ // signed 32 bit integer
48146
+ int32: { type: "number", validate: validateInt32 },
48147
+ // signed 64 bit integer
48148
+ int64: { type: "number", validate: validateInt64 },
48149
+ // C-type float
48150
+ float: { type: "number", validate: validateNumber },
48151
+ // C-type double
48152
+ double: { type: "number", validate: validateNumber },
48153
+ // hint to the UI to hide input strings
48154
+ password: true,
48155
+ // unchecked string payload
48156
+ binary: true
48157
+ };
48158
+ exports.fastFormats = {
48159
+ ...exports.fullFormats,
48160
+ date: fmtDef(/^\d\d\d\d-[0-1]\d-[0-3]\d$/, compareDate),
48161
+ time: fmtDef(/^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)?$/i, compareTime),
48162
+ "date-time": fmtDef(/^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i, compareDateTime),
48163
+ // uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
48164
+ uri: /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/)?[^\s]*$/i,
48165
+ "uri-reference": /^(?:(?:[a-z][a-z0-9+\-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,
48166
+ // email (sources from jsen validator):
48167
+ // http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363
48168
+ // http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'wilful violation')
48169
+ email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i
48170
+ };
48171
+ exports.formatNames = Object.keys(exports.fullFormats);
48172
+ function isLeapYear(year) {
48173
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
48174
+ }
48175
+ var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
48176
+ var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
48177
+ function date(str) {
48178
+ const matches = DATE.exec(str);
48179
+ if (!matches)
48180
+ return false;
48181
+ const year = +matches[1];
48182
+ const month = +matches[2];
48183
+ const day = +matches[3];
48184
+ return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month]);
48185
+ }
48186
+ function compareDate(d1, d2) {
48187
+ if (!(d1 && d2))
48188
+ return void 0;
48189
+ if (d1 > d2)
48190
+ return 1;
48191
+ if (d1 < d2)
48192
+ return -1;
48193
+ return 0;
48194
+ }
48195
+ var TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d(?::?\d\d)?)?$/i;
48196
+ function time(str, withTimeZone) {
48197
+ const matches = TIME.exec(str);
48198
+ if (!matches)
48199
+ return false;
48200
+ const hour = +matches[1];
48201
+ const minute = +matches[2];
48202
+ const second = +matches[3];
48203
+ const timeZone = matches[5];
48204
+ return (hour <= 23 && minute <= 59 && second <= 59 || hour === 23 && minute === 59 && second === 60) && (!withTimeZone || timeZone !== "");
48205
+ }
48206
+ function compareTime(t1, t22) {
48207
+ if (!(t1 && t22))
48208
+ return void 0;
48209
+ const a1 = TIME.exec(t1);
48210
+ const a22 = TIME.exec(t22);
48211
+ if (!(a1 && a22))
48212
+ return void 0;
48213
+ t1 = a1[1] + a1[2] + a1[3] + (a1[4] || "");
48214
+ t22 = a22[1] + a22[2] + a22[3] + (a22[4] || "");
48215
+ if (t1 > t22)
48216
+ return 1;
48217
+ if (t1 < t22)
48218
+ return -1;
48219
+ return 0;
48220
+ }
48221
+ var DATE_TIME_SEPARATOR = /t|\s/i;
48222
+ function date_time(str) {
48223
+ const dateTime = str.split(DATE_TIME_SEPARATOR);
48224
+ return dateTime.length === 2 && date(dateTime[0]) && time(dateTime[1], true);
48225
+ }
48226
+ function compareDateTime(dt1, dt2) {
48227
+ if (!(dt1 && dt2))
48228
+ return void 0;
48229
+ const [d1, t1] = dt1.split(DATE_TIME_SEPARATOR);
48230
+ const [d2, t22] = dt2.split(DATE_TIME_SEPARATOR);
48231
+ const res = compareDate(d1, d2);
48232
+ if (res === void 0)
48233
+ return void 0;
48234
+ return res || compareTime(t1, t22);
48235
+ }
48236
+ var NOT_URI_FRAGMENT = /\/|:/;
48237
+ var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
48238
+ function uri(str) {
48239
+ return NOT_URI_FRAGMENT.test(str) && URI.test(str);
48240
+ }
48241
+ var BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm;
48242
+ function byte(str) {
48243
+ BYTE.lastIndex = 0;
48244
+ return BYTE.test(str);
48245
+ }
48246
+ var MIN_INT32 = -(2 ** 31);
48247
+ var MAX_INT32 = 2 ** 31 - 1;
48248
+ function validateInt32(value) {
48249
+ return Number.isInteger(value) && value <= MAX_INT32 && value >= MIN_INT32;
48250
+ }
48251
+ function validateInt64(value) {
48252
+ return Number.isInteger(value);
48253
+ }
48254
+ function validateNumber() {
48255
+ return true;
48256
+ }
48257
+ var Z_ANCHOR = /[^\\]\\Z/;
48258
+ function regex(str) {
48259
+ if (Z_ANCHOR.test(str))
48260
+ return false;
48261
+ try {
48262
+ new RegExp(str);
48263
+ return true;
48264
+ } catch (e3) {
48265
+ return false;
48266
+ }
48267
+ }
48268
+ }
48269
+ });
48270
+
48271
+ // node_modules/@stoplight/spectral-functions/node_modules/ajv-formats/dist/limit.js
48272
+ var require_limit2 = __commonJS({
48273
+ "node_modules/@stoplight/spectral-functions/node_modules/ajv-formats/dist/limit.js"(exports) {
48274
+ "use strict";
48275
+ Object.defineProperty(exports, "__esModule", { value: true });
48276
+ exports.formatLimitDefinition = void 0;
48277
+ var ajv_1 = __require("ajv");
48278
+ var codegen_1 = __require("ajv/dist/compile/codegen");
48279
+ var ops = codegen_1.operators;
48280
+ var KWDs = {
48281
+ formatMaximum: { okStr: "<=", ok: ops.LTE, fail: ops.GT },
48282
+ formatMinimum: { okStr: ">=", ok: ops.GTE, fail: ops.LT },
48283
+ formatExclusiveMaximum: { okStr: "<", ok: ops.LT, fail: ops.GTE },
48284
+ formatExclusiveMinimum: { okStr: ">", ok: ops.GT, fail: ops.LTE }
48285
+ };
48286
+ var error = {
48287
+ message: ({ keyword, schemaCode }) => codegen_1.str`should be ${KWDs[keyword].okStr} ${schemaCode}`,
48288
+ params: ({ keyword, schemaCode }) => codegen_1._`{comparison: ${KWDs[keyword].okStr}, limit: ${schemaCode}}`
48289
+ };
48290
+ exports.formatLimitDefinition = {
48291
+ keyword: Object.keys(KWDs),
48292
+ type: "string",
48293
+ schemaType: "string",
48294
+ $data: true,
48295
+ error,
48296
+ code(cxt) {
48297
+ const { gen, data, schemaCode, keyword, it } = cxt;
48298
+ const { opts, self: self2 } = it;
48299
+ if (!opts.validateFormats)
48300
+ return;
48301
+ const fCxt = new ajv_1.KeywordCxt(it, self2.RULES.all.format.definition, "format");
48302
+ if (fCxt.$data)
48303
+ validate$DataFormat();
48304
+ else
48305
+ validateFormat();
48306
+ function validate$DataFormat() {
48307
+ const fmts = gen.scopeValue("formats", {
48308
+ ref: self2.formats,
48309
+ code: opts.code.formats
48310
+ });
48311
+ const fmt = gen.const("fmt", codegen_1._`${fmts}[${fCxt.schemaCode}]`);
48312
+ cxt.fail$data(codegen_1.or(codegen_1._`typeof ${fmt} != "object"`, codegen_1._`${fmt} instanceof RegExp`, codegen_1._`typeof ${fmt}.compare != "function"`, compareCode(fmt)));
48313
+ }
48314
+ function validateFormat() {
48315
+ const format2 = fCxt.schema;
48316
+ const fmtDef = self2.formats[format2];
48317
+ if (!fmtDef || fmtDef === true)
48318
+ return;
48319
+ if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") {
48320
+ throw new Error(`"${keyword}": format "${format2}" does not define "compare" function`);
48321
+ }
48322
+ const fmt = gen.scopeValue("formats", {
48323
+ key: format2,
48324
+ ref: fmtDef,
48325
+ code: opts.code.formats ? codegen_1._`${opts.code.formats}${codegen_1.getProperty(format2)}` : void 0
48326
+ });
48327
+ cxt.fail$data(compareCode(fmt));
48328
+ }
48329
+ function compareCode(fmt) {
48330
+ return codegen_1._`${fmt}.compare(${data}, ${schemaCode}) ${KWDs[keyword].fail} 0`;
48331
+ }
48332
+ },
48333
+ dependencies: ["format"]
48334
+ };
48335
+ var formatLimitPlugin = (ajv2) => {
48336
+ ajv2.addKeyword(exports.formatLimitDefinition);
48337
+ return ajv2;
48338
+ };
48339
+ exports.default = formatLimitPlugin;
48340
+ }
48341
+ });
48342
+
48343
+ // node_modules/@stoplight/spectral-functions/node_modules/ajv-formats/dist/index.js
48344
+ var require_dist13 = __commonJS({
48345
+ "node_modules/@stoplight/spectral-functions/node_modules/ajv-formats/dist/index.js"(exports, module) {
48346
+ "use strict";
48347
+ Object.defineProperty(exports, "__esModule", { value: true });
48348
+ var formats_1 = require_formats3();
48349
+ var limit_1 = require_limit2();
48350
+ var codegen_1 = __require("ajv/dist/compile/codegen");
48351
+ var fullName = new codegen_1.Name("fullFormats");
48352
+ var fastName = new codegen_1.Name("fastFormats");
48353
+ var formatsPlugin = (ajv2, opts = { keywords: true }) => {
48354
+ if (Array.isArray(opts)) {
48355
+ addFormats(ajv2, opts, formats_1.fullFormats, fullName);
48356
+ return ajv2;
48357
+ }
48358
+ const [formats, exportName] = opts.mode === "fast" ? [formats_1.fastFormats, fastName] : [formats_1.fullFormats, fullName];
48359
+ const list = opts.formats || formats_1.formatNames;
48360
+ addFormats(ajv2, list, formats, exportName);
48361
+ if (opts.keywords)
48362
+ limit_1.default(ajv2);
48363
+ return ajv2;
48364
+ };
48365
+ formatsPlugin.get = (name, mode = "full") => {
48366
+ const formats = mode === "fast" ? formats_1.fastFormats : formats_1.fullFormats;
48367
+ const f2 = formats[name];
48368
+ if (!f2)
48369
+ throw new Error(`Unknown format "${name}"`);
48370
+ return f2;
48371
+ };
48372
+ function addFormats(ajv2, list, fs, exportName) {
48373
+ var _a;
48374
+ var _b;
48375
+ (_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = codegen_1._`require("ajv-formats/dist/formats").${exportName}`;
48376
+ for (const f2 of list)
48377
+ ajv2.addFormat(f2, fs[f2]);
48378
+ }
48379
+ module.exports = exports = formatsPlugin;
48380
+ Object.defineProperty(exports, "__esModule", { value: true });
48381
+ exports.default = formatsPlugin;
48382
+ }
48383
+ });
48384
+
48104
48385
  // node_modules/@stoplight/spectral-functions/dist/schema/draft4.json
48105
48386
  var require_draft42 = __commonJS({
48106
48387
  "node_modules/@stoplight/spectral-functions/dist/schema/draft4.json"(exports, module) {
@@ -48255,7 +48536,7 @@ var require_ajv2 = __commonJS({
48255
48536
  var _2019_1 = (0, tslib_1.__importDefault)(__require("ajv/dist/2019"));
48256
48537
  var _2020_1 = (0, tslib_1.__importDefault)(__require("ajv/dist/2020"));
48257
48538
  var ajv_draft_04_1 = (0, tslib_1.__importDefault)(require_dist12());
48258
- var ajv_formats_1 = (0, tslib_1.__importDefault)(require_dist7());
48539
+ var ajv_formats_1 = (0, tslib_1.__importDefault)(require_dist13());
48259
48540
  var ajv_errors_1 = (0, tslib_1.__importDefault)(require_dist8());
48260
48541
  var draft6MetaSchema = (0, tslib_1.__importStar)(__require("ajv/dist/refs/json-schema-draft-06.json"));
48261
48542
  var draft4MetaSchema = (0, tslib_1.__importStar)(require_draft42());
@@ -48546,7 +48827,7 @@ var require_or = __commonJS({
48546
48827
  });
48547
48828
 
48548
48829
  // node_modules/@stoplight/spectral-functions/dist/index.js
48549
- var require_dist13 = __commonJS({
48830
+ var require_dist14 = __commonJS({
48550
48831
  "node_modules/@stoplight/spectral-functions/dist/index.js"(exports) {
48551
48832
  "use strict";
48552
48833
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -52251,7 +52532,7 @@ function lint(dsl, rules = builtinRules) {
52251
52532
  var import_spectral_core7 = __toESM(require_dist9(), 1);
52252
52533
 
52253
52534
  // src/linter/spectral/ruleset.ts
52254
- var import_spectral_functions = __toESM(require_dist13(), 1);
52535
+ var import_spectral_functions = __toESM(require_dist14(), 1);
52255
52536
 
52256
52537
  // src/linter/spectral/functions/ref-exists.ts
52257
52538
  var import_spectral_core = __toESM(require_dist9(), 1);
@@ -52709,2184 +52990,1738 @@ var ruleset = {
52709
52990
  severity: "error",
52710
52991
  given: "$.tools.*",
52711
52992
  then: {
52712
- field: "invokable_by",
52713
- function: ref_exists_default,
52714
- functionOptions: { referenceTo: "agents" }
52715
- }
52716
- },
52717
- // ========== 15.2.2 Artifact responsibility integrity ==========
52718
- "artifact-editors-not-empty": {
52719
- description: "Artifact editors must not be empty (15.2.2)",
52720
- message: "{{error}}",
52721
- severity: "error",
52722
- given: "$.artifacts.*.editors",
52723
- then: {
52724
- function: editors_not_empty_default
52725
- }
52726
- },
52727
- "artifact-owner-exists": {
52728
- description: "Every artifact must have an owner",
52729
- severity: "error",
52730
- given: "$.artifacts.*",
52731
- then: {
52732
- field: "owner",
52733
- function: import_spectral_functions.truthy
52734
- }
52735
- },
52736
- // ========== 15.2.5 Handoff integrity ==========
52737
- "workflow-step-refs": {
52738
- description: "Workflow step references (task, from_agent, gate_kind, handoff_kind, validation) must exist",
52739
- message: "{{error}}",
52740
- severity: "error",
52741
- given: "$.workflow.*",
52742
- then: {
52743
- function: workflow_handoff_kind_exists_default
52744
- }
52745
- },
52746
- // ========== 15.2.7 Agent behavioral spec integrity ==========
52747
- "readonly-agent-no-writes": {
52748
- description: 'Agent with mode "read-only" must have empty can_write_artifacts',
52749
- message: "{{error}}",
52750
- severity: "error",
52751
- given: "$.agents.*",
52752
- then: {
52753
- function: readonly_no_writes_default
52754
- }
52755
- },
52756
- "agent-prerequisite-readable": {
52757
- description: "Agent prerequisites target must be in can_read_artifacts",
52758
- message: "{{error}}",
52759
- severity: "error",
52760
- given: "$.agents.*",
52761
- then: {
52762
- function: prerequisite_readable_default
52763
- }
52764
- },
52765
- // ========== 15.2.10 Handoff schema integrity ==========
52766
- "handoff-payload-integrity": {
52767
- description: "Handoff schema required/properties consistency, enum non-empty, nested validation",
52768
- message: "{{error}}",
52769
- severity: "error",
52770
- given: "$.handoff_types.*.schema",
52771
- then: {
52772
- function: payload_schema_integrity_default
52773
- }
52774
- },
52775
- // ========== naming convention ==========
52776
- "agent-key-casing": {
52777
- description: "Agent keys must use kebab-case",
52778
- severity: "warn",
52779
- given: "$.agents",
52780
- then: {
52781
- field: "@key",
52782
- function: import_spectral_functions.casing,
52783
- functionOptions: { type: "kebab" }
52784
- }
52785
- },
52786
- "task-key-casing": {
52787
- description: "Task keys must use kebab-case",
52788
- severity: "warn",
52789
- given: "$.tasks",
52790
- then: {
52791
- field: "@key",
52792
- function: import_spectral_functions.casing,
52793
- functionOptions: { type: "kebab" }
52794
- }
52795
- },
52796
- "artifact-key-casing": {
52797
- description: "Artifact keys must use kebab-case",
52798
- severity: "warn",
52799
- given: "$.artifacts",
52800
- then: {
52801
- field: "@key",
52802
- function: import_spectral_functions.casing,
52803
- functionOptions: { type: "kebab" }
52804
- }
52805
- },
52806
- "tool-key-casing": {
52807
- description: "Tool keys must use kebab-case",
52808
- severity: "warn",
52809
- given: "$.tools",
52810
- then: {
52811
- field: "@key",
52812
- function: import_spectral_functions.casing,
52813
- functionOptions: { type: "kebab" }
52814
- }
52815
- },
52816
- "validation-key-casing": {
52817
- description: "Validation keys must use kebab-case",
52818
- severity: "warn",
52819
- given: "$.validations",
52820
- then: {
52821
- field: "@key",
52822
- function: import_spectral_functions.casing,
52823
- functionOptions: { type: "kebab" }
52824
- }
52825
- },
52826
- "handoff-type-key-casing": {
52827
- description: "Handoff type keys must use kebab-case",
52828
- severity: "warn",
52829
- given: "$.handoff_types",
52830
- then: {
52831
- field: "@key",
52832
- function: import_spectral_functions.casing,
52833
- functionOptions: { type: "kebab" }
52834
- }
52835
- },
52836
- "policy-key-casing": {
52837
- description: "Policy keys must use kebab-case",
52838
- severity: "warn",
52839
- given: "$.policies",
52840
- then: {
52841
- field: "@key",
52842
- function: import_spectral_functions.casing,
52843
- functionOptions: { type: "kebab" }
52844
- }
52845
- },
52846
- // ========== version ==========
52847
- "version-must-be-1": {
52848
- description: "DSL version must be 1",
52849
- severity: "error",
52850
- given: "$.version",
52851
- then: {
52852
- function: import_spectral_functions.enumeration,
52853
- functionOptions: { values: [1] }
52854
- }
52855
- }
52856
- }
52857
- };
52858
- var ruleset_default = ruleset;
52859
-
52860
- // src/linter/spectral-lint.ts
52861
- var severityMap = {
52862
- 0: "error",
52863
- 1: "warning",
52864
- 2: "info",
52865
- 3: "info"
52866
- };
52867
- var spectralInstance = null;
52868
- function getSpectral() {
52869
- if (!spectralInstance) {
52870
- spectralInstance = new import_spectral_core7.Spectral();
52871
- spectralInstance.setRuleset(ruleset_default);
52872
- }
52873
- return spectralInstance;
52874
- }
52875
- async function spectralLint(dslObject) {
52876
- const spectral = getSpectral();
52877
- const results = await spectral.run(dslObject);
52878
- return results.map((r3) => ({
52879
- ruleId: r3.code,
52880
- severity: severityMap[r3.severity] ?? "info",
52881
- path: r3.path.join("."),
52882
- message: r3.message
52883
- }));
52884
- }
52885
-
52886
- // src/cli/commands/lint.ts
52887
- var DIR_DEFAULT3 = "agent-contracts.yaml";
52888
- var lintCommand = new Command3("lint").description("Run semantic lint rules on resolved DSL").argument("[dir]", "Path to agent-contracts.yaml", DIR_DEFAULT3).option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--format <format>", "Output format (text|json)", "text").option("--quiet", "Suppress output on success", false).option("--strict", "Treat warnings as errors", false).action(
52889
- async (dir, opts) => {
52890
- try {
52891
- const config = await loadConfig(opts.config);
52892
- if (config !== null && isMultiTeamConfig(config)) {
52893
- const teamEntries = getTeamEntries(config, opts.team);
52894
- let hasErrors = false;
52895
- let allClean = true;
52896
- for (const [teamId, teamConfig] of teamEntries) {
52897
- if (!opts.quiet) process.stdout.write(`
52898
- --- Team: ${teamId} ---
52899
- `);
52900
- const resolved2 = await resolve4(teamConfig.dsl);
52901
- const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
52902
- const schemaResult2 = validateSchema(data2);
52903
- const schemaWarnings2 = schemaResult2.diagnostics.filter(
52904
- (d2) => d2.severity === "warning"
52905
- );
52906
- if (!schemaResult2.success) {
52907
- const output = formatDiagnostics(schemaResult2.diagnostics, {
52908
- format: opts.format,
52909
- quiet: opts.quiet
52910
- });
52911
- if (output) process.stderr.write(output + "\n");
52912
- hasErrors = true;
52913
- allClean = false;
52914
- continue;
52915
- }
52916
- const tsDiagnostics2 = lint(schemaResult2.data);
52917
- const spectralDiagnostics2 = await spectralLint(
52918
- schemaResult2.data
52919
- );
52920
- const diagnostics2 = [
52921
- ...tsDiagnostics2,
52922
- ...spectralDiagnostics2,
52923
- ...schemaWarnings2
52924
- ];
52925
- if (diagnostics2.length > 0) {
52926
- allClean = false;
52927
- const output = formatDiagnostics(diagnostics2, {
52928
- format: opts.format,
52929
- quiet: opts.quiet
52930
- });
52931
- if (output) process.stderr.write(output + "\n");
52932
- const teamHasErrors = diagnostics2.some((d2) => d2.severity === "error");
52933
- const teamHasWarnings = diagnostics2.some((d2) => d2.severity === "warning");
52934
- if (teamHasErrors || opts.strict && teamHasWarnings) {
52935
- hasErrors = true;
52936
- }
52937
- }
52938
- }
52939
- if (hasErrors) process.exit(1);
52940
- if (!opts.quiet && allClean) {
52941
- process.stdout.write("Lint passed.\n");
52942
- }
52943
- return;
52944
- }
52945
- const dslPath = resolveDslPath(dir, DIR_DEFAULT3, config);
52946
- const resolved = await resolve4(dslPath);
52947
- const data = config?.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
52948
- const schemaResult = validateSchema(data);
52949
- const schemaWarnings = schemaResult.diagnostics.filter(
52950
- (d2) => d2.severity === "warning"
52951
- );
52952
- if (!schemaResult.success) {
52953
- const output = formatDiagnostics(schemaResult.diagnostics, {
52954
- format: opts.format,
52955
- quiet: opts.quiet
52956
- });
52957
- if (output) process.stderr.write(output + "\n");
52958
- process.exit(1);
52993
+ field: "invokable_by",
52994
+ function: ref_exists_default,
52995
+ functionOptions: { referenceTo: "agents" }
52959
52996
  }
52960
- const tsDiagnostics = lint(schemaResult.data);
52961
- const spectralDiagnostics = await spectralLint(schemaResult.data);
52962
- const diagnostics = [...tsDiagnostics, ...spectralDiagnostics, ...schemaWarnings];
52963
- if (diagnostics.length > 0) {
52964
- const output = formatDiagnostics(diagnostics, {
52965
- format: opts.format,
52966
- quiet: opts.quiet
52967
- });
52968
- if (output) process.stderr.write(output + "\n");
52969
- const hasErrors = diagnostics.some((d2) => d2.severity === "error");
52970
- const hasWarnings = diagnostics.some((d2) => d2.severity === "warning");
52971
- if (hasErrors || opts.strict && hasWarnings) {
52972
- process.exit(1);
52973
- }
52997
+ },
52998
+ // ========== 15.2.2 Artifact responsibility integrity ==========
52999
+ "artifact-editors-not-empty": {
53000
+ description: "Artifact editors must not be empty (15.2.2)",
53001
+ message: "{{error}}",
53002
+ severity: "error",
53003
+ given: "$.artifacts.*.editors",
53004
+ then: {
53005
+ function: editors_not_empty_default
52974
53006
  }
52975
- if (!opts.quiet && diagnostics.length === 0) {
52976
- process.stdout.write("Lint passed.\n");
53007
+ },
53008
+ "artifact-owner-exists": {
53009
+ description: "Every artifact must have an owner",
53010
+ severity: "error",
53011
+ given: "$.artifacts.*",
53012
+ then: {
53013
+ field: "owner",
53014
+ function: import_spectral_functions.truthy
52977
53015
  }
52978
- } catch (err) {
52979
- const msg = err instanceof Error ? err.message : String(err);
52980
- process.stderr.write(`Error: ${msg}
52981
- `);
52982
- process.exit(1);
52983
- }
52984
- }
52985
- );
52986
-
52987
- // src/cli/commands/render.ts
52988
- import { Command as Command4 } from "commander";
52989
-
52990
- // src/renderer/renderer.ts
52991
- import { readFile as readFile4, writeFile, mkdir, unlink } from "fs/promises";
52992
- import { dirname as dirname5 } from "path";
52993
- import Handlebars from "handlebars";
52994
-
52995
- // src/renderer/context.ts
52996
- function buildSystemContext(dsl, options) {
52997
- const ctx = { system: dsl.system, dsl };
52998
- if (options?.loadedBindings && options.loadedBindings.length > 0) {
52999
- ctx.bindings = options.loadedBindings.map((lb) => lb.binding);
53000
- const policyName = options.activeGuardrailPolicy;
53001
- const policy = policyName ? dsl.guardrail_policies[policyName] : void 0;
53002
- if (policy) {
53003
- ctx.guardrailEnforcement = buildGuardrailEnforcement(dsl, policy, options.loadedBindings);
53004
- }
53005
- }
53006
- return ctx;
53007
- }
53008
- function buildGuardrailEnforcement(dsl, policy, loadedBindings) {
53009
- const entries = [];
53010
- const bindingTriggers = /* @__PURE__ */ new Map();
53011
- for (const lb of loadedBindings) {
53012
- const impl = lb.binding.guardrail_impl ?? {};
53013
- for (const [guardrailId, gi] of Object.entries(impl)) {
53014
- for (const check of gi.checks) {
53015
- if (check.matcher) {
53016
- bindingTriggers.set(guardrailId, check.matcher.type);
53017
- }
53016
+ },
53017
+ // ========== 15.2.5 Handoff integrity ==========
53018
+ "workflow-step-refs": {
53019
+ description: "Workflow step references (task, from_agent, gate_kind, handoff_kind, validation) must exist",
53020
+ message: "{{error}}",
53021
+ severity: "error",
53022
+ given: "$.workflow.*",
53023
+ then: {
53024
+ function: workflow_handoff_kind_exists_default
53018
53025
  }
53019
- }
53020
- }
53021
- for (const rule of policy.rules) {
53022
- const guardrail = dsl.guardrails[rule.guardrail];
53023
- if (!guardrail) continue;
53024
- const scope = guardrail.scope ?? {};
53025
- entries.push({
53026
- guardrail_id: rule.guardrail,
53027
- description: guardrail.description,
53028
- severity: rule.severity,
53029
- action: rule.action,
53030
- scoped_agents: scope.agents ?? [],
53031
- scoped_tasks: scope.tasks ?? [],
53032
- scoped_workflows: scope.workflows ?? [],
53033
- scoped_tools: scope.tools ?? [],
53034
- scoped_artifacts: scope.artifacts ?? [],
53035
- allow_override: rule.allow_override,
53036
- override_requires: rule.override_requires ?? [],
53037
- trigger: bindingTriggers.get(rule.guardrail) ?? null,
53038
- escalation: rule.escalation ? { target: rule.escalation.target, condition: rule.escalation.condition } : null
53039
- });
53040
- }
53041
- return entries;
53042
- }
53043
- function resolveEffectiveGuardrails(dsl, entityType, entityId) {
53044
- const entityDef = dsl[entityType][entityId];
53045
- const entitySide = new Set(entityDef?.guardrails ?? []);
53046
- const scopeSide = /* @__PURE__ */ new Set();
53047
- for (const [guardrailId, guardrail] of Object.entries(dsl.guardrails)) {
53048
- const scopeIds = guardrail.scope[entityType];
53049
- if (scopeIds?.includes(entityId)) {
53050
- scopeSide.add(guardrailId);
53051
- }
53052
- }
53053
- const allIds = /* @__PURE__ */ new Set([...entitySide, ...scopeSide]);
53054
- const activePolicyRules = /* @__PURE__ */ new Map();
53055
- for (const policy of Object.values(dsl.guardrail_policies)) {
53056
- for (const rule of policy.rules) {
53057
- if (!activePolicyRules.has(rule.guardrail)) {
53058
- activePolicyRules.set(rule.guardrail, {
53059
- severity: rule.severity,
53060
- action: rule.action
53061
- });
53026
+ },
53027
+ // ========== 15.2.7 Agent behavioral spec integrity ==========
53028
+ "readonly-agent-no-writes": {
53029
+ description: 'Agent with mode "read-only" must have empty can_write_artifacts',
53030
+ message: "{{error}}",
53031
+ severity: "error",
53032
+ given: "$.agents.*",
53033
+ then: {
53034
+ function: readonly_no_writes_default
53062
53035
  }
53063
- }
53064
- }
53065
- const entries = [];
53066
- for (const id of allIds) {
53067
- const guardrail = dsl.guardrails[id];
53068
- if (!guardrail) continue;
53069
- const fromEntity = entitySide.has(id);
53070
- const fromScope = scopeSide.has(id);
53071
- const source = fromEntity && fromScope ? "both" : fromEntity ? "entity" : "scope";
53072
- const policyInfo = activePolicyRules.get(id);
53073
- entries.push({
53074
- guardrail_id: id,
53075
- description: guardrail.description,
53076
- rationale: guardrail.rationale,
53077
- tags: guardrail.tags,
53078
- source,
53079
- severity: policyInfo?.severity,
53080
- action: policyInfo?.action
53081
- });
53082
- }
53083
- return entries;
53084
- }
53085
- function validationToEntityEntry(validationId, validation) {
53086
- return {
53087
- validation_id: validationId,
53088
- kind: validation.kind,
53089
- target_artifact: validation.target_artifact,
53090
- executor_type: validation.executor_type,
53091
- blocking: validation.blocking,
53092
- produces_evidence: validation.produces_evidence
53093
- };
53094
- }
53095
- function resolveEntityValidations(dsl, entityType, entityId) {
53096
- if (entityType === "agents") {
53097
- const agent = dsl.agents[entityId];
53098
- if (!agent) return [];
53099
- const entries2 = [];
53100
- for (const vid of agent.can_perform_validations ?? []) {
53101
- const v2 = dsl.validations[vid];
53102
- if (v2) entries2.push(validationToEntityEntry(vid, v2));
53103
- }
53104
- return entries2;
53105
- }
53106
- if (entityType === "tasks") {
53107
- const task = dsl.tasks[entityId];
53108
- if (!task) return [];
53109
- const entries2 = [];
53110
- for (const vid of task.validations ?? []) {
53111
- const v2 = dsl.validations[vid];
53112
- if (v2) entries2.push(validationToEntityEntry(vid, v2));
53113
- }
53114
- return entries2;
53115
- }
53116
- const entries = [];
53117
- for (const [vid, v2] of Object.entries(dsl.validations)) {
53118
- if (v2.executor_type === "tool" && v2.executor === entityId) {
53119
- entries.push(validationToEntityEntry(vid, v2));
53120
- }
53121
- }
53122
- entries.sort((a3, b3) => a3.validation_id.localeCompare(b3.validation_id));
53123
- return entries;
53124
- }
53125
- function buildTaskContext(dsl, taskId) {
53126
- const taskDef = dsl.tasks[taskId];
53127
- const task = { ...taskDef, id: taskId };
53128
- const agentDef = dsl.agents[taskDef.target_agent];
53129
- const targetAgent = agentDef ? { ...agentDef, id: taskDef.target_agent } : null;
53130
- const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tasks", taskId);
53131
- const relatedValidations = resolveEntityValidations(dsl, "tasks", taskId);
53132
- return { task, targetAgent, relatedGuardrails, relatedValidations, dsl };
53133
- }
53134
- function buildArtifactContext(dsl, artifactId) {
53135
- const artifactDef = dsl.artifacts[artifactId];
53136
- const artifact = { ...artifactDef, id: artifactId };
53137
- const relatedTools = {};
53138
- for (const [id, tool] of Object.entries(dsl.tools)) {
53139
- if (tool.input_artifacts.includes(artifactId) || tool.output_artifacts.includes(artifactId)) {
53140
- relatedTools[id] = tool;
53141
- }
53142
- }
53143
- const relatedValidations = {};
53144
- for (const [id, val] of Object.entries(dsl.validations)) {
53145
- if (val.target_artifact === artifactId) {
53146
- relatedValidations[id] = val;
53147
- }
53148
- }
53149
- const pickAgents = (ids) => {
53150
- const result = {};
53151
- for (const id of ids) {
53152
- if (dsl.agents[id]) result[id] = dsl.agents[id];
53153
- }
53154
- return result;
53155
- };
53156
- const producerAgents = pickAgents(artifactDef.producers);
53157
- const consumerAgents = pickAgents(artifactDef.consumers);
53158
- const editorAgents = pickAgents(artifactDef.editors);
53159
- const createdInWorkflows = [];
53160
- for (const [_taskId, task] of Object.entries(dsl.tasks)) {
53161
- if (createdInWorkflows.includes(task.workflow)) continue;
53162
- const targetAgent = dsl.agents[task.target_agent];
53163
- if (targetAgent?.can_write_artifacts.includes(artifactId)) {
53164
- createdInWorkflows.push(task.workflow);
53165
- continue;
53166
- }
53167
- const steps = task.execution_steps ?? [];
53168
- for (const step of steps) {
53169
- if (step["produces_artifact"] === artifactId) {
53170
- createdInWorkflows.push(task.workflow);
53171
- break;
53036
+ },
53037
+ "agent-prerequisite-readable": {
53038
+ description: "Agent prerequisites target must be in can_read_artifacts",
53039
+ message: "{{error}}",
53040
+ severity: "error",
53041
+ given: "$.agents.*",
53042
+ then: {
53043
+ function: prerequisite_readable_default
53044
+ }
53045
+ },
53046
+ // ========== 15.2.10 Handoff schema integrity ==========
53047
+ "handoff-payload-integrity": {
53048
+ description: "Handoff schema required/properties consistency, enum non-empty, nested validation",
53049
+ message: "{{error}}",
53050
+ severity: "error",
53051
+ given: "$.handoff_types.*.schema",
53052
+ then: {
53053
+ function: payload_schema_integrity_default
53172
53054
  }
53173
- }
53174
- }
53175
- const relatedGuardrails = resolveEffectiveGuardrails(dsl, "artifacts", artifactId);
53176
- return {
53177
- artifact,
53178
- relatedTools,
53179
- relatedValidations,
53180
- producerAgents,
53181
- consumerAgents,
53182
- editorAgents,
53183
- createdInWorkflows,
53184
- relatedGuardrails,
53185
- dsl
53186
- };
53187
- }
53188
- function buildToolContext(dsl, toolId) {
53189
- const toolDef = dsl.tools[toolId];
53190
- const tool = { ...toolDef, id: toolId };
53191
- const invokableAgents = {};
53192
- for (const agentId of toolDef.invokable_by) {
53193
- if (dsl.agents[agentId]) invokableAgents[agentId] = dsl.agents[agentId];
53194
- }
53195
- const pickArtifacts = (ids) => {
53196
- const result = {};
53197
- for (const id of ids) {
53198
- if (dsl.artifacts[id]) result[id] = dsl.artifacts[id];
53199
- }
53200
- return result;
53201
- };
53202
- const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tools", toolId);
53203
- const relatedValidations = resolveEntityValidations(dsl, "tools", toolId);
53204
- return {
53205
- tool,
53206
- invokableAgents,
53207
- inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
53208
- outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
53209
- relatedGuardrails,
53210
- relatedValidations,
53211
- dsl
53212
- };
53213
- }
53214
- function buildValidationContext(dsl, validationId) {
53215
- const validationDef = dsl.validations[validationId];
53216
- const validation = { ...validationDef, id: validationId };
53217
- return { validation, dsl };
53218
- }
53219
- function buildHandoffTypeContext(dsl, handoffTypeId) {
53220
- const htDef = dsl.handoff_types[handoffTypeId];
53221
- const handoff_type = { ...htDef, id: handoffTypeId };
53222
- const relatedTasks = Object.entries(dsl.tasks).filter(
53223
- ([, t3]) => t3.invocation_handoff === handoffTypeId || t3.result_handoff === handoffTypeId
53224
- ).map(([id, t3]) => ({ ...t3, id }));
53225
- return { handoff_type, relatedTasks, dsl };
53226
- }
53227
- function buildWorkflowContext(dsl, workflowId) {
53228
- const wfDef = dsl.workflow[workflowId];
53229
- const workflow = { ...wfDef, id: workflowId };
53230
- const stepReferencedTaskIds = /* @__PURE__ */ new Set();
53231
- for (const step of wfDef.steps) {
53232
- if (step.type === "delegate") {
53233
- stepReferencedTaskIds.add(step.task);
53234
- if (step.retry) {
53235
- stepReferencedTaskIds.add(step.retry.fix_task);
53236
- if (step.retry.revalidate_task) stepReferencedTaskIds.add(step.retry.revalidate_task);
53055
+ },
53056
+ // ========== naming convention ==========
53057
+ "agent-key-casing": {
53058
+ description: "Agent keys must use kebab-case",
53059
+ severity: "warn",
53060
+ given: "$.agents",
53061
+ then: {
53062
+ field: "@key",
53063
+ function: import_spectral_functions.casing,
53064
+ functionOptions: { type: "kebab" }
53237
53065
  }
53238
- } else if (step.type === "handoff" && step.task) {
53239
- stepReferencedTaskIds.add(step.task);
53240
- if (step.retry) {
53241
- stepReferencedTaskIds.add(step.retry.fix_task);
53242
- if (step.retry.revalidate_task) stepReferencedTaskIds.add(step.retry.revalidate_task);
53066
+ },
53067
+ "task-key-casing": {
53068
+ description: "Task keys must use kebab-case",
53069
+ severity: "warn",
53070
+ given: "$.tasks",
53071
+ then: {
53072
+ field: "@key",
53073
+ function: import_spectral_functions.casing,
53074
+ functionOptions: { type: "kebab" }
53243
53075
  }
53244
- }
53245
- }
53246
- const relatedTasks = Object.entries(dsl.tasks).filter(([id, t3]) => t3.workflow === workflowId || stepReferencedTaskIds.has(id)).map(([id, t3]) => ({ ...t3, id }));
53247
- const agentIds = /* @__PURE__ */ new Set();
53248
- for (const task of relatedTasks) {
53249
- agentIds.add(task.target_agent);
53250
- for (const fromAgent of task.allowed_from_agents) {
53251
- agentIds.add(fromAgent);
53252
- }
53253
- }
53254
- for (const step of wfDef.steps) {
53255
- if (step.type === "delegate") {
53256
- agentIds.add(step.from_agent);
53257
- } else if (step.type === "handoff" && step.from_agent) {
53258
- agentIds.add(step.from_agent);
53259
- }
53260
- if (step.type === "validation") {
53261
- const val = dsl.validations[step.validation];
53262
- if (val?.executor_type === "agent" && val.executor) {
53263
- agentIds.add(val.executor);
53076
+ },
53077
+ "artifact-key-casing": {
53078
+ description: "Artifact keys must use kebab-case",
53079
+ severity: "warn",
53080
+ given: "$.artifacts",
53081
+ then: {
53082
+ field: "@key",
53083
+ function: import_spectral_functions.casing,
53084
+ functionOptions: { type: "kebab" }
53264
53085
  }
53265
- }
53266
- }
53267
- const relatedAgents = {};
53268
- for (const id of agentIds) {
53269
- if (dsl.agents[id]) relatedAgents[id] = dsl.agents[id];
53270
- }
53271
- const toolIds = /* @__PURE__ */ new Set();
53272
- for (const id of agentIds) {
53273
- const agent = dsl.agents[id];
53274
- if (agent) {
53275
- for (const toolId of agent.can_execute_tools) {
53276
- toolIds.add(toolId);
53086
+ },
53087
+ "tool-key-casing": {
53088
+ description: "Tool keys must use kebab-case",
53089
+ severity: "warn",
53090
+ given: "$.tools",
53091
+ then: {
53092
+ field: "@key",
53093
+ function: import_spectral_functions.casing,
53094
+ functionOptions: { type: "kebab" }
53095
+ }
53096
+ },
53097
+ "validation-key-casing": {
53098
+ description: "Validation keys must use kebab-case",
53099
+ severity: "warn",
53100
+ given: "$.validations",
53101
+ then: {
53102
+ field: "@key",
53103
+ function: import_spectral_functions.casing,
53104
+ functionOptions: { type: "kebab" }
53105
+ }
53106
+ },
53107
+ "handoff-type-key-casing": {
53108
+ description: "Handoff type keys must use kebab-case",
53109
+ severity: "warn",
53110
+ given: "$.handoff_types",
53111
+ then: {
53112
+ field: "@key",
53113
+ function: import_spectral_functions.casing,
53114
+ functionOptions: { type: "kebab" }
53115
+ }
53116
+ },
53117
+ "policy-key-casing": {
53118
+ description: "Policy keys must use kebab-case",
53119
+ severity: "warn",
53120
+ given: "$.policies",
53121
+ then: {
53122
+ field: "@key",
53123
+ function: import_spectral_functions.casing,
53124
+ functionOptions: { type: "kebab" }
53125
+ }
53126
+ },
53127
+ // ========== version ==========
53128
+ "version-must-be-1": {
53129
+ description: "DSL version must be 1",
53130
+ severity: "error",
53131
+ given: "$.version",
53132
+ then: {
53133
+ function: import_spectral_functions.enumeration,
53134
+ functionOptions: { values: [1] }
53277
53135
  }
53278
53136
  }
53279
53137
  }
53280
- for (const task of relatedTasks) {
53281
- for (const step of task.execution_steps ?? []) {
53282
- if (step.uses_tool) toolIds.add(step.uses_tool);
53283
- }
53284
- }
53285
- const relatedTools = {};
53286
- for (const id of toolIds) {
53287
- if (dsl.tools[id]) relatedTools[id] = dsl.tools[id];
53288
- }
53289
- const artifactIds = /* @__PURE__ */ new Set();
53290
- for (const task of relatedTasks) {
53291
- for (const artId of task.input_artifacts) artifactIds.add(artId);
53292
- for (const step of task.execution_steps ?? []) {
53293
- if (step.produces_artifact) artifactIds.add(step.produces_artifact);
53294
- if (step.reads_artifact) artifactIds.add(step.reads_artifact);
53295
- }
53296
- }
53297
- for (const id of agentIds) {
53298
- const agent = dsl.agents[id];
53299
- if (agent) {
53300
- for (const artId of agent.can_read_artifacts) artifactIds.add(artId);
53301
- for (const artId of agent.can_write_artifacts) artifactIds.add(artId);
53302
- }
53303
- }
53304
- const relatedArtifacts = {};
53305
- for (const id of artifactIds) {
53306
- if (dsl.artifacts[id]) relatedArtifacts[id] = dsl.artifacts[id];
53307
- }
53308
- const validationIds = /* @__PURE__ */ new Set();
53309
- for (const step of wfDef.steps) {
53310
- if (step.type === "validation") {
53311
- validationIds.add(step.validation);
53312
- }
53313
- }
53314
- for (const task of relatedTasks) {
53315
- for (const valId of task.validations ?? []) {
53316
- validationIds.add(valId);
53317
- }
53318
- }
53319
- const relatedValidations = {};
53320
- for (const id of validationIds) {
53321
- if (dsl.validations[id]) relatedValidations[id] = dsl.validations[id];
53322
- }
53323
- return {
53324
- workflow,
53325
- relatedAgents,
53326
- relatedTasks,
53327
- relatedTools,
53328
- relatedArtifacts,
53329
- relatedValidations,
53330
- dsl
53331
- };
53332
- }
53333
- function buildPolicyContext(dsl, policyId) {
53334
- const policyDef = dsl.policies[policyId];
53335
- const policy = { ...policyDef, id: policyId };
53336
- return { policy, dsl };
53337
- }
53338
- function buildGuardrailContext(dsl, guardrailId) {
53339
- const guardrailDef = dsl.guardrails[guardrailId];
53340
- const guardrail = { ...guardrailDef, id: guardrailId };
53341
- return { guardrail, dsl };
53342
- }
53343
- function buildGuardrailPolicyContext(dsl, policyId) {
53344
- const policyDef = dsl.guardrail_policies[policyId];
53345
- const guardrail_policy = { ...policyDef, id: policyId };
53346
- return { guardrail_policy, dsl };
53347
- }
53348
- function mergeRules(agentRules, taskRules) {
53349
- const result = [...agentRules];
53350
- const existingIds = new Set(result.map((r3) => r3["id"]));
53351
- for (const rule of taskRules) {
53352
- const id = rule["id"];
53353
- if (existingIds.has(id)) {
53354
- const idx = result.findIndex((r3) => r3["id"] === id);
53355
- result[idx] = rule;
53356
- } else {
53357
- result.push(rule);
53358
- }
53359
- }
53360
- return result;
53361
- }
53362
- function mergeBehavioralSpec(agent, tasks) {
53363
- let responsibilities = agent.responsibilities ?? [];
53364
- let constraints = agent.constraints ?? [];
53365
- let rules = agent.rules ?? [];
53366
- let antiPatterns = agent.anti_patterns ?? [];
53367
- let escalation = agent.escalation_criteria ?? [];
53368
- let executionSteps = [];
53369
- let completionCriteria = [];
53370
- for (const task of tasks) {
53371
- responsibilities = [...responsibilities, ...task.responsibilities ?? []];
53372
- constraints = [...constraints, ...task.constraints ?? []];
53373
- rules = mergeRules(rules, task.rules ?? []);
53374
- antiPatterns = [...antiPatterns, ...task.anti_patterns ?? []];
53375
- escalation = [...escalation, ...task.escalation_criteria ?? []];
53376
- executionSteps = [...executionSteps, ...task.execution_steps ?? []];
53377
- completionCriteria = [...completionCriteria, ...task.completion_criteria ?? []];
53378
- }
53379
- return {
53380
- responsibilities,
53381
- constraints,
53382
- rules,
53383
- anti_patterns: antiPatterns,
53384
- escalation_criteria: escalation,
53385
- execution_steps: executionSteps,
53386
- completion_criteria: completionCriteria
53387
- };
53388
- }
53389
- function extractSchemaFieldNames(schema) {
53390
- const effective = resolveAllOf(schema);
53391
- const props = effective["properties"];
53392
- if (props && typeof props === "object") {
53393
- return Object.keys(props);
53394
- }
53395
- return Object.keys(schema);
53396
- }
53397
- function buildDelegatableTasks(dsl, agentId) {
53398
- return Object.entries(dsl.tasks).filter(([, t3]) => t3.allowed_from_agents.includes(agentId)).map(([taskId, t3]) => {
53399
- const invocationHandoff = dsl.handoff_types[t3.invocation_handoff];
53400
- const resultHandoff = dsl.handoff_types[t3.result_handoff];
53401
- return {
53402
- id: taskId,
53403
- description: t3.description,
53404
- target_agent: t3.target_agent,
53405
- workflow: t3.workflow,
53406
- input_artifacts: t3.input_artifacts,
53407
- invocation_handoff: t3.invocation_handoff,
53408
- invocation_payload_keys: invocationHandoff ? extractSchemaFieldNames(invocationHandoff.schema) : [],
53409
- result_handoff: t3.result_handoff,
53410
- result_payload_keys: resultHandoff ? extractSchemaFieldNames(resultHandoff.schema) : []
53411
- };
53412
- });
53413
- }
53414
- function buildPerAgentContext(dsl, agent) {
53415
- const agentId = agent.id;
53416
- const receivableTasks = Object.entries(dsl.tasks).filter(([, t3]) => t3.target_agent === agentId).map(([id, t3]) => ({ ...t3, id }));
53417
- const delegatableTasks = buildDelegatableTasks(dsl, agentId);
53418
- const artifactIds = /* @__PURE__ */ new Set([
53419
- ...agent.can_read_artifacts,
53420
- ...agent.can_write_artifacts
53421
- ]);
53422
- const relatedArtifacts = {};
53423
- for (const [id, art] of Object.entries(dsl.artifacts)) {
53424
- if (artifactIds.has(id)) relatedArtifacts[id] = art;
53425
- }
53426
- const toolIdSet = new Set(agent.can_execute_tools);
53427
- const relatedTools = {};
53428
- for (const [id, tool] of Object.entries(dsl.tools)) {
53429
- if (toolIdSet.has(id)) relatedTools[id] = tool;
53430
- }
53431
- const handoffKinds = /* @__PURE__ */ new Set([
53432
- ...agent.can_return_handoffs,
53433
- ...receivableTasks.map((t3) => t3.invocation_handoff),
53434
- ...receivableTasks.map((t3) => t3.result_handoff),
53435
- ...delegatableTasks.map((t3) => t3.invocation_handoff),
53436
- ...delegatableTasks.map((t3) => t3.result_handoff)
53437
- ]);
53438
- const relatedHandoffTypes = {};
53439
- for (const [kind, ht] of Object.entries(dsl.handoff_types)) {
53440
- if (handoffKinds.has(kind)) relatedHandoffTypes[kind] = ht;
53441
- }
53442
- const rawReceivableTasks = receivableTasks.map(({ id: _id, ...rest }) => rest);
53443
- const mergedBehavior = mergeBehavioralSpec(agent, rawReceivableTasks);
53444
- const relatedGuardrails = resolveEffectiveGuardrails(dsl, "agents", agentId);
53445
- const relatedValidations = resolveEntityValidations(dsl, "agents", agentId);
53446
- return {
53447
- agent,
53448
- tasks: receivableTasks,
53449
- receivableTasks,
53450
- delegatableTasks,
53451
- relatedArtifacts,
53452
- relatedTools,
53453
- relatedHandoffTypes,
53454
- mergedBehavior,
53455
- relatedGuardrails,
53456
- relatedValidations,
53457
- dsl
53458
- };
53459
- }
53138
+ };
53139
+ var ruleset_default = ruleset;
53460
53140
 
53461
- // src/renderer/sequence-diagram.ts
53462
- function hashToColor(s2, saturation, lightness) {
53463
- let hash = 0;
53464
- for (const ch of s2) hash = (hash << 5) - hash + ch.charCodeAt(0) | 0;
53465
- const h2 = (hash % 360 + 360) % 360;
53466
- const c2 = (1 - Math.abs(2 * lightness - 1)) * saturation;
53467
- const x3 = c2 * (1 - Math.abs(h2 / 60 % 2 - 1));
53468
- const m2 = lightness - c2 / 2;
53469
- let r3 = 0, g2 = 0, b3 = 0;
53470
- if (h2 < 60) {
53471
- r3 = c2;
53472
- g2 = x3;
53473
- } else if (h2 < 120) {
53474
- r3 = x3;
53475
- g2 = c2;
53476
- } else if (h2 < 180) {
53477
- g2 = c2;
53478
- b3 = x3;
53479
- } else if (h2 < 240) {
53480
- g2 = x3;
53481
- b3 = c2;
53482
- } else if (h2 < 300) {
53483
- r3 = x3;
53484
- b3 = c2;
53485
- } else {
53486
- r3 = c2;
53487
- b3 = x3;
53141
+ // src/linter/spectral-lint.ts
53142
+ var severityMap = {
53143
+ 0: "error",
53144
+ 1: "warning",
53145
+ 2: "info",
53146
+ 3: "info"
53147
+ };
53148
+ var spectralInstance = null;
53149
+ function getSpectral() {
53150
+ if (!spectralInstance) {
53151
+ spectralInstance = new import_spectral_core7.Spectral();
53152
+ spectralInstance.setRuleset(ruleset_default);
53488
53153
  }
53489
- return `rgb(${Math.round((r3 + m2) * 255)},${Math.round((g2 + m2) * 255)},${Math.round((b3 + m2) * 255)})`;
53490
- }
53491
- function sanitizeAlias(id) {
53492
- return id.replace(/[^a-zA-Z0-9_]/g, "_");
53154
+ return spectralInstance;
53493
53155
  }
53494
- function agentAlias(id, agent) {
53495
- const words = agent.role_name.split(/\s+/);
53496
- if (words.length === 1) return sanitizeAlias(words[0].slice(0, 4));
53497
- return sanitizeAlias(words.map((w2) => w2[0]).join(""));
53156
+ async function spectralLint(dslObject) {
53157
+ const spectral = getSpectral();
53158
+ const results = await spectral.run(dslObject);
53159
+ return results.map((r3) => ({
53160
+ ruleId: r3.code,
53161
+ severity: severityMap[r3.severity] ?? "info",
53162
+ path: r3.path.join("."),
53163
+ message: r3.message
53164
+ }));
53498
53165
  }
53499
- function collectReferencedIds(workflow, dsl, relatedTasks) {
53500
- const agents = /* @__PURE__ */ new Set();
53501
- const auditAgents = /* @__PURE__ */ new Set();
53502
- const tools = /* @__PURE__ */ new Set();
53503
- const artifacts = /* @__PURE__ */ new Set();
53504
- const taskMap = /* @__PURE__ */ new Map();
53505
- for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
53506
- function collectTaskIds(task) {
53507
- addAgent(task.target_agent);
53508
- for (const es of task.execution_steps ?? []) {
53509
- collectExecutionStepIds(es, tools, artifacts);
53510
- }
53511
- }
53512
- function collectRetryIds(retry) {
53513
- const fixTask = taskMap.get(retry.fix_task);
53514
- if (fixTask) collectTaskIds(fixTask);
53515
- if (retry.revalidate_task) {
53516
- const revalTask = taskMap.get(retry.revalidate_task);
53517
- if (revalTask) addAgent(revalTask.target_agent);
53518
- }
53519
- }
53520
- for (const step of workflow.steps) {
53521
- if (step.type === "delegate") {
53522
- addAgent(step.from_agent);
53523
- const task = taskMap.get(step.task);
53524
- if (task) collectTaskIds(task);
53525
- if (step.retry) collectRetryIds(step.retry);
53526
- } else if (step.type === "gate") {
53527
- } else if (step.type === "handoff") {
53528
- if (step.from_agent) addAgent(step.from_agent);
53529
- if (step.task) {
53530
- const task = taskMap.get(step.task);
53531
- if (task) collectTaskIds(task);
53166
+
53167
+ // src/cli/commands/lint.ts
53168
+ var DIR_DEFAULT3 = "agent-contracts.yaml";
53169
+ var lintCommand = new Command3("lint").description("Run semantic lint rules on resolved DSL").argument("[dir]", "Path to agent-contracts.yaml", DIR_DEFAULT3).option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--format <format>", "Output format (text|json)", "text").option("--quiet", "Suppress output on success", false).option("--strict", "Treat warnings as errors", false).action(
53170
+ async (dir, opts) => {
53171
+ try {
53172
+ const config = await loadConfig(opts.config);
53173
+ if (config !== null && isMultiTeamConfig(config)) {
53174
+ const teamEntries = getTeamEntries(config, opts.team);
53175
+ let hasErrors = false;
53176
+ let allClean = true;
53177
+ for (const [teamId, teamConfig] of teamEntries) {
53178
+ if (!opts.quiet) process.stdout.write(`
53179
+ --- Team: ${teamId} ---
53180
+ `);
53181
+ const resolved2 = await resolve4(teamConfig.dsl);
53182
+ const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
53183
+ const schemaResult2 = validateSchema(data2);
53184
+ const schemaWarnings2 = schemaResult2.diagnostics.filter(
53185
+ (d2) => d2.severity === "warning"
53186
+ );
53187
+ if (!schemaResult2.success) {
53188
+ const output = formatDiagnostics(schemaResult2.diagnostics, {
53189
+ format: opts.format,
53190
+ quiet: opts.quiet
53191
+ });
53192
+ if (output) process.stderr.write(output + "\n");
53193
+ hasErrors = true;
53194
+ allClean = false;
53195
+ continue;
53196
+ }
53197
+ const tsDiagnostics2 = lint(schemaResult2.data);
53198
+ const spectralDiagnostics2 = await spectralLint(
53199
+ schemaResult2.data
53200
+ );
53201
+ const diagnostics2 = [
53202
+ ...tsDiagnostics2,
53203
+ ...spectralDiagnostics2,
53204
+ ...schemaWarnings2
53205
+ ];
53206
+ if (diagnostics2.length > 0) {
53207
+ allClean = false;
53208
+ const output = formatDiagnostics(diagnostics2, {
53209
+ format: opts.format,
53210
+ quiet: opts.quiet
53211
+ });
53212
+ if (output) process.stderr.write(output + "\n");
53213
+ const teamHasErrors = diagnostics2.some((d2) => d2.severity === "error");
53214
+ const teamHasWarnings = diagnostics2.some((d2) => d2.severity === "warning");
53215
+ if (teamHasErrors || opts.strict && teamHasWarnings) {
53216
+ hasErrors = true;
53217
+ }
53218
+ }
53219
+ }
53220
+ if (hasErrors) process.exit(1);
53221
+ if (!opts.quiet && allClean) {
53222
+ process.stdout.write("Lint passed.\n");
53223
+ }
53224
+ return;
53532
53225
  }
53533
- if (step.retry) collectRetryIds(step.retry);
53534
- } else if (step.type === "validation") {
53535
- const val = dsl.validations[step.validation];
53536
- if (val) {
53537
- if (val.executor_type === "agent") addAgent(val.executor);
53538
- else tools.add(val.executor);
53539
- artifacts.add(val.target_artifact);
53226
+ const dslPath = resolveDslPath(dir, DIR_DEFAULT3, config);
53227
+ const resolved = await resolve4(dslPath);
53228
+ const data = config?.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
53229
+ const schemaResult = validateSchema(data);
53230
+ const schemaWarnings = schemaResult.diagnostics.filter(
53231
+ (d2) => d2.severity === "warning"
53232
+ );
53233
+ if (!schemaResult.success) {
53234
+ const output = formatDiagnostics(schemaResult.diagnostics, {
53235
+ format: opts.format,
53236
+ quiet: opts.quiet
53237
+ });
53238
+ if (output) process.stderr.write(output + "\n");
53239
+ process.exit(1);
53240
+ }
53241
+ const tsDiagnostics = lint(schemaResult.data);
53242
+ const spectralDiagnostics = await spectralLint(schemaResult.data);
53243
+ const diagnostics = [...tsDiagnostics, ...spectralDiagnostics, ...schemaWarnings];
53244
+ if (diagnostics.length > 0) {
53245
+ const output = formatDiagnostics(diagnostics, {
53246
+ format: opts.format,
53247
+ quiet: opts.quiet
53248
+ });
53249
+ if (output) process.stderr.write(output + "\n");
53250
+ const hasErrors = diagnostics.some((d2) => d2.severity === "error");
53251
+ const hasWarnings = diagnostics.some((d2) => d2.severity === "warning");
53252
+ if (hasErrors || opts.strict && hasWarnings) {
53253
+ process.exit(1);
53254
+ }
53255
+ }
53256
+ if (!opts.quiet && diagnostics.length === 0) {
53257
+ process.stdout.write("Lint passed.\n");
53540
53258
  }
53259
+ } catch (err) {
53260
+ const msg = err instanceof Error ? err.message : String(err);
53261
+ process.stderr.write(`Error: ${msg}
53262
+ `);
53263
+ process.exit(1);
53541
53264
  }
53542
53265
  }
53543
- function addAgent(agentId) {
53544
- const agent = dsl.agents[agentId];
53545
- if (agent?.mode === "read-only") {
53546
- auditAgents.add(agentId);
53547
- } else {
53548
- agents.add(agentId);
53266
+ );
53267
+
53268
+ // src/cli/commands/render.ts
53269
+ import { Command as Command5 } from "commander";
53270
+
53271
+ // src/cli/commands/generate.ts
53272
+ import { Command as Command4 } from "commander";
53273
+
53274
+ // src/guardrail-generator/generator.ts
53275
+ import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink as unlink2, copyFile } from "fs/promises";
53276
+ import { resolve as resolve6, dirname as dirname6 } from "path";
53277
+ import Handlebars2 from "handlebars";
53278
+ import YAML from "yaml";
53279
+
53280
+ // src/guardrail-generator/resolve-checks.ts
53281
+ function resolveChecks(dsl, binding, policy) {
53282
+ const resolved = [];
53283
+ const diagnostics = [];
53284
+ const guardrailImpl = binding.guardrail_impl ?? {};
53285
+ for (const [guardrailId, impl] of Object.entries(guardrailImpl)) {
53286
+ const guardrail = dsl.guardrails[guardrailId];
53287
+ if (!guardrail) {
53288
+ diagnostics.push({
53289
+ path: `binding.${binding.software}.guardrail_impl.${guardrailId}`,
53290
+ message: `Binding "${binding.software}" implements guardrail "${guardrailId}" which is not defined in the DSL`,
53291
+ severity: "error"
53292
+ });
53293
+ continue;
53294
+ }
53295
+ const policyRule = policy.rules.find((r3) => r3.guardrail === guardrailId);
53296
+ if (!policyRule) {
53297
+ diagnostics.push({
53298
+ path: `binding.${binding.software}.guardrail_impl.${guardrailId}`,
53299
+ message: `Guardrail "${guardrailId}" has no policy rule in the active policy \u2014 skipping`,
53300
+ severity: "info"
53301
+ });
53302
+ continue;
53303
+ }
53304
+ for (const check of impl.checks) {
53305
+ resolved.push({
53306
+ guardrail_id: guardrailId,
53307
+ guardrail,
53308
+ policy_rule: policyRule,
53309
+ check
53310
+ });
53549
53311
  }
53550
53312
  }
53551
- return { agents, auditAgents, tools, artifacts };
53313
+ return { resolved, diagnostics };
53552
53314
  }
53553
- function collectExecutionStepIds(es, tools, artifacts) {
53554
- if (es.uses_tool) tools.add(es.uses_tool);
53555
- if (es.produces_artifact) artifacts.add(es.produces_artifact);
53556
- if (es.reads_artifact) artifacts.add(es.reads_artifact);
53315
+
53316
+ // src/guardrail-generator/resolve-paths.ts
53317
+ function resolveBindingTargetPath(target, paths, bindingSoftware) {
53318
+ const diagnostics = [];
53319
+ const resolved = target.replace(/\{(\w+)\}/g, (match, varName) => {
53320
+ const value = paths[varName];
53321
+ if (value === void 0) {
53322
+ diagnostics.push({
53323
+ path: `binding.${bindingSoftware}.outputs`,
53324
+ message: `Path variable "${varName}" used in target "${target}" but not defined in config.paths`,
53325
+ severity: "error"
53326
+ });
53327
+ return match;
53328
+ }
53329
+ return value;
53330
+ });
53331
+ return { resolved, diagnostics };
53557
53332
  }
53558
- function buildParticipants(ids, externals, dsl) {
53559
- const participants = [];
53560
- const usedAliases = /* @__PURE__ */ new Set();
53561
- function uniqueAlias(preferred) {
53562
- let alias = preferred;
53563
- let i3 = 2;
53564
- while (usedAliases.has(alias)) {
53565
- alias = `${preferred}${i3}`;
53566
- i3++;
53333
+
53334
+ // src/renderer/renderer.ts
53335
+ import { readFile as readFile4, writeFile, mkdir, unlink } from "fs/promises";
53336
+ import { dirname as dirname5 } from "path";
53337
+ import Handlebars from "handlebars";
53338
+
53339
+ // src/renderer/context.ts
53340
+ function buildSystemContext(dsl, options) {
53341
+ const ctx = { system: dsl.system, dsl };
53342
+ if (options?.loadedBindings && options.loadedBindings.length > 0) {
53343
+ ctx.bindings = options.loadedBindings.map((lb) => lb.binding);
53344
+ const policyName = options.activeGuardrailPolicy;
53345
+ const policy = policyName ? dsl.guardrail_policies[policyName] : void 0;
53346
+ if (policy) {
53347
+ ctx.guardrailEnforcement = buildGuardrailEnforcement(dsl, policy, options.loadedBindings);
53567
53348
  }
53568
- usedAliases.add(alias);
53569
- return alias;
53570
- }
53571
- for (const ep of externals) {
53572
- const alias = uniqueAlias(sanitizeAlias(ep.id));
53573
- participants.push({ id: ep.id, alias, label: ep.label, group: "external" });
53574
- }
53575
- for (const id of ids.agents) {
53576
- const agent = dsl.agents[id];
53577
- if (!agent) continue;
53578
- const alias = uniqueAlias(agentAlias(id, agent));
53579
- participants.push({ id, alias, label: agent.role_name, group: "agents" });
53580
- }
53581
- for (const id of ids.auditAgents) {
53582
- const agent = dsl.agents[id];
53583
- if (!agent) continue;
53584
- const alias = uniqueAlias(agentAlias(id, agent));
53585
- participants.push({ id, alias, label: agent.role_name, group: "audit" });
53586
- }
53587
- for (const id of ids.tools) {
53588
- const tool = dsl.tools[id];
53589
- if (!tool) continue;
53590
- const alias = uniqueAlias(sanitizeAlias(id));
53591
- participants.push({ id, alias, label: id, group: "toolchain" });
53592
- }
53593
- for (const id of ids.artifacts) {
53594
- const art = dsl.artifacts[id];
53595
- if (!art) continue;
53596
- const alias = uniqueAlias(sanitizeAlias(id));
53597
- participants.push({ id, alias, label: id, group: "artifacts" });
53598
53349
  }
53599
- return participants;
53600
- }
53601
- function participantAlias(participants, id) {
53602
- const p2 = participants.find((pp) => pp.id === id);
53603
- return p2 ? p2.alias : sanitizeAlias(id);
53350
+ return ctx;
53604
53351
  }
53605
- function emitParticipants(participants, externals, lines, indent) {
53606
- const groups = {
53607
- external: [],
53608
- agents: [],
53609
- audit: [],
53610
- toolchain: [],
53611
- artifacts: []
53612
- };
53613
- for (const p2 of participants) groups[p2.group].push(p2);
53614
- const externalMap = /* @__PURE__ */ new Map();
53615
- for (const ep of externals) externalMap.set(ep.id, ep);
53616
- if (groups.external.length > 0) {
53617
- lines.push(`${indent}box rgb(255,245,230) External`);
53618
- for (const p2 of groups.external) {
53619
- const ep = externalMap.get(p2.id);
53620
- const keyword = ep?.kind === "actor" ? "actor" : "participant";
53621
- if (p2.alias === p2.label) {
53622
- lines.push(`${indent}${keyword} ${p2.alias}`);
53623
- } else {
53624
- lines.push(`${indent}${keyword} ${p2.alias} as ${p2.label}`);
53352
+ function buildGuardrailEnforcement(dsl, policy, loadedBindings) {
53353
+ const entries = [];
53354
+ const bindingTriggers = /* @__PURE__ */ new Map();
53355
+ for (const lb of loadedBindings) {
53356
+ const impl = lb.binding.guardrail_impl ?? {};
53357
+ for (const [guardrailId, gi] of Object.entries(impl)) {
53358
+ for (const check of gi.checks) {
53359
+ if (check.matcher) {
53360
+ bindingTriggers.set(guardrailId, check.matcher.type);
53361
+ }
53625
53362
  }
53626
53363
  }
53627
- lines.push(`${indent}end`);
53628
53364
  }
53629
- const groupConfig = [
53630
- { key: "agents", label: "Agents", color: "rgb(200,220,255)" },
53631
- { key: "audit", label: "Audit", color: "rgb(255,220,220)" },
53632
- { key: "toolchain", label: "Toolchain", color: "rgb(220,255,220)" },
53633
- { key: "artifacts", label: "Artifacts", color: "rgb(255,230,210)" }
53634
- ];
53635
- for (const { key, label, color } of groupConfig) {
53636
- const members = groups[key];
53637
- if (members.length === 0) continue;
53638
- lines.push(`${indent}box ${color} ${label}`);
53639
- for (const p2 of members) {
53640
- if (p2.alias === p2.label) {
53641
- lines.push(`${indent}participant ${p2.alias}`);
53642
- } else {
53643
- lines.push(`${indent}participant ${p2.alias} as ${p2.label}`);
53644
- }
53365
+ for (const rule of policy.rules) {
53366
+ const guardrail = dsl.guardrails[rule.guardrail];
53367
+ if (!guardrail) continue;
53368
+ const scope = guardrail.scope ?? {};
53369
+ entries.push({
53370
+ guardrail_id: rule.guardrail,
53371
+ description: guardrail.description,
53372
+ severity: rule.severity,
53373
+ action: rule.action,
53374
+ scoped_agents: scope.agents ?? [],
53375
+ scoped_tasks: scope.tasks ?? [],
53376
+ scoped_workflows: scope.workflows ?? [],
53377
+ scoped_tools: scope.tools ?? [],
53378
+ scoped_artifacts: scope.artifacts ?? [],
53379
+ allow_override: rule.allow_override,
53380
+ override_requires: rule.override_requires ?? [],
53381
+ trigger: bindingTriggers.get(rule.guardrail) ?? null,
53382
+ escalation: rule.escalation ? { target: rule.escalation.target, condition: rule.escalation.condition } : null
53383
+ });
53384
+ }
53385
+ return entries;
53386
+ }
53387
+ function resolveEffectiveGuardrails(dsl, entityType, entityId) {
53388
+ const entityDef = dsl[entityType][entityId];
53389
+ const entitySide = new Set(entityDef?.guardrails ?? []);
53390
+ const scopeSide = /* @__PURE__ */ new Set();
53391
+ for (const [guardrailId, guardrail] of Object.entries(dsl.guardrails)) {
53392
+ const scopeIds = guardrail.scope[entityType];
53393
+ if (scopeIds?.includes(entityId)) {
53394
+ scopeSide.add(guardrailId);
53645
53395
  }
53646
- lines.push(`${indent}end`);
53647
53396
  }
53648
- }
53649
- function emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent) {
53650
- const taskMap = /* @__PURE__ */ new Map();
53651
- for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
53652
- if (!step.task) {
53653
- if (step.from_agent) {
53654
- const fromAlias2 = participantAlias(participants, step.from_agent);
53655
- lines.push(`${indent}${fromAlias2}->>${fromAlias2}: ${step.handoff_kind}`);
53397
+ const allIds = /* @__PURE__ */ new Set([...entitySide, ...scopeSide]);
53398
+ const activePolicyRules = /* @__PURE__ */ new Map();
53399
+ for (const policy of Object.values(dsl.guardrail_policies)) {
53400
+ for (const rule of policy.rules) {
53401
+ if (!activePolicyRules.has(rule.guardrail)) {
53402
+ activePolicyRules.set(rule.guardrail, {
53403
+ severity: rule.severity,
53404
+ action: rule.action
53405
+ });
53406
+ }
53656
53407
  }
53657
- return;
53658
- }
53659
- const task = taskMap.get(step.task);
53660
- if (!task) return;
53661
- const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
53662
- const targetAlias = participantAlias(participants, task.target_agent);
53663
- if (fromAlias) {
53664
- lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
53665
- }
53666
- for (const es of task.execution_steps ?? []) {
53667
- emitExecutionStep(es, targetAlias, participants, lines, indent);
53668
53408
  }
53669
- if (fromAlias) {
53670
- lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
53409
+ const entries = [];
53410
+ for (const id of allIds) {
53411
+ const guardrail = dsl.guardrails[id];
53412
+ if (!guardrail) continue;
53413
+ const fromEntity = entitySide.has(id);
53414
+ const fromScope = scopeSide.has(id);
53415
+ const source = fromEntity && fromScope ? "both" : fromEntity ? "entity" : "scope";
53416
+ const policyInfo = activePolicyRules.get(id);
53417
+ entries.push({
53418
+ guardrail_id: id,
53419
+ description: guardrail.description,
53420
+ rationale: guardrail.rationale,
53421
+ tags: guardrail.tags,
53422
+ source,
53423
+ severity: policyInfo?.severity,
53424
+ action: policyInfo?.action
53425
+ });
53671
53426
  }
53427
+ return entries;
53672
53428
  }
53673
- function emitExecutionStep(es, agentAlias2, participants, lines, indent) {
53674
- if (es.reads_artifact) {
53675
- const artAlias = participantAlias(participants, es.reads_artifact);
53676
- lines.push(`${indent}${agentAlias2}->>${artAlias}: [R] ${es.action}`);
53677
- }
53678
- if (es.produces_artifact) {
53679
- const artAlias = participantAlias(participants, es.produces_artifact);
53680
- lines.push(`${indent}${agentAlias2}->>${artAlias}: [W] ${es.action}`);
53429
+ function validationToEntityEntry(validationId, validation) {
53430
+ return {
53431
+ validation_id: validationId,
53432
+ kind: validation.kind,
53433
+ target_artifact: validation.target_artifact,
53434
+ executor_type: validation.executor_type,
53435
+ blocking: validation.blocking,
53436
+ produces_evidence: validation.produces_evidence
53437
+ };
53438
+ }
53439
+ function resolveEntityValidations(dsl, entityType, entityId) {
53440
+ if (entityType === "agents") {
53441
+ const agent = dsl.agents[entityId];
53442
+ if (!agent) return [];
53443
+ const entries2 = [];
53444
+ for (const vid of agent.can_perform_validations ?? []) {
53445
+ const v2 = dsl.validations[vid];
53446
+ if (v2) entries2.push(validationToEntityEntry(vid, v2));
53447
+ }
53448
+ return entries2;
53681
53449
  }
53682
- if (es.uses_tool) {
53683
- const toolAlias = participantAlias(participants, es.uses_tool);
53684
- lines.push(`${indent}${agentAlias2}->>${toolAlias}: ${es.action}`);
53450
+ if (entityType === "tasks") {
53451
+ const task = dsl.tasks[entityId];
53452
+ if (!task) return [];
53453
+ const entries2 = [];
53454
+ for (const vid of task.validations ?? []) {
53455
+ const v2 = dsl.validations[vid];
53456
+ if (v2) entries2.push(validationToEntityEntry(vid, v2));
53457
+ }
53458
+ return entries2;
53685
53459
  }
53686
- if (!es.reads_artifact && !es.produces_artifact && !es.uses_tool) {
53687
- lines.push(`${indent}${agentAlias2}->>${agentAlias2}: ${es.action}`);
53460
+ const entries = [];
53461
+ for (const [vid, v2] of Object.entries(dsl.validations)) {
53462
+ if (v2.executor_type === "tool" && v2.executor === entityId) {
53463
+ entries.push(validationToEntityEntry(vid, v2));
53464
+ }
53688
53465
  }
53466
+ entries.sort((a3, b3) => a3.validation_id.localeCompare(b3.validation_id));
53467
+ return entries;
53689
53468
  }
53690
- function emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent) {
53691
- const val = dsl.validations[step.validation];
53692
- if (!val) return;
53693
- const executorAlias = participantAlias(participants, val.executor);
53694
- const artifactAlias = participantAlias(participants, val.target_artifact);
53695
- const fromAlias = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
53696
- if (fromAlias && fromAlias !== executorAlias) {
53697
- lines.push(`${indent}${fromAlias}->>${executorAlias}: ${step.validation}`);
53469
+ function buildTaskContext(dsl, taskId) {
53470
+ const taskDef = dsl.tasks[taskId];
53471
+ const task = { ...taskDef, id: taskId };
53472
+ const agentDef = dsl.agents[taskDef.target_agent];
53473
+ const targetAgent = agentDef ? { ...agentDef, id: taskDef.target_agent } : null;
53474
+ const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tasks", taskId);
53475
+ const relatedValidations = resolveEntityValidations(dsl, "tasks", taskId);
53476
+ return { task, targetAgent, relatedGuardrails, relatedValidations, dsl };
53477
+ }
53478
+ function buildArtifactContext(dsl, artifactId) {
53479
+ const artifactDef = dsl.artifacts[artifactId];
53480
+ const artifact = { ...artifactDef, id: artifactId };
53481
+ const relatedTools = {};
53482
+ for (const [id, tool] of Object.entries(dsl.tools)) {
53483
+ if (tool.input_artifacts.includes(artifactId) || tool.output_artifacts.includes(artifactId)) {
53484
+ relatedTools[id] = tool;
53485
+ }
53698
53486
  }
53699
- lines.push(`${indent}${executorAlias}->>${artifactAlias}: [R] ${val.target_artifact}`);
53700
- if (fromAlias && fromAlias !== executorAlias) {
53701
- lines.push(`${indent}${executorAlias}-->>${fromAlias}: results`);
53487
+ const relatedValidations = {};
53488
+ for (const [id, val] of Object.entries(dsl.validations)) {
53489
+ if (val.target_artifact === artifactId) {
53490
+ relatedValidations[id] = val;
53491
+ }
53702
53492
  }
53703
- }
53704
- function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
53705
- const branches = Object.entries(step.branches);
53706
- if (branches.length === 0) return;
53707
- const agentAl = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
53708
- for (let i3 = 0; i3 < branches.length; i3++) {
53709
- const [key, values] = branches[i3];
53710
- if (i3 === 0) {
53711
- lines.push(`${indent}alt ${key}`);
53712
- } else {
53713
- lines.push(`${indent}else ${key}`);
53493
+ const pickAgents = (ids) => {
53494
+ const result = {};
53495
+ for (const id of ids) {
53496
+ if (dsl.agents[id]) result[id] = dsl.agents[id];
53714
53497
  }
53715
- if (agentAl) {
53716
- lines.push(`${indent} Note over ${agentAl}: ${values.join(", ")}`);
53498
+ return result;
53499
+ };
53500
+ const producerAgents = pickAgents(artifactDef.producers);
53501
+ const consumerAgents = pickAgents(artifactDef.consumers);
53502
+ const editorAgents = pickAgents(artifactDef.editors);
53503
+ const createdInWorkflows = [];
53504
+ for (const [_taskId, task] of Object.entries(dsl.tasks)) {
53505
+ if (createdInWorkflows.includes(task.workflow)) continue;
53506
+ const targetAgent = dsl.agents[task.target_agent];
53507
+ if (targetAgent?.can_write_artifacts.includes(artifactId)) {
53508
+ createdInWorkflows.push(task.workflow);
53509
+ continue;
53510
+ }
53511
+ const steps = task.execution_steps ?? [];
53512
+ for (const step of steps) {
53513
+ if (step["produces_artifact"] === artifactId) {
53514
+ createdInWorkflows.push(task.workflow);
53515
+ break;
53516
+ }
53717
53517
  }
53718
53518
  }
53719
- lines.push(`${indent}end`);
53519
+ const relatedGuardrails = resolveEffectiveGuardrails(dsl, "artifacts", artifactId);
53520
+ return {
53521
+ artifact,
53522
+ relatedTools,
53523
+ relatedValidations,
53524
+ producerAgents,
53525
+ consumerAgents,
53526
+ editorAgents,
53527
+ createdInWorkflows,
53528
+ relatedGuardrails,
53529
+ dsl
53530
+ };
53720
53531
  }
53721
- function emitDelegateStep(step, participants, dsl, relatedTasks, lines, indent) {
53722
- const taskMap = /* @__PURE__ */ new Map();
53723
- for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
53724
- const task = taskMap.get(step.task);
53725
- if (!task) return;
53726
- const fromAlias = participantAlias(participants, step.from_agent);
53727
- const targetAlias = participantAlias(participants, task.target_agent);
53728
- lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
53729
- for (const es of task.execution_steps ?? []) {
53730
- emitExecutionStep(es, targetAlias, participants, lines, indent);
53532
+ function buildToolContext(dsl, toolId) {
53533
+ const toolDef = dsl.tools[toolId];
53534
+ const tool = { ...toolDef, id: toolId };
53535
+ const invokableAgents = {};
53536
+ for (const agentId of toolDef.invokable_by) {
53537
+ if (dsl.agents[agentId]) invokableAgents[agentId] = dsl.agents[agentId];
53731
53538
  }
53732
- lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
53539
+ const pickArtifacts = (ids) => {
53540
+ const result = {};
53541
+ for (const id of ids) {
53542
+ if (dsl.artifacts[id]) result[id] = dsl.artifacts[id];
53543
+ }
53544
+ return result;
53545
+ };
53546
+ const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tools", toolId);
53547
+ const relatedValidations = resolveEntityValidations(dsl, "tools", toolId);
53548
+ return {
53549
+ tool,
53550
+ invokableAgents,
53551
+ inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
53552
+ outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
53553
+ relatedGuardrails,
53554
+ relatedValidations,
53555
+ dsl
53556
+ };
53733
53557
  }
53734
- function emitGateStep(step, participants, lastFromAgent, lines, indent) {
53735
- if (lastFromAgent) {
53736
- const agentAl = participantAlias(participants, lastFromAgent);
53737
- lines.push(`${indent}${agentAl}->>${agentAl}: ${step.gate_kind}`);
53738
- }
53558
+ function buildValidationContext(dsl, validationId) {
53559
+ const validationDef = dsl.validations[validationId];
53560
+ const validation = { ...validationDef, id: validationId };
53561
+ return { validation, dsl };
53739
53562
  }
53740
- function emitRetryBlock(fromAgent, retry, participants, relatedTasks, lines, indent) {
53741
- const taskMap = /* @__PURE__ */ new Map();
53742
- for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
53743
- lines.push(`${indent}opt ${retry.condition}`);
53744
- const innerIndent = indent + " ";
53745
- const fixTask = taskMap.get(retry.fix_task);
53746
- if (fixTask) {
53747
- const fromAlias = fromAgent ? participantAlias(participants, fromAgent) : null;
53748
- const targetAlias = participantAlias(participants, fixTask.target_agent);
53749
- if (fromAlias) {
53750
- lines.push(`${innerIndent}${fromAlias}->>${targetAlias}: fix ${retry.fix_task}`);
53751
- }
53752
- for (const es of fixTask.execution_steps ?? []) {
53753
- emitExecutionStep(es, targetAlias, participants, lines, innerIndent);
53754
- }
53755
- if (fromAlias) {
53756
- lines.push(`${innerIndent}${targetAlias}-->>${fromAlias}: ${fixTask.result_handoff}`);
53563
+ function buildHandoffTypeContext(dsl, handoffTypeId) {
53564
+ const htDef = dsl.handoff_types[handoffTypeId];
53565
+ const handoff_type = { ...htDef, id: handoffTypeId };
53566
+ const relatedTasks = Object.entries(dsl.tasks).filter(
53567
+ ([, t3]) => t3.invocation_handoff === handoffTypeId || t3.result_handoff === handoffTypeId
53568
+ ).map(([id, t3]) => ({ ...t3, id }));
53569
+ return { handoff_type, relatedTasks, dsl };
53570
+ }
53571
+ function buildWorkflowContext(dsl, workflowId) {
53572
+ const wfDef = dsl.workflow[workflowId];
53573
+ const workflow = { ...wfDef, id: workflowId };
53574
+ const stepReferencedTaskIds = /* @__PURE__ */ new Set();
53575
+ for (const step of wfDef.steps) {
53576
+ if (step.type === "delegate") {
53577
+ stepReferencedTaskIds.add(step.task);
53578
+ if (step.retry) {
53579
+ stepReferencedTaskIds.add(step.retry.fix_task);
53580
+ if (step.retry.revalidate_task) stepReferencedTaskIds.add(step.retry.revalidate_task);
53581
+ }
53582
+ } else if (step.type === "handoff" && step.task) {
53583
+ stepReferencedTaskIds.add(step.task);
53584
+ if (step.retry) {
53585
+ stepReferencedTaskIds.add(step.retry.fix_task);
53586
+ if (step.retry.revalidate_task) stepReferencedTaskIds.add(step.retry.revalidate_task);
53587
+ }
53757
53588
  }
53758
53589
  }
53759
- if (retry.revalidate_task) {
53760
- const revalTask = taskMap.get(retry.revalidate_task);
53761
- if (revalTask) {
53762
- const fromAlias = fromAgent ? participantAlias(participants, fromAgent) : null;
53763
- const revalAlias = participantAlias(participants, revalTask.target_agent);
53764
- if (fromAlias) {
53765
- lines.push(`${innerIndent}${fromAlias}->>${revalAlias}: revalidate ${retry.revalidate_task}`);
53766
- lines.push(`${innerIndent}${revalAlias}-->>${fromAlias}: ${revalTask.result_handoff}`);
53767
- }
53590
+ const relatedTasks = Object.entries(dsl.tasks).filter(([id, t3]) => t3.workflow === workflowId || stepReferencedTaskIds.has(id)).map(([id, t3]) => ({ ...t3, id }));
53591
+ const agentIds = /* @__PURE__ */ new Set();
53592
+ for (const task of relatedTasks) {
53593
+ agentIds.add(task.target_agent);
53594
+ for (const fromAgent of task.allowed_from_agents) {
53595
+ agentIds.add(fromAgent);
53768
53596
  }
53769
53597
  }
53770
- lines.push(`${indent}end`);
53771
- }
53772
- function groupSteps(steps) {
53773
- const result = [];
53774
- let currentGroup = null;
53775
- for (let i3 = 0; i3 < steps.length; i3++) {
53776
- const step = steps[i3];
53777
- const group = "group" in step ? step.group : void 0;
53778
- if (group) {
53779
- if (currentGroup && currentGroup.group === group) {
53780
- currentGroup.steps.push({ step, index: i3 });
53781
- } else {
53782
- if (currentGroup) result.push(currentGroup);
53783
- currentGroup = { group, steps: [{ step, index: i3 }] };
53784
- }
53785
- } else {
53786
- if (currentGroup) {
53787
- result.push(currentGroup);
53788
- currentGroup = null;
53598
+ for (const step of wfDef.steps) {
53599
+ if (step.type === "delegate") {
53600
+ agentIds.add(step.from_agent);
53601
+ } else if (step.type === "handoff" && step.from_agent) {
53602
+ agentIds.add(step.from_agent);
53603
+ }
53604
+ if (step.type === "validation") {
53605
+ const val = dsl.validations[step.validation];
53606
+ if (val?.executor_type === "agent" && val.executor) {
53607
+ agentIds.add(val.executor);
53789
53608
  }
53790
- result.push({ group: null, steps: [{ step, index: i3 }] });
53791
53609
  }
53792
53610
  }
53793
- if (currentGroup) result.push(currentGroup);
53794
- return result;
53795
- }
53796
- function generateSequenceDiagram(workflow, relatedTasks, dsl) {
53797
- const ids = collectReferencedIds(workflow, dsl, relatedTasks);
53798
- const externals = workflow.external_participants ?? [];
53799
- const participants = buildParticipants(ids, externals, dsl);
53800
- const lines = [];
53801
- const indent = " ";
53802
- lines.push("sequenceDiagram");
53803
- emitParticipants(participants, externals, lines, indent);
53804
- lines.push("");
53805
- lines.push(`${indent}rect ${hashToColor(workflow.id, 0.15, 0.95)}`);
53806
- const firstP = participants[0];
53807
- const lastP = participants[participants.length - 1];
53808
- if (firstP && lastP) {
53809
- const noteLabel = workflow.description ? `${workflow.id} \u2014 ${workflow.description}` : workflow.id;
53810
- lines.push(`${indent}Note over ${firstP.alias},${lastP.alias}: ${noteLabel}`);
53611
+ const relatedAgents = {};
53612
+ for (const id of agentIds) {
53613
+ if (dsl.agents[id]) relatedAgents[id] = dsl.agents[id];
53811
53614
  }
53812
- if (workflow.trigger && externals.some((ep) => ep.kind === "actor")) {
53813
- const actor = externals.find((ep) => ep.kind === "actor");
53814
- const actorAlias = participantAlias(participants, actor.id);
53815
- const firstAgent = participants.find((p2) => p2.group === "agents" || p2.group === "audit");
53816
- if (firstAgent) {
53817
- lines.push(`${indent}${actorAlias}->>${firstAgent.alias}: ${workflow.trigger}`);
53615
+ const toolIds = /* @__PURE__ */ new Set();
53616
+ for (const id of agentIds) {
53617
+ const agent = dsl.agents[id];
53618
+ if (agent) {
53619
+ for (const toolId of agent.can_execute_tools) {
53620
+ toolIds.add(toolId);
53621
+ }
53818
53622
  }
53819
53623
  }
53820
- let lastFromAgent;
53821
- const grouped = groupSteps(workflow.steps);
53822
- for (const g2 of grouped) {
53823
- if (g2.group && g2.steps.length > 1) {
53824
- lines.push("");
53825
- lines.push(`${indent}par ${g2.group}`);
53826
- const parIndent = indent + " ";
53827
- for (let i3 = 0; i3 < g2.steps.length; i3++) {
53828
- const { step } = g2.steps[i3];
53829
- if (i3 > 0) lines.push(`${indent}and`);
53830
- emitStep(step, participants, dsl, relatedTasks, lines, parIndent, lastFromAgent, (a3) => {
53831
- lastFromAgent = a3;
53832
- });
53833
- }
53834
- lines.push(`${indent}end`);
53835
- } else {
53836
- for (const { step } of g2.steps) {
53837
- lines.push("");
53838
- emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, (a3) => {
53839
- lastFromAgent = a3;
53840
- });
53841
- }
53624
+ for (const task of relatedTasks) {
53625
+ for (const step of task.execution_steps ?? []) {
53626
+ if (step.uses_tool) toolIds.add(step.uses_tool);
53842
53627
  }
53843
53628
  }
53844
- lines.push("");
53845
- lines.push(`${indent}end`);
53846
- return lines.join("\n");
53847
- }
53848
- function emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, setLastFromAgent) {
53849
- if (step.type === "delegate") {
53850
- setLastFromAgent(step.from_agent);
53851
- emitDelegateStep(step, participants, dsl, relatedTasks, lines, indent);
53852
- if (step.retry) {
53853
- emitRetryBlock(step.from_agent, step.retry, participants, relatedTasks, lines, indent);
53629
+ const relatedTools = {};
53630
+ for (const id of toolIds) {
53631
+ if (dsl.tools[id]) relatedTools[id] = dsl.tools[id];
53632
+ }
53633
+ const artifactIds = /* @__PURE__ */ new Set();
53634
+ for (const task of relatedTasks) {
53635
+ for (const artId of task.input_artifacts) artifactIds.add(artId);
53636
+ for (const step of task.execution_steps ?? []) {
53637
+ if (step.produces_artifact) artifactIds.add(step.produces_artifact);
53638
+ if (step.reads_artifact) artifactIds.add(step.reads_artifact);
53854
53639
  }
53855
- } else if (step.type === "gate") {
53856
- emitGateStep(step, participants, lastFromAgent, lines, indent);
53857
- } else if (step.type === "handoff") {
53858
- if (step.from_agent) setLastFromAgent(step.from_agent);
53859
- emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
53860
- if (step.retry) {
53861
- emitRetryBlock(step.from_agent, step.retry, participants, relatedTasks, lines, indent);
53640
+ }
53641
+ for (const id of agentIds) {
53642
+ const agent = dsl.agents[id];
53643
+ if (agent) {
53644
+ for (const artId of agent.can_read_artifacts) artifactIds.add(artId);
53645
+ for (const artId of agent.can_write_artifacts) artifactIds.add(artId);
53862
53646
  }
53863
- } else if (step.type === "validation") {
53864
- emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
53865
- } else if (step.type === "decision") {
53866
- emitDecisionStep(step, participants, lastFromAgent, lines, indent);
53867
53647
  }
53868
- }
53869
-
53870
- // src/renderer/overview-flowchart.ts
53871
- function collectPhaseOps(dsl, wfId) {
53872
- const ctx = buildWorkflowContext(dsl, wfId);
53873
- const wf = dsl.workflow[wfId];
53874
- const agentOps = /* @__PURE__ */ new Map();
53875
- const artifactOps = /* @__PURE__ */ new Map();
53876
- const toolOps = /* @__PURE__ */ new Map();
53877
- function addOp(map, id, op) {
53878
- if (!map.has(id)) map.set(id, /* @__PURE__ */ new Set());
53879
- map.get(id).add(op);
53648
+ const relatedArtifacts = {};
53649
+ for (const id of artifactIds) {
53650
+ if (dsl.artifacts[id]) relatedArtifacts[id] = dsl.artifacts[id];
53880
53651
  }
53881
- const taskMap = new Map(ctx.relatedTasks.map((t3) => [t3.id, t3]));
53882
- function collectTaskOps(task) {
53883
- addOp(agentOps, task.target_agent, "execute");
53884
- for (const es of task.execution_steps ?? []) {
53885
- if (es.reads_artifact) addOp(artifactOps, es.reads_artifact, "R");
53886
- if (es.produces_artifact) addOp(artifactOps, es.produces_artifact, "W");
53887
- if (es.uses_tool) {
53888
- const tool = dsl.tools[es.uses_tool];
53889
- if (tool) {
53890
- const cats = tool.commands.map((c2) => c2.category).filter((v2, i3, a3) => a3.indexOf(v2) === i3);
53891
- for (const cat of cats) addOp(toolOps, es.uses_tool, cat);
53892
- if (cats.length === 0) addOp(toolOps, es.uses_tool, "\u2713");
53893
- } else {
53894
- addOp(toolOps, es.uses_tool, "\u2713");
53895
- }
53896
- }
53652
+ const validationIds = /* @__PURE__ */ new Set();
53653
+ for (const step of wfDef.steps) {
53654
+ if (step.type === "validation") {
53655
+ validationIds.add(step.validation);
53897
53656
  }
53898
53657
  }
53899
- for (const step of wf.steps) {
53900
- if (step.type === "delegate") {
53901
- addOp(agentOps, step.from_agent, "delegate");
53902
- const task = taskMap.get(step.task);
53903
- if (task) collectTaskOps(task);
53904
- } else if (step.type === "gate") {
53905
- } else if (step.type === "handoff") {
53906
- if (step.from_agent) addOp(agentOps, step.from_agent, "delegate");
53907
- if (step.task) {
53908
- const task = taskMap.get(step.task);
53909
- if (task) collectTaskOps(task);
53910
- }
53911
- } else if (step.type === "validation") {
53912
- const val = dsl.validations[step.validation];
53913
- if (val) {
53914
- if (val.executor_type === "agent") {
53915
- addOp(agentOps, val.executor, "validate");
53916
- } else {
53917
- addOp(toolOps, val.executor, "verification");
53918
- }
53919
- addOp(artifactOps, val.target_artifact, "V");
53920
- }
53658
+ for (const task of relatedTasks) {
53659
+ for (const valId of task.validations ?? []) {
53660
+ validationIds.add(valId);
53921
53661
  }
53922
53662
  }
53923
- return { agentOps, artifactOps, toolOps };
53663
+ const relatedValidations = {};
53664
+ for (const id of validationIds) {
53665
+ if (dsl.validations[id]) relatedValidations[id] = dsl.validations[id];
53666
+ }
53667
+ return {
53668
+ workflow,
53669
+ relatedAgents,
53670
+ relatedTasks,
53671
+ relatedTools,
53672
+ relatedArtifacts,
53673
+ relatedValidations,
53674
+ dsl
53675
+ };
53924
53676
  }
53925
- function formatOps(ops) {
53926
- if (!ops || ops.size === 0) return "\u2014";
53927
- return [...ops].join(", ");
53677
+ function buildPolicyContext(dsl, policyId) {
53678
+ const policyDef = dsl.policies[policyId];
53679
+ const policy = { ...policyDef, id: policyId };
53680
+ return { policy, dsl };
53928
53681
  }
53929
- function buildTable(header, rows) {
53930
- const lines = [];
53931
- lines.push("| " + header.join(" | ") + " |");
53932
- lines.push("|" + header.map(() => "---").join("|") + "|");
53933
- for (const row of rows) {
53934
- lines.push("| " + row.join(" | ") + " |");
53682
+ function buildGuardrailContext(dsl, guardrailId) {
53683
+ const guardrailDef = dsl.guardrails[guardrailId];
53684
+ const guardrail = { ...guardrailDef, id: guardrailId };
53685
+ return { guardrail, dsl };
53686
+ }
53687
+ function buildGuardrailPolicyContext(dsl, policyId) {
53688
+ const policyDef = dsl.guardrail_policies[policyId];
53689
+ const guardrail_policy = { ...policyDef, id: policyId };
53690
+ return { guardrail_policy, dsl };
53691
+ }
53692
+ function mergeRules(agentRules, taskRules) {
53693
+ const result = [...agentRules];
53694
+ const existingIds = new Set(result.map((r3) => r3["id"]));
53695
+ for (const rule of taskRules) {
53696
+ const id = rule["id"];
53697
+ if (existingIds.has(id)) {
53698
+ const idx = result.findIndex((r3) => r3["id"] === id);
53699
+ result[idx] = rule;
53700
+ } else {
53701
+ result.push(rule);
53702
+ }
53935
53703
  }
53936
- return lines.join("\n");
53704
+ return result;
53937
53705
  }
53938
- function generateOverviewFlowchart(dsl) {
53939
- const workflowOrder = dsl.system.default_workflow_order ?? Object.keys(dsl.workflow);
53940
- const phases = workflowOrder.filter((id) => dsl.workflow[id]);
53941
- const phaseData = /* @__PURE__ */ new Map();
53942
- for (const wfId of phases) {
53943
- phaseData.set(wfId, collectPhaseOps(dsl, wfId));
53706
+ function mergeBehavioralSpec(agent, tasks) {
53707
+ let responsibilities = agent.responsibilities ?? [];
53708
+ let constraints = agent.constraints ?? [];
53709
+ let rules = agent.rules ?? [];
53710
+ let antiPatterns = agent.anti_patterns ?? [];
53711
+ let escalation = agent.escalation_criteria ?? [];
53712
+ let executionSteps = [];
53713
+ let completionCriteria = [];
53714
+ for (const task of tasks) {
53715
+ responsibilities = [...responsibilities, ...task.responsibilities ?? []];
53716
+ constraints = [...constraints, ...task.constraints ?? []];
53717
+ rules = mergeRules(rules, task.rules ?? []);
53718
+ antiPatterns = [...antiPatterns, ...task.anti_patterns ?? []];
53719
+ escalation = [...escalation, ...task.escalation_criteria ?? []];
53720
+ executionSteps = [...executionSteps, ...task.execution_steps ?? []];
53721
+ completionCriteria = [...completionCriteria, ...task.completion_criteria ?? []];
53944
53722
  }
53945
- const allAgentIds = /* @__PURE__ */ new Set();
53946
- const allArtifactIds = /* @__PURE__ */ new Set();
53947
- const allToolIds = /* @__PURE__ */ new Set();
53948
- for (const ops of phaseData.values()) {
53949
- for (const id of ops.agentOps.keys()) allAgentIds.add(id);
53950
- for (const id of ops.artifactOps.keys()) allArtifactIds.add(id);
53951
- for (const id of ops.toolOps.keys()) allToolIds.add(id);
53723
+ return {
53724
+ responsibilities,
53725
+ constraints,
53726
+ rules,
53727
+ anti_patterns: antiPatterns,
53728
+ escalation_criteria: escalation,
53729
+ execution_steps: executionSteps,
53730
+ completion_criteria: completionCriteria
53731
+ };
53732
+ }
53733
+ function extractSchemaFieldNames(schema) {
53734
+ const effective = resolveAllOf(schema);
53735
+ const props = effective["properties"];
53736
+ if (props && typeof props === "object") {
53737
+ return Object.keys(props);
53952
53738
  }
53953
- const sections = [];
53954
- if (allAgentIds.size > 0) {
53955
- const header = ["Agent", ...phases];
53956
- const rows = [];
53957
- for (const agentId of allAgentIds) {
53958
- const agent = dsl.agents[agentId];
53959
- const label = agent ? agent.role_name : agentId;
53960
- const row = [label];
53961
- for (const wfId of phases) {
53962
- row.push(formatOps(phaseData.get(wfId).agentOps.get(agentId)));
53963
- }
53964
- rows.push(row);
53965
- }
53966
- sections.push("#### Agent \xD7 Phase\n\n" + buildTable(header, rows));
53739
+ return Object.keys(schema);
53740
+ }
53741
+ function buildDelegatableTasks(dsl, agentId) {
53742
+ return Object.entries(dsl.tasks).filter(([, t3]) => t3.allowed_from_agents.includes(agentId)).map(([taskId, t3]) => {
53743
+ const invocationHandoff = dsl.handoff_types[t3.invocation_handoff];
53744
+ const resultHandoff = dsl.handoff_types[t3.result_handoff];
53745
+ return {
53746
+ id: taskId,
53747
+ description: t3.description,
53748
+ target_agent: t3.target_agent,
53749
+ workflow: t3.workflow,
53750
+ input_artifacts: t3.input_artifacts,
53751
+ invocation_handoff: t3.invocation_handoff,
53752
+ invocation_payload_keys: invocationHandoff ? extractSchemaFieldNames(invocationHandoff.schema) : [],
53753
+ result_handoff: t3.result_handoff,
53754
+ result_payload_keys: resultHandoff ? extractSchemaFieldNames(resultHandoff.schema) : []
53755
+ };
53756
+ });
53757
+ }
53758
+ function buildPerAgentContext(dsl, agent) {
53759
+ const agentId = agent.id;
53760
+ const receivableTasks = Object.entries(dsl.tasks).filter(([, t3]) => t3.target_agent === agentId).map(([id, t3]) => ({ ...t3, id }));
53761
+ const delegatableTasks = buildDelegatableTasks(dsl, agentId);
53762
+ const artifactIds = /* @__PURE__ */ new Set([
53763
+ ...agent.can_read_artifacts,
53764
+ ...agent.can_write_artifacts
53765
+ ]);
53766
+ const relatedArtifacts = {};
53767
+ for (const [id, art] of Object.entries(dsl.artifacts)) {
53768
+ if (artifactIds.has(id)) relatedArtifacts[id] = art;
53967
53769
  }
53968
- if (allArtifactIds.size > 0) {
53969
- const header = ["Artifact", ...phases];
53970
- const rows = [];
53971
- for (const artId of allArtifactIds) {
53972
- const row = [artId];
53973
- for (const wfId of phases) {
53974
- row.push(formatOps(phaseData.get(wfId).artifactOps.get(artId)));
53975
- }
53976
- rows.push(row);
53977
- }
53978
- sections.push("#### Artifact \xD7 Phase\n\n" + buildTable(header, rows));
53770
+ const toolIdSet = new Set(agent.can_execute_tools);
53771
+ const relatedTools = {};
53772
+ for (const [id, tool] of Object.entries(dsl.tools)) {
53773
+ if (toolIdSet.has(id)) relatedTools[id] = tool;
53979
53774
  }
53980
- if (allToolIds.size > 0) {
53981
- const header = ["Tool", ...phases];
53982
- const rows = [];
53983
- for (const toolId of allToolIds) {
53984
- const row = [toolId];
53985
- for (const wfId of phases) {
53986
- row.push(formatOps(phaseData.get(wfId).toolOps.get(toolId)));
53987
- }
53988
- rows.push(row);
53989
- }
53990
- sections.push("#### Tool \xD7 Phase\n\n" + buildTable(header, rows));
53775
+ const handoffKinds = /* @__PURE__ */ new Set([
53776
+ ...agent.can_return_handoffs,
53777
+ ...receivableTasks.map((t3) => t3.invocation_handoff),
53778
+ ...receivableTasks.map((t3) => t3.result_handoff),
53779
+ ...delegatableTasks.map((t3) => t3.invocation_handoff),
53780
+ ...delegatableTasks.map((t3) => t3.result_handoff)
53781
+ ]);
53782
+ const relatedHandoffTypes = {};
53783
+ for (const [kind, ht] of Object.entries(dsl.handoff_types)) {
53784
+ if (handoffKinds.has(kind)) relatedHandoffTypes[kind] = ht;
53991
53785
  }
53992
- return sections.join("\n\n");
53786
+ const rawReceivableTasks = receivableTasks.map(({ id: _id, ...rest }) => rest);
53787
+ const mergedBehavior = mergeBehavioralSpec(agent, rawReceivableTasks);
53788
+ const relatedGuardrails = resolveEffectiveGuardrails(dsl, "agents", agentId);
53789
+ const relatedValidations = resolveEntityValidations(dsl, "agents", agentId);
53790
+ return {
53791
+ agent,
53792
+ tasks: receivableTasks,
53793
+ receivableTasks,
53794
+ delegatableTasks,
53795
+ relatedArtifacts,
53796
+ relatedTools,
53797
+ relatedHandoffTypes,
53798
+ mergedBehavior,
53799
+ relatedGuardrails,
53800
+ relatedValidations,
53801
+ dsl
53802
+ };
53993
53803
  }
53994
53804
 
53995
- // src/renderer/renderer.ts
53996
- Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
53997
- Handlebars.registerHelper("notEmpty", (obj) => {
53998
- if (!obj || typeof obj !== "object") return false;
53999
- return Object.keys(obj).length > 0;
54000
- });
54001
- Handlebars.registerHelper("inc", (val) => val + 1);
54002
- Handlebars.registerHelper(
54003
- "lookupPayloadFields",
54004
- (schema) => {
54005
- const effective = resolveAllOf(schema ?? {});
54006
- const props = effective["properties"];
54007
- if (!props) return [];
54008
- const requiredSet = new Set(
54009
- effective["required"] ?? []
54010
- );
54011
- return Object.entries(props).map(([name, sub]) => {
54012
- const enumVals = sub["enum"];
54013
- return {
54014
- name,
54015
- type: sub["type"] ?? "any",
54016
- required: requiredSet.has(name),
54017
- enum: enumVals ? enumVals.join(" | ") : void 0
54018
- };
54019
- });
54020
- }
54021
- );
54022
- function toYamlLines(obj, indent) {
54023
- const pad = " ".repeat(indent);
54024
- if (obj === null || obj === void 0) return [`${pad}null`];
54025
- if (typeof obj === "boolean" || typeof obj === "number")
54026
- return [`${pad}${obj}`];
54027
- if (typeof obj === "string") {
54028
- if (obj.includes("\n")) {
54029
- const lines = [`${pad}|`];
54030
- for (const line of obj.split("\n")) {
54031
- lines.push(line === "" ? "" : `${pad} ${line}`);
54032
- }
54033
- return lines;
54034
- }
54035
- return [`${pad}${JSON.stringify(obj)}`];
54036
- }
54037
- if (Array.isArray(obj)) {
54038
- const lines = [];
54039
- for (const item of obj) {
54040
- if (typeof item === "object" && item !== null && !Array.isArray(item)) {
54041
- const entries = Object.entries(item);
54042
- if (entries.length > 0) {
54043
- const [firstKey, firstVal] = entries[0];
54044
- const firstValLines = toYamlLines(firstVal, 0);
54045
- if (firstValLines.length === 1 && !firstValLines[0].includes("\n")) {
54046
- lines.push(`${pad}- ${firstKey}: ${firstValLines[0].trim()}`);
54047
- } else {
54048
- lines.push(`${pad}- ${firstKey}:`);
54049
- lines.push(...toYamlLines(firstVal, indent + 2));
54050
- }
54051
- for (let i3 = 1; i3 < entries.length; i3++) {
54052
- const [k2, v2] = entries[i3];
54053
- const vLines = toYamlLines(v2, indent + 2);
54054
- if (vLines.length === 1) {
54055
- lines.push(`${pad} ${k2}: ${vLines[0].trim()}`);
54056
- } else {
54057
- lines.push(`${pad} ${k2}:`);
54058
- lines.push(...vLines);
54059
- }
54060
- }
54061
- } else {
54062
- lines.push(`${pad}- {}`);
54063
- }
54064
- } else {
54065
- const valLines = toYamlLines(item, 0);
54066
- lines.push(`${pad}- ${valLines[0].trim()}`);
54067
- }
54068
- }
54069
- return lines;
54070
- }
54071
- if (typeof obj === "object") {
54072
- const lines = [];
54073
- for (const [key, value] of Object.entries(
54074
- obj
54075
- )) {
54076
- const valLines = toYamlLines(value, indent + 1);
54077
- if (valLines.length === 1 && !valLines[0].includes("|")) {
54078
- lines.push(`${pad}${key}: ${valLines[0].trim()}`);
54079
- } else {
54080
- lines.push(`${pad}${key}:`);
54081
- lines.push(...valLines);
54082
- }
54083
- }
54084
- return lines;
53805
+ // src/renderer/sequence-diagram.ts
53806
+ function hashToColor(s2, saturation, lightness) {
53807
+ let hash = 0;
53808
+ for (const ch of s2) hash = (hash << 5) - hash + ch.charCodeAt(0) | 0;
53809
+ const h2 = (hash % 360 + 360) % 360;
53810
+ const c2 = (1 - Math.abs(2 * lightness - 1)) * saturation;
53811
+ const x3 = c2 * (1 - Math.abs(h2 / 60 % 2 - 1));
53812
+ const m2 = lightness - c2 / 2;
53813
+ let r3 = 0, g2 = 0, b3 = 0;
53814
+ if (h2 < 60) {
53815
+ r3 = c2;
53816
+ g2 = x3;
53817
+ } else if (h2 < 120) {
53818
+ r3 = x3;
53819
+ g2 = c2;
53820
+ } else if (h2 < 180) {
53821
+ g2 = c2;
53822
+ b3 = x3;
53823
+ } else if (h2 < 240) {
53824
+ g2 = x3;
53825
+ b3 = c2;
53826
+ } else if (h2 < 300) {
53827
+ r3 = x3;
53828
+ b3 = c2;
53829
+ } else {
53830
+ r3 = c2;
53831
+ b3 = x3;
54085
53832
  }
54086
- return [`${pad}${String(obj)}`];
53833
+ return `rgb(${Math.round((r3 + m2) * 255)},${Math.round((g2 + m2) * 255)},${Math.round((b3 + m2) * 255)})`;
54087
53834
  }
54088
- Handlebars.registerHelper("yamlBlock", (obj) => {
54089
- return toYamlLines(obj, 0).join("\n");
54090
- });
54091
- Handlebars.registerHelper(
54092
- "join",
54093
- (arr, separator) => {
54094
- if (!Array.isArray(arr)) return "";
54095
- const sep = typeof separator === "string" ? separator : ", ";
54096
- return arr.join(sep);
54097
- }
54098
- );
54099
- Handlebars.registerHelper("contains", (arr, value) => {
54100
- if (!Array.isArray(arr)) return false;
54101
- return arr.includes(value);
54102
- });
54103
- Handlebars.registerHelper(
54104
- "groupBy",
54105
- (arr, key) => {
54106
- if (!Array.isArray(arr)) return {};
54107
- const result = {};
54108
- for (const item of arr) {
54109
- const k2 = String(
54110
- item?.[key] ?? "undefined"
54111
- );
54112
- (result[k2] ??= []).push(item);
53835
+ function sanitizeAlias(id) {
53836
+ return id.replace(/[^a-zA-Z0-9_]/g, "_");
53837
+ }
53838
+ function agentAlias(id, agent) {
53839
+ const words = agent.role_name.split(/\s+/);
53840
+ if (words.length === 1) return sanitizeAlias(words[0].slice(0, 4));
53841
+ return sanitizeAlias(words.map((w2) => w2[0]).join(""));
53842
+ }
53843
+ function collectReferencedIds(workflow, dsl, relatedTasks) {
53844
+ const agents = /* @__PURE__ */ new Set();
53845
+ const auditAgents = /* @__PURE__ */ new Set();
53846
+ const tools = /* @__PURE__ */ new Set();
53847
+ const artifacts = /* @__PURE__ */ new Set();
53848
+ const taskMap = /* @__PURE__ */ new Map();
53849
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
53850
+ function collectTaskIds(task) {
53851
+ addAgent(task.target_agent);
53852
+ for (const es of task.execution_steps ?? []) {
53853
+ collectExecutionStepIds(es, tools, artifacts);
54113
53854
  }
54114
- return result;
54115
- }
54116
- );
54117
- Handlebars.registerHelper(
54118
- "keys",
54119
- (obj) => {
54120
- if (!obj || typeof obj !== "object") return [];
54121
- return Object.keys(obj);
54122
53855
  }
54123
- );
54124
- Handlebars.registerHelper(
54125
- "values",
54126
- (obj) => {
54127
- if (!obj || typeof obj !== "object") return [];
54128
- return Object.values(obj);
53856
+ function collectRetryIds(retry) {
53857
+ const fixTask = taskMap.get(retry.fix_task);
53858
+ if (fixTask) collectTaskIds(fixTask);
53859
+ if (retry.revalidate_task) {
53860
+ const revalTask = taskMap.get(retry.revalidate_task);
53861
+ if (revalTask) addAgent(revalTask.target_agent);
53862
+ }
54129
53863
  }
54130
- );
54131
- Handlebars.registerHelper(
54132
- "filterByField",
54133
- (arr, field, value) => {
54134
- if (!Array.isArray(arr)) return [];
54135
- return arr.filter(
54136
- (item) => item?.[field] === value
54137
- );
53864
+ for (const step of workflow.steps) {
53865
+ if (step.type === "delegate") {
53866
+ addAgent(step.from_agent);
53867
+ const task = taskMap.get(step.task);
53868
+ if (task) collectTaskIds(task);
53869
+ if (step.retry) collectRetryIds(step.retry);
53870
+ } else if (step.type === "gate") {
53871
+ } else if (step.type === "handoff") {
53872
+ if (step.from_agent) addAgent(step.from_agent);
53873
+ if (step.task) {
53874
+ const task = taskMap.get(step.task);
53875
+ if (task) collectTaskIds(task);
53876
+ }
53877
+ if (step.retry) collectRetryIds(step.retry);
53878
+ } else if (step.type === "validation") {
53879
+ const val = dsl.validations[step.validation];
53880
+ if (val) {
53881
+ if (val.executor_type === "agent") addAgent(val.executor);
53882
+ else tools.add(val.executor);
53883
+ artifacts.add(val.target_artifact);
53884
+ }
53885
+ }
54138
53886
  }
54139
- );
54140
- Handlebars.registerHelper("not", (value) => !value);
54141
- Handlebars.registerHelper("or", (...args) => {
54142
- const _options = args.pop();
54143
- return args.some((a3) => !!a3);
54144
- });
54145
- Handlebars.registerHelper("coalesce", (...args) => {
54146
- const _options = args.pop();
54147
- return args.find((a3) => a3 != null && a3 !== false && a3 !== "");
54148
- });
54149
- Handlebars.registerHelper("and", (...args) => {
54150
- const _options = args.pop();
54151
- return args.every((a3) => !!a3);
54152
- });
54153
- Handlebars.registerHelper("gt", (a3, b3) => a3 > b3);
54154
- Handlebars.registerHelper("gte", (a3, b3) => a3 >= b3);
54155
- Handlebars.registerHelper("lt", (a3, b3) => a3 < b3);
54156
- Handlebars.registerHelper("size", (obj) => {
54157
- if (Array.isArray(obj)) return obj.length;
54158
- if (obj && typeof obj === "object") return Object.keys(obj).length;
54159
- return 0;
54160
- });
54161
- Handlebars.registerHelper(
54162
- "sequenceDiagram",
54163
- function(...args) {
54164
- const opts = args[args.length - 1];
54165
- const positionalArgs = args.slice(0, -1);
54166
- if (typeof positionalArgs[0] === "string" && positionalArgs[1]) {
54167
- const workflowId = positionalArgs[0];
54168
- const dsl2 = positionalArgs[1];
54169
- if (!dsl2.workflow[workflowId]) return "";
54170
- const ctx = buildWorkflowContext(dsl2, workflowId);
54171
- return generateSequenceDiagram(
54172
- ctx.workflow,
54173
- ctx.relatedTasks,
54174
- dsl2
54175
- );
53887
+ function addAgent(agentId) {
53888
+ const agent = dsl.agents[agentId];
53889
+ if (agent?.mode === "read-only") {
53890
+ auditAgents.add(agentId);
53891
+ } else {
53892
+ agents.add(agentId);
54176
53893
  }
54177
- const workflow = this["workflow"];
54178
- const relatedTasks = this["relatedTasks"];
54179
- const dsl = opts?.hash?.["dsl"] ?? this["dsl"];
54180
- if (!workflow || !dsl) return "";
54181
- return generateSequenceDiagram(workflow, relatedTasks ?? [], dsl);
54182
53894
  }
54183
- );
54184
- Handlebars.registerHelper(
54185
- "overviewFlowchart",
54186
- function(...args) {
54187
- const positionalArgs = args.slice(0, -1);
54188
- if (positionalArgs[0] && typeof positionalArgs[0] === "object") {
54189
- return generateOverviewFlowchart(positionalArgs[0]);
53895
+ return { agents, auditAgents, tools, artifacts };
53896
+ }
53897
+ function collectExecutionStepIds(es, tools, artifacts) {
53898
+ if (es.uses_tool) tools.add(es.uses_tool);
53899
+ if (es.produces_artifact) artifacts.add(es.produces_artifact);
53900
+ if (es.reads_artifact) artifacts.add(es.reads_artifact);
53901
+ }
53902
+ function buildParticipants(ids, externals, dsl) {
53903
+ const participants = [];
53904
+ const usedAliases = /* @__PURE__ */ new Set();
53905
+ function uniqueAlias(preferred) {
53906
+ let alias = preferred;
53907
+ let i3 = 2;
53908
+ while (usedAliases.has(alias)) {
53909
+ alias = `${preferred}${i3}`;
53910
+ i3++;
54190
53911
  }
54191
- const dsl = this["dsl"];
54192
- if (!dsl) return "";
54193
- return generateOverviewFlowchart(dsl);
53912
+ usedAliases.add(alias);
53913
+ return alias;
54194
53914
  }
54195
- );
54196
- Handlebars.registerHelper(
54197
- "guardrailCoverageMatrix",
54198
- function() {
54199
- const enforcement = this["guardrailEnforcement"];
54200
- if (!enforcement || enforcement.length === 0) return "";
54201
- const header = "| Guardrail | Severity | Action | Agents | Tasks | Workflows | Tools | Artifacts | Trigger | Override | Escalation |";
54202
- const divider = "|-----------|----------|--------|--------|-------|-----------|-------|-----------|---------|----------|------------|";
54203
- const rows = enforcement.map((e3) => {
54204
- const agents = e3["scoped_agents"]?.join(", ") || "\u2014";
54205
- const tasks = e3["scoped_tasks"]?.join(", ") || "\u2014";
54206
- const workflows = e3["scoped_workflows"]?.join(", ") || "\u2014";
54207
- const tools = e3["scoped_tools"]?.join(", ") || "\u2014";
54208
- const artifacts = e3["scoped_artifacts"]?.join(", ") || "\u2014";
54209
- const trigger = e3["trigger"] || "\u2014";
54210
- const override = e3["allow_override"] ? "yes" : "no";
54211
- const esc = e3["escalation"];
54212
- const escalation = esc ? esc["target"] : "\u2014";
54213
- return `| ${e3["guardrail_id"]} | ${e3["severity"]} | ${e3["action"]} | ${agents} | ${tasks} | ${workflows} | ${tools} | ${artifacts} | ${trigger} | ${override} | ${escalation} |`;
54214
- });
54215
- return [header, divider, ...rows].join("\n");
53915
+ for (const ep of externals) {
53916
+ const alias = uniqueAlias(sanitizeAlias(ep.id));
53917
+ participants.push({ id: ep.id, alias, label: ep.label, group: "external" });
54216
53918
  }
54217
- );
54218
- Handlebars.registerHelper(
54219
- "taskGuardrailMatrix",
54220
- function() {
54221
- const dsl = this["dsl"];
54222
- const enforcement = this["guardrailEnforcement"];
54223
- if (!dsl || !enforcement || enforcement.length === 0) return "";
54224
- const taskIds = Object.keys(dsl.tasks);
54225
- if (taskIds.length === 0) return "";
54226
- const guardrailIds = enforcement.map((e3) => e3["guardrail_id"]);
54227
- const header = `| Task | ${guardrailIds.join(" | ")} |`;
54228
- const divider = `|------|${guardrailIds.map(() => "------").join("|")}|`;
54229
- const rows = taskIds.map((taskId) => {
54230
- const cells = enforcement.map((e3) => {
54231
- const scopedTasks = e3["scoped_tasks"];
54232
- if (scopedTasks.length > 0 && !scopedTasks.includes(taskId)) return "n/a";
54233
- return e3["action"];
54234
- });
54235
- return `| ${taskId} | ${cells.join(" | ")} |`;
54236
- });
54237
- return [header, divider, ...rows].join("\n");
53919
+ for (const id of ids.agents) {
53920
+ const agent = dsl.agents[id];
53921
+ if (!agent) continue;
53922
+ const alias = uniqueAlias(agentAlias(id, agent));
53923
+ participants.push({ id, alias, label: agent.role_name, group: "agents" });
54238
53924
  }
54239
- );
54240
- function getDslSection(dsl, context) {
54241
- const sectionMap = {
54242
- agent: dsl.agents,
54243
- task: dsl.tasks,
54244
- artifact: dsl.artifacts,
54245
- tool: dsl.tools,
54246
- validation: dsl.validations,
54247
- handoff_type: dsl.handoff_types,
54248
- workflow: dsl.workflow,
54249
- policy: dsl.policies,
54250
- guardrail: dsl.guardrails,
54251
- guardrail_policy: dsl.guardrail_policies
54252
- };
54253
- return sectionMap[context] ?? {};
54254
- }
54255
- function filterIds(allIds, include, exclude) {
54256
- if (include) return allIds.filter((id) => include.includes(id));
54257
- if (exclude) return allIds.filter((id) => !exclude.includes(id));
54258
- return allIds;
53925
+ for (const id of ids.auditAgents) {
53926
+ const agent = dsl.agents[id];
53927
+ if (!agent) continue;
53928
+ const alias = uniqueAlias(agentAlias(id, agent));
53929
+ participants.push({ id, alias, label: agent.role_name, group: "audit" });
53930
+ }
53931
+ for (const id of ids.tools) {
53932
+ const tool = dsl.tools[id];
53933
+ if (!tool) continue;
53934
+ const alias = uniqueAlias(sanitizeAlias(id));
53935
+ participants.push({ id, alias, label: id, group: "toolchain" });
53936
+ }
53937
+ for (const id of ids.artifacts) {
53938
+ const art = dsl.artifacts[id];
53939
+ if (!art) continue;
53940
+ const alias = uniqueAlias(sanitizeAlias(id));
53941
+ participants.push({ id, alias, label: id, group: "artifacts" });
53942
+ }
53943
+ return participants;
54259
53944
  }
54260
- function expandOutputPath(pattern, context, entityId) {
54261
- return pattern.replace(new RegExp(`\\{${context}\\.id\\}`, "g"), entityId);
53945
+ function participantAlias(participants, id) {
53946
+ const p2 = participants.find((pp) => pp.id === id);
53947
+ return p2 ? p2.alias : sanitizeAlias(id);
54262
53948
  }
54263
- function buildEntityContext(dsl, context, entityId) {
54264
- switch (context) {
54265
- case "agent": {
54266
- const agentDef = dsl.agents[entityId];
54267
- const agentWithId = { ...agentDef, id: entityId };
54268
- return buildPerAgentContext(dsl, agentWithId);
53949
+ function emitParticipants(participants, externals, lines, indent) {
53950
+ const groups = {
53951
+ external: [],
53952
+ agents: [],
53953
+ audit: [],
53954
+ toolchain: [],
53955
+ artifacts: []
53956
+ };
53957
+ for (const p2 of participants) groups[p2.group].push(p2);
53958
+ const externalMap = /* @__PURE__ */ new Map();
53959
+ for (const ep of externals) externalMap.set(ep.id, ep);
53960
+ if (groups.external.length > 0) {
53961
+ lines.push(`${indent}box rgb(255,245,230) External`);
53962
+ for (const p2 of groups.external) {
53963
+ const ep = externalMap.get(p2.id);
53964
+ const keyword = ep?.kind === "actor" ? "actor" : "participant";
53965
+ if (p2.alias === p2.label) {
53966
+ lines.push(`${indent}${keyword} ${p2.alias}`);
53967
+ } else {
53968
+ lines.push(`${indent}${keyword} ${p2.alias} as ${p2.label}`);
53969
+ }
54269
53970
  }
54270
- case "task":
54271
- return buildTaskContext(dsl, entityId);
54272
- case "artifact":
54273
- return buildArtifactContext(dsl, entityId);
54274
- case "tool":
54275
- return buildToolContext(dsl, entityId);
54276
- case "validation":
54277
- return buildValidationContext(dsl, entityId);
54278
- case "handoff_type":
54279
- return buildHandoffTypeContext(dsl, entityId);
54280
- case "workflow":
54281
- return buildWorkflowContext(dsl, entityId);
54282
- case "policy":
54283
- return buildPolicyContext(dsl, entityId);
54284
- case "guardrail":
54285
- return buildGuardrailContext(dsl, entityId);
54286
- case "guardrail_policy":
54287
- return buildGuardrailPolicyContext(dsl, entityId);
54288
- case "system":
54289
- return buildSystemContext(dsl);
53971
+ lines.push(`${indent}end`);
53972
+ }
53973
+ const groupConfig = [
53974
+ { key: "agents", label: "Agents", color: "rgb(200,220,255)" },
53975
+ { key: "audit", label: "Audit", color: "rgb(255,220,220)" },
53976
+ { key: "toolchain", label: "Toolchain", color: "rgb(220,255,220)" },
53977
+ { key: "artifacts", label: "Artifacts", color: "rgb(255,230,210)" }
53978
+ ];
53979
+ for (const { key, label, color } of groupConfig) {
53980
+ const members = groups[key];
53981
+ if (members.length === 0) continue;
53982
+ lines.push(`${indent}box ${color} ${label}`);
53983
+ for (const p2 of members) {
53984
+ if (p2.alias === p2.label) {
53985
+ lines.push(`${indent}participant ${p2.alias}`);
53986
+ } else {
53987
+ lines.push(`${indent}participant ${p2.alias} as ${p2.label}`);
53988
+ }
53989
+ }
53990
+ lines.push(`${indent}end`);
54290
53991
  }
54291
53992
  }
54292
- async function loadTemplate(templatePath) {
54293
- return readFile4(templatePath, "utf8");
53993
+ function emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent) {
53994
+ const taskMap = /* @__PURE__ */ new Map();
53995
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
53996
+ if (!step.task) {
53997
+ if (step.from_agent) {
53998
+ const fromAlias2 = participantAlias(participants, step.from_agent);
53999
+ lines.push(`${indent}${fromAlias2}->>${fromAlias2}: ${step.handoff_kind}`);
54000
+ }
54001
+ return;
54002
+ }
54003
+ const task = taskMap.get(step.task);
54004
+ if (!task) return;
54005
+ const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
54006
+ const targetAlias = participantAlias(participants, task.target_agent);
54007
+ if (fromAlias) {
54008
+ lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
54009
+ }
54010
+ for (const es of task.execution_steps ?? []) {
54011
+ emitExecutionStep(es, targetAlias, participants, lines, indent);
54012
+ }
54013
+ if (fromAlias) {
54014
+ lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
54015
+ }
54294
54016
  }
54295
- function isEffectivelyEmpty(output) {
54296
- return output.trim().length === 0;
54017
+ function emitExecutionStep(es, agentAlias2, participants, lines, indent) {
54018
+ if (es.reads_artifact) {
54019
+ const artAlias = participantAlias(participants, es.reads_artifact);
54020
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [R] ${es.action}`);
54021
+ }
54022
+ if (es.produces_artifact) {
54023
+ const artAlias = participantAlias(participants, es.produces_artifact);
54024
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [W] ${es.action}`);
54025
+ }
54026
+ if (es.uses_tool) {
54027
+ const toolAlias = participantAlias(participants, es.uses_tool);
54028
+ lines.push(`${indent}${agentAlias2}->>${toolAlias}: ${es.action}`);
54029
+ }
54030
+ if (!es.reads_artifact && !es.produces_artifact && !es.uses_tool) {
54031
+ lines.push(`${indent}${agentAlias2}->>${agentAlias2}: ${es.action}`);
54032
+ }
54297
54033
  }
54298
- async function removeIfExists(filePath) {
54299
- try {
54300
- await unlink(filePath);
54301
- } catch {
54034
+ function emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent) {
54035
+ const val = dsl.validations[step.validation];
54036
+ if (!val) return;
54037
+ const executorAlias = participantAlias(participants, val.executor);
54038
+ const artifactAlias = participantAlias(participants, val.target_artifact);
54039
+ const fromAlias = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
54040
+ if (fromAlias && fromAlias !== executorAlias) {
54041
+ lines.push(`${indent}${fromAlias}->>${executorAlias}: ${step.validation}`);
54042
+ }
54043
+ lines.push(`${indent}${executorAlias}->>${artifactAlias}: [R] ${val.target_artifact}`);
54044
+ if (fromAlias && fromAlias !== executorAlias) {
54045
+ lines.push(`${indent}${executorAlias}-->>${fromAlias}: results`);
54302
54046
  }
54303
54047
  }
54304
- async function renderFromConfig(dsl, renderTargets, options) {
54305
- const outputFiles = [];
54306
- for (const target of renderTargets) {
54307
- const templateContent = await loadTemplate(target.template);
54308
- const compiled = Handlebars.compile(templateContent, { noEscape: false });
54309
- if (target.context === "system") {
54310
- const ctx = buildSystemContext(dsl, options);
54311
- const output = compiled(ctx);
54312
- if (target.skip_empty && isEffectivelyEmpty(output)) {
54313
- await removeIfExists(target.output);
54314
- continue;
54315
- }
54316
- await mkdir(dirname5(target.output), { recursive: true });
54317
- await writeFile(target.output, output, "utf8");
54318
- outputFiles.push(target.output);
54048
+ function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
54049
+ const branches = Object.entries(step.branches);
54050
+ if (branches.length === 0) return;
54051
+ const agentAl = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
54052
+ for (let i3 = 0; i3 < branches.length; i3++) {
54053
+ const [key, values] = branches[i3];
54054
+ if (i3 === 0) {
54055
+ lines.push(`${indent}alt ${key}`);
54319
54056
  } else {
54320
- const section = getDslSection(dsl, target.context);
54321
- const allIds = Object.keys(section);
54322
- const ids = filterIds(allIds, target.include, target.exclude);
54323
- for (const entityId of ids) {
54324
- const ctx = buildEntityContext(dsl, target.context, entityId);
54325
- const output = compiled(ctx);
54326
- const outputPath = expandOutputPath(target.output, target.context, entityId);
54327
- if (target.skip_empty && isEffectivelyEmpty(output)) {
54328
- await removeIfExists(outputPath);
54329
- continue;
54330
- }
54331
- await mkdir(dirname5(outputPath), { recursive: true });
54332
- await writeFile(outputPath, output, "utf8");
54333
- outputFiles.push(outputPath);
54334
- }
54057
+ lines.push(`${indent}else ${key}`);
54058
+ }
54059
+ if (agentAl) {
54060
+ lines.push(`${indent} Note over ${agentAl}: ${values.join(", ")}`);
54335
54061
  }
54336
54062
  }
54337
- return outputFiles;
54063
+ lines.push(`${indent}end`);
54338
54064
  }
54339
- async function fileExists2(filePath) {
54340
- try {
54341
- await readFile4(filePath);
54342
- return true;
54343
- } catch {
54344
- return false;
54065
+ function emitDelegateStep(step, participants, dsl, relatedTasks, lines, indent) {
54066
+ const taskMap = /* @__PURE__ */ new Map();
54067
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
54068
+ const task = taskMap.get(step.task);
54069
+ if (!task) return;
54070
+ const fromAlias = participantAlias(participants, step.from_agent);
54071
+ const targetAlias = participantAlias(participants, task.target_agent);
54072
+ lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
54073
+ for (const es of task.execution_steps ?? []) {
54074
+ emitExecutionStep(es, targetAlias, participants, lines, indent);
54345
54075
  }
54076
+ lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
54346
54077
  }
54347
- function checkExpectedVsExisting(expected, outputPath, skipEmpty, diffs) {
54348
- if (skipEmpty && isEffectivelyEmpty(expected)) {
54349
- return fileExists2(outputPath).then((exists) => {
54350
- if (exists) diffs.push(outputPath);
54351
- });
54078
+ function emitGateStep(step, participants, lastFromAgent, lines, indent) {
54079
+ if (lastFromAgent) {
54080
+ const agentAl = participantAlias(participants, lastFromAgent);
54081
+ lines.push(`${indent}${agentAl}->>${agentAl}: ${step.gate_kind}`);
54352
54082
  }
54353
- return readFile4(outputPath, "utf8").then((existing) => {
54354
- if (existing !== expected) diffs.push(outputPath);
54355
- }).catch(() => {
54356
- diffs.push(outputPath);
54357
- });
54358
54083
  }
54359
- async function checkDriftFromConfig(dsl, renderTargets, options) {
54360
- const diffs = [];
54361
- for (const target of renderTargets) {
54362
- const templateContent = await loadTemplate(target.template);
54363
- const compiled = Handlebars.compile(templateContent, { noEscape: false });
54364
- if (target.context === "system") {
54365
- const ctx = buildSystemContext(dsl, options);
54366
- const expected = compiled(ctx);
54367
- await checkExpectedVsExisting(expected, target.output, target.skip_empty, diffs);
54368
- } else {
54369
- const section = getDslSection(dsl, target.context);
54370
- const allIds = Object.keys(section);
54371
- const ids = filterIds(allIds, target.include, target.exclude);
54372
- for (const entityId of ids) {
54373
- const ctx = buildEntityContext(dsl, target.context, entityId);
54374
- const expected = compiled(ctx);
54375
- const outputPath = expandOutputPath(target.output, target.context, entityId);
54376
- await checkExpectedVsExisting(expected, outputPath, target.skip_empty, diffs);
54084
+ function emitRetryBlock(fromAgent, retry, participants, relatedTasks, lines, indent) {
54085
+ const taskMap = /* @__PURE__ */ new Map();
54086
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
54087
+ lines.push(`${indent}opt ${retry.condition}`);
54088
+ const innerIndent = indent + " ";
54089
+ const fixTask = taskMap.get(retry.fix_task);
54090
+ if (fixTask) {
54091
+ const fromAlias = fromAgent ? participantAlias(participants, fromAgent) : null;
54092
+ const targetAlias = participantAlias(participants, fixTask.target_agent);
54093
+ if (fromAlias) {
54094
+ lines.push(`${innerIndent}${fromAlias}->>${targetAlias}: fix ${retry.fix_task}`);
54095
+ }
54096
+ for (const es of fixTask.execution_steps ?? []) {
54097
+ emitExecutionStep(es, targetAlias, participants, lines, innerIndent);
54098
+ }
54099
+ if (fromAlias) {
54100
+ lines.push(`${innerIndent}${targetAlias}-->>${fromAlias}: ${fixTask.result_handoff}`);
54101
+ }
54102
+ }
54103
+ if (retry.revalidate_task) {
54104
+ const revalTask = taskMap.get(retry.revalidate_task);
54105
+ if (revalTask) {
54106
+ const fromAlias = fromAgent ? participantAlias(participants, fromAgent) : null;
54107
+ const revalAlias = participantAlias(participants, revalTask.target_agent);
54108
+ if (fromAlias) {
54109
+ lines.push(`${innerIndent}${fromAlias}->>${revalAlias}: revalidate ${retry.revalidate_task}`);
54110
+ lines.push(`${innerIndent}${revalAlias}-->>${fromAlias}: ${revalTask.result_handoff}`);
54377
54111
  }
54378
54112
  }
54379
54113
  }
54380
- return { hasDrift: diffs.length > 0, diffs };
54114
+ lines.push(`${indent}end`);
54381
54115
  }
54382
-
54383
- // src/cli/commands/render.ts
54384
- var renderCommand = new Command4("render").description("Render resolved DSL with Handlebars templates (requires config)").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--check", "Check for drift without writing files", false).option("--quiet", "Suppress output on success", false).action(
54385
- async (opts) => {
54386
- try {
54387
- const config = await loadConfig(opts.config);
54388
- if (!config) {
54389
- process.stderr.write(
54390
- "Error: agent-contracts.config.yaml not found. Use --config to specify path.\n"
54391
- );
54392
- process.exit(1);
54393
- }
54394
- if (isMultiTeamConfig(config)) {
54395
- const teamEntries = getTeamEntries(config, opts.team);
54396
- for (const [teamId, teamConfig] of teamEntries) {
54397
- if (!opts.quiet) process.stdout.write(`
54398
- --- Team: ${teamId} ---
54399
- `);
54400
- const resolved2 = await resolve4(teamConfig.dsl);
54401
- const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
54402
- const schemaResult2 = validateSchema(data2);
54403
- if (!schemaResult2.success) {
54404
- process.stderr.write(
54405
- `Schema validation failed for team ${teamId}. Run 'agent-contracts validate' for details.
54406
- `
54407
- );
54408
- process.exit(1);
54409
- }
54410
- let renderOptions2;
54411
- if (teamConfig.bindings.length > 0) {
54412
- const loadedBindings = await loadBindings(teamConfig.bindings);
54413
- renderOptions2 = {
54414
- loadedBindings,
54415
- activeGuardrailPolicy: teamConfig.activeGuardrailPolicy
54416
- };
54417
- }
54418
- if (opts.check) {
54419
- const drift = await checkDriftFromConfig(
54420
- schemaResult2.data,
54421
- config.renders,
54422
- renderOptions2
54423
- );
54424
- if (drift.hasDrift) {
54425
- process.stderr.write(
54426
- `Drift detected for team ${teamId} in the following files:
54427
- `
54428
- );
54429
- for (const f2 of drift.diffs) {
54430
- process.stderr.write(` ${f2}
54431
- `);
54432
- }
54433
- process.exit(1);
54434
- }
54435
- if (!opts.quiet) {
54436
- process.stdout.write("No drift detected.\n");
54437
- }
54438
- } else {
54439
- const files = await renderFromConfig(
54440
- schemaResult2.data,
54441
- config.renders,
54442
- renderOptions2
54443
- );
54444
- if (!opts.quiet) {
54445
- process.stdout.write(`Rendered ${files.length} file(s):
54446
- `);
54447
- for (const f2 of files) {
54448
- process.stdout.write(` ${f2}
54449
- `);
54450
- }
54451
- }
54452
- }
54453
- }
54454
- return;
54455
- }
54456
- const resolved = await resolve4(config.dsl);
54457
- const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
54458
- const schemaResult = validateSchema(data);
54459
- if (!schemaResult.success) {
54460
- process.stderr.write(
54461
- "Schema validation failed. Run 'agent-contracts validate' for details.\n"
54462
- );
54463
- process.exit(1);
54464
- }
54465
- let renderOptions;
54466
- if (config.bindings.length > 0) {
54467
- const loadedBindings = await loadBindings(config.bindings);
54468
- renderOptions = {
54469
- loadedBindings,
54470
- activeGuardrailPolicy: config.activeGuardrailPolicy
54471
- };
54472
- }
54473
- if (opts.check) {
54474
- const drift = await checkDriftFromConfig(
54475
- schemaResult.data,
54476
- config.renders,
54477
- renderOptions
54478
- );
54479
- if (drift.hasDrift) {
54480
- process.stderr.write("Drift detected in the following files:\n");
54481
- for (const f2 of drift.diffs) {
54482
- process.stderr.write(` ${f2}
54483
- `);
54484
- }
54485
- process.exit(1);
54486
- }
54487
- if (!opts.quiet) {
54488
- process.stdout.write("No drift detected.\n");
54489
- }
54116
+ function groupSteps(steps) {
54117
+ const result = [];
54118
+ let currentGroup = null;
54119
+ for (let i3 = 0; i3 < steps.length; i3++) {
54120
+ const step = steps[i3];
54121
+ const group = "group" in step ? step.group : void 0;
54122
+ if (group) {
54123
+ if (currentGroup && currentGroup.group === group) {
54124
+ currentGroup.steps.push({ step, index: i3 });
54490
54125
  } else {
54491
- const files = await renderFromConfig(
54492
- schemaResult.data,
54493
- config.renders,
54494
- renderOptions
54495
- );
54496
- if (!opts.quiet) {
54497
- process.stdout.write(`Rendered ${files.length} file(s):
54498
- `);
54499
- for (const f2 of files) {
54500
- process.stdout.write(` ${f2}
54501
- `);
54502
- }
54503
- }
54126
+ if (currentGroup) result.push(currentGroup);
54127
+ currentGroup = { group, steps: [{ step, index: i3 }] };
54504
54128
  }
54505
- } catch (err) {
54506
- if (err instanceof ConfigLoadError) {
54507
- process.stderr.write(`Config error: ${err.message}
54508
- `);
54509
- process.exit(1);
54129
+ } else {
54130
+ if (currentGroup) {
54131
+ result.push(currentGroup);
54132
+ currentGroup = null;
54510
54133
  }
54511
- const msg = err instanceof Error ? err.message : String(err);
54512
- process.stderr.write(`Error: ${msg}
54513
- `);
54514
- process.exit(1);
54134
+ result.push({ group: null, steps: [{ step, index: i3 }] });
54515
54135
  }
54516
54136
  }
54517
- );
54518
-
54519
- // src/cli/commands/check.ts
54520
- import { existsSync, readFileSync } from "fs";
54521
- import { join as join3 } from "path";
54522
- import { Command as Command5 } from "commander";
54523
- import { parse as parseYaml4, stringify as stringify3 } from "yaml";
54524
- import { access as access2 } from "fs/promises";
54525
- import { resolve as pathResolve, dirname as dirname6 } from "path";
54526
-
54527
- // src/interface-generator/generator.ts
54528
- import { stringify as stringify2 } from "yaml";
54529
- function buildInterfaceDocument(dsl, generatedAt) {
54530
- const ti = dsl.team_interface;
54531
- const doc = {
54532
- team_id: dsl.system.id,
54533
- team_name: dsl.system.name,
54534
- version: ti.version,
54535
- generated_at: generatedAt
54536
- };
54537
- if (ti.description !== void 0) {
54538
- doc.description = ti.description;
54137
+ if (currentGroup) result.push(currentGroup);
54138
+ return result;
54139
+ }
54140
+ function generateSequenceDiagram(workflow, relatedTasks, dsl) {
54141
+ const ids = collectReferencedIds(workflow, dsl, relatedTasks);
54142
+ const externals = workflow.external_participants ?? [];
54143
+ const participants = buildParticipants(ids, externals, dsl);
54144
+ const lines = [];
54145
+ const indent = " ";
54146
+ lines.push("sequenceDiagram");
54147
+ emitParticipants(participants, externals, lines, indent);
54148
+ lines.push("");
54149
+ lines.push(`${indent}rect ${hashToColor(workflow.id, 0.15, 0.95)}`);
54150
+ const firstP = participants[0];
54151
+ const lastP = participants[participants.length - 1];
54152
+ if (firstP && lastP) {
54153
+ const noteLabel = workflow.description ? `${workflow.id} \u2014 ${workflow.description}` : workflow.id;
54154
+ lines.push(`${indent}Note over ${firstP.alias},${lastP.alias}: ${noteLabel}`);
54539
54155
  }
54540
- if (ti.accepts?.workflows && Object.keys(ti.accepts.workflows).length > 0) {
54541
- doc.accepts = { workflows: { ...ti.accepts.workflows } };
54156
+ if (workflow.trigger && externals.some((ep) => ep.kind === "actor")) {
54157
+ const actor = externals.find((ep) => ep.kind === "actor");
54158
+ const actorAlias = participantAlias(participants, actor.id);
54159
+ const firstAgent = participants.find((p2) => p2.group === "agents" || p2.group === "audit");
54160
+ if (firstAgent) {
54161
+ lines.push(`${indent}${actorAlias}->>${firstAgent.alias}: ${workflow.trigger}`);
54162
+ }
54542
54163
  }
54543
- const handoffKeys = /* @__PURE__ */ new Set();
54544
- if (ti.accepts?.workflows) {
54545
- for (const spec of Object.values(ti.accepts.workflows)) {
54546
- handoffKeys.add(spec.input_handoff);
54547
- handoffKeys.add(spec.output_handoff);
54164
+ let lastFromAgent;
54165
+ const grouped = groupSteps(workflow.steps);
54166
+ for (const g2 of grouped) {
54167
+ if (g2.group && g2.steps.length > 1) {
54168
+ lines.push("");
54169
+ lines.push(`${indent}par ${g2.group}`);
54170
+ const parIndent = indent + " ";
54171
+ for (let i3 = 0; i3 < g2.steps.length; i3++) {
54172
+ const { step } = g2.steps[i3];
54173
+ if (i3 > 0) lines.push(`${indent}and`);
54174
+ emitStep(step, participants, dsl, relatedTasks, lines, parIndent, lastFromAgent, (a3) => {
54175
+ lastFromAgent = a3;
54176
+ });
54177
+ }
54178
+ lines.push(`${indent}end`);
54179
+ } else {
54180
+ for (const { step } of g2.steps) {
54181
+ lines.push("");
54182
+ emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, (a3) => {
54183
+ lastFromAgent = a3;
54184
+ });
54185
+ }
54548
54186
  }
54549
54187
  }
54550
- const handoff_types = {};
54551
- for (const k2 of [...handoffKeys].sort()) {
54552
- const ht = dsl.handoff_types[k2];
54553
- if (ht) {
54554
- const entry = {
54555
- version: ht.version,
54556
- schema: ht.schema
54557
- };
54558
- if (ht.description !== void 0) {
54559
- entry.description = ht.description;
54188
+ lines.push("");
54189
+ lines.push(`${indent}end`);
54190
+ return lines.join("\n");
54191
+ }
54192
+ function emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, setLastFromAgent) {
54193
+ if (step.type === "delegate") {
54194
+ setLastFromAgent(step.from_agent);
54195
+ emitDelegateStep(step, participants, dsl, relatedTasks, lines, indent);
54196
+ if (step.retry) {
54197
+ emitRetryBlock(step.from_agent, step.retry, participants, relatedTasks, lines, indent);
54198
+ }
54199
+ } else if (step.type === "gate") {
54200
+ emitGateStep(step, participants, lastFromAgent, lines, indent);
54201
+ } else if (step.type === "handoff") {
54202
+ if (step.from_agent) setLastFromAgent(step.from_agent);
54203
+ emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
54204
+ if (step.retry) {
54205
+ emitRetryBlock(step.from_agent, step.retry, participants, relatedTasks, lines, indent);
54206
+ }
54207
+ } else if (step.type === "validation") {
54208
+ emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
54209
+ } else if (step.type === "decision") {
54210
+ emitDecisionStep(step, participants, lastFromAgent, lines, indent);
54211
+ }
54212
+ }
54213
+
54214
+ // src/renderer/overview-flowchart.ts
54215
+ function collectPhaseOps(dsl, wfId) {
54216
+ const ctx = buildWorkflowContext(dsl, wfId);
54217
+ const wf = dsl.workflow[wfId];
54218
+ const agentOps = /* @__PURE__ */ new Map();
54219
+ const artifactOps = /* @__PURE__ */ new Map();
54220
+ const toolOps = /* @__PURE__ */ new Map();
54221
+ function addOp(map, id, op) {
54222
+ if (!map.has(id)) map.set(id, /* @__PURE__ */ new Set());
54223
+ map.get(id).add(op);
54224
+ }
54225
+ const taskMap = new Map(ctx.relatedTasks.map((t3) => [t3.id, t3]));
54226
+ function collectTaskOps(task) {
54227
+ addOp(agentOps, task.target_agent, "execute");
54228
+ for (const es of task.execution_steps ?? []) {
54229
+ if (es.reads_artifact) addOp(artifactOps, es.reads_artifact, "R");
54230
+ if (es.produces_artifact) addOp(artifactOps, es.produces_artifact, "W");
54231
+ if (es.uses_tool) {
54232
+ const tool = dsl.tools[es.uses_tool];
54233
+ if (tool) {
54234
+ const cats = tool.commands.map((c2) => c2.category).filter((v2, i3, a3) => a3.indexOf(v2) === i3);
54235
+ for (const cat of cats) addOp(toolOps, es.uses_tool, cat);
54236
+ if (cats.length === 0) addOp(toolOps, es.uses_tool, "\u2713");
54237
+ } else {
54238
+ addOp(toolOps, es.uses_tool, "\u2713");
54239
+ }
54560
54240
  }
54561
- handoff_types[k2] = entry;
54562
54241
  }
54563
54242
  }
54564
- if (Object.keys(handoff_types).length > 0) {
54565
- doc.handoff_types = handoff_types;
54566
- }
54567
- const artifactsOut = {};
54568
- if (ti.exposes?.artifacts) {
54569
- for (const key of [...ti.exposes.artifacts].sort()) {
54570
- const art = dsl.artifacts[key];
54571
- if (art) {
54572
- const entry = {
54573
- type: art.type,
54574
- states: art.states
54575
- };
54576
- if (art.description !== void 0) {
54577
- entry.description = art.description;
54243
+ for (const step of wf.steps) {
54244
+ if (step.type === "delegate") {
54245
+ addOp(agentOps, step.from_agent, "delegate");
54246
+ const task = taskMap.get(step.task);
54247
+ if (task) collectTaskOps(task);
54248
+ } else if (step.type === "gate") {
54249
+ } else if (step.type === "handoff") {
54250
+ if (step.from_agent) addOp(agentOps, step.from_agent, "delegate");
54251
+ if (step.task) {
54252
+ const task = taskMap.get(step.task);
54253
+ if (task) collectTaskOps(task);
54254
+ }
54255
+ } else if (step.type === "validation") {
54256
+ const val = dsl.validations[step.validation];
54257
+ if (val) {
54258
+ if (val.executor_type === "agent") {
54259
+ addOp(agentOps, val.executor, "validate");
54260
+ } else {
54261
+ addOp(toolOps, val.executor, "verification");
54578
54262
  }
54579
- artifactsOut[key] = entry;
54263
+ addOp(artifactOps, val.target_artifact, "V");
54580
54264
  }
54581
54265
  }
54582
54266
  }
54583
- if (Object.keys(artifactsOut).length > 0) {
54584
- doc.exposes = { artifacts: artifactsOut };
54585
- }
54586
- if (ti.constraints !== void 0 && ti.constraints.length > 0) {
54587
- doc.constraints = ti.constraints;
54588
- }
54589
- return doc;
54267
+ return { agentOps, artifactOps, toolOps };
54590
54268
  }
54591
- function generateInterface(options) {
54592
- if (!options.dsl.team_interface) {
54593
- throw new Error("DSL has no team_interface section");
54269
+ function formatOps(ops) {
54270
+ if (!ops || ops.size === 0) return "\u2014";
54271
+ return [...ops].join(", ");
54272
+ }
54273
+ function buildTable(header, rows) {
54274
+ const lines = [];
54275
+ lines.push("| " + header.join(" | ") + " |");
54276
+ lines.push("|" + header.map(() => "---").join("|") + "|");
54277
+ for (const row of rows) {
54278
+ lines.push("| " + row.join(" | ") + " |");
54594
54279
  }
54595
- const doc = buildInterfaceDocument(options.dsl, (/* @__PURE__ */ new Date()).toISOString());
54596
- const content = options.format === "json" ? `${JSON.stringify(doc, null, 2)}
54597
- ` : `${stringify2(doc, { sortMapEntries: true })}
54598
- `;
54599
- const outputPath = options.output ?? "team-interface.yaml";
54600
- return { outputPath, content };
54280
+ return lines.join("\n");
54601
54281
  }
54602
-
54603
- // src/cli/commands/check.ts
54604
- var checkCommand = new Command5("check").description("Run full pipeline: resolve \u2192 validate \u2192 lint \u2192 render --check").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--format <format>", "Output format (text|json)", "text").option("--quiet", "Suppress output on success", false).option("--strict", "Treat warnings as errors", false).action(
54605
- async (opts) => {
54606
- let hasErrors = false;
54607
- try {
54608
- const config = await loadConfig(opts.config);
54609
- if (!config) {
54610
- process.stderr.write(
54611
- "Error: agent-contracts.config.yaml not found. Use --config to specify path.\n"
54612
- );
54613
- process.exit(1);
54614
- }
54615
- if (isMultiTeamConfig(config)) {
54616
- const teamEntries = getTeamEntries(config, opts.team);
54617
- for (const [teamId, teamConfig] of teamEntries) {
54618
- if (!opts.quiet) process.stderr.write(`
54619
- --- Team: ${teamId} ---
54620
- `);
54621
- const resolved2 = await resolve4(teamConfig.dsl);
54622
- const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
54623
- const schemaResult2 = validateSchema(data2);
54624
- const schemaWarnings2 = schemaResult2.diagnostics.filter(
54625
- (d2) => d2.severity === "warning"
54626
- );
54627
- if (!schemaResult2.success) {
54628
- const output = formatDiagnostics(schemaResult2.diagnostics, {
54629
- format: opts.format,
54630
- quiet: opts.quiet
54631
- });
54632
- if (output) process.stderr.write(output + "\n");
54633
- hasErrors = true;
54634
- continue;
54635
- }
54636
- const refDiags2 = checkReferences(schemaResult2.data);
54637
- const handoffDiags2 = validateHandoffSchemas(schemaResult2.data);
54638
- const allRefDiags2 = [...refDiags2, ...handoffDiags2, ...schemaWarnings2];
54639
- if (allRefDiags2.length > 0) {
54640
- const output = formatDiagnostics(allRefDiags2, {
54641
- format: opts.format,
54642
- quiet: opts.quiet
54643
- });
54644
- if (output) process.stderr.write(output + "\n");
54645
- hasErrors = true;
54646
- }
54647
- const tsLintDiags2 = lint(schemaResult2.data);
54648
- const spectralDiags2 = await spectralLint(
54649
- schemaResult2.data
54650
- );
54651
- const lintDiags2 = [...tsLintDiags2, ...spectralDiags2];
54652
- if (lintDiags2.length > 0) {
54653
- const output = formatDiagnostics(lintDiags2, {
54654
- format: opts.format,
54655
- quiet: opts.quiet
54656
- });
54657
- if (output) process.stderr.write(output + "\n");
54658
- if (lintDiags2.some((d2) => d2.severity === "error")) {
54659
- hasErrors = true;
54660
- }
54661
- if (opts.strict && lintDiags2.some((d2) => d2.severity === "warning")) {
54662
- hasErrors = true;
54663
- }
54664
- }
54665
- let renderOptions2;
54666
- if (teamConfig.bindings.length > 0) {
54667
- const loadedBindings = await loadBindings(teamConfig.bindings);
54668
- renderOptions2 = {
54669
- loadedBindings,
54670
- activeGuardrailPolicy: teamConfig.activeGuardrailPolicy
54671
- };
54672
- }
54673
- const drift2 = await checkDriftFromConfig(
54674
- schemaResult2.data,
54675
- config.renders,
54676
- renderOptions2
54677
- );
54678
- if (drift2.hasDrift) {
54679
- process.stderr.write(`Drift detected for team ${teamId} in:
54680
- `);
54681
- for (const f2 of drift2.diffs) {
54682
- process.stderr.write(` ${f2}
54683
- `);
54684
- }
54685
- hasErrors = true;
54686
- }
54687
- }
54688
- if (!hasErrors) {
54689
- for (const [teamId, teamConfig] of teamEntries) {
54690
- const resolved2 = await resolve4(teamConfig.dsl);
54691
- const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
54692
- const schemaResult2 = validateSchema(data2);
54693
- if (!schemaResult2.success || !schemaResult2.data) continue;
54694
- const dsl = schemaResult2.data;
54695
- const imports = dsl.imports;
54696
- if (!imports) continue;
54697
- for (const [importName, importDef] of Object.entries(imports)) {
54698
- const interfacePathRel = importDef?.interface;
54699
- if (typeof interfacePathRel !== "string") continue;
54700
- const interfacePath = pathResolve(
54701
- dirname6(teamConfig.dsl),
54702
- interfacePathRel
54703
- );
54704
- try {
54705
- await access2(interfacePath);
54706
- } catch {
54707
- process.stderr.write(
54708
- `Cross-team error: Team "${teamId}" imports "${importName}" but interface file not found: ${interfacePath}
54709
- `
54710
- );
54711
- hasErrors = true;
54712
- }
54713
- }
54714
- }
54715
- }
54716
- if (hasErrors) process.exit(1);
54717
- if (!opts.quiet) process.stdout.write("All checks passed.\n");
54718
- return;
54719
- }
54720
- const resolved = await resolve4(config.dsl);
54721
- const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
54722
- const schemaResult = validateSchema(data);
54723
- const schemaWarnings = schemaResult.diagnostics.filter(
54724
- (d2) => d2.severity === "warning"
54725
- );
54726
- if (!schemaResult.success) {
54727
- const output = formatDiagnostics(schemaResult.diagnostics, {
54728
- format: opts.format,
54729
- quiet: opts.quiet
54730
- });
54731
- if (output) process.stderr.write(output + "\n");
54732
- process.exit(1);
54733
- }
54734
- const refDiags = checkReferences(schemaResult.data);
54735
- const handoffDiags = validateHandoffSchemas(schemaResult.data);
54736
- const allRefDiags = [...refDiags, ...handoffDiags, ...schemaWarnings];
54737
- if (allRefDiags.length > 0) {
54738
- const output = formatDiagnostics(allRefDiags, {
54739
- format: opts.format,
54740
- quiet: opts.quiet
54741
- });
54742
- if (output) process.stderr.write(output + "\n");
54743
- hasErrors = true;
54744
- }
54745
- const tsLintDiags = lint(schemaResult.data);
54746
- const spectralDiags = await spectralLint(schemaResult.data);
54747
- const lintDiags = [...tsLintDiags, ...spectralDiags];
54748
- if (lintDiags.length > 0) {
54749
- const output = formatDiagnostics(lintDiags, {
54750
- format: opts.format,
54751
- quiet: opts.quiet
54752
- });
54753
- if (output) process.stderr.write(output + "\n");
54754
- if (lintDiags.some((d2) => d2.severity === "error")) {
54755
- hasErrors = true;
54756
- }
54757
- if (opts.strict && lintDiags.some((d2) => d2.severity === "warning")) {
54758
- hasErrors = true;
54759
- }
54282
+ function generateOverviewFlowchart(dsl) {
54283
+ const workflowOrder = dsl.system.default_workflow_order ?? Object.keys(dsl.workflow);
54284
+ const phases = workflowOrder.filter((id) => dsl.workflow[id]);
54285
+ const phaseData = /* @__PURE__ */ new Map();
54286
+ for (const wfId of phases) {
54287
+ phaseData.set(wfId, collectPhaseOps(dsl, wfId));
54288
+ }
54289
+ const allAgentIds = /* @__PURE__ */ new Set();
54290
+ const allArtifactIds = /* @__PURE__ */ new Set();
54291
+ const allToolIds = /* @__PURE__ */ new Set();
54292
+ for (const ops of phaseData.values()) {
54293
+ for (const id of ops.agentOps.keys()) allAgentIds.add(id);
54294
+ for (const id of ops.artifactOps.keys()) allArtifactIds.add(id);
54295
+ for (const id of ops.toolOps.keys()) allToolIds.add(id);
54296
+ }
54297
+ const sections = [];
54298
+ if (allAgentIds.size > 0) {
54299
+ const header = ["Agent", ...phases];
54300
+ const rows = [];
54301
+ for (const agentId of allAgentIds) {
54302
+ const agent = dsl.agents[agentId];
54303
+ const label = agent ? agent.role_name : agentId;
54304
+ const row = [label];
54305
+ for (const wfId of phases) {
54306
+ row.push(formatOps(phaseData.get(wfId).agentOps.get(agentId)));
54760
54307
  }
54761
- let renderOptions;
54762
- if (config.bindings.length > 0) {
54763
- const loadedBindings = await loadBindings(config.bindings);
54764
- renderOptions = {
54765
- loadedBindings,
54766
- activeGuardrailPolicy: config.activeGuardrailPolicy
54767
- };
54308
+ rows.push(row);
54309
+ }
54310
+ sections.push("#### Agent \xD7 Phase\n\n" + buildTable(header, rows));
54311
+ }
54312
+ if (allArtifactIds.size > 0) {
54313
+ const header = ["Artifact", ...phases];
54314
+ const rows = [];
54315
+ for (const artId of allArtifactIds) {
54316
+ const row = [artId];
54317
+ for (const wfId of phases) {
54318
+ row.push(formatOps(phaseData.get(wfId).artifactOps.get(artId)));
54768
54319
  }
54769
- const drift = await checkDriftFromConfig(
54770
- schemaResult.data,
54771
- config.renders,
54772
- renderOptions
54773
- );
54774
- if (drift.hasDrift) {
54775
- process.stderr.write("Drift detected in:\n");
54776
- for (const f2 of drift.diffs) {
54777
- process.stderr.write(` ${f2}
54778
- `);
54779
- }
54780
- hasErrors = true;
54320
+ rows.push(row);
54321
+ }
54322
+ sections.push("#### Artifact \xD7 Phase\n\n" + buildTable(header, rows));
54323
+ }
54324
+ if (allToolIds.size > 0) {
54325
+ const header = ["Tool", ...phases];
54326
+ const rows = [];
54327
+ for (const toolId of allToolIds) {
54328
+ const row = [toolId];
54329
+ for (const wfId of phases) {
54330
+ row.push(formatOps(phaseData.get(wfId).toolOps.get(toolId)));
54781
54331
  }
54782
- if (schemaResult.data.team_interface) {
54783
- const interfacePath = join3(config.configDir, "team-interface.yaml");
54784
- if (existsSync(interfacePath)) {
54785
- const result = generateInterface({
54786
- dsl: schemaResult.data,
54787
- dryRun: true,
54788
- format: "yaml"
54789
- });
54790
- const existing = readFileSync(interfacePath, "utf8");
54791
- const normalize = (raw) => {
54792
- try {
54793
- const parsed = parseYaml4(raw);
54794
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
54795
- const { generated_at: _t, ...rest } = parsed;
54796
- return `${stringify3(rest, { sortMapEntries: true })}
54797
- `;
54798
- }
54799
- } catch {
54332
+ rows.push(row);
54333
+ }
54334
+ sections.push("#### Tool \xD7 Phase\n\n" + buildTable(header, rows));
54335
+ }
54336
+ return sections.join("\n\n");
54337
+ }
54338
+
54339
+ // src/renderer/renderer.ts
54340
+ Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
54341
+ Handlebars.registerHelper("notEmpty", (obj) => {
54342
+ if (!obj || typeof obj !== "object") return false;
54343
+ return Object.keys(obj).length > 0;
54344
+ });
54345
+ Handlebars.registerHelper("inc", (val) => val + 1);
54346
+ Handlebars.registerHelper(
54347
+ "lookupPayloadFields",
54348
+ (schema) => {
54349
+ const effective = resolveAllOf(schema ?? {});
54350
+ const props = effective["properties"];
54351
+ if (!props) return [];
54352
+ const requiredSet = new Set(
54353
+ effective["required"] ?? []
54354
+ );
54355
+ return Object.entries(props).map(([name, sub]) => {
54356
+ const enumVals = sub["enum"];
54357
+ return {
54358
+ name,
54359
+ type: sub["type"] ?? "any",
54360
+ required: requiredSet.has(name),
54361
+ enum: enumVals ? enumVals.join(" | ") : void 0
54362
+ };
54363
+ });
54364
+ }
54365
+ );
54366
+ function toYamlLines(obj, indent) {
54367
+ const pad = " ".repeat(indent);
54368
+ if (obj === null || obj === void 0) return [`${pad}null`];
54369
+ if (typeof obj === "boolean" || typeof obj === "number")
54370
+ return [`${pad}${obj}`];
54371
+ if (typeof obj === "string") {
54372
+ if (obj.includes("\n")) {
54373
+ const lines = [`${pad}|`];
54374
+ for (const line of obj.split("\n")) {
54375
+ lines.push(line === "" ? "" : `${pad} ${line}`);
54376
+ }
54377
+ return lines;
54378
+ }
54379
+ return [`${pad}${JSON.stringify(obj)}`];
54380
+ }
54381
+ if (Array.isArray(obj)) {
54382
+ const lines = [];
54383
+ for (const item of obj) {
54384
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
54385
+ const entries = Object.entries(item);
54386
+ if (entries.length > 0) {
54387
+ const [firstKey, firstVal] = entries[0];
54388
+ const firstValLines = toYamlLines(firstVal, 0);
54389
+ if (firstValLines.length === 1 && !firstValLines[0].includes("\n")) {
54390
+ lines.push(`${pad}- ${firstKey}: ${firstValLines[0].trim()}`);
54391
+ } else {
54392
+ lines.push(`${pad}- ${firstKey}:`);
54393
+ lines.push(...toYamlLines(firstVal, indent + 2));
54394
+ }
54395
+ for (let i3 = 1; i3 < entries.length; i3++) {
54396
+ const [k2, v2] = entries[i3];
54397
+ const vLines = toYamlLines(v2, indent + 2);
54398
+ if (vLines.length === 1) {
54399
+ lines.push(`${pad} ${k2}: ${vLines[0].trim()}`);
54400
+ } else {
54401
+ lines.push(`${pad} ${k2}:`);
54402
+ lines.push(...vLines);
54800
54403
  }
54801
- return raw.trim();
54802
- };
54803
- if (normalize(existing) !== normalize(result.content)) {
54804
- process.stderr.write("Drift detected in team-interface.yaml\n");
54805
- hasErrors = true;
54806
54404
  }
54405
+ } else {
54406
+ lines.push(`${pad}- {}`);
54807
54407
  }
54408
+ } else {
54409
+ const valLines = toYamlLines(item, 0);
54410
+ lines.push(`${pad}- ${valLines[0].trim()}`);
54808
54411
  }
54809
- if (hasErrors) {
54810
- process.exit(1);
54811
- }
54812
- if (!opts.quiet) {
54813
- process.stdout.write("All checks passed.\n");
54814
- }
54815
- } catch (err) {
54816
- if (err instanceof ConfigLoadError) {
54817
- process.stderr.write(`Config error: ${err.message}
54818
- `);
54819
- process.exit(1);
54412
+ }
54413
+ return lines;
54414
+ }
54415
+ if (typeof obj === "object") {
54416
+ const lines = [];
54417
+ for (const [key, value] of Object.entries(
54418
+ obj
54419
+ )) {
54420
+ const valLines = toYamlLines(value, indent + 1);
54421
+ if (valLines.length === 1 && !valLines[0].includes("|")) {
54422
+ lines.push(`${pad}${key}: ${valLines[0].trim()}`);
54423
+ } else {
54424
+ lines.push(`${pad}${key}:`);
54425
+ lines.push(...valLines);
54820
54426
  }
54821
- const msg = err instanceof Error ? err.message : String(err);
54822
- process.stderr.write(`Error: ${msg}
54823
- `);
54824
- process.exit(1);
54825
54427
  }
54428
+ return lines;
54429
+ }
54430
+ return [`${pad}${String(obj)}`];
54431
+ }
54432
+ Handlebars.registerHelper("yamlBlock", (obj) => {
54433
+ return toYamlLines(obj, 0).join("\n");
54434
+ });
54435
+ Handlebars.registerHelper(
54436
+ "join",
54437
+ (arr, separator) => {
54438
+ if (!Array.isArray(arr)) return "";
54439
+ const sep = typeof separator === "string" ? separator : ", ";
54440
+ return arr.join(sep);
54441
+ }
54442
+ );
54443
+ Handlebars.registerHelper("contains", (arr, value) => {
54444
+ if (!Array.isArray(arr)) return false;
54445
+ return arr.includes(value);
54446
+ });
54447
+ Handlebars.registerHelper(
54448
+ "groupBy",
54449
+ (arr, key) => {
54450
+ if (!Array.isArray(arr)) return {};
54451
+ const result = {};
54452
+ for (const item of arr) {
54453
+ const k2 = String(
54454
+ item?.[key] ?? "undefined"
54455
+ );
54456
+ (result[k2] ??= []).push(item);
54457
+ }
54458
+ return result;
54459
+ }
54460
+ );
54461
+ Handlebars.registerHelper(
54462
+ "keys",
54463
+ (obj) => {
54464
+ if (!obj || typeof obj !== "object") return [];
54465
+ return Object.keys(obj);
54466
+ }
54467
+ );
54468
+ Handlebars.registerHelper(
54469
+ "values",
54470
+ (obj) => {
54471
+ if (!obj || typeof obj !== "object") return [];
54472
+ return Object.values(obj);
54473
+ }
54474
+ );
54475
+ Handlebars.registerHelper(
54476
+ "filterByField",
54477
+ (arr, field, value) => {
54478
+ if (!Array.isArray(arr)) return [];
54479
+ return arr.filter(
54480
+ (item) => item?.[field] === value
54481
+ );
54482
+ }
54483
+ );
54484
+ Handlebars.registerHelper("not", (value) => !value);
54485
+ Handlebars.registerHelper("or", (...args) => {
54486
+ const _options = args.pop();
54487
+ return args.some((a3) => !!a3);
54488
+ });
54489
+ Handlebars.registerHelper("coalesce", (...args) => {
54490
+ const _options = args.pop();
54491
+ return args.find((a3) => a3 != null && a3 !== false && a3 !== "");
54492
+ });
54493
+ Handlebars.registerHelper("and", (...args) => {
54494
+ const _options = args.pop();
54495
+ return args.every((a3) => !!a3);
54496
+ });
54497
+ Handlebars.registerHelper("gt", (a3, b3) => a3 > b3);
54498
+ Handlebars.registerHelper("gte", (a3, b3) => a3 >= b3);
54499
+ Handlebars.registerHelper("lt", (a3, b3) => a3 < b3);
54500
+ Handlebars.registerHelper("size", (obj) => {
54501
+ if (Array.isArray(obj)) return obj.length;
54502
+ if (obj && typeof obj === "object") return Object.keys(obj).length;
54503
+ return 0;
54504
+ });
54505
+ Handlebars.registerHelper(
54506
+ "sequenceDiagram",
54507
+ function(...args) {
54508
+ const opts = args[args.length - 1];
54509
+ const positionalArgs = args.slice(0, -1);
54510
+ if (typeof positionalArgs[0] === "string" && positionalArgs[1]) {
54511
+ const workflowId = positionalArgs[0];
54512
+ const dsl2 = positionalArgs[1];
54513
+ if (!dsl2.workflow[workflowId]) return "";
54514
+ const ctx = buildWorkflowContext(dsl2, workflowId);
54515
+ return generateSequenceDiagram(
54516
+ ctx.workflow,
54517
+ ctx.relatedTasks,
54518
+ dsl2
54519
+ );
54520
+ }
54521
+ const workflow = this["workflow"];
54522
+ const relatedTasks = this["relatedTasks"];
54523
+ const dsl = opts?.hash?.["dsl"] ?? this["dsl"];
54524
+ if (!workflow || !dsl) return "";
54525
+ return generateSequenceDiagram(workflow, relatedTasks ?? [], dsl);
54826
54526
  }
54827
54527
  );
54828
-
54829
- // src/cli/commands/generate-guardrails.ts
54830
- import { Command as Command6 } from "commander";
54831
-
54832
- // src/guardrail-generator/generator.ts
54833
- import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink as unlink2, copyFile } from "fs/promises";
54834
- import { resolve as resolve6, dirname as dirname7 } from "path";
54835
- import Handlebars2 from "handlebars";
54836
- import YAML from "yaml";
54837
-
54838
- // src/guardrail-generator/resolve-checks.ts
54839
- function resolveChecks(dsl, binding, policy) {
54840
- const resolved = [];
54841
- const diagnostics = [];
54842
- const guardrailImpl = binding.guardrail_impl ?? {};
54843
- for (const [guardrailId, impl] of Object.entries(guardrailImpl)) {
54844
- const guardrail = dsl.guardrails[guardrailId];
54845
- if (!guardrail) {
54846
- diagnostics.push({
54847
- path: `binding.${binding.software}.guardrail_impl.${guardrailId}`,
54848
- message: `Binding "${binding.software}" implements guardrail "${guardrailId}" which is not defined in the DSL`,
54849
- severity: "error"
54850
- });
54851
- continue;
54852
- }
54853
- const policyRule = policy.rules.find((r3) => r3.guardrail === guardrailId);
54854
- if (!policyRule) {
54855
- diagnostics.push({
54856
- path: `binding.${binding.software}.guardrail_impl.${guardrailId}`,
54857
- message: `Guardrail "${guardrailId}" has no policy rule in the active policy \u2014 skipping`,
54858
- severity: "info"
54859
- });
54860
- continue;
54528
+ Handlebars.registerHelper(
54529
+ "overviewFlowchart",
54530
+ function(...args) {
54531
+ const positionalArgs = args.slice(0, -1);
54532
+ if (positionalArgs[0] && typeof positionalArgs[0] === "object") {
54533
+ return generateOverviewFlowchart(positionalArgs[0]);
54861
54534
  }
54862
- for (const check of impl.checks) {
54863
- resolved.push({
54864
- guardrail_id: guardrailId,
54865
- guardrail,
54866
- policy_rule: policyRule,
54867
- check
54535
+ const dsl = this["dsl"];
54536
+ if (!dsl) return "";
54537
+ return generateOverviewFlowchart(dsl);
54538
+ }
54539
+ );
54540
+ Handlebars.registerHelper(
54541
+ "guardrailCoverageMatrix",
54542
+ function() {
54543
+ const enforcement = this["guardrailEnforcement"];
54544
+ if (!enforcement || enforcement.length === 0) return "";
54545
+ const header = "| Guardrail | Severity | Action | Agents | Tasks | Workflows | Tools | Artifacts | Trigger | Override | Escalation |";
54546
+ const divider = "|-----------|----------|--------|--------|-------|-----------|-------|-----------|---------|----------|------------|";
54547
+ const rows = enforcement.map((e3) => {
54548
+ const agents = e3["scoped_agents"]?.join(", ") || "\u2014";
54549
+ const tasks = e3["scoped_tasks"]?.join(", ") || "\u2014";
54550
+ const workflows = e3["scoped_workflows"]?.join(", ") || "\u2014";
54551
+ const tools = e3["scoped_tools"]?.join(", ") || "\u2014";
54552
+ const artifacts = e3["scoped_artifacts"]?.join(", ") || "\u2014";
54553
+ const trigger = e3["trigger"] || "\u2014";
54554
+ const override = e3["allow_override"] ? "yes" : "no";
54555
+ const esc = e3["escalation"];
54556
+ const escalation = esc ? esc["target"] : "\u2014";
54557
+ return `| ${e3["guardrail_id"]} | ${e3["severity"]} | ${e3["action"]} | ${agents} | ${tasks} | ${workflows} | ${tools} | ${artifacts} | ${trigger} | ${override} | ${escalation} |`;
54558
+ });
54559
+ return [header, divider, ...rows].join("\n");
54560
+ }
54561
+ );
54562
+ Handlebars.registerHelper(
54563
+ "taskGuardrailMatrix",
54564
+ function() {
54565
+ const dsl = this["dsl"];
54566
+ const enforcement = this["guardrailEnforcement"];
54567
+ if (!dsl || !enforcement || enforcement.length === 0) return "";
54568
+ const taskIds = Object.keys(dsl.tasks);
54569
+ if (taskIds.length === 0) return "";
54570
+ const guardrailIds = enforcement.map((e3) => e3["guardrail_id"]);
54571
+ const header = `| Task | ${guardrailIds.join(" | ")} |`;
54572
+ const divider = `|------|${guardrailIds.map(() => "------").join("|")}|`;
54573
+ const rows = taskIds.map((taskId) => {
54574
+ const cells = enforcement.map((e3) => {
54575
+ const scopedTasks = e3["scoped_tasks"];
54576
+ if (scopedTasks.length > 0 && !scopedTasks.includes(taskId)) return "n/a";
54577
+ return e3["action"];
54868
54578
  });
54579
+ return `| ${taskId} | ${cells.join(" | ")} |`;
54580
+ });
54581
+ return [header, divider, ...rows].join("\n");
54582
+ }
54583
+ );
54584
+ function getDslSection(dsl, context) {
54585
+ const sectionMap = {
54586
+ agent: dsl.agents,
54587
+ task: dsl.tasks,
54588
+ artifact: dsl.artifacts,
54589
+ tool: dsl.tools,
54590
+ validation: dsl.validations,
54591
+ handoff_type: dsl.handoff_types,
54592
+ workflow: dsl.workflow,
54593
+ policy: dsl.policies,
54594
+ guardrail: dsl.guardrails,
54595
+ guardrail_policy: dsl.guardrail_policies
54596
+ };
54597
+ return sectionMap[context] ?? {};
54598
+ }
54599
+ function filterIds(allIds, include, exclude) {
54600
+ if (include) return allIds.filter((id) => include.includes(id));
54601
+ if (exclude) return allIds.filter((id) => !exclude.includes(id));
54602
+ return allIds;
54603
+ }
54604
+ function expandOutputPath(pattern, context, entityId) {
54605
+ return pattern.replace(new RegExp(`\\{${context}\\.id\\}`, "g"), entityId);
54606
+ }
54607
+ function buildEntityContext(dsl, context, entityId) {
54608
+ switch (context) {
54609
+ case "agent": {
54610
+ const agentDef = dsl.agents[entityId];
54611
+ const agentWithId = { ...agentDef, id: entityId };
54612
+ return buildPerAgentContext(dsl, agentWithId);
54869
54613
  }
54614
+ case "task":
54615
+ return buildTaskContext(dsl, entityId);
54616
+ case "artifact":
54617
+ return buildArtifactContext(dsl, entityId);
54618
+ case "tool":
54619
+ return buildToolContext(dsl, entityId);
54620
+ case "validation":
54621
+ return buildValidationContext(dsl, entityId);
54622
+ case "handoff_type":
54623
+ return buildHandoffTypeContext(dsl, entityId);
54624
+ case "workflow":
54625
+ return buildWorkflowContext(dsl, entityId);
54626
+ case "policy":
54627
+ return buildPolicyContext(dsl, entityId);
54628
+ case "guardrail":
54629
+ return buildGuardrailContext(dsl, entityId);
54630
+ case "guardrail_policy":
54631
+ return buildGuardrailPolicyContext(dsl, entityId);
54632
+ case "system":
54633
+ return buildSystemContext(dsl);
54870
54634
  }
54871
- return { resolved, diagnostics };
54872
54635
  }
54873
-
54874
- // src/guardrail-generator/resolve-paths.ts
54875
- function resolveBindingTargetPath(target, paths, bindingSoftware) {
54876
- const diagnostics = [];
54877
- const resolved = target.replace(/\{(\w+)\}/g, (match, varName) => {
54878
- const value = paths[varName];
54879
- if (value === void 0) {
54880
- diagnostics.push({
54881
- path: `binding.${bindingSoftware}.outputs`,
54882
- message: `Path variable "${varName}" used in target "${target}" but not defined in config.paths`,
54883
- severity: "error"
54884
- });
54885
- return match;
54636
+ async function loadTemplate(templatePath) {
54637
+ return readFile4(templatePath, "utf8");
54638
+ }
54639
+ function isEffectivelyEmpty(output) {
54640
+ return output.trim().length === 0;
54641
+ }
54642
+ async function removeIfExists(filePath) {
54643
+ try {
54644
+ await unlink(filePath);
54645
+ } catch {
54646
+ }
54647
+ }
54648
+ async function renderFromConfig(dsl, renderTargets, options) {
54649
+ const outputFiles = [];
54650
+ for (const target of renderTargets) {
54651
+ const templateContent = await loadTemplate(target.template);
54652
+ const compiled = Handlebars.compile(templateContent, { noEscape: false });
54653
+ if (target.context === "system") {
54654
+ const ctx = buildSystemContext(dsl, options);
54655
+ const output = compiled(ctx);
54656
+ if (target.skip_empty && isEffectivelyEmpty(output)) {
54657
+ await removeIfExists(target.output);
54658
+ continue;
54659
+ }
54660
+ await mkdir(dirname5(target.output), { recursive: true });
54661
+ await writeFile(target.output, output, "utf8");
54662
+ outputFiles.push(target.output);
54663
+ } else {
54664
+ const section = getDslSection(dsl, target.context);
54665
+ const allIds = Object.keys(section);
54666
+ const ids = filterIds(allIds, target.include, target.exclude);
54667
+ for (const entityId of ids) {
54668
+ const ctx = buildEntityContext(dsl, target.context, entityId);
54669
+ const output = compiled(ctx);
54670
+ const outputPath = expandOutputPath(target.output, target.context, entityId);
54671
+ if (target.skip_empty && isEffectivelyEmpty(output)) {
54672
+ await removeIfExists(outputPath);
54673
+ continue;
54674
+ }
54675
+ await mkdir(dirname5(outputPath), { recursive: true });
54676
+ await writeFile(outputPath, output, "utf8");
54677
+ outputFiles.push(outputPath);
54678
+ }
54886
54679
  }
54887
- return value;
54680
+ }
54681
+ return outputFiles;
54682
+ }
54683
+ async function fileExists2(filePath) {
54684
+ try {
54685
+ await readFile4(filePath);
54686
+ return true;
54687
+ } catch {
54688
+ return false;
54689
+ }
54690
+ }
54691
+ function checkExpectedVsExisting(expected, outputPath, skipEmpty, diffs) {
54692
+ if (skipEmpty && isEffectivelyEmpty(expected)) {
54693
+ return fileExists2(outputPath).then((exists) => {
54694
+ if (exists) diffs.push(outputPath);
54695
+ });
54696
+ }
54697
+ return readFile4(outputPath, "utf8").then((existing) => {
54698
+ if (existing !== expected) diffs.push(outputPath);
54699
+ }).catch(() => {
54700
+ diffs.push(outputPath);
54888
54701
  });
54889
- return { resolved, diagnostics };
54702
+ }
54703
+ async function checkDriftFromConfig(dsl, renderTargets, options) {
54704
+ const diffs = [];
54705
+ for (const target of renderTargets) {
54706
+ const templateContent = await loadTemplate(target.template);
54707
+ const compiled = Handlebars.compile(templateContent, { noEscape: false });
54708
+ if (target.context === "system") {
54709
+ const ctx = buildSystemContext(dsl, options);
54710
+ const expected = compiled(ctx);
54711
+ await checkExpectedVsExisting(expected, target.output, target.skip_empty, diffs);
54712
+ } else {
54713
+ const section = getDslSection(dsl, target.context);
54714
+ const allIds = Object.keys(section);
54715
+ const ids = filterIds(allIds, target.include, target.exclude);
54716
+ for (const entityId of ids) {
54717
+ const ctx = buildEntityContext(dsl, target.context, entityId);
54718
+ const expected = compiled(ctx);
54719
+ const outputPath = expandOutputPath(target.output, target.context, entityId);
54720
+ await checkExpectedVsExisting(expected, outputPath, target.skip_empty, diffs);
54721
+ }
54722
+ }
54723
+ }
54724
+ return { hasDrift: diffs.length > 0, diffs };
54890
54725
  }
54891
54726
 
54892
54727
  // src/guardrail-generator/generator.ts
@@ -55058,7 +54893,7 @@ async function generateGuardrails(options) {
55058
54893
  const sourcePath = resolve6(config.configDir, outputDef.source);
55059
54894
  if (!dryRun) {
55060
54895
  try {
55061
- await mkdir2(dirname7(targetPath), { recursive: true });
54896
+ await mkdir2(dirname6(targetPath), { recursive: true });
55062
54897
  await copyFile(sourcePath, targetPath);
55063
54898
  if (outputDef.executable) {
55064
54899
  await chmod(targetPath, 493);
@@ -55142,7 +54977,7 @@ async function generateGuardrails(options) {
55142
54977
  }
55143
54978
  const output = isPatch && !dryRun ? await applyPatch(groupTarget, rendered, outputDef) : rendered;
55144
54979
  if (!dryRun) {
55145
- await mkdir2(dirname7(groupTarget), { recursive: true });
54980
+ await mkdir2(dirname6(groupTarget), { recursive: true });
55146
54981
  await writeFile2(groupTarget, output, "utf8");
55147
54982
  if (outputDef.executable) {
55148
54983
  await chmod(groupTarget, 493);
@@ -55163,7 +54998,7 @@ async function generateGuardrails(options) {
55163
54998
  } else {
55164
54999
  const output = isPatch && !dryRun ? await applyPatch(targetPath, rendered, outputDef) : rendered;
55165
55000
  if (!dryRun) {
55166
- await mkdir2(dirname7(targetPath), { recursive: true });
55001
+ await mkdir2(dirname6(targetPath), { recursive: true });
55167
55002
  await writeFile2(targetPath, output, "utf8");
55168
55003
  if (outputDef.executable) {
55169
55004
  await chmod(targetPath, 493);
@@ -55216,7 +55051,7 @@ async function generateGuardrails(options) {
55216
55051
  continue;
55217
55052
  }
55218
55053
  if (!dryRun) {
55219
- await mkdir2(dirname7(outputPath), { recursive: true });
55054
+ await mkdir2(dirname6(outputPath), { recursive: true });
55220
55055
  await writeFile2(outputPath, rendered, "utf8");
55221
55056
  if (renderTarget.executable) {
55222
55057
  await chmod(outputPath, 493);
@@ -55246,7 +55081,7 @@ async function generateGuardrails(options) {
55246
55081
  continue;
55247
55082
  }
55248
55083
  if (!dryRun) {
55249
- await mkdir2(dirname7(outputPath), { recursive: true });
55084
+ await mkdir2(dirname6(outputPath), { recursive: true });
55250
55085
  await writeFile2(outputPath, rendered, "utf8");
55251
55086
  if (renderTarget.executable) {
55252
55087
  await chmod(outputPath, 493);
@@ -55269,6 +55104,84 @@ function resolveBindingRenderOutputPath(output, paths) {
55269
55104
  // src/cli/commands/generate-interface.ts
55270
55105
  import { writeFileSync } from "fs";
55271
55106
  import { resolve as resolve7 } from "path";
55107
+
55108
+ // src/interface-generator/generator.ts
55109
+ import { stringify as stringify2 } from "yaml";
55110
+ function buildInterfaceDocument(dsl, generatedAt) {
55111
+ const ti = dsl.team_interface;
55112
+ const doc = {
55113
+ team_id: dsl.system.id,
55114
+ team_name: dsl.system.name,
55115
+ version: ti.version,
55116
+ generated_at: generatedAt
55117
+ };
55118
+ if (ti.description !== void 0) {
55119
+ doc.description = ti.description;
55120
+ }
55121
+ if (ti.accepts?.workflows && Object.keys(ti.accepts.workflows).length > 0) {
55122
+ doc.accepts = { workflows: { ...ti.accepts.workflows } };
55123
+ }
55124
+ const handoffKeys = /* @__PURE__ */ new Set();
55125
+ if (ti.accepts?.workflows) {
55126
+ for (const spec of Object.values(ti.accepts.workflows)) {
55127
+ handoffKeys.add(spec.input_handoff);
55128
+ handoffKeys.add(spec.output_handoff);
55129
+ }
55130
+ }
55131
+ const handoff_types = {};
55132
+ for (const k2 of [...handoffKeys].sort()) {
55133
+ const ht = dsl.handoff_types[k2];
55134
+ if (ht) {
55135
+ const entry = {
55136
+ version: ht.version,
55137
+ schema: ht.schema
55138
+ };
55139
+ if (ht.description !== void 0) {
55140
+ entry.description = ht.description;
55141
+ }
55142
+ handoff_types[k2] = entry;
55143
+ }
55144
+ }
55145
+ if (Object.keys(handoff_types).length > 0) {
55146
+ doc.handoff_types = handoff_types;
55147
+ }
55148
+ const artifactsOut = {};
55149
+ if (ti.exposes?.artifacts) {
55150
+ for (const key of [...ti.exposes.artifacts].sort()) {
55151
+ const art = dsl.artifacts[key];
55152
+ if (art) {
55153
+ const entry = {
55154
+ type: art.type,
55155
+ states: art.states
55156
+ };
55157
+ if (art.description !== void 0) {
55158
+ entry.description = art.description;
55159
+ }
55160
+ artifactsOut[key] = entry;
55161
+ }
55162
+ }
55163
+ }
55164
+ if (Object.keys(artifactsOut).length > 0) {
55165
+ doc.exposes = { artifacts: artifactsOut };
55166
+ }
55167
+ if (ti.constraints !== void 0 && ti.constraints.length > 0) {
55168
+ doc.constraints = ti.constraints;
55169
+ }
55170
+ return doc;
55171
+ }
55172
+ function generateInterface(options) {
55173
+ if (!options.dsl.team_interface) {
55174
+ throw new Error("DSL has no team_interface section");
55175
+ }
55176
+ const doc = buildInterfaceDocument(options.dsl, (/* @__PURE__ */ new Date()).toISOString());
55177
+ const content = options.format === "json" ? `${JSON.stringify(doc, null, 2)}
55178
+ ` : `${stringify2(doc, { sortMapEntries: true })}
55179
+ `;
55180
+ const outputPath = options.output ?? "team-interface.yaml";
55181
+ return { outputPath, content };
55182
+ }
55183
+
55184
+ // src/cli/commands/generate-interface.ts
55272
55185
  function runGenerateInterfaceCli(opts) {
55273
55186
  if (!opts.dsl.team_interface) {
55274
55187
  process.stderr.write("Error: DSL has no team_interface section.\n");
@@ -55285,44 +55198,351 @@ function runGenerateInterfaceCli(opts) {
55285
55198
  process.stdout.write(result.content);
55286
55199
  return;
55287
55200
  }
55288
- writeFileSync(result.outputPath, result.content, "utf8");
55289
- if (!opts.quiet) {
55290
- process.stdout.write(`Wrote ${result.outputPath}
55201
+ writeFileSync(result.outputPath, result.content, "utf8");
55202
+ if (!opts.quiet) {
55203
+ process.stdout.write(`Wrote ${result.outputPath}
55204
+ `);
55205
+ }
55206
+ }
55207
+
55208
+ // src/cli/commands/generate.ts
55209
+ var VALID_TYPES = ["templates", "guardrails", "interface"];
55210
+ function resolvedConfigForTeam(workspace, teamConfig) {
55211
+ return {
55212
+ dsl: "",
55213
+ vars: teamConfig.vars,
55214
+ renders: workspace.renders,
55215
+ configDir: workspace.configDir,
55216
+ bindings: teamConfig.bindings,
55217
+ activeGuardrailPolicy: teamConfig.activeGuardrailPolicy,
55218
+ paths: teamConfig.paths
55219
+ };
55220
+ }
55221
+ async function runGenerate(type, opts) {
55222
+ if (type !== void 0 && !VALID_TYPES.includes(type)) {
55223
+ process.stderr.write(`Unknown generate type: ${type}
55224
+ `);
55225
+ process.exit(1);
55226
+ }
55227
+ if (opts.format !== "yaml" && opts.format !== "json") {
55228
+ process.stderr.write(
55229
+ `Invalid --format: expected yaml or json, got ${opts.format}
55230
+ `
55231
+ );
55232
+ process.exit(1);
55233
+ }
55234
+ const normalizedType = type;
55235
+ const targets = {
55236
+ templates: normalizedType === void 0 || normalizedType === "templates",
55237
+ guardrails: normalizedType === void 0 || normalizedType === "guardrails",
55238
+ interface: normalizedType === void 0 || normalizedType === "interface"
55239
+ };
55240
+ try {
55241
+ const config = await loadConfig(opts.config);
55242
+ if (!config) {
55243
+ process.stderr.write(
55244
+ "Error: agent-contracts.config.yaml not found. Use --config to specify path.\n"
55245
+ );
55246
+ process.exit(1);
55247
+ }
55248
+ if (isMultiTeamConfig(config)) {
55249
+ await runMultiTeam(config, targets, normalizedType, opts);
55250
+ return;
55251
+ }
55252
+ await runSingleTeam(config, targets, normalizedType, opts);
55253
+ } catch (err) {
55254
+ if (err instanceof ConfigLoadError) {
55255
+ process.stderr.write(`Config error: ${err.message}
55256
+ `);
55257
+ process.exit(1);
55258
+ }
55259
+ const msg = err instanceof Error ? err.message : String(err);
55260
+ process.stderr.write(`Error: ${msg}
55261
+ `);
55262
+ process.exit(1);
55263
+ }
55264
+ }
55265
+ async function runMultiTeam(config, targets, normalizedType, opts) {
55266
+ const teamEntries = getTeamEntries(config, opts.team);
55267
+ let exitWithError = false;
55268
+ for (const [teamId, teamConfig] of teamEntries) {
55269
+ if (!opts.quiet) process.stdout.write(`
55270
+ --- Team: ${teamId} ---
55271
+ `);
55272
+ const resolved = await resolve4(teamConfig.dsl);
55273
+ const data = teamConfig.vars ? substituteVars(resolved.data, teamConfig.vars) : resolved.data;
55274
+ const schemaResult = validateSchema(data);
55275
+ if (!schemaResult.success) {
55276
+ process.stderr.write(
55277
+ `Schema validation failed for team ${teamId}. Run 'agent-contracts validate' for details.
55278
+ `
55279
+ );
55280
+ exitWithError = true;
55281
+ continue;
55282
+ }
55283
+ if (targets.templates) {
55284
+ let renderOptions;
55285
+ if (teamConfig.bindings.length > 0) {
55286
+ const loadedBindings = await loadBindings(teamConfig.bindings);
55287
+ renderOptions = {
55288
+ loadedBindings,
55289
+ activeGuardrailPolicy: teamConfig.activeGuardrailPolicy
55290
+ };
55291
+ }
55292
+ if (opts.check) {
55293
+ const drift = await checkDriftFromConfig(
55294
+ schemaResult.data,
55295
+ config.renders,
55296
+ renderOptions
55297
+ );
55298
+ if (drift.hasDrift) {
55299
+ process.stderr.write(
55300
+ `Drift detected for team ${teamId} in the following files:
55301
+ `
55302
+ );
55303
+ for (const f2 of drift.diffs) {
55304
+ process.stderr.write(` ${f2}
55305
+ `);
55306
+ }
55307
+ exitWithError = true;
55308
+ } else if (!opts.quiet) {
55309
+ process.stdout.write("No drift detected.\n");
55310
+ }
55311
+ } else {
55312
+ const files = await renderFromConfig(
55313
+ schemaResult.data,
55314
+ config.renders,
55315
+ renderOptions
55316
+ );
55317
+ if (!opts.quiet) {
55318
+ process.stdout.write(`Rendered ${files.length} file(s):
55319
+ `);
55320
+ for (const f2 of files) {
55321
+ process.stdout.write(` ${f2}
55322
+ `);
55323
+ }
55324
+ }
55325
+ }
55326
+ }
55327
+ if (targets.interface) {
55328
+ if (schemaResult.data.team_interface) {
55329
+ runGenerateInterfaceCli({
55330
+ dsl: schemaResult.data,
55331
+ output: teamConfig.interfaceOutput ?? opts.output,
55332
+ dryRun: opts.dryRun,
55333
+ format: opts.format,
55334
+ quiet: opts.quiet
55335
+ });
55336
+ } else if (normalizedType === "interface") {
55337
+ process.stderr.write("Error: DSL has no team_interface section.\n");
55338
+ exitWithError = true;
55339
+ }
55340
+ }
55341
+ if (targets.guardrails) {
55342
+ const loadedBindings = await loadBindings(teamConfig.bindings);
55343
+ const result = await generateGuardrails({
55344
+ dsl: schemaResult.data,
55345
+ config: resolvedConfigForTeam(config, teamConfig),
55346
+ loadedBindings,
55347
+ filterBindings: opts.binding,
55348
+ dryRun: opts.dryRun
55349
+ });
55350
+ const errors = result.diagnostics.filter((d2) => d2.severity === "error");
55351
+ const warnings = result.diagnostics.filter((d2) => d2.severity === "warning");
55352
+ const infos = result.diagnostics.filter((d2) => d2.severity === "info");
55353
+ if (errors.length > 0) {
55354
+ process.stderr.write(`Errors (team ${teamId}):
55355
+ `);
55356
+ for (const d2 of errors) {
55357
+ process.stderr.write(` error [${d2.path}] ${d2.message}
55358
+ `);
55359
+ }
55360
+ exitWithError = true;
55361
+ }
55362
+ if (warnings.length > 0 && !opts.quiet) {
55363
+ process.stderr.write(`Warnings (team ${teamId}):
55364
+ `);
55365
+ for (const d2 of warnings) {
55366
+ process.stderr.write(` warning [${d2.path}] ${d2.message}
55367
+ `);
55368
+ }
55369
+ }
55370
+ if (infos.length > 0 && !opts.quiet) {
55371
+ for (const d2 of infos) {
55372
+ process.stderr.write(` info [${d2.path}] ${d2.message}
55373
+ `);
55374
+ }
55375
+ }
55376
+ if (!opts.quiet) {
55377
+ const action = opts.dryRun ? "Would generate" : "Generated";
55378
+ process.stdout.write(
55379
+ `${action} ${result.outputFiles.length} file(s):
55380
+ `
55381
+ );
55382
+ for (const f2 of result.outputFiles) {
55383
+ process.stdout.write(` ${f2}
55384
+ `);
55385
+ }
55386
+ }
55387
+ }
55388
+ }
55389
+ if (exitWithError) process.exit(1);
55390
+ }
55391
+ async function runSingleTeam(config, targets, normalizedType, opts) {
55392
+ const resolved = await resolve4(config.dsl);
55393
+ const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
55394
+ const schemaResult = validateSchema(data);
55395
+ if (!schemaResult.success) {
55396
+ process.stderr.write(
55397
+ "Schema validation failed. Run 'agent-contracts validate' for details.\n"
55398
+ );
55399
+ process.exit(1);
55400
+ }
55401
+ let exitWithError = false;
55402
+ if (targets.templates) {
55403
+ let renderOptions;
55404
+ if (config.bindings.length > 0) {
55405
+ const loadedBindings = await loadBindings(config.bindings);
55406
+ renderOptions = {
55407
+ loadedBindings,
55408
+ activeGuardrailPolicy: config.activeGuardrailPolicy
55409
+ };
55410
+ }
55411
+ if (opts.check) {
55412
+ const drift = await checkDriftFromConfig(
55413
+ schemaResult.data,
55414
+ config.renders,
55415
+ renderOptions
55416
+ );
55417
+ if (drift.hasDrift) {
55418
+ process.stderr.write("Drift detected in the following files:\n");
55419
+ for (const f2 of drift.diffs) {
55420
+ process.stderr.write(` ${f2}
55421
+ `);
55422
+ }
55423
+ exitWithError = true;
55424
+ } else if (!opts.quiet) {
55425
+ process.stdout.write("No drift detected.\n");
55426
+ }
55427
+ } else {
55428
+ const files = await renderFromConfig(
55429
+ schemaResult.data,
55430
+ config.renders,
55431
+ renderOptions
55432
+ );
55433
+ if (!opts.quiet) {
55434
+ process.stdout.write(`Rendered ${files.length} file(s):
55435
+ `);
55436
+ for (const f2 of files) {
55437
+ process.stdout.write(` ${f2}
55438
+ `);
55439
+ }
55440
+ }
55441
+ }
55442
+ }
55443
+ if (targets.interface) {
55444
+ if (schemaResult.data.team_interface) {
55445
+ runGenerateInterfaceCli({
55446
+ dsl: schemaResult.data,
55447
+ output: opts.output,
55448
+ dryRun: opts.dryRun,
55449
+ format: opts.format,
55450
+ quiet: opts.quiet
55451
+ });
55452
+ } else if (normalizedType === "interface") {
55453
+ process.stderr.write("Error: DSL has no team_interface section.\n");
55454
+ process.exit(1);
55455
+ }
55456
+ }
55457
+ if (targets.guardrails) {
55458
+ const loadedBindings = await loadBindings(config.bindings);
55459
+ const result = await generateGuardrails({
55460
+ dsl: schemaResult.data,
55461
+ config,
55462
+ loadedBindings,
55463
+ filterBindings: opts.binding,
55464
+ dryRun: opts.dryRun
55465
+ });
55466
+ const errors = result.diagnostics.filter((d2) => d2.severity === "error");
55467
+ const warnings = result.diagnostics.filter((d2) => d2.severity === "warning");
55468
+ const infos = result.diagnostics.filter((d2) => d2.severity === "info");
55469
+ if (errors.length > 0) {
55470
+ process.stderr.write("Errors:\n");
55471
+ for (const d2 of errors) {
55472
+ process.stderr.write(` error [${d2.path}] ${d2.message}
55473
+ `);
55474
+ }
55475
+ exitWithError = true;
55476
+ }
55477
+ if (warnings.length > 0 && !opts.quiet) {
55478
+ process.stderr.write("Warnings:\n");
55479
+ for (const d2 of warnings) {
55480
+ process.stderr.write(` warning [${d2.path}] ${d2.message}
55481
+ `);
55482
+ }
55483
+ }
55484
+ if (infos.length > 0 && !opts.quiet) {
55485
+ for (const d2 of infos) {
55486
+ process.stderr.write(` info [${d2.path}] ${d2.message}
55487
+ `);
55488
+ }
55489
+ }
55490
+ if (!opts.quiet) {
55491
+ const action = opts.dryRun ? "Would generate" : "Generated";
55492
+ process.stdout.write(
55493
+ `${action} ${result.outputFiles.length} file(s):
55494
+ `
55495
+ );
55496
+ for (const f2 of result.outputFiles) {
55497
+ process.stdout.write(` ${f2}
55291
55498
  `);
55499
+ }
55500
+ }
55292
55501
  }
55502
+ if (exitWithError) process.exit(1);
55293
55503
  }
55294
-
55295
- // src/cli/commands/generate-guardrails.ts
55296
- function resolvedConfigForTeam(workspace, teamConfig) {
55297
- return {
55298
- dsl: "",
55299
- vars: teamConfig.vars,
55300
- renders: workspace.renders,
55301
- configDir: workspace.configDir,
55302
- bindings: teamConfig.bindings,
55303
- activeGuardrailPolicy: teamConfig.activeGuardrailPolicy,
55304
- paths: teamConfig.paths
55305
- };
55306
- }
55307
- var generateGuardrailsCommand = new Command6("generate").description("Generate guardrail runtime artifacts from DSL, policies, and bindings").argument("[type]", "Type of artifacts to generate (guardrails|interface)", "guardrails").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--binding <name...>", "Filter to specific software binding(s)").option(
55504
+ var generateCommand = new Command4("generate").description("Generate artifacts from DSL \u2014 templates, guardrails, and/or interface").argument(
55505
+ "[type]",
55506
+ "Type of artifacts to generate (templates|guardrails|interface). Omit to run all."
55507
+ ).option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option(
55508
+ "--check",
55509
+ "Check for template drift without writing files (templates only)",
55510
+ false
55511
+ ).option("--binding <name...>", "Filter to specific software binding(s) (guardrails only)").option(
55308
55512
  "-o, --output <path>",
55309
- "Output path for generated team interface (interface type only)"
55513
+ "Output path for generated team interface (interface only)"
55310
55514
  ).option(
55311
55515
  "--format <format>",
55312
55516
  "Output format for team interface: yaml or json",
55313
55517
  "yaml"
55314
- ).option("--dry-run", "Print what would be generated without writing files", false).option("--quiet", "Suppress output on success", false).action(
55315
- async (type, opts) => {
55316
- if (type !== "guardrails" && type !== "interface") {
55317
- process.stderr.write(`Unknown generate type: ${type}
55318
- `);
55319
- process.exit(1);
55320
- }
55321
- if (type === "interface" && opts.format !== "yaml" && opts.format !== "json") {
55322
- process.stderr.write(`Invalid --format: expected yaml or json, got ${opts.format}
55323
- `);
55324
- process.exit(1);
55325
- }
55518
+ ).option("--dry-run", "Print what would be generated without writing files", false).option("--quiet", "Suppress output on success", false).action(runGenerate);
55519
+
55520
+ // src/cli/commands/render.ts
55521
+ var renderCommand = new Command5("render").description("(deprecated) Alias for 'generate templates'. Use 'generate templates' instead.").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--check", "Check for template drift without writing files", false).option("--quiet", "Suppress output on success", false).action(
55522
+ async (opts) => {
55523
+ process.stderr.write(
55524
+ "Warning: 'render' is deprecated. Use 'agent-contracts generate templates' instead.\n"
55525
+ );
55526
+ await runGenerate("templates", {
55527
+ ...opts,
55528
+ binding: void 0,
55529
+ output: void 0,
55530
+ format: "yaml",
55531
+ dryRun: false
55532
+ });
55533
+ }
55534
+ );
55535
+
55536
+ // src/cli/commands/check.ts
55537
+ import { existsSync, readFileSync } from "fs";
55538
+ import { join as join3 } from "path";
55539
+ import { Command as Command6 } from "commander";
55540
+ import { parse as parseYaml4, stringify as stringify3 } from "yaml";
55541
+ import { access as access2 } from "fs/promises";
55542
+ import { resolve as pathResolve, dirname as dirname7 } from "path";
55543
+ var checkCommand = new Command6("check").description("Run full pipeline: resolve \u2192 validate \u2192 lint \u2192 render --check").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--format <format>", "Output format (text|json)", "text").option("--quiet", "Suppress output on success", false).option("--strict", "Treat warnings as errors", false).action(
55544
+ async (opts) => {
55545
+ let hasErrors = false;
55326
55546
  try {
55327
55547
  const config = await loadConfig(opts.config);
55328
55548
  if (!config) {
@@ -55333,144 +55553,203 @@ var generateGuardrailsCommand = new Command6("generate").description("Generate g
55333
55553
  }
55334
55554
  if (isMultiTeamConfig(config)) {
55335
55555
  const teamEntries = getTeamEntries(config, opts.team);
55336
- let exitWithError = false;
55337
55556
  for (const [teamId, teamConfig] of teamEntries) {
55338
- if (!opts.quiet) process.stdout.write(`
55557
+ if (!opts.quiet) process.stderr.write(`
55339
55558
  --- Team: ${teamId} ---
55340
55559
  `);
55341
55560
  const resolved2 = await resolve4(teamConfig.dsl);
55342
55561
  const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
55343
55562
  const schemaResult2 = validateSchema(data2);
55563
+ const schemaWarnings2 = schemaResult2.diagnostics.filter(
55564
+ (d2) => d2.severity === "warning"
55565
+ );
55344
55566
  if (!schemaResult2.success) {
55345
- process.stderr.write(
55346
- `Schema validation failed for team ${teamId}. Run 'agent-contracts validate' for details.
55347
- `
55348
- );
55349
- exitWithError = true;
55567
+ const output = formatDiagnostics(schemaResult2.diagnostics, {
55568
+ format: opts.format,
55569
+ quiet: opts.quiet
55570
+ });
55571
+ if (output) process.stderr.write(output + "\n");
55572
+ hasErrors = true;
55350
55573
  continue;
55351
55574
  }
55352
- if (type === "interface") {
55353
- runGenerateInterfaceCli({
55354
- dsl: schemaResult2.data,
55355
- output: teamConfig.interfaceOutput ?? opts.output,
55356
- dryRun: opts.dryRun,
55575
+ const refDiags2 = checkReferences(schemaResult2.data);
55576
+ const handoffDiags2 = validateHandoffSchemas(schemaResult2.data);
55577
+ const allRefDiags2 = [...refDiags2, ...handoffDiags2, ...schemaWarnings2];
55578
+ if (allRefDiags2.length > 0) {
55579
+ const output = formatDiagnostics(allRefDiags2, {
55357
55580
  format: opts.format,
55358
55581
  quiet: opts.quiet
55359
55582
  });
55360
- continue;
55583
+ if (output) process.stderr.write(output + "\n");
55584
+ hasErrors = true;
55361
55585
  }
55362
- const loadedBindings2 = await loadBindings(teamConfig.bindings);
55363
- const result2 = await generateGuardrails({
55364
- dsl: schemaResult2.data,
55365
- config: resolvedConfigForTeam(config, teamConfig),
55366
- loadedBindings: loadedBindings2,
55367
- filterBindings: opts.binding,
55368
- dryRun: opts.dryRun
55369
- });
55370
- const errors2 = result2.diagnostics.filter((d2) => d2.severity === "error");
55371
- const warnings2 = result2.diagnostics.filter((d2) => d2.severity === "warning");
55372
- const infos2 = result2.diagnostics.filter((d2) => d2.severity === "info");
55373
- if (errors2.length > 0) {
55374
- process.stderr.write(`Errors (team ${teamId}):
55375
- `);
55376
- for (const d2 of errors2) {
55377
- process.stderr.write(` error [${d2.path}] ${d2.message}
55378
- `);
55586
+ const tsLintDiags2 = lint(schemaResult2.data);
55587
+ const spectralDiags2 = await spectralLint(
55588
+ schemaResult2.data
55589
+ );
55590
+ const lintDiags2 = [...tsLintDiags2, ...spectralDiags2];
55591
+ if (lintDiags2.length > 0) {
55592
+ const output = formatDiagnostics(lintDiags2, {
55593
+ format: opts.format,
55594
+ quiet: opts.quiet
55595
+ });
55596
+ if (output) process.stderr.write(output + "\n");
55597
+ if (lintDiags2.some((d2) => d2.severity === "error")) {
55598
+ hasErrors = true;
55379
55599
  }
55380
- exitWithError = true;
55381
- }
55382
- if (warnings2.length > 0 && !opts.quiet) {
55383
- process.stderr.write(`Warnings (team ${teamId}):
55384
- `);
55385
- for (const d2 of warnings2) {
55386
- process.stderr.write(` warning [${d2.path}] ${d2.message}
55387
- `);
55600
+ if (opts.strict && lintDiags2.some((d2) => d2.severity === "warning")) {
55601
+ hasErrors = true;
55388
55602
  }
55389
55603
  }
55390
- if (infos2.length > 0 && !opts.quiet) {
55391
- for (const d2 of infos2) {
55392
- process.stderr.write(` info [${d2.path}] ${d2.message}
55604
+ let renderOptions2;
55605
+ if (teamConfig.bindings.length > 0) {
55606
+ const loadedBindings = await loadBindings(teamConfig.bindings);
55607
+ renderOptions2 = {
55608
+ loadedBindings,
55609
+ activeGuardrailPolicy: teamConfig.activeGuardrailPolicy
55610
+ };
55611
+ }
55612
+ const drift2 = await checkDriftFromConfig(
55613
+ schemaResult2.data,
55614
+ config.renders,
55615
+ renderOptions2
55616
+ );
55617
+ if (drift2.hasDrift) {
55618
+ process.stderr.write(`Drift detected for team ${teamId} in:
55619
+ `);
55620
+ for (const f2 of drift2.diffs) {
55621
+ process.stderr.write(` ${f2}
55393
55622
  `);
55394
55623
  }
55624
+ hasErrors = true;
55395
55625
  }
55396
- if (!opts.quiet) {
55397
- const action = opts.dryRun ? "Would generate" : "Generated";
55398
- process.stdout.write(
55399
- `${action} ${result2.outputFiles.length} file(s):
55626
+ }
55627
+ if (!hasErrors) {
55628
+ for (const [teamId, teamConfig] of teamEntries) {
55629
+ const resolved2 = await resolve4(teamConfig.dsl);
55630
+ const data2 = teamConfig.vars ? substituteVars(resolved2.data, teamConfig.vars) : resolved2.data;
55631
+ const schemaResult2 = validateSchema(data2);
55632
+ if (!schemaResult2.success || !schemaResult2.data) continue;
55633
+ const dsl = schemaResult2.data;
55634
+ const imports = dsl.imports;
55635
+ if (!imports) continue;
55636
+ for (const [importName, importDef] of Object.entries(imports)) {
55637
+ const interfacePathRel = importDef?.interface;
55638
+ if (typeof interfacePathRel !== "string") continue;
55639
+ const interfacePath = pathResolve(
55640
+ dirname7(teamConfig.dsl),
55641
+ interfacePathRel
55642
+ );
55643
+ try {
55644
+ await access2(interfacePath);
55645
+ } catch {
55646
+ process.stderr.write(
55647
+ `Cross-team error: Team "${teamId}" imports "${importName}" but interface file not found: ${interfacePath}
55400
55648
  `
55401
- );
55402
- for (const f2 of result2.outputFiles) {
55403
- process.stdout.write(` ${f2}
55404
- `);
55649
+ );
55650
+ hasErrors = true;
55651
+ }
55405
55652
  }
55406
55653
  }
55407
55654
  }
55408
- if (exitWithError) process.exit(1);
55655
+ if (hasErrors) process.exit(1);
55656
+ if (!opts.quiet) process.stdout.write("All checks passed.\n");
55409
55657
  return;
55410
55658
  }
55411
55659
  const resolved = await resolve4(config.dsl);
55412
55660
  const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
55413
55661
  const schemaResult = validateSchema(data);
55662
+ const schemaWarnings = schemaResult.diagnostics.filter(
55663
+ (d2) => d2.severity === "warning"
55664
+ );
55414
55665
  if (!schemaResult.success) {
55415
- process.stderr.write(
55416
- "Schema validation failed. Run 'agent-contracts validate' for details.\n"
55417
- );
55666
+ const output = formatDiagnostics(schemaResult.diagnostics, {
55667
+ format: opts.format,
55668
+ quiet: opts.quiet
55669
+ });
55670
+ if (output) process.stderr.write(output + "\n");
55418
55671
  process.exit(1);
55419
55672
  }
55420
- if (type === "interface") {
55421
- runGenerateInterfaceCli({
55422
- dsl: schemaResult.data,
55423
- output: opts.output,
55424
- dryRun: opts.dryRun,
55673
+ const refDiags = checkReferences(schemaResult.data);
55674
+ const handoffDiags = validateHandoffSchemas(schemaResult.data);
55675
+ const allRefDiags = [...refDiags, ...handoffDiags, ...schemaWarnings];
55676
+ if (allRefDiags.length > 0) {
55677
+ const output = formatDiagnostics(allRefDiags, {
55425
55678
  format: opts.format,
55426
55679
  quiet: opts.quiet
55427
55680
  });
55428
- return;
55681
+ if (output) process.stderr.write(output + "\n");
55682
+ hasErrors = true;
55429
55683
  }
55430
- const loadedBindings = await loadBindings(config.bindings);
55431
- const result = await generateGuardrails({
55432
- dsl: schemaResult.data,
55433
- config,
55434
- loadedBindings,
55435
- filterBindings: opts.binding,
55436
- dryRun: opts.dryRun
55437
- });
55438
- const errors = result.diagnostics.filter((d2) => d2.severity === "error");
55439
- const warnings = result.diagnostics.filter((d2) => d2.severity === "warning");
55440
- const infos = result.diagnostics.filter((d2) => d2.severity === "info");
55441
- if (errors.length > 0) {
55442
- process.stderr.write("Errors:\n");
55443
- for (const d2 of errors) {
55444
- process.stderr.write(` error [${d2.path}] ${d2.message}
55445
- `);
55684
+ const tsLintDiags = lint(schemaResult.data);
55685
+ const spectralDiags = await spectralLint(schemaResult.data);
55686
+ const lintDiags = [...tsLintDiags, ...spectralDiags];
55687
+ if (lintDiags.length > 0) {
55688
+ const output = formatDiagnostics(lintDiags, {
55689
+ format: opts.format,
55690
+ quiet: opts.quiet
55691
+ });
55692
+ if (output) process.stderr.write(output + "\n");
55693
+ if (lintDiags.some((d2) => d2.severity === "error")) {
55694
+ hasErrors = true;
55695
+ }
55696
+ if (opts.strict && lintDiags.some((d2) => d2.severity === "warning")) {
55697
+ hasErrors = true;
55446
55698
  }
55447
55699
  }
55448
- if (warnings.length > 0 && !opts.quiet) {
55449
- process.stderr.write("Warnings:\n");
55450
- for (const d2 of warnings) {
55451
- process.stderr.write(` warning [${d2.path}] ${d2.message}
55700
+ let renderOptions;
55701
+ if (config.bindings.length > 0) {
55702
+ const loadedBindings = await loadBindings(config.bindings);
55703
+ renderOptions = {
55704
+ loadedBindings,
55705
+ activeGuardrailPolicy: config.activeGuardrailPolicy
55706
+ };
55707
+ }
55708
+ const drift = await checkDriftFromConfig(
55709
+ schemaResult.data,
55710
+ config.renders,
55711
+ renderOptions
55712
+ );
55713
+ if (drift.hasDrift) {
55714
+ process.stderr.write("Drift detected in:\n");
55715
+ for (const f2 of drift.diffs) {
55716
+ process.stderr.write(` ${f2}
55452
55717
  `);
55453
55718
  }
55719
+ hasErrors = true;
55454
55720
  }
55455
- if (infos.length > 0 && !opts.quiet) {
55456
- for (const d2 of infos) {
55457
- process.stderr.write(` info [${d2.path}] ${d2.message}
55458
- `);
55721
+ if (schemaResult.data.team_interface) {
55722
+ const interfacePath = join3(config.configDir, "team-interface.yaml");
55723
+ if (existsSync(interfacePath)) {
55724
+ const result = generateInterface({
55725
+ dsl: schemaResult.data,
55726
+ dryRun: true,
55727
+ format: "yaml"
55728
+ });
55729
+ const existing = readFileSync(interfacePath, "utf8");
55730
+ const normalize = (raw) => {
55731
+ try {
55732
+ const parsed = parseYaml4(raw);
55733
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
55734
+ const { generated_at: _t, ...rest } = parsed;
55735
+ return `${stringify3(rest, { sortMapEntries: true })}
55736
+ `;
55737
+ }
55738
+ } catch {
55739
+ }
55740
+ return raw.trim();
55741
+ };
55742
+ if (normalize(existing) !== normalize(result.content)) {
55743
+ process.stderr.write("Drift detected in team-interface.yaml\n");
55744
+ hasErrors = true;
55745
+ }
55459
55746
  }
55460
55747
  }
55461
- if (errors.length > 0) {
55748
+ if (hasErrors) {
55462
55749
  process.exit(1);
55463
55750
  }
55464
55751
  if (!opts.quiet) {
55465
- const action = opts.dryRun ? "Would generate" : "Generated";
55466
- process.stdout.write(
55467
- `${action} ${result.outputFiles.length} file(s):
55468
- `
55469
- );
55470
- for (const f2 of result.outputFiles) {
55471
- process.stdout.write(` ${f2}
55472
- `);
55473
- }
55752
+ process.stdout.write("All checks passed.\n");
55474
55753
  }
55475
55754
  } catch (err) {
55476
55755
  if (err instanceof ConfigLoadError) {
@@ -56809,7 +57088,7 @@ program.addCommand(validateCommand);
56809
57088
  program.addCommand(lintCommand);
56810
57089
  program.addCommand(renderCommand);
56811
57090
  program.addCommand(checkCommand);
56812
- program.addCommand(generateGuardrailsCommand);
57091
+ program.addCommand(generateCommand);
56813
57092
  program.addCommand(scoreCommand);
56814
57093
  program.addCommand(auditCommand);
56815
57094
  program.parse();