agent-contracts 0.11.7 → 0.12.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 +39 -1
- package/dist/cli.js +171 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +42 -9
- package/dist/index.js +159 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -346,6 +346,9 @@ declare const DslSchema: z.ZodObject<{
|
|
|
346
346
|
mechanical: "mechanical";
|
|
347
347
|
semantic: "semantic";
|
|
348
348
|
approval: "approval";
|
|
349
|
+
provenance: "provenance";
|
|
350
|
+
traceability: "traceability";
|
|
351
|
+
fidelity: "fidelity";
|
|
349
352
|
}>;
|
|
350
353
|
executor_type: z.ZodEnum<{
|
|
351
354
|
tool: "tool";
|
|
@@ -731,6 +734,9 @@ declare const ValidationSchema: z.ZodObject<{
|
|
|
731
734
|
mechanical: "mechanical";
|
|
732
735
|
semantic: "semantic";
|
|
733
736
|
approval: "approval";
|
|
737
|
+
provenance: "provenance";
|
|
738
|
+
traceability: "traceability";
|
|
739
|
+
fidelity: "fidelity";
|
|
734
740
|
}>;
|
|
735
741
|
executor_type: z.ZodEnum<{
|
|
736
742
|
tool: "tool";
|
|
@@ -1028,8 +1034,18 @@ interface ResolvedConfig {
|
|
|
1028
1034
|
paths?: Record<string, string>;
|
|
1029
1035
|
}
|
|
1030
1036
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1037
|
+
interface LoadedBinding {
|
|
1038
|
+
filePath: string;
|
|
1039
|
+
binding: SoftwareBinding;
|
|
1040
|
+
}
|
|
1041
|
+
declare function loadBindings(bindingPaths: string[]): Promise<LoadedBinding[]>;
|
|
1042
|
+
|
|
1043
|
+
interface RenderOptions {
|
|
1044
|
+
loadedBindings?: LoadedBinding[];
|
|
1045
|
+
activeGuardrailPolicy?: string;
|
|
1046
|
+
}
|
|
1047
|
+
declare function renderFromConfig(dsl: Dsl, renderTargets: ResolvedRenderTarget[], options?: RenderOptions): Promise<string[]>;
|
|
1048
|
+
declare function checkDriftFromConfig(dsl: Dsl, renderTargets: ResolvedRenderTarget[], options?: RenderOptions): Promise<{
|
|
1033
1049
|
hasDrift: boolean;
|
|
1034
1050
|
diffs: string[];
|
|
1035
1051
|
}>;
|
|
@@ -1048,9 +1064,29 @@ interface GlobalContext {
|
|
|
1048
1064
|
guardrail_policies: Dsl["guardrail_policies"];
|
|
1049
1065
|
[key: string]: unknown;
|
|
1050
1066
|
}
|
|
1067
|
+
interface GuardrailEnforcementEntry {
|
|
1068
|
+
guardrail_id: string;
|
|
1069
|
+
description: string;
|
|
1070
|
+
severity: string;
|
|
1071
|
+
action: string;
|
|
1072
|
+
scoped_agents: string[];
|
|
1073
|
+
scoped_tasks: string[];
|
|
1074
|
+
scoped_workflows: string[];
|
|
1075
|
+
scoped_tools: string[];
|
|
1076
|
+
scoped_artifacts: string[];
|
|
1077
|
+
allow_override: boolean;
|
|
1078
|
+
override_requires: string[];
|
|
1079
|
+
trigger: string | null;
|
|
1080
|
+
escalation: {
|
|
1081
|
+
target: string;
|
|
1082
|
+
condition?: string;
|
|
1083
|
+
} | null;
|
|
1084
|
+
}
|
|
1051
1085
|
interface SystemContext {
|
|
1052
1086
|
system: System;
|
|
1053
1087
|
dsl: Dsl;
|
|
1088
|
+
guardrailEnforcement?: GuardrailEnforcementEntry[];
|
|
1089
|
+
bindings?: SoftwareBinding[];
|
|
1054
1090
|
[key: string]: unknown;
|
|
1055
1091
|
}
|
|
1056
1092
|
interface PerTaskContext {
|
|
@@ -1177,7 +1213,10 @@ interface PerAgentContext {
|
|
|
1177
1213
|
[key: string]: unknown;
|
|
1178
1214
|
}
|
|
1179
1215
|
declare function buildGlobalContext(dsl: Dsl): GlobalContext;
|
|
1180
|
-
declare function buildSystemContext(dsl: Dsl
|
|
1216
|
+
declare function buildSystemContext(dsl: Dsl, options?: {
|
|
1217
|
+
loadedBindings?: LoadedBinding[];
|
|
1218
|
+
activeGuardrailPolicy?: string;
|
|
1219
|
+
}): SystemContext;
|
|
1181
1220
|
declare function buildTaskContext(dsl: Dsl, taskId: string): PerTaskContext;
|
|
1182
1221
|
declare function buildArtifactContext(dsl: Dsl, artifactId: string): PerArtifactContext;
|
|
1183
1222
|
declare function buildToolContext(dsl: Dsl, toolId: string): PerToolContext;
|
|
@@ -1191,12 +1230,6 @@ declare function buildPerAgentContext(dsl: Dsl, agent: Agent & {
|
|
|
1191
1230
|
id: string;
|
|
1192
1231
|
}): PerAgentContext;
|
|
1193
1232
|
|
|
1194
|
-
interface LoadedBinding {
|
|
1195
|
-
filePath: string;
|
|
1196
|
-
binding: SoftwareBinding;
|
|
1197
|
-
}
|
|
1198
|
-
declare function loadBindings(bindingPaths: string[]): Promise<LoadedBinding[]>;
|
|
1199
|
-
|
|
1200
1233
|
declare class ConfigLoadError extends Error {
|
|
1201
1234
|
readonly filePath?: string | undefined;
|
|
1202
1235
|
constructor(message: string, filePath?: string | undefined);
|
package/dist/index.js
CHANGED
|
@@ -50660,7 +50660,7 @@ var ToolSchema = z9.object({
|
|
|
50660
50660
|
import { z as z10 } from "zod";
|
|
50661
50661
|
var ValidationSchema = z10.object({
|
|
50662
50662
|
target_artifact: z10.string(),
|
|
50663
|
-
kind: z10.enum(["schema", "mechanical", "semantic", "approval"]),
|
|
50663
|
+
kind: z10.enum(["schema", "mechanical", "semantic", "approval", "provenance", "traceability", "fidelity"]),
|
|
50664
50664
|
executor_type: z10.enum(["tool", "agent"]),
|
|
50665
50665
|
executor: z10.string(),
|
|
50666
50666
|
blocking: z10.boolean(),
|
|
@@ -52388,6 +52388,68 @@ var taskOutputValidationCompletenessRule = {
|
|
|
52388
52388
|
}
|
|
52389
52389
|
};
|
|
52390
52390
|
|
|
52391
|
+
// src/linter/rules/semantic-validation-phase-coverage.ts
|
|
52392
|
+
var SEMANTIC_KINDS = /* @__PURE__ */ new Set(["semantic", "fidelity"]);
|
|
52393
|
+
var semanticValidationPhaseCoverageRule = {
|
|
52394
|
+
id: "semantic-validation-phase-coverage",
|
|
52395
|
+
description: "Semantic and fidelity validations should appear in early workflow phases, not only in late phases.",
|
|
52396
|
+
run(dsl) {
|
|
52397
|
+
const diagnostics = [];
|
|
52398
|
+
const semanticValIds = /* @__PURE__ */ new Set();
|
|
52399
|
+
for (const [valId, val] of Object.entries(dsl.validations)) {
|
|
52400
|
+
if (SEMANTIC_KINDS.has(val.kind)) {
|
|
52401
|
+
semanticValIds.add(valId);
|
|
52402
|
+
}
|
|
52403
|
+
}
|
|
52404
|
+
if (semanticValIds.size === 0) {
|
|
52405
|
+
return diagnostics;
|
|
52406
|
+
}
|
|
52407
|
+
const phaseOrder = dsl.system.default_workflow_order;
|
|
52408
|
+
if (phaseOrder.length < 2) {
|
|
52409
|
+
return diagnostics;
|
|
52410
|
+
}
|
|
52411
|
+
const phaseValidations = /* @__PURE__ */ new Map();
|
|
52412
|
+
for (const phase of phaseOrder) {
|
|
52413
|
+
phaseValidations.set(phase, /* @__PURE__ */ new Set());
|
|
52414
|
+
}
|
|
52415
|
+
for (const [phase, wf] of Object.entries(dsl.workflow)) {
|
|
52416
|
+
if (!phaseValidations.has(phase)) continue;
|
|
52417
|
+
for (const step of wf.steps) {
|
|
52418
|
+
if (step.type === "validation" && semanticValIds.has(step.validation)) {
|
|
52419
|
+
phaseValidations.get(phase).add(step.validation);
|
|
52420
|
+
}
|
|
52421
|
+
}
|
|
52422
|
+
}
|
|
52423
|
+
for (const task of Object.values(dsl.tasks)) {
|
|
52424
|
+
const phase = task.workflow;
|
|
52425
|
+
if (!phaseValidations.has(phase)) continue;
|
|
52426
|
+
for (const valId of task.validations) {
|
|
52427
|
+
if (semanticValIds.has(valId)) {
|
|
52428
|
+
phaseValidations.get(phase).add(valId);
|
|
52429
|
+
}
|
|
52430
|
+
}
|
|
52431
|
+
}
|
|
52432
|
+
const earlyBoundary = Math.ceil(phaseOrder.length / 2);
|
|
52433
|
+
const earlyPhases = phaseOrder.slice(0, earlyBoundary);
|
|
52434
|
+
const latePhases = phaseOrder.slice(earlyBoundary);
|
|
52435
|
+
const earlyHasAny = earlyPhases.some(
|
|
52436
|
+
(p2) => (phaseValidations.get(p2)?.size ?? 0) > 0
|
|
52437
|
+
);
|
|
52438
|
+
const lateWithSemantic = latePhases.filter(
|
|
52439
|
+
(p2) => (phaseValidations.get(p2)?.size ?? 0) > 0
|
|
52440
|
+
);
|
|
52441
|
+
if (!earlyHasAny && lateWithSemantic.length > 0) {
|
|
52442
|
+
diagnostics.push({
|
|
52443
|
+
ruleId: "semantic-validation-phase-coverage",
|
|
52444
|
+
severity: "warning",
|
|
52445
|
+
path: "validations",
|
|
52446
|
+
message: `Semantic validations are only referenced in workflow phases [${lateWithSemantic.join(", ")}]. Consider adding semantic review to earlier phases [${earlyPhases.join(", ")}] to catch issues before implementation.`
|
|
52447
|
+
});
|
|
52448
|
+
}
|
|
52449
|
+
return diagnostics;
|
|
52450
|
+
}
|
|
52451
|
+
};
|
|
52452
|
+
|
|
52391
52453
|
// src/linter/linter.ts
|
|
52392
52454
|
var builtinRules = [
|
|
52393
52455
|
validationCoverageRule,
|
|
@@ -52399,7 +52461,8 @@ var builtinRules = [
|
|
|
52399
52461
|
guardrailPolicyCoverageRule,
|
|
52400
52462
|
yamlReservedKeySafetyRule,
|
|
52401
52463
|
artifactRequiredValidationWiringRule,
|
|
52402
|
-
taskOutputValidationCompletenessRule
|
|
52464
|
+
taskOutputValidationCompletenessRule,
|
|
52465
|
+
semanticValidationPhaseCoverageRule
|
|
52403
52466
|
];
|
|
52404
52467
|
function lint(dsl, rules = builtinRules) {
|
|
52405
52468
|
const diagnostics = [];
|
|
@@ -53066,8 +53129,52 @@ function buildGlobalContext(dsl) {
|
|
|
53066
53129
|
guardrail_policies: dsl.guardrail_policies
|
|
53067
53130
|
};
|
|
53068
53131
|
}
|
|
53069
|
-
function buildSystemContext(dsl) {
|
|
53070
|
-
|
|
53132
|
+
function buildSystemContext(dsl, options) {
|
|
53133
|
+
const ctx = { system: dsl.system, dsl };
|
|
53134
|
+
if (options?.loadedBindings && options.loadedBindings.length > 0) {
|
|
53135
|
+
ctx.bindings = options.loadedBindings.map((lb) => lb.binding);
|
|
53136
|
+
const policyName = options.activeGuardrailPolicy;
|
|
53137
|
+
const policy = policyName ? dsl.guardrail_policies[policyName] : void 0;
|
|
53138
|
+
if (policy) {
|
|
53139
|
+
ctx.guardrailEnforcement = buildGuardrailEnforcement(dsl, policy, options.loadedBindings);
|
|
53140
|
+
}
|
|
53141
|
+
}
|
|
53142
|
+
return ctx;
|
|
53143
|
+
}
|
|
53144
|
+
function buildGuardrailEnforcement(dsl, policy, loadedBindings) {
|
|
53145
|
+
const entries = [];
|
|
53146
|
+
const bindingTriggers = /* @__PURE__ */ new Map();
|
|
53147
|
+
for (const lb of loadedBindings) {
|
|
53148
|
+
const impl = lb.binding.guardrail_impl ?? {};
|
|
53149
|
+
for (const [guardrailId, gi] of Object.entries(impl)) {
|
|
53150
|
+
for (const check of gi.checks) {
|
|
53151
|
+
if (check.matcher) {
|
|
53152
|
+
bindingTriggers.set(guardrailId, check.matcher.type);
|
|
53153
|
+
}
|
|
53154
|
+
}
|
|
53155
|
+
}
|
|
53156
|
+
}
|
|
53157
|
+
for (const rule of policy.rules) {
|
|
53158
|
+
const guardrail = dsl.guardrails[rule.guardrail];
|
|
53159
|
+
if (!guardrail) continue;
|
|
53160
|
+
const scope = guardrail.scope ?? {};
|
|
53161
|
+
entries.push({
|
|
53162
|
+
guardrail_id: rule.guardrail,
|
|
53163
|
+
description: guardrail.description,
|
|
53164
|
+
severity: rule.severity,
|
|
53165
|
+
action: rule.action,
|
|
53166
|
+
scoped_agents: scope.agents ?? [],
|
|
53167
|
+
scoped_tasks: scope.tasks ?? [],
|
|
53168
|
+
scoped_workflows: scope.workflows ?? [],
|
|
53169
|
+
scoped_tools: scope.tools ?? [],
|
|
53170
|
+
scoped_artifacts: scope.artifacts ?? [],
|
|
53171
|
+
allow_override: rule.allow_override,
|
|
53172
|
+
override_requires: rule.override_requires ?? [],
|
|
53173
|
+
trigger: bindingTriggers.get(rule.guardrail) ?? null,
|
|
53174
|
+
escalation: rule.escalation ? { target: rule.escalation.target, condition: rule.escalation.condition } : null
|
|
53175
|
+
});
|
|
53176
|
+
}
|
|
53177
|
+
return entries;
|
|
53071
53178
|
}
|
|
53072
53179
|
function buildTaskContext(dsl, taskId) {
|
|
53073
53180
|
const taskDef = dsl.tasks[taskId];
|
|
@@ -54122,6 +54229,50 @@ Handlebars.registerHelper(
|
|
|
54122
54229
|
return generateOverviewFlowchart(dsl);
|
|
54123
54230
|
}
|
|
54124
54231
|
);
|
|
54232
|
+
Handlebars.registerHelper(
|
|
54233
|
+
"guardrailCoverageMatrix",
|
|
54234
|
+
function() {
|
|
54235
|
+
const enforcement = this["guardrailEnforcement"];
|
|
54236
|
+
if (!enforcement || enforcement.length === 0) return "";
|
|
54237
|
+
const header = "| Guardrail | Severity | Action | Agents | Tasks | Workflows | Tools | Artifacts | Trigger | Override | Escalation |";
|
|
54238
|
+
const divider = "|-----------|----------|--------|--------|-------|-----------|-------|-----------|---------|----------|------------|";
|
|
54239
|
+
const rows = enforcement.map((e3) => {
|
|
54240
|
+
const agents = e3["scoped_agents"]?.join(", ") || "\u2014";
|
|
54241
|
+
const tasks = e3["scoped_tasks"]?.join(", ") || "\u2014";
|
|
54242
|
+
const workflows = e3["scoped_workflows"]?.join(", ") || "\u2014";
|
|
54243
|
+
const tools = e3["scoped_tools"]?.join(", ") || "\u2014";
|
|
54244
|
+
const artifacts = e3["scoped_artifacts"]?.join(", ") || "\u2014";
|
|
54245
|
+
const trigger = e3["trigger"] || "\u2014";
|
|
54246
|
+
const override = e3["allow_override"] ? "yes" : "no";
|
|
54247
|
+
const esc = e3["escalation"];
|
|
54248
|
+
const escalation = esc ? esc["target"] : "\u2014";
|
|
54249
|
+
return `| ${e3["guardrail_id"]} | ${e3["severity"]} | ${e3["action"]} | ${agents} | ${tasks} | ${workflows} | ${tools} | ${artifacts} | ${trigger} | ${override} | ${escalation} |`;
|
|
54250
|
+
});
|
|
54251
|
+
return [header, divider, ...rows].join("\n");
|
|
54252
|
+
}
|
|
54253
|
+
);
|
|
54254
|
+
Handlebars.registerHelper(
|
|
54255
|
+
"taskGuardrailMatrix",
|
|
54256
|
+
function() {
|
|
54257
|
+
const dsl = this["dsl"];
|
|
54258
|
+
const enforcement = this["guardrailEnforcement"];
|
|
54259
|
+
if (!dsl || !enforcement || enforcement.length === 0) return "";
|
|
54260
|
+
const taskIds = Object.keys(dsl.tasks);
|
|
54261
|
+
if (taskIds.length === 0) return "";
|
|
54262
|
+
const guardrailIds = enforcement.map((e3) => e3["guardrail_id"]);
|
|
54263
|
+
const header = `| Task | ${guardrailIds.join(" | ")} |`;
|
|
54264
|
+
const divider = `|------|${guardrailIds.map(() => "------").join("|")}|`;
|
|
54265
|
+
const rows = taskIds.map((taskId) => {
|
|
54266
|
+
const cells = enforcement.map((e3) => {
|
|
54267
|
+
const scopedTasks = e3["scoped_tasks"];
|
|
54268
|
+
if (scopedTasks.length > 0 && !scopedTasks.includes(taskId)) return "n/a";
|
|
54269
|
+
return e3["action"];
|
|
54270
|
+
});
|
|
54271
|
+
return `| ${taskId} | ${cells.join(" | ")} |`;
|
|
54272
|
+
});
|
|
54273
|
+
return [header, divider, ...rows].join("\n");
|
|
54274
|
+
}
|
|
54275
|
+
);
|
|
54125
54276
|
function getDslSection(dsl, context) {
|
|
54126
54277
|
const sectionMap = {
|
|
54127
54278
|
agent: dsl.agents,
|
|
@@ -54186,13 +54337,13 @@ async function removeIfExists(filePath) {
|
|
|
54186
54337
|
} catch {
|
|
54187
54338
|
}
|
|
54188
54339
|
}
|
|
54189
|
-
async function renderFromConfig(dsl, renderTargets) {
|
|
54340
|
+
async function renderFromConfig(dsl, renderTargets, options) {
|
|
54190
54341
|
const outputFiles = [];
|
|
54191
54342
|
for (const target of renderTargets) {
|
|
54192
54343
|
const templateContent = await loadTemplate(target.template);
|
|
54193
54344
|
const compiled = Handlebars.compile(templateContent, { noEscape: false });
|
|
54194
54345
|
if (target.context === "system") {
|
|
54195
|
-
const ctx = buildSystemContext(dsl);
|
|
54346
|
+
const ctx = buildSystemContext(dsl, options);
|
|
54196
54347
|
const output = compiled(ctx);
|
|
54197
54348
|
if (target.skip_empty && isEffectivelyEmpty(output)) {
|
|
54198
54349
|
await removeIfExists(target.output);
|
|
@@ -54241,13 +54392,13 @@ function checkExpectedVsExisting(expected, outputPath, skipEmpty, diffs) {
|
|
|
54241
54392
|
diffs.push(outputPath);
|
|
54242
54393
|
});
|
|
54243
54394
|
}
|
|
54244
|
-
async function checkDriftFromConfig(dsl, renderTargets) {
|
|
54395
|
+
async function checkDriftFromConfig(dsl, renderTargets, options) {
|
|
54245
54396
|
const diffs = [];
|
|
54246
54397
|
for (const target of renderTargets) {
|
|
54247
54398
|
const templateContent = await loadTemplate(target.template);
|
|
54248
54399
|
const compiled = Handlebars.compile(templateContent, { noEscape: false });
|
|
54249
54400
|
if (target.context === "system") {
|
|
54250
|
-
const ctx = buildSystemContext(dsl);
|
|
54401
|
+
const ctx = buildSystemContext(dsl, options);
|
|
54251
54402
|
const expected = compiled(ctx);
|
|
54252
54403
|
await checkExpectedVsExisting(expected, target.output, target.skip_empty, diffs);
|
|
54253
54404
|
} else {
|