agent-contracts 0.12.2 → 0.12.4
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 +22 -9
- package/dist/cli.js +326 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +328 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -999,10 +999,10 @@ Each `context` type provides a different rendering scope:
|
|
|
999
999
|
| Context | Scope | Output | Key variables |
|
|
1000
1000
|
|---------|-------|--------|---------------|
|
|
1001
1001
|
| `system` | Single file | `output` as-is | `system`, `dsl`, `guardrailEnforcement`\*, `bindings`\* |
|
|
1002
|
-
| `agent` | Per agent | `{agent.id}` in output path | `agent`, `receivableTasks`, `delegatableTasks`, `relatedArtifacts`, `relatedTools`, `relatedHandoffTypes`, `mergedBehavior`, `dsl` |
|
|
1003
|
-
| `task` | Per task | `{task.id}` in output path | `task`, `targetAgent`, `dsl` |
|
|
1004
|
-
| `artifact` | Per artifact | `{artifact.id}` in output path | `artifact`, `relatedTools`, `relatedValidations`, `producerAgents`, `consumerAgents`, `editorAgents`, `createdInWorkflows`, `dsl` |
|
|
1005
|
-
| `tool` | Per tool | `{tool.id}` in output path | `tool`, `invokableAgents`, `inputArtifactDetails`, `outputArtifactDetails`, `dsl` |
|
|
1002
|
+
| `agent` | Per agent | `{agent.id}` in output path | `agent`, `receivableTasks`, `delegatableTasks`, `relatedArtifacts`, `relatedTools`, `relatedHandoffTypes`, `mergedBehavior`, `relatedGuardrails`, `relatedValidations`, `dsl` |
|
|
1003
|
+
| `task` | Per task | `{task.id}` in output path | `task`, `targetAgent`, `relatedGuardrails`, `relatedValidations`, `dsl` |
|
|
1004
|
+
| `artifact` | Per artifact | `{artifact.id}` in output path | `artifact`, `relatedTools`, `relatedValidations`, `relatedGuardrails`, `producerAgents`, `consumerAgents`, `editorAgents`, `createdInWorkflows`, `dsl` |
|
|
1005
|
+
| `tool` | Per tool | `{tool.id}` in output path | `tool`, `invokableAgents`, `inputArtifactDetails`, `outputArtifactDetails`, `relatedGuardrails`, `relatedValidations`, `dsl` |
|
|
1006
1006
|
| `validation` | Per validation | `{validation.id}` in output path | `validation`, `dsl` |
|
|
1007
1007
|
| `handoff_type` | Per handoff type | `{handoff_type.id}` in output path | `handoff_type`, `relatedTasks`, `dsl` |
|
|
1008
1008
|
| `workflow` | Per workflow phase | `{workflow.id}` in output path | `workflow`, `relatedAgents`, `relatedTasks`, `relatedTools`, `relatedArtifacts`, `relatedValidations`, `dsl` |
|
|
@@ -1027,6 +1027,23 @@ Each `context` type provides a different rendering scope:
|
|
|
1027
1027
|
* `producerAgents` / `consumerAgents` / `editorAgents` — resolved agent records
|
|
1028
1028
|
* `createdInWorkflows` — workflow phases where this artifact is written
|
|
1029
1029
|
|
|
1030
|
+
**`agent` context** provides merged behavioral specs and cross-references:
|
|
1031
|
+
|
|
1032
|
+
* `relatedGuardrails` — guardrails bound via `agent.guardrails[]` or guardrail `scope.agents[]`, merged and deduplicated
|
|
1033
|
+
* `relatedValidations` — validations from `agent.can_perform_validations`, resolved into full entries (kind, target_artifact, executor_type, blocking)
|
|
1034
|
+
|
|
1035
|
+
**`task` context** provides execution details:
|
|
1036
|
+
|
|
1037
|
+
* `relatedGuardrails` — guardrails bound via `task.guardrails[]` or guardrail `scope.tasks[]`
|
|
1038
|
+
* `relatedValidations` — validations from `task.validations[]`, resolved into full entries
|
|
1039
|
+
|
|
1040
|
+
**`tool` context** provides invocation and artifact details:
|
|
1041
|
+
|
|
1042
|
+
* `relatedGuardrails` — guardrails bound via `tool.guardrails[]` or guardrail `scope.tools[]`
|
|
1043
|
+
* `relatedValidations` — validations where `executor_type` is `"tool"` and `executor` matches this tool ID
|
|
1044
|
+
* `invokableAgents` — agents listed in `invokable_by`
|
|
1045
|
+
* `inputArtifactDetails` / `outputArtifactDetails` — resolved artifact records
|
|
1046
|
+
|
|
1030
1047
|
**`system` context** includes binding-aware guardrail enforcement data when `bindings` and `active_guardrail_policy` are configured:
|
|
1031
1048
|
|
|
1032
1049
|
* `guardrailEnforcement` — array of enforcement entries, each with `guardrail_id`, `description`, `severity`, `action`, scoped entities (`scoped_agents`, `scoped_tasks`, `scoped_workflows`, `scoped_tools`, `scoped_artifacts`), `allow_override`, `override_requires`, `trigger` (from binding matcher type), and `escalation`
|
|
@@ -1039,11 +1056,6 @@ These fields are only populated when the config specifies `bindings` and `active
|
|
|
1039
1056
|
* `guardrailCoverageMatrix` — generates a Guardrail Coverage Matrix table (guardrail × severity × action × scoped entities × trigger × override × escalation)
|
|
1040
1057
|
* `taskGuardrailMatrix` — generates a Task × Guardrail cross-reference table showing which action applies to each task
|
|
1041
1058
|
|
|
1042
|
-
**`tool` context** resolves agent and artifact references:
|
|
1043
|
-
|
|
1044
|
-
* `invokableAgents` — agents listed in `invokable_by`
|
|
1045
|
-
* `inputArtifactDetails` / `outputArtifactDetails` — resolved artifact records
|
|
1046
|
-
|
|
1047
1059
|
### Handlebars helpers
|
|
1048
1060
|
|
|
1049
1061
|
Templates can use these built-in helpers:
|
|
@@ -1306,6 +1318,7 @@ Checks:
|
|
|
1306
1318
|
* artifact ownership — `produces_artifact`/`reads_artifact` in execution steps vs. artifact producers/editors/consumers
|
|
1307
1319
|
* tool commands — `commands[].reads`/`commands[].writes` reference valid artifacts and align with `output_artifacts`
|
|
1308
1320
|
* semantic validation phase coverage — warns when `semantic` or `fidelity` validations only appear in late workflow phases (e.g., audit) but not earlier phases (e.g., specify, plan)
|
|
1321
|
+
* validation executor context wiring — warns when a validation's executor (agent or tool) exists in the DSL but the validation is not surfaced in the executor's prompt context
|
|
1309
1322
|
* YAML safety — warns when YAML 1.1 reserved words (`on`, `yes`, `no`, `true`, `false`, etc.) are used in positions where they may be misinterpreted by non-1.2 parsers
|
|
1310
1323
|
* naming/style issues through Spectral rules
|
|
1311
1324
|
|
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,148 @@ 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
|
+
|
|
53012
|
+
// src/linter/rules/validation-executor-no-context.ts
|
|
53013
|
+
var validationExecutorNoContextRule = {
|
|
53014
|
+
id: "validation-executor-no-context",
|
|
53015
|
+
description: "Validation executor is not wired so the validation appears in the executor's rendered context",
|
|
53016
|
+
run(dsl) {
|
|
53017
|
+
const diagnostics = [];
|
|
53018
|
+
for (const [validationId, val] of Object.entries(dsl.validations)) {
|
|
53019
|
+
if (val.executor_type === "agent") {
|
|
53020
|
+
const agent = dsl.agents[val.executor];
|
|
53021
|
+
if (!agent) continue;
|
|
53022
|
+
const allowed = new Set(agent.can_perform_validations ?? []);
|
|
53023
|
+
if (!allowed.has(validationId)) {
|
|
53024
|
+
diagnostics.push({
|
|
53025
|
+
ruleId: "validation-executor-no-context",
|
|
53026
|
+
severity: "warning",
|
|
53027
|
+
path: `agents.${val.executor}.can_perform_validations`,
|
|
53028
|
+
message: `Validation "${validationId}" is executed by agent "${val.executor}" but is not listed in can_perform_validations, so it will be missing from that agent's prompt context`
|
|
53029
|
+
});
|
|
53030
|
+
}
|
|
53031
|
+
} else if (val.executor_type === "tool") {
|
|
53032
|
+
if (!dsl.tools[val.executor]) {
|
|
53033
|
+
diagnostics.push({
|
|
53034
|
+
ruleId: "validation-executor-no-context",
|
|
53035
|
+
severity: "warning",
|
|
53036
|
+
path: `validations.${validationId}.executor`,
|
|
53037
|
+
message: `Validation "${validationId}" references tool executor "${val.executor}" which is not defined in tools`
|
|
53038
|
+
});
|
|
53039
|
+
}
|
|
53040
|
+
}
|
|
53041
|
+
}
|
|
53042
|
+
return diagnostics;
|
|
53043
|
+
}
|
|
53044
|
+
};
|
|
53045
|
+
|
|
52872
53046
|
// src/linter/linter.ts
|
|
52873
53047
|
var builtinRules = [
|
|
52874
53048
|
validationCoverageRule,
|
|
@@ -52881,7 +53055,11 @@ var builtinRules = [
|
|
|
52881
53055
|
yamlReservedKeySafetyRule,
|
|
52882
53056
|
artifactRequiredValidationWiringRule,
|
|
52883
53057
|
taskOutputValidationCompletenessRule,
|
|
52884
|
-
semanticValidationPhaseCoverageRule
|
|
53058
|
+
semanticValidationPhaseCoverageRule,
|
|
53059
|
+
entityGuardrailUndefinedRule,
|
|
53060
|
+
entityNoGuardrailsRule,
|
|
53061
|
+
guardrailOrphanedRule,
|
|
53062
|
+
validationExecutorNoContextRule
|
|
52885
53063
|
];
|
|
52886
53064
|
function lint(dsl, rules = builtinRules) {
|
|
52887
53065
|
const diagnostics = [];
|
|
@@ -53628,12 +53806,96 @@ function buildGuardrailEnforcement(dsl, policy, loadedBindings) {
|
|
|
53628
53806
|
}
|
|
53629
53807
|
return entries;
|
|
53630
53808
|
}
|
|
53809
|
+
function resolveEffectiveGuardrails(dsl, entityType, entityId) {
|
|
53810
|
+
const entityDef = dsl[entityType][entityId];
|
|
53811
|
+
const entitySide = new Set(entityDef?.guardrails ?? []);
|
|
53812
|
+
const scopeSide = /* @__PURE__ */ new Set();
|
|
53813
|
+
for (const [guardrailId, guardrail] of Object.entries(dsl.guardrails)) {
|
|
53814
|
+
const scopeIds = guardrail.scope[entityType];
|
|
53815
|
+
if (scopeIds?.includes(entityId)) {
|
|
53816
|
+
scopeSide.add(guardrailId);
|
|
53817
|
+
}
|
|
53818
|
+
}
|
|
53819
|
+
const allIds = /* @__PURE__ */ new Set([...entitySide, ...scopeSide]);
|
|
53820
|
+
const activePolicyRules = /* @__PURE__ */ new Map();
|
|
53821
|
+
for (const policy of Object.values(dsl.guardrail_policies)) {
|
|
53822
|
+
for (const rule of policy.rules) {
|
|
53823
|
+
if (!activePolicyRules.has(rule.guardrail)) {
|
|
53824
|
+
activePolicyRules.set(rule.guardrail, {
|
|
53825
|
+
severity: rule.severity,
|
|
53826
|
+
action: rule.action
|
|
53827
|
+
});
|
|
53828
|
+
}
|
|
53829
|
+
}
|
|
53830
|
+
}
|
|
53831
|
+
const entries = [];
|
|
53832
|
+
for (const id of allIds) {
|
|
53833
|
+
const guardrail = dsl.guardrails[id];
|
|
53834
|
+
if (!guardrail) continue;
|
|
53835
|
+
const fromEntity = entitySide.has(id);
|
|
53836
|
+
const fromScope = scopeSide.has(id);
|
|
53837
|
+
const source = fromEntity && fromScope ? "both" : fromEntity ? "entity" : "scope";
|
|
53838
|
+
const policyInfo = activePolicyRules.get(id);
|
|
53839
|
+
entries.push({
|
|
53840
|
+
guardrail_id: id,
|
|
53841
|
+
description: guardrail.description,
|
|
53842
|
+
rationale: guardrail.rationale,
|
|
53843
|
+
tags: guardrail.tags,
|
|
53844
|
+
source,
|
|
53845
|
+
severity: policyInfo?.severity,
|
|
53846
|
+
action: policyInfo?.action
|
|
53847
|
+
});
|
|
53848
|
+
}
|
|
53849
|
+
return entries;
|
|
53850
|
+
}
|
|
53851
|
+
function validationToEntityEntry(validationId, validation) {
|
|
53852
|
+
return {
|
|
53853
|
+
validation_id: validationId,
|
|
53854
|
+
kind: validation.kind,
|
|
53855
|
+
target_artifact: validation.target_artifact,
|
|
53856
|
+
executor_type: validation.executor_type,
|
|
53857
|
+
blocking: validation.blocking,
|
|
53858
|
+
produces_evidence: validation.produces_evidence
|
|
53859
|
+
};
|
|
53860
|
+
}
|
|
53861
|
+
function resolveEntityValidations(dsl, entityType, entityId) {
|
|
53862
|
+
if (entityType === "agents") {
|
|
53863
|
+
const agent = dsl.agents[entityId];
|
|
53864
|
+
if (!agent) return [];
|
|
53865
|
+
const entries2 = [];
|
|
53866
|
+
for (const vid of agent.can_perform_validations ?? []) {
|
|
53867
|
+
const v2 = dsl.validations[vid];
|
|
53868
|
+
if (v2) entries2.push(validationToEntityEntry(vid, v2));
|
|
53869
|
+
}
|
|
53870
|
+
return entries2;
|
|
53871
|
+
}
|
|
53872
|
+
if (entityType === "tasks") {
|
|
53873
|
+
const task = dsl.tasks[entityId];
|
|
53874
|
+
if (!task) return [];
|
|
53875
|
+
const entries2 = [];
|
|
53876
|
+
for (const vid of task.validations ?? []) {
|
|
53877
|
+
const v2 = dsl.validations[vid];
|
|
53878
|
+
if (v2) entries2.push(validationToEntityEntry(vid, v2));
|
|
53879
|
+
}
|
|
53880
|
+
return entries2;
|
|
53881
|
+
}
|
|
53882
|
+
const entries = [];
|
|
53883
|
+
for (const [vid, v2] of Object.entries(dsl.validations)) {
|
|
53884
|
+
if (v2.executor_type === "tool" && v2.executor === entityId) {
|
|
53885
|
+
entries.push(validationToEntityEntry(vid, v2));
|
|
53886
|
+
}
|
|
53887
|
+
}
|
|
53888
|
+
entries.sort((a3, b3) => a3.validation_id.localeCompare(b3.validation_id));
|
|
53889
|
+
return entries;
|
|
53890
|
+
}
|
|
53631
53891
|
function buildTaskContext(dsl, taskId) {
|
|
53632
53892
|
const taskDef = dsl.tasks[taskId];
|
|
53633
53893
|
const task = { ...taskDef, id: taskId };
|
|
53634
53894
|
const agentDef = dsl.agents[taskDef.target_agent];
|
|
53635
53895
|
const targetAgent = agentDef ? { ...agentDef, id: taskDef.target_agent } : null;
|
|
53636
|
-
|
|
53896
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tasks", taskId);
|
|
53897
|
+
const relatedValidations = resolveEntityValidations(dsl, "tasks", taskId);
|
|
53898
|
+
return { task, targetAgent, relatedGuardrails, relatedValidations, dsl };
|
|
53637
53899
|
}
|
|
53638
53900
|
function buildArtifactContext(dsl, artifactId) {
|
|
53639
53901
|
const artifactDef = dsl.artifacts[artifactId];
|
|
@@ -53676,6 +53938,7 @@ function buildArtifactContext(dsl, artifactId) {
|
|
|
53676
53938
|
}
|
|
53677
53939
|
}
|
|
53678
53940
|
}
|
|
53941
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "artifacts", artifactId);
|
|
53679
53942
|
return {
|
|
53680
53943
|
artifact,
|
|
53681
53944
|
relatedTools,
|
|
@@ -53684,6 +53947,7 @@ function buildArtifactContext(dsl, artifactId) {
|
|
|
53684
53947
|
consumerAgents,
|
|
53685
53948
|
editorAgents,
|
|
53686
53949
|
createdInWorkflows,
|
|
53950
|
+
relatedGuardrails,
|
|
53687
53951
|
dsl
|
|
53688
53952
|
};
|
|
53689
53953
|
}
|
|
@@ -53701,11 +53965,15 @@ function buildToolContext(dsl, toolId) {
|
|
|
53701
53965
|
}
|
|
53702
53966
|
return result;
|
|
53703
53967
|
};
|
|
53968
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "tools", toolId);
|
|
53969
|
+
const relatedValidations = resolveEntityValidations(dsl, "tools", toolId);
|
|
53704
53970
|
return {
|
|
53705
53971
|
tool,
|
|
53706
53972
|
invokableAgents,
|
|
53707
53973
|
inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
|
|
53708
53974
|
outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
|
|
53975
|
+
relatedGuardrails,
|
|
53976
|
+
relatedValidations,
|
|
53709
53977
|
dsl
|
|
53710
53978
|
};
|
|
53711
53979
|
}
|
|
@@ -53937,6 +54205,8 @@ function buildPerAgentContext(dsl, agent) {
|
|
|
53937
54205
|
}
|
|
53938
54206
|
const rawReceivableTasks = receivableTasks.map(({ id: _id, ...rest }) => rest);
|
|
53939
54207
|
const mergedBehavior = mergeBehavioralSpec(agent, rawReceivableTasks);
|
|
54208
|
+
const relatedGuardrails = resolveEffectiveGuardrails(dsl, "agents", agentId);
|
|
54209
|
+
const relatedValidations = resolveEntityValidations(dsl, "agents", agentId);
|
|
53940
54210
|
return {
|
|
53941
54211
|
agent,
|
|
53942
54212
|
tasks: receivableTasks,
|
|
@@ -53946,6 +54216,8 @@ function buildPerAgentContext(dsl, agent) {
|
|
|
53946
54216
|
relatedTools,
|
|
53947
54217
|
relatedHandoffTypes,
|
|
53948
54218
|
mergedBehavior,
|
|
54219
|
+
relatedGuardrails,
|
|
54220
|
+
relatedValidations,
|
|
53949
54221
|
dsl
|
|
53950
54222
|
};
|
|
53951
54223
|
}
|
|
@@ -55676,6 +55948,52 @@ function crossReferenceBidirectionality(dsl) {
|
|
|
55676
55948
|
recommendations: issues.length > 0 ? [`${issues.length} unreciprocated cross-references: ${issues.slice(0, 5).join(", ")}${issues.length > 5 ? `, ... (${issues.length - 5} more)` : ""}`] : []
|
|
55677
55949
|
};
|
|
55678
55950
|
}
|
|
55951
|
+
function entityGuardrailCoverage(dsl) {
|
|
55952
|
+
const entitySections = [
|
|
55953
|
+
{ name: "agents", entities: dsl.agents },
|
|
55954
|
+
{ name: "tasks", entities: dsl.tasks },
|
|
55955
|
+
{ name: "tools", entities: dsl.tools },
|
|
55956
|
+
{ name: "artifacts", entities: dsl.artifacts }
|
|
55957
|
+
];
|
|
55958
|
+
const scopeBindings = {
|
|
55959
|
+
agents: /* @__PURE__ */ new Set(),
|
|
55960
|
+
tasks: /* @__PURE__ */ new Set(),
|
|
55961
|
+
tools: /* @__PURE__ */ new Set(),
|
|
55962
|
+
artifacts: /* @__PURE__ */ new Set()
|
|
55963
|
+
};
|
|
55964
|
+
for (const guardrail of Object.values(dsl.guardrails)) {
|
|
55965
|
+
for (const key of Object.keys(scopeBindings)) {
|
|
55966
|
+
const ids = guardrail.scope[key];
|
|
55967
|
+
if (ids) {
|
|
55968
|
+
for (const id of ids) scopeBindings[key].add(id);
|
|
55969
|
+
}
|
|
55970
|
+
}
|
|
55971
|
+
}
|
|
55972
|
+
let total = 0;
|
|
55973
|
+
let covered = 0;
|
|
55974
|
+
const missing = [];
|
|
55975
|
+
for (const { name, entities } of entitySections) {
|
|
55976
|
+
for (const [entityId, entity] of Object.entries(entities)) {
|
|
55977
|
+
total++;
|
|
55978
|
+
const hasEntitySide = (entity.guardrails ?? []).length > 0;
|
|
55979
|
+
const hasScopeSide = scopeBindings[name].has(entityId);
|
|
55980
|
+
if (hasEntitySide || hasScopeSide) {
|
|
55981
|
+
covered++;
|
|
55982
|
+
} else {
|
|
55983
|
+
missing.push(`${name}.${entityId}`);
|
|
55984
|
+
}
|
|
55985
|
+
}
|
|
55986
|
+
}
|
|
55987
|
+
return {
|
|
55988
|
+
id: "entity-guardrail-coverage",
|
|
55989
|
+
label: "Entity guardrail coverage",
|
|
55990
|
+
score: covered,
|
|
55991
|
+
total,
|
|
55992
|
+
percent: pct(covered, total),
|
|
55993
|
+
weight: 1,
|
|
55994
|
+
recommendations: missing.length > 0 ? [`${missing.length} entities without guardrails: ${missing.slice(0, 5).join(", ")}${missing.length > 5 ? `, ... (${missing.length - 5} more)` : ""}`] : []
|
|
55995
|
+
};
|
|
55996
|
+
}
|
|
55679
55997
|
function guardrailScopeResolution(dsl) {
|
|
55680
55998
|
let totalRefs = 0;
|
|
55681
55999
|
let resolvedRefs = 0;
|
|
@@ -55721,7 +56039,8 @@ function score(dsl) {
|
|
|
55721
56039
|
workflowValidationIntegration(dsl),
|
|
55722
56040
|
schemaCompleteness(dsl),
|
|
55723
56041
|
crossReferenceBidirectionality(dsl),
|
|
55724
|
-
guardrailScopeResolution(dsl)
|
|
56042
|
+
guardrailScopeResolution(dsl),
|
|
56043
|
+
entityGuardrailCoverage(dsl)
|
|
55725
56044
|
];
|
|
55726
56045
|
const totalWeight = dimensions.reduce((s2, d2) => s2 + d2.weight, 0);
|
|
55727
56046
|
const weightedSum = dimensions.reduce(
|