agent-contracts 0.20.0 → 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/README.md +12 -9
- package/cli-contract.yaml +49 -31
- package/dist/cli.js +2445 -2166
- package/dist/cli.js.map +1 -1
- package/dist/index.js +290 -9
- package/dist/index.js.map +1 -1
- package/docs/cli-reference.md +460 -15
- package/package.json +3 -3
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)(
|
|
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
|
|
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(
|
|
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
|
-
|
|
52961
|
-
|
|
52962
|
-
|
|
52963
|
-
|
|
52964
|
-
|
|
52965
|
-
|
|
52966
|
-
|
|
52967
|
-
|
|
52968
|
-
|
|
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
|
-
|
|
52976
|
-
|
|
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
|
-
}
|
|
52979
|
-
|
|
52980
|
-
|
|
52981
|
-
|
|
52982
|
-
|
|
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
|
-
|
|
53022
|
-
|
|
53023
|
-
|
|
53024
|
-
|
|
53025
|
-
|
|
53026
|
-
|
|
53027
|
-
|
|
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
|
-
|
|
53066
|
-
|
|
53067
|
-
|
|
53068
|
-
|
|
53069
|
-
|
|
53070
|
-
|
|
53071
|
-
|
|
53072
|
-
|
|
53073
|
-
|
|
53074
|
-
|
|
53075
|
-
description:
|
|
53076
|
-
|
|
53077
|
-
|
|
53078
|
-
|
|
53079
|
-
|
|
53080
|
-
|
|
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
|
-
|
|
53176
|
-
|
|
53177
|
-
|
|
53178
|
-
|
|
53179
|
-
|
|
53180
|
-
|
|
53181
|
-
|
|
53182
|
-
|
|
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
|
-
}
|
|
53239
|
-
|
|
53240
|
-
|
|
53241
|
-
|
|
53242
|
-
|
|
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
|
-
|
|
53247
|
-
|
|
53248
|
-
|
|
53249
|
-
|
|
53250
|
-
|
|
53251
|
-
|
|
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
|
-
|
|
53268
|
-
|
|
53269
|
-
|
|
53270
|
-
|
|
53271
|
-
|
|
53272
|
-
|
|
53273
|
-
|
|
53274
|
-
|
|
53275
|
-
|
|
53276
|
-
|
|
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
|
-
|
|
53281
|
-
|
|
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/
|
|
53462
|
-
|
|
53463
|
-
|
|
53464
|
-
|
|
53465
|
-
|
|
53466
|
-
|
|
53467
|
-
|
|
53468
|
-
|
|
53469
|
-
|
|
53470
|
-
if (
|
|
53471
|
-
|
|
53472
|
-
|
|
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
|
|
53490
|
-
}
|
|
53491
|
-
function sanitizeAlias(id) {
|
|
53492
|
-
return id.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
53154
|
+
return spectralInstance;
|
|
53493
53155
|
}
|
|
53494
|
-
function
|
|
53495
|
-
const
|
|
53496
|
-
|
|
53497
|
-
return
|
|
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
|
-
|
|
53500
|
-
|
|
53501
|
-
|
|
53502
|
-
|
|
53503
|
-
|
|
53504
|
-
|
|
53505
|
-
|
|
53506
|
-
|
|
53507
|
-
|
|
53508
|
-
|
|
53509
|
-
|
|
53510
|
-
|
|
53511
|
-
|
|
53512
|
-
|
|
53513
|
-
|
|
53514
|
-
|
|
53515
|
-
|
|
53516
|
-
|
|
53517
|
-
|
|
53518
|
-
|
|
53519
|
-
|
|
53520
|
-
|
|
53521
|
-
|
|
53522
|
-
|
|
53523
|
-
|
|
53524
|
-
|
|
53525
|
-
|
|
53526
|
-
|
|
53527
|
-
|
|
53528
|
-
|
|
53529
|
-
|
|
53530
|
-
|
|
53531
|
-
|
|
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
|
-
|
|
53534
|
-
|
|
53535
|
-
const
|
|
53536
|
-
|
|
53537
|
-
|
|
53538
|
-
|
|
53539
|
-
|
|
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
|
-
|
|
53544
|
-
|
|
53545
|
-
|
|
53546
|
-
|
|
53547
|
-
|
|
53548
|
-
|
|
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 {
|
|
53313
|
+
return { resolved, diagnostics };
|
|
53552
53314
|
}
|
|
53553
|
-
|
|
53554
|
-
|
|
53555
|
-
|
|
53556
|
-
|
|
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
|
-
|
|
53559
|
-
|
|
53560
|
-
|
|
53561
|
-
|
|
53562
|
-
|
|
53563
|
-
|
|
53564
|
-
|
|
53565
|
-
|
|
53566
|
-
|
|
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
|
|
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
|
|
53606
|
-
const
|
|
53607
|
-
|
|
53608
|
-
|
|
53609
|
-
|
|
53610
|
-
|
|
53611
|
-
|
|
53612
|
-
|
|
53613
|
-
|
|
53614
|
-
|
|
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
|
|
53630
|
-
|
|
53631
|
-
|
|
53632
|
-
|
|
53633
|
-
{
|
|
53634
|
-
|
|
53635
|
-
|
|
53636
|
-
|
|
53637
|
-
|
|
53638
|
-
|
|
53639
|
-
|
|
53640
|
-
|
|
53641
|
-
|
|
53642
|
-
|
|
53643
|
-
|
|
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
|
-
|
|
53650
|
-
const
|
|
53651
|
-
|
|
53652
|
-
|
|
53653
|
-
|
|
53654
|
-
|
|
53655
|
-
|
|
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
|
-
|
|
53670
|
-
|
|
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
|
|
53674
|
-
|
|
53675
|
-
|
|
53676
|
-
|
|
53677
|
-
|
|
53678
|
-
|
|
53679
|
-
|
|
53680
|
-
|
|
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 (
|
|
53683
|
-
const
|
|
53684
|
-
|
|
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
|
-
|
|
53687
|
-
|
|
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
|
|
53691
|
-
const
|
|
53692
|
-
|
|
53693
|
-
const
|
|
53694
|
-
const
|
|
53695
|
-
const
|
|
53696
|
-
|
|
53697
|
-
|
|
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
|
-
|
|
53700
|
-
|
|
53701
|
-
|
|
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
|
-
|
|
53705
|
-
|
|
53706
|
-
|
|
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
|
-
|
|
53716
|
-
|
|
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
|
-
|
|
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
|
|
53722
|
-
const
|
|
53723
|
-
|
|
53724
|
-
const
|
|
53725
|
-
|
|
53726
|
-
|
|
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
|
-
|
|
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
|
|
53735
|
-
|
|
53736
|
-
|
|
53737
|
-
|
|
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
|
|
53741
|
-
const
|
|
53742
|
-
|
|
53743
|
-
|
|
53744
|
-
|
|
53745
|
-
|
|
53746
|
-
|
|
53747
|
-
|
|
53748
|
-
|
|
53749
|
-
|
|
53750
|
-
|
|
53751
|
-
|
|
53752
|
-
|
|
53753
|
-
|
|
53754
|
-
|
|
53755
|
-
|
|
53756
|
-
|
|
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
|
-
|
|
53760
|
-
|
|
53761
|
-
|
|
53762
|
-
|
|
53763
|
-
|
|
53764
|
-
|
|
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
|
-
|
|
53771
|
-
|
|
53772
|
-
|
|
53773
|
-
|
|
53774
|
-
|
|
53775
|
-
|
|
53776
|
-
|
|
53777
|
-
|
|
53778
|
-
|
|
53779
|
-
|
|
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
|
-
|
|
53794
|
-
|
|
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
|
-
|
|
53813
|
-
|
|
53814
|
-
const
|
|
53815
|
-
|
|
53816
|
-
|
|
53817
|
-
|
|
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
|
-
|
|
53821
|
-
|
|
53822
|
-
|
|
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
|
-
|
|
53845
|
-
|
|
53846
|
-
|
|
53847
|
-
}
|
|
53848
|
-
|
|
53849
|
-
|
|
53850
|
-
|
|
53851
|
-
|
|
53852
|
-
|
|
53853
|
-
|
|
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
|
-
}
|
|
53856
|
-
|
|
53857
|
-
|
|
53858
|
-
if (
|
|
53859
|
-
|
|
53860
|
-
|
|
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
|
-
|
|
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
|
|
53882
|
-
|
|
53883
|
-
|
|
53884
|
-
|
|
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
|
|
53900
|
-
|
|
53901
|
-
|
|
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
|
-
|
|
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
|
|
53926
|
-
|
|
53927
|
-
|
|
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
|
|
53930
|
-
const
|
|
53931
|
-
|
|
53932
|
-
|
|
53933
|
-
|
|
53934
|
-
|
|
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
|
|
53704
|
+
return result;
|
|
53937
53705
|
}
|
|
53938
|
-
function
|
|
53939
|
-
|
|
53940
|
-
|
|
53941
|
-
|
|
53942
|
-
|
|
53943
|
-
|
|
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
|
-
|
|
53946
|
-
|
|
53947
|
-
|
|
53948
|
-
|
|
53949
|
-
|
|
53950
|
-
|
|
53951
|
-
|
|
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
|
-
|
|
53954
|
-
|
|
53955
|
-
|
|
53956
|
-
|
|
53957
|
-
|
|
53958
|
-
|
|
53959
|
-
|
|
53960
|
-
|
|
53961
|
-
|
|
53962
|
-
|
|
53963
|
-
|
|
53964
|
-
|
|
53965
|
-
|
|
53966
|
-
|
|
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
|
-
|
|
53969
|
-
|
|
53970
|
-
|
|
53971
|
-
|
|
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
|
-
|
|
53981
|
-
|
|
53982
|
-
|
|
53983
|
-
|
|
53984
|
-
|
|
53985
|
-
|
|
53986
|
-
|
|
53987
|
-
|
|
53988
|
-
|
|
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
|
-
|
|
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/
|
|
53996
|
-
|
|
53997
|
-
|
|
53998
|
-
|
|
53999
|
-
|
|
54000
|
-
|
|
54001
|
-
|
|
54002
|
-
|
|
54003
|
-
|
|
54004
|
-
(
|
|
54005
|
-
|
|
54006
|
-
|
|
54007
|
-
|
|
54008
|
-
|
|
54009
|
-
|
|
54010
|
-
|
|
54011
|
-
|
|
54012
|
-
|
|
54013
|
-
|
|
54014
|
-
|
|
54015
|
-
|
|
54016
|
-
|
|
54017
|
-
|
|
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
|
|
53833
|
+
return `rgb(${Math.round((r3 + m2) * 255)},${Math.round((g2 + m2) * 255)},${Math.round((b3 + m2) * 255)})`;
|
|
54087
53834
|
}
|
|
54088
|
-
|
|
54089
|
-
return
|
|
54090
|
-
}
|
|
54091
|
-
|
|
54092
|
-
|
|
54093
|
-
(
|
|
54094
|
-
|
|
54095
|
-
|
|
54096
|
-
|
|
54097
|
-
|
|
54098
|
-
);
|
|
54099
|
-
|
|
54100
|
-
|
|
54101
|
-
|
|
54102
|
-
|
|
54103
|
-
|
|
54104
|
-
|
|
54105
|
-
|
|
54106
|
-
|
|
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
|
-
|
|
54125
|
-
|
|
54126
|
-
|
|
54127
|
-
|
|
54128
|
-
|
|
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
|
-
|
|
54132
|
-
|
|
54133
|
-
|
|
54134
|
-
|
|
54135
|
-
|
|
54136
|
-
|
|
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
|
-
|
|
54141
|
-
|
|
54142
|
-
|
|
54143
|
-
|
|
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
|
-
|
|
54185
|
-
|
|
54186
|
-
|
|
54187
|
-
|
|
54188
|
-
|
|
54189
|
-
|
|
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
|
-
|
|
54192
|
-
|
|
54193
|
-
return generateOverviewFlowchart(dsl);
|
|
53912
|
+
usedAliases.add(alias);
|
|
53913
|
+
return alias;
|
|
54194
53914
|
}
|
|
54195
|
-
)
|
|
54196
|
-
|
|
54197
|
-
|
|
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
|
-
|
|
54219
|
-
|
|
54220
|
-
|
|
54221
|
-
|
|
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
|
-
|
|
54241
|
-
|
|
54242
|
-
|
|
54243
|
-
|
|
54244
|
-
|
|
54245
|
-
|
|
54246
|
-
|
|
54247
|
-
|
|
54248
|
-
|
|
54249
|
-
|
|
54250
|
-
|
|
54251
|
-
|
|
54252
|
-
|
|
54253
|
-
|
|
54254
|
-
|
|
54255
|
-
|
|
54256
|
-
|
|
54257
|
-
|
|
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
|
|
54261
|
-
|
|
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
|
|
54264
|
-
|
|
54265
|
-
|
|
54266
|
-
|
|
54267
|
-
|
|
54268
|
-
|
|
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
|
-
|
|
54271
|
-
|
|
54272
|
-
|
|
54273
|
-
|
|
54274
|
-
|
|
54275
|
-
|
|
54276
|
-
|
|
54277
|
-
|
|
54278
|
-
|
|
54279
|
-
|
|
54280
|
-
|
|
54281
|
-
|
|
54282
|
-
|
|
54283
|
-
|
|
54284
|
-
|
|
54285
|
-
|
|
54286
|
-
|
|
54287
|
-
|
|
54288
|
-
|
|
54289
|
-
|
|
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
|
-
|
|
54293
|
-
|
|
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
|
|
54296
|
-
|
|
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
|
-
|
|
54299
|
-
|
|
54300
|
-
|
|
54301
|
-
|
|
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
|
-
|
|
54305
|
-
const
|
|
54306
|
-
|
|
54307
|
-
|
|
54308
|
-
|
|
54309
|
-
|
|
54310
|
-
|
|
54311
|
-
|
|
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
|
-
|
|
54321
|
-
|
|
54322
|
-
|
|
54323
|
-
|
|
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
|
-
|
|
54063
|
+
lines.push(`${indent}end`);
|
|
54338
54064
|
}
|
|
54339
|
-
|
|
54340
|
-
|
|
54341
|
-
|
|
54342
|
-
|
|
54343
|
-
|
|
54344
|
-
|
|
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
|
|
54348
|
-
if (
|
|
54349
|
-
|
|
54350
|
-
|
|
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
|
-
|
|
54360
|
-
const
|
|
54361
|
-
for (const
|
|
54362
|
-
|
|
54363
|
-
|
|
54364
|
-
|
|
54365
|
-
|
|
54366
|
-
|
|
54367
|
-
|
|
54368
|
-
|
|
54369
|
-
|
|
54370
|
-
|
|
54371
|
-
|
|
54372
|
-
|
|
54373
|
-
|
|
54374
|
-
|
|
54375
|
-
|
|
54376
|
-
|
|
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
|
-
|
|
54114
|
+
lines.push(`${indent}end`);
|
|
54381
54115
|
}
|
|
54382
|
-
|
|
54383
|
-
|
|
54384
|
-
|
|
54385
|
-
|
|
54386
|
-
|
|
54387
|
-
|
|
54388
|
-
|
|
54389
|
-
|
|
54390
|
-
|
|
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
|
-
|
|
54492
|
-
|
|
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
|
-
}
|
|
54506
|
-
if (
|
|
54507
|
-
|
|
54508
|
-
|
|
54509
|
-
process.exit(1);
|
|
54129
|
+
} else {
|
|
54130
|
+
if (currentGroup) {
|
|
54131
|
+
result.push(currentGroup);
|
|
54132
|
+
currentGroup = null;
|
|
54510
54133
|
}
|
|
54511
|
-
|
|
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
|
-
|
|
54520
|
-
|
|
54521
|
-
|
|
54522
|
-
|
|
54523
|
-
|
|
54524
|
-
|
|
54525
|
-
|
|
54526
|
-
|
|
54527
|
-
|
|
54528
|
-
|
|
54529
|
-
|
|
54530
|
-
const
|
|
54531
|
-
const
|
|
54532
|
-
|
|
54533
|
-
|
|
54534
|
-
|
|
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 (
|
|
54541
|
-
|
|
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
|
-
|
|
54544
|
-
|
|
54545
|
-
|
|
54546
|
-
|
|
54547
|
-
|
|
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
|
-
|
|
54551
|
-
|
|
54552
|
-
|
|
54553
|
-
|
|
54554
|
-
|
|
54555
|
-
|
|
54556
|
-
|
|
54557
|
-
|
|
54558
|
-
|
|
54559
|
-
|
|
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
|
-
|
|
54565
|
-
|
|
54566
|
-
|
|
54567
|
-
|
|
54568
|
-
|
|
54569
|
-
|
|
54570
|
-
|
|
54571
|
-
if (
|
|
54572
|
-
|
|
54573
|
-
|
|
54574
|
-
|
|
54575
|
-
|
|
54576
|
-
|
|
54577
|
-
|
|
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
|
-
|
|
54263
|
+
addOp(artifactOps, val.target_artifact, "V");
|
|
54580
54264
|
}
|
|
54581
54265
|
}
|
|
54582
54266
|
}
|
|
54583
|
-
|
|
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
|
|
54592
|
-
if (!
|
|
54593
|
-
|
|
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
|
-
|
|
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
|
-
|
|
54604
|
-
|
|
54605
|
-
|
|
54606
|
-
|
|
54607
|
-
|
|
54608
|
-
|
|
54609
|
-
|
|
54610
|
-
|
|
54611
|
-
|
|
54612
|
-
|
|
54613
|
-
|
|
54614
|
-
|
|
54615
|
-
|
|
54616
|
-
|
|
54617
|
-
|
|
54618
|
-
|
|
54619
|
-
|
|
54620
|
-
|
|
54621
|
-
|
|
54622
|
-
|
|
54623
|
-
|
|
54624
|
-
|
|
54625
|
-
|
|
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
|
-
|
|
54762
|
-
|
|
54763
|
-
|
|
54764
|
-
|
|
54765
|
-
|
|
54766
|
-
|
|
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
|
-
|
|
54770
|
-
|
|
54771
|
-
|
|
54772
|
-
|
|
54773
|
-
|
|
54774
|
-
|
|
54775
|
-
|
|
54776
|
-
|
|
54777
|
-
|
|
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
|
-
|
|
54783
|
-
|
|
54784
|
-
|
|
54785
|
-
|
|
54786
|
-
|
|
54787
|
-
|
|
54788
|
-
|
|
54789
|
-
|
|
54790
|
-
|
|
54791
|
-
|
|
54792
|
-
|
|
54793
|
-
|
|
54794
|
-
|
|
54795
|
-
|
|
54796
|
-
|
|
54797
|
-
|
|
54798
|
-
|
|
54799
|
-
|
|
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
|
-
|
|
54810
|
-
|
|
54811
|
-
|
|
54812
|
-
|
|
54813
|
-
|
|
54814
|
-
|
|
54815
|
-
|
|
54816
|
-
|
|
54817
|
-
|
|
54818
|
-
|
|
54819
|
-
|
|
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
|
-
|
|
54830
|
-
|
|
54831
|
-
|
|
54832
|
-
|
|
54833
|
-
|
|
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
|
-
|
|
54863
|
-
|
|
54864
|
-
|
|
54865
|
-
|
|
54866
|
-
|
|
54867
|
-
|
|
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
|
-
|
|
54875
|
-
|
|
54876
|
-
|
|
54877
|
-
|
|
54878
|
-
|
|
54879
|
-
|
|
54880
|
-
|
|
54881
|
-
|
|
54882
|
-
|
|
54883
|
-
|
|
54884
|
-
|
|
54885
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
55296
|
-
|
|
55297
|
-
|
|
55298
|
-
|
|
55299
|
-
|
|
55300
|
-
|
|
55301
|
-
|
|
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
|
|
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
|
-
|
|
55316
|
-
|
|
55317
|
-
|
|
55318
|
-
|
|
55319
|
-
|
|
55320
|
-
|
|
55321
|
-
|
|
55322
|
-
|
|
55323
|
-
|
|
55324
|
-
|
|
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.
|
|
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
|
-
|
|
55346
|
-
|
|
55347
|
-
|
|
55348
|
-
);
|
|
55349
|
-
|
|
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
|
-
|
|
55353
|
-
|
|
55354
|
-
|
|
55355
|
-
|
|
55356
|
-
|
|
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
|
-
|
|
55583
|
+
if (output) process.stderr.write(output + "\n");
|
|
55584
|
+
hasErrors = true;
|
|
55361
55585
|
}
|
|
55362
|
-
const
|
|
55363
|
-
const
|
|
55364
|
-
|
|
55365
|
-
|
|
55366
|
-
|
|
55367
|
-
|
|
55368
|
-
|
|
55369
|
-
|
|
55370
|
-
|
|
55371
|
-
|
|
55372
|
-
|
|
55373
|
-
|
|
55374
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55391
|
-
|
|
55392
|
-
|
|
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
|
-
|
|
55397
|
-
|
|
55398
|
-
|
|
55399
|
-
|
|
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
|
-
|
|
55403
|
-
|
|
55404
|
-
`);
|
|
55649
|
+
);
|
|
55650
|
+
hasErrors = true;
|
|
55651
|
+
}
|
|
55405
55652
|
}
|
|
55406
55653
|
}
|
|
55407
55654
|
}
|
|
55408
|
-
if (
|
|
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
|
-
|
|
55416
|
-
|
|
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
|
-
|
|
55421
|
-
|
|
55422
|
-
|
|
55423
|
-
|
|
55424
|
-
|
|
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
|
-
|
|
55681
|
+
if (output) process.stderr.write(output + "\n");
|
|
55682
|
+
hasErrors = true;
|
|
55429
55683
|
}
|
|
55430
|
-
const
|
|
55431
|
-
const
|
|
55432
|
-
|
|
55433
|
-
|
|
55434
|
-
|
|
55435
|
-
|
|
55436
|
-
|
|
55437
|
-
|
|
55438
|
-
|
|
55439
|
-
|
|
55440
|
-
|
|
55441
|
-
|
|
55442
|
-
|
|
55443
|
-
|
|
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
|
-
|
|
55449
|
-
|
|
55450
|
-
|
|
55451
|
-
|
|
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 (
|
|
55456
|
-
|
|
55457
|
-
|
|
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 (
|
|
55748
|
+
if (hasErrors) {
|
|
55462
55749
|
process.exit(1);
|
|
55463
55750
|
}
|
|
55464
55751
|
if (!opts.quiet) {
|
|
55465
|
-
|
|
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(
|
|
57091
|
+
program.addCommand(generateCommand);
|
|
56813
57092
|
program.addCommand(scoreCommand);
|
|
56814
57093
|
program.addCommand(auditCommand);
|
|
56815
57094
|
program.parse();
|