agent-contracts 0.12.2 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +246 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +247 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50479,7 +50479,8 @@ var AgentSchema = z.object({
|
|
|
50479
50479
|
rules: z.array(RuleSchema).optional(),
|
|
50480
50480
|
anti_patterns: z.array(z.string()).optional(),
|
|
50481
50481
|
escalation_criteria: z.array(EscalationCriterionSchema).optional(),
|
|
50482
|
-
prerequisites: z.array(PrerequisiteSchema).optional()
|
|
50482
|
+
prerequisites: z.array(PrerequisiteSchema).optional(),
|
|
50483
|
+
guardrails: z.array(z.string()).optional()
|
|
50483
50484
|
}).passthrough();
|
|
50484
50485
|
|
|
50485
50486
|
// src/schema/artifact.ts
|
|
@@ -50493,7 +50494,8 @@ var ArtifactSchema = z2.object({
|
|
|
50493
50494
|
consumers: z2.array(z2.string()),
|
|
50494
50495
|
states: z2.array(z2.string()),
|
|
50495
50496
|
required_validations: z2.array(z2.string()).default([]),
|
|
50496
|
-
visibility: z2.string().optional()
|
|
50497
|
+
visibility: z2.string().optional(),
|
|
50498
|
+
guardrails: z2.array(z2.string()).optional()
|
|
50497
50499
|
}).passthrough();
|
|
50498
50500
|
|
|
50499
50501
|
// src/schema/binding.ts
|
|
@@ -50657,7 +50659,8 @@ var TaskSchema = z8.object({
|
|
|
50657
50659
|
rules: z8.array(RuleSchema).optional(),
|
|
50658
50660
|
anti_patterns: z8.array(z8.string()).optional(),
|
|
50659
50661
|
escalation_criteria: z8.array(EscalationCriterionSchema).optional(),
|
|
50660
|
-
validations: z8.array(z8.string()).default([])
|
|
50662
|
+
validations: z8.array(z8.string()).default([]),
|
|
50663
|
+
guardrails: z8.array(z8.string()).optional()
|
|
50661
50664
|
}).passthrough();
|
|
50662
50665
|
|
|
50663
50666
|
// src/schema/tool.ts
|
|
@@ -50676,7 +50679,8 @@ var ToolSchema = z9.object({
|
|
|
50676
50679
|
output_artifacts: z9.array(z9.string()).default([]),
|
|
50677
50680
|
invokable_by: z9.array(z9.string()),
|
|
50678
50681
|
side_effects: z9.array(z9.string()).default([]),
|
|
50679
|
-
commands: z9.array(CommandSchema).default([])
|
|
50682
|
+
commands: z9.array(CommandSchema).default([]),
|
|
50683
|
+
guardrails: z9.array(z9.string()).optional()
|
|
50680
50684
|
}).passthrough();
|
|
50681
50685
|
|
|
50682
50686
|
// src/schema/validation.ts
|
|
@@ -52139,6 +52143,34 @@ function checkReferences(dsl) {
|
|
|
52139
52143
|
}
|
|
52140
52144
|
}
|
|
52141
52145
|
}
|
|
52146
|
+
for (const [id, agent] of Object.entries(dsl.agents)) {
|
|
52147
|
+
if (agent.guardrails) {
|
|
52148
|
+
for (const ref of agent.guardrails) {
|
|
52149
|
+
checkExists(ref, guardrailIds, "guardrails", `agents.${id}.guardrails`, "entity-guardrail-ref-not-found");
|
|
52150
|
+
}
|
|
52151
|
+
}
|
|
52152
|
+
}
|
|
52153
|
+
for (const [id, task] of Object.entries(dsl.tasks)) {
|
|
52154
|
+
if (task.guardrails) {
|
|
52155
|
+
for (const ref of task.guardrails) {
|
|
52156
|
+
checkExists(ref, guardrailIds, "guardrails", `tasks.${id}.guardrails`, "entity-guardrail-ref-not-found");
|
|
52157
|
+
}
|
|
52158
|
+
}
|
|
52159
|
+
}
|
|
52160
|
+
for (const [id, tool] of Object.entries(dsl.tools)) {
|
|
52161
|
+
if (tool.guardrails) {
|
|
52162
|
+
for (const ref of tool.guardrails) {
|
|
52163
|
+
checkExists(ref, guardrailIds, "guardrails", `tools.${id}.guardrails`, "entity-guardrail-ref-not-found");
|
|
52164
|
+
}
|
|
52165
|
+
}
|
|
52166
|
+
}
|
|
52167
|
+
for (const [id, art] of Object.entries(dsl.artifacts)) {
|
|
52168
|
+
if (art.guardrails) {
|
|
52169
|
+
for (const ref of art.guardrails) {
|
|
52170
|
+
checkExists(ref, guardrailIds, "guardrails", `artifacts.${id}.guardrails`, "entity-guardrail-ref-not-found");
|
|
52171
|
+
}
|
|
52172
|
+
}
|
|
52173
|
+
}
|
|
52142
52174
|
for (const [id, guardrail] of Object.entries(dsl.guardrails)) {
|
|
52143
52175
|
if (guardrail.scope.agents) {
|
|
52144
52176
|
for (const ref of guardrail.scope.agents) {
|
|
@@ -52869,6 +52901,114 @@ var semanticValidationPhaseCoverageRule = {
|
|
|
52869
52901
|
}
|
|
52870
52902
|
};
|
|
52871
52903
|
|
|
52904
|
+
// src/linter/rules/entity-guardrail-binding.ts
|
|
52905
|
+
var entityGuardrailUndefinedRule = {
|
|
52906
|
+
id: "entity-guardrail-undefined",
|
|
52907
|
+
description: "Entity references a guardrail ID not defined in guardrails",
|
|
52908
|
+
run(dsl) {
|
|
52909
|
+
const diagnostics = [];
|
|
52910
|
+
const guardrailIds = new Set(Object.keys(dsl.guardrails));
|
|
52911
|
+
const sections = [
|
|
52912
|
+
{ name: "agents", entities: dsl.agents },
|
|
52913
|
+
{ name: "tasks", entities: dsl.tasks },
|
|
52914
|
+
{ name: "tools", entities: dsl.tools },
|
|
52915
|
+
{ name: "artifacts", entities: dsl.artifacts }
|
|
52916
|
+
];
|
|
52917
|
+
for (const { name, entities } of sections) {
|
|
52918
|
+
for (const [entityId, entity] of Object.entries(entities)) {
|
|
52919
|
+
for (const ref of entity.guardrails ?? []) {
|
|
52920
|
+
if (!guardrailIds.has(ref)) {
|
|
52921
|
+
diagnostics.push({
|
|
52922
|
+
ruleId: "entity-guardrail-undefined",
|
|
52923
|
+
severity: "error",
|
|
52924
|
+
path: `${name}.${entityId}.guardrails`,
|
|
52925
|
+
message: `${name.slice(0, -1)} "${entityId}" references guardrail "${ref}" which is not defined in guardrails`
|
|
52926
|
+
});
|
|
52927
|
+
}
|
|
52928
|
+
}
|
|
52929
|
+
}
|
|
52930
|
+
}
|
|
52931
|
+
return diagnostics;
|
|
52932
|
+
}
|
|
52933
|
+
};
|
|
52934
|
+
var entityNoGuardrailsRule = {
|
|
52935
|
+
id: "entity-no-guardrails",
|
|
52936
|
+
description: "Entity has no effective guardrails (neither entity-side nor scope-side)",
|
|
52937
|
+
run(dsl) {
|
|
52938
|
+
const diagnostics = [];
|
|
52939
|
+
const scopeBindings = {
|
|
52940
|
+
agents: /* @__PURE__ */ new Set(),
|
|
52941
|
+
tasks: /* @__PURE__ */ new Set(),
|
|
52942
|
+
tools: /* @__PURE__ */ new Set(),
|
|
52943
|
+
artifacts: /* @__PURE__ */ new Set()
|
|
52944
|
+
};
|
|
52945
|
+
for (const guardrail of Object.values(dsl.guardrails)) {
|
|
52946
|
+
for (const key of Object.keys(scopeBindings)) {
|
|
52947
|
+
const ids = guardrail.scope[key];
|
|
52948
|
+
if (ids) {
|
|
52949
|
+
for (const id of ids) scopeBindings[key].add(id);
|
|
52950
|
+
}
|
|
52951
|
+
}
|
|
52952
|
+
}
|
|
52953
|
+
const sections = [
|
|
52954
|
+
{ name: "agents", entities: dsl.agents },
|
|
52955
|
+
{ name: "tasks", entities: dsl.tasks },
|
|
52956
|
+
{ name: "tools", entities: dsl.tools },
|
|
52957
|
+
{ name: "artifacts", entities: dsl.artifacts }
|
|
52958
|
+
];
|
|
52959
|
+
for (const { name, entities } of sections) {
|
|
52960
|
+
for (const [entityId, entity] of Object.entries(entities)) {
|
|
52961
|
+
const hasEntitySide = (entity.guardrails ?? []).length > 0;
|
|
52962
|
+
const hasScopeSide = scopeBindings[name].has(entityId);
|
|
52963
|
+
if (!hasEntitySide && !hasScopeSide) {
|
|
52964
|
+
diagnostics.push({
|
|
52965
|
+
ruleId: "entity-no-guardrails",
|
|
52966
|
+
severity: "info",
|
|
52967
|
+
path: `${name}.${entityId}`,
|
|
52968
|
+
message: `${name.slice(0, -1)} "${entityId}" has no effective guardrails`
|
|
52969
|
+
});
|
|
52970
|
+
}
|
|
52971
|
+
}
|
|
52972
|
+
}
|
|
52973
|
+
return diagnostics;
|
|
52974
|
+
}
|
|
52975
|
+
};
|
|
52976
|
+
var guardrailOrphanedRule = {
|
|
52977
|
+
id: "guardrail-orphaned",
|
|
52978
|
+
description: "Guardrail is not referenced by any entity and not bound to any entity via scope",
|
|
52979
|
+
run(dsl) {
|
|
52980
|
+
const diagnostics = [];
|
|
52981
|
+
const referencedByEntities = /* @__PURE__ */ new Set();
|
|
52982
|
+
const sections = [
|
|
52983
|
+
dsl.agents,
|
|
52984
|
+
dsl.tasks,
|
|
52985
|
+
dsl.tools,
|
|
52986
|
+
dsl.artifacts
|
|
52987
|
+
];
|
|
52988
|
+
for (const entities of sections) {
|
|
52989
|
+
for (const entity of Object.values(entities)) {
|
|
52990
|
+
for (const ref of entity.guardrails ?? []) {
|
|
52991
|
+
referencedByEntities.add(ref);
|
|
52992
|
+
}
|
|
52993
|
+
}
|
|
52994
|
+
}
|
|
52995
|
+
for (const [guardrailId, guardrail] of Object.entries(dsl.guardrails)) {
|
|
52996
|
+
const hasEntityRef = referencedByEntities.has(guardrailId);
|
|
52997
|
+
const scope = guardrail.scope;
|
|
52998
|
+
const hasScopeBinding = (scope.agents?.length ?? 0) > 0 || (scope.tasks?.length ?? 0) > 0 || (scope.tools?.length ?? 0) > 0 || (scope.artifacts?.length ?? 0) > 0 || (scope.workflows?.length ?? 0) > 0;
|
|
52999
|
+
if (!hasEntityRef && !hasScopeBinding) {
|
|
53000
|
+
diagnostics.push({
|
|
53001
|
+
ruleId: "guardrail-orphaned",
|
|
53002
|
+
severity: "warning",
|
|
53003
|
+
path: `guardrails.${guardrailId}`,
|
|
53004
|
+
message: `Guardrail "${guardrailId}" is not referenced by any entity and has no scope bindings`
|
|
53005
|
+
});
|
|
53006
|
+
}
|
|
53007
|
+
}
|
|
53008
|
+
return diagnostics;
|
|
53009
|
+
}
|
|
53010
|
+
};
|
|
53011
|
+
|
|
52872
53012
|
// src/linter/linter.ts
|
|
52873
53013
|
var builtinRules = [
|
|
52874
53014
|
validationCoverageRule,
|
|
@@ -52881,7 +53021,10 @@ var builtinRules = [
|
|
|
52881
53021
|
yamlReservedKeySafetyRule,
|
|
52882
53022
|
artifactRequiredValidationWiringRule,
|
|
52883
53023
|
taskOutputValidationCompletenessRule,
|
|
52884
|
-
semanticValidationPhaseCoverageRule
|
|
53024
|
+
semanticValidationPhaseCoverageRule,
|
|
53025
|
+
entityGuardrailUndefinedRule,
|
|
53026
|
+
entityNoGuardrailsRule,
|
|
53027
|
+
guardrailOrphanedRule
|
|
52885
53028
|
];
|
|
52886
53029
|
function lint(dsl, rules = builtinRules) {
|
|
52887
53030
|
const diagnostics = [];
|
|
@@ -53628,12 +53771,55 @@ function buildGuardrailEnforcement(dsl, policy, loadedBindings) {
|
|
|
53628
53771
|
}
|
|
53629
53772
|
return entries;
|
|
53630
53773
|
}
|
|
53774
|
+
function resolveEffectiveGuardrails(dsl, entityType, entityId) {
|
|
53775
|
+
const entityDef = dsl[entityType][entityId];
|
|
53776
|
+
const entitySide = new Set(entityDef?.guardrails ?? []);
|
|
53777
|
+
const scopeSide = /* @__PURE__ */ new Set();
|
|
53778
|
+
for (const [guardrailId, guardrail] of Object.entries(dsl.guardrails)) {
|
|
53779
|
+
const scopeIds = guardrail.scope[entityType];
|
|
53780
|
+
if (scopeIds?.includes(entityId)) {
|
|
53781
|
+
scopeSide.add(guardrailId);
|
|
53782
|
+
}
|
|
53783
|
+
}
|
|
53784
|
+
const allIds = /* @__PURE__ */ new Set([...entitySide, ...scopeSide]);
|
|
53785
|
+
const activePolicyRules = /* @__PURE__ */ new Map();
|
|
53786
|
+
for (const policy of Object.values(dsl.guardrail_policies)) {
|
|
53787
|
+
for (const rule of policy.rules) {
|
|
53788
|
+
if (!activePolicyRules.has(rule.guardrail)) {
|
|
53789
|
+
activePolicyRules.set(rule.guardrail, {
|
|
53790
|
+
severity: rule.severity,
|
|
53791
|
+
action: rule.action
|
|
53792
|
+
});
|
|
53793
|
+
}
|
|
53794
|
+
}
|
|
53795
|
+
}
|
|
53796
|
+
const entries = [];
|
|
53797
|
+
for (const id of allIds) {
|
|
53798
|
+
const guardrail = dsl.guardrails[id];
|
|
53799
|
+
if (!guardrail) continue;
|
|
53800
|
+
const fromEntity = entitySide.has(id);
|
|
53801
|
+
const fromScope = scopeSide.has(id);
|
|
53802
|
+
const source = fromEntity && fromScope ? "both" : fromEntity ? "entity" : "scope";
|
|
53803
|
+
const policyInfo = activePolicyRules.get(id);
|
|
53804
|
+
entries.push({
|
|
53805
|
+
guardrail_id: id,
|
|
53806
|
+
description: guardrail.description,
|
|
53807
|
+
rationale: guardrail.rationale,
|
|
53808
|
+
tags: guardrail.tags,
|
|
53809
|
+
source,
|
|
53810
|
+
severity: policyInfo?.severity,
|
|
53811
|
+
action: policyInfo?.action
|
|
53812
|
+
});
|
|
53813
|
+
}
|
|
53814
|
+
return entries;
|
|
53815
|
+
}
|
|
53631
53816
|
function buildTaskContext(dsl, taskId) {
|
|
53632
53817
|
const taskDef = dsl.tasks[taskId];
|
|
53633
53818
|
const task = { ...taskDef, id: taskId };
|
|
53634
53819
|
const agentDef = dsl.agents[taskDef.target_agent];
|
|
53635
53820
|
const targetAgent = agentDef ? { ...agentDef, id: taskDef.target_agent } : null;
|
|
53636
|
-
|
|
53821
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tasks", taskId);
|
|
53822
|
+
return { task, targetAgent, relatedGuardrails, dsl };
|
|
53637
53823
|
}
|
|
53638
53824
|
function buildArtifactContext(dsl, artifactId) {
|
|
53639
53825
|
const artifactDef = dsl.artifacts[artifactId];
|
|
@@ -53676,6 +53862,7 @@ function buildArtifactContext(dsl, artifactId) {
|
|
|
53676
53862
|
}
|
|
53677
53863
|
}
|
|
53678
53864
|
}
|
|
53865
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "artifacts", artifactId);
|
|
53679
53866
|
return {
|
|
53680
53867
|
artifact,
|
|
53681
53868
|
relatedTools,
|
|
@@ -53684,6 +53871,7 @@ function buildArtifactContext(dsl, artifactId) {
|
|
|
53684
53871
|
consumerAgents,
|
|
53685
53872
|
editorAgents,
|
|
53686
53873
|
createdInWorkflows,
|
|
53874
|
+
relatedGuardrails,
|
|
53687
53875
|
dsl
|
|
53688
53876
|
};
|
|
53689
53877
|
}
|
|
@@ -53701,11 +53889,13 @@ function buildToolContext(dsl, toolId) {
|
|
|
53701
53889
|
}
|
|
53702
53890
|
return result;
|
|
53703
53891
|
};
|
|
53892
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tools", toolId);
|
|
53704
53893
|
return {
|
|
53705
53894
|
tool,
|
|
53706
53895
|
invokableAgents,
|
|
53707
53896
|
inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
|
|
53708
53897
|
outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
|
|
53898
|
+
relatedGuardrails,
|
|
53709
53899
|
dsl
|
|
53710
53900
|
};
|
|
53711
53901
|
}
|
|
@@ -53937,6 +54127,7 @@ function buildPerAgentContext(dsl, agent) {
|
|
|
53937
54127
|
}
|
|
53938
54128
|
const rawReceivableTasks = receivableTasks.map(({ id: _id, ...rest }) => rest);
|
|
53939
54129
|
const mergedBehavior = mergeBehavioralSpec(agent, rawReceivableTasks);
|
|
54130
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "agents", agentId);
|
|
53940
54131
|
return {
|
|
53941
54132
|
agent,
|
|
53942
54133
|
tasks: receivableTasks,
|
|
@@ -53946,6 +54137,7 @@ function buildPerAgentContext(dsl, agent) {
|
|
|
53946
54137
|
relatedTools,
|
|
53947
54138
|
relatedHandoffTypes,
|
|
53948
54139
|
mergedBehavior,
|
|
54140
|
+
relatedGuardrails,
|
|
53949
54141
|
dsl
|
|
53950
54142
|
};
|
|
53951
54143
|
}
|
|
@@ -55676,6 +55868,52 @@ function crossReferenceBidirectionality(dsl) {
|
|
|
55676
55868
|
recommendations: issues.length > 0 ? [`${issues.length} unreciprocated cross-references: ${issues.slice(0, 5).join(", ")}${issues.length > 5 ? `, ... (${issues.length - 5} more)` : ""}`] : []
|
|
55677
55869
|
};
|
|
55678
55870
|
}
|
|
55871
|
+
function entityGuardrailCoverage(dsl) {
|
|
55872
|
+
const entitySections = [
|
|
55873
|
+
{ name: "agents", entities: dsl.agents },
|
|
55874
|
+
{ name: "tasks", entities: dsl.tasks },
|
|
55875
|
+
{ name: "tools", entities: dsl.tools },
|
|
55876
|
+
{ name: "artifacts", entities: dsl.artifacts }
|
|
55877
|
+
];
|
|
55878
|
+
const scopeBindings = {
|
|
55879
|
+
agents: /* @__PURE__ */ new Set(),
|
|
55880
|
+
tasks: /* @__PURE__ */ new Set(),
|
|
55881
|
+
tools: /* @__PURE__ */ new Set(),
|
|
55882
|
+
artifacts: /* @__PURE__ */ new Set()
|
|
55883
|
+
};
|
|
55884
|
+
for (const guardrail of Object.values(dsl.guardrails)) {
|
|
55885
|
+
for (const key of Object.keys(scopeBindings)) {
|
|
55886
|
+
const ids = guardrail.scope[key];
|
|
55887
|
+
if (ids) {
|
|
55888
|
+
for (const id of ids) scopeBindings[key].add(id);
|
|
55889
|
+
}
|
|
55890
|
+
}
|
|
55891
|
+
}
|
|
55892
|
+
let total = 0;
|
|
55893
|
+
let covered = 0;
|
|
55894
|
+
const missing = [];
|
|
55895
|
+
for (const { name, entities } of entitySections) {
|
|
55896
|
+
for (const [entityId, entity] of Object.entries(entities)) {
|
|
55897
|
+
total++;
|
|
55898
|
+
const hasEntitySide = (entity.guardrails ?? []).length > 0;
|
|
55899
|
+
const hasScopeSide = scopeBindings[name].has(entityId);
|
|
55900
|
+
if (hasEntitySide || hasScopeSide) {
|
|
55901
|
+
covered++;
|
|
55902
|
+
} else {
|
|
55903
|
+
missing.push(`${name}.${entityId}`);
|
|
55904
|
+
}
|
|
55905
|
+
}
|
|
55906
|
+
}
|
|
55907
|
+
return {
|
|
55908
|
+
id: "entity-guardrail-coverage",
|
|
55909
|
+
label: "Entity guardrail coverage",
|
|
55910
|
+
score: covered,
|
|
55911
|
+
total,
|
|
55912
|
+
percent: pct(covered, total),
|
|
55913
|
+
weight: 1,
|
|
55914
|
+
recommendations: missing.length > 0 ? [`${missing.length} entities without guardrails: ${missing.slice(0, 5).join(", ")}${missing.length > 5 ? `, ... (${missing.length - 5} more)` : ""}`] : []
|
|
55915
|
+
};
|
|
55916
|
+
}
|
|
55679
55917
|
function guardrailScopeResolution(dsl) {
|
|
55680
55918
|
let totalRefs = 0;
|
|
55681
55919
|
let resolvedRefs = 0;
|
|
@@ -55721,7 +55959,8 @@ function score(dsl) {
|
|
|
55721
55959
|
workflowValidationIntegration(dsl),
|
|
55722
55960
|
schemaCompleteness(dsl),
|
|
55723
55961
|
crossReferenceBidirectionality(dsl),
|
|
55724
|
-
guardrailScopeResolution(dsl)
|
|
55962
|
+
guardrailScopeResolution(dsl),
|
|
55963
|
+
entityGuardrailCoverage(dsl)
|
|
55725
55964
|
];
|
|
55726
55965
|
const totalWeight = dimensions.reduce((s2, d2) => s2 + d2.weight, 0);
|
|
55727
55966
|
const weightedSum = dimensions.reduce(
|