agent-contracts 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -59175,7 +59175,8 @@ var TaskSchema = z7.object({
59175
59175
  completion_criteria: z7.array(z7.string()).optional(),
59176
59176
  rules: z7.array(RuleSchema).optional(),
59177
59177
  anti_patterns: z7.array(z7.string()).optional(),
59178
- escalation_criteria: z7.array(EscalationCriterionSchema).optional()
59178
+ escalation_criteria: z7.array(EscalationCriterionSchema).optional(),
59179
+ validations: z7.array(z7.string()).default([])
59179
59180
  }).passthrough();
59180
59181
 
59181
59182
  // src/schema/tool.ts
@@ -59221,6 +59222,20 @@ var ExternalParticipantSchema = z10.object({
59221
59222
  label: z10.string(),
59222
59223
  description: z10.string().optional()
59223
59224
  });
59225
+ var WorkflowDelegateStepSchema = z10.object({
59226
+ type: z10.literal("delegate"),
59227
+ description: z10.string().optional(),
59228
+ task: z10.string(),
59229
+ from_agent: z10.string(),
59230
+ group: z10.string().optional(),
59231
+ retry: RetrySchema.optional()
59232
+ }).passthrough();
59233
+ var WorkflowGateStepSchema = z10.object({
59234
+ type: z10.literal("gate"),
59235
+ description: z10.string().optional(),
59236
+ gate_kind: z10.string(),
59237
+ group: z10.string().optional()
59238
+ }).passthrough();
59224
59239
  var WorkflowHandoffStepSchema = z10.object({
59225
59240
  type: z10.literal("handoff"),
59226
59241
  description: z10.string().optional(),
@@ -59244,6 +59259,8 @@ var WorkflowDecisionStepSchema = z10.object({
59244
59259
  group: z10.string().optional()
59245
59260
  }).passthrough();
59246
59261
  var WorkflowStepSchema = z10.discriminatedUnion("type", [
59262
+ WorkflowDelegateStepSchema,
59263
+ WorkflowGateStepSchema,
59247
59264
  WorkflowHandoffStepSchema,
59248
59265
  WorkflowValidationStepSchema,
59249
59266
  WorkflowDecisionStepSchema
@@ -59469,12 +59486,20 @@ function checkReferences(dsl) {
59469
59486
  for (const ref of task.input_artifacts) {
59470
59487
  checkExists(ref, artifactIds, "artifacts", `tasks.${id}.input_artifacts`);
59471
59488
  }
59489
+ for (const ref of task.validations) {
59490
+ checkExists(ref, validationIds, "validations", `tasks.${id}.validations`);
59491
+ }
59472
59492
  }
59473
59493
  for (const [wfId, wf] of Object.entries(dsl.workflow)) {
59474
59494
  checkExists(wfId, workflowIds, "system.default_workflow_order", `workflow.${wfId}`);
59475
59495
  for (let j2 = 0; j2 < wf.steps.length; j2++) {
59476
59496
  const step = wf.steps[j2];
59477
- if (step.type === "handoff") {
59497
+ if (step.type === "delegate") {
59498
+ checkExists(step.task, taskIds, "tasks", `workflow.${wfId}.steps[${j2}].task`);
59499
+ checkExists(step.from_agent, agentIds, "agents", `workflow.${wfId}.steps[${j2}].from_agent`);
59500
+ } else if (step.type === "gate") {
59501
+ checkExists(step.gate_kind, handoffKinds, "handoff_types", `workflow.${wfId}.steps[${j2}].gate_kind`);
59502
+ } else if (step.type === "handoff") {
59478
59503
  if (step.task) {
59479
59504
  checkExists(step.task, taskIds, "tasks", `workflow.${wfId}.steps[${j2}].task`);
59480
59505
  }
@@ -59646,21 +59671,26 @@ var validationCoverageRule = {
59646
59671
  });
59647
59672
  }
59648
59673
  }
59649
- const validationsReferencedInWorkflow = /* @__PURE__ */ new Set();
59674
+ const referencedValidations = /* @__PURE__ */ new Set();
59650
59675
  for (const wf of Object.values(dsl.workflow)) {
59651
59676
  for (const step of wf.steps) {
59652
59677
  if (step.type === "validation") {
59653
- validationsReferencedInWorkflow.add(step.validation);
59678
+ referencedValidations.add(step.validation);
59654
59679
  }
59655
59680
  }
59656
59681
  }
59682
+ for (const task of Object.values(dsl.tasks)) {
59683
+ for (const valId of task.validations) {
59684
+ referencedValidations.add(valId);
59685
+ }
59686
+ }
59657
59687
  for (const [valId, val] of Object.entries(dsl.validations)) {
59658
- if (val.blocking && !validationsReferencedInWorkflow.has(valId)) {
59688
+ if (val.blocking && !referencedValidations.has(valId)) {
59659
59689
  diagnostics.push({
59660
59690
  ruleId: "validation-coverage",
59661
59691
  severity: "warning",
59662
59692
  path: `validations.${valId}`,
59663
- message: `Blocking validation "${valId}" is not referenced in any workflow step`
59693
+ message: `Blocking validation "${valId}" is not referenced in any workflow step or task`
59664
59694
  });
59665
59695
  }
59666
59696
  }
@@ -60136,6 +60166,28 @@ var workflow_handoff_kind_exists_default = (0, import_spectral_core6.createRules
60136
60166
  for (let i3 = 0; i3 < steps.length; i3++) {
60137
60167
  const step = steps[i3];
60138
60168
  const stepPath = [...context.path, "steps", i3];
60169
+ if (step.type === "delegate") {
60170
+ if (step.task && !taskKeys.has(step.task)) {
60171
+ results.push({
60172
+ message: `task "${step.task}" does not exist in tasks`,
60173
+ path: [...stepPath, "task"]
60174
+ });
60175
+ }
60176
+ if (step.from_agent && !agentKeys.has(step.from_agent)) {
60177
+ results.push({
60178
+ message: `from_agent "${step.from_agent}" does not exist in agents`,
60179
+ path: [...stepPath, "from_agent"]
60180
+ });
60181
+ }
60182
+ }
60183
+ if (step.type === "gate") {
60184
+ if (step.gate_kind && !handoffKeys.has(step.gate_kind)) {
60185
+ results.push({
60186
+ message: `gate_kind "${step.gate_kind}" does not exist in handoff_types`,
60187
+ path: [...stepPath, "gate_kind"]
60188
+ });
60189
+ }
60190
+ }
60139
60191
  if (step.type === "handoff") {
60140
60192
  if (step.handoff_kind && !handoffKeys.has(step.handoff_kind)) {
60141
60193
  results.push({
@@ -60349,6 +60401,17 @@ var ruleset = {
60349
60401
  functionOptions: { referenceTo: "artifacts" }
60350
60402
  }
60351
60403
  },
60404
+ "task-validations-ref": {
60405
+ description: "Task validations must reference existing validations",
60406
+ message: "{{error}}",
60407
+ severity: "error",
60408
+ given: "$.tasks.*",
60409
+ then: {
60410
+ field: "validations",
60411
+ function: ref_exists_default,
60412
+ functionOptions: { referenceTo: "validations" }
60413
+ }
60414
+ },
60352
60415
  "validation-target-artifact-ref": {
60353
60416
  description: "Validation target_artifact must reference an existing artifact",
60354
60417
  message: "{{error}}",
@@ -60392,7 +60455,7 @@ var ruleset = {
60392
60455
  },
60393
60456
  // ========== 15.2.5 Handoff integrity ==========
60394
60457
  "workflow-step-refs": {
60395
- description: "Workflow step references (handoff_kind, task, from_agent, validation) must exist",
60458
+ description: "Workflow step references (task, from_agent, gate_kind, handoff_kind, validation) must exist",
60396
60459
  message: "{{error}}",
60397
60460
  severity: "error",
60398
60461
  given: "$.workflow.*",
@@ -60694,7 +60757,23 @@ function buildHandoffTypeContext(dsl, handoffTypeId) {
60694
60757
  function buildWorkflowContext(dsl, workflowId) {
60695
60758
  const wfDef = dsl.workflow[workflowId];
60696
60759
  const workflow = { ...wfDef, id: workflowId };
60697
- const relatedTasks = Object.entries(dsl.tasks).filter(([, t3]) => t3.workflow === workflowId).map(([id, t3]) => ({ ...t3, id }));
60760
+ const stepReferencedTaskIds = /* @__PURE__ */ new Set();
60761
+ for (const step of wfDef.steps) {
60762
+ if (step.type === "delegate") {
60763
+ stepReferencedTaskIds.add(step.task);
60764
+ if (step.retry) {
60765
+ stepReferencedTaskIds.add(step.retry.fix_task);
60766
+ if (step.retry.revalidate_task) stepReferencedTaskIds.add(step.retry.revalidate_task);
60767
+ }
60768
+ } else if (step.type === "handoff" && step.task) {
60769
+ stepReferencedTaskIds.add(step.task);
60770
+ if (step.retry) {
60771
+ stepReferencedTaskIds.add(step.retry.fix_task);
60772
+ if (step.retry.revalidate_task) stepReferencedTaskIds.add(step.retry.revalidate_task);
60773
+ }
60774
+ }
60775
+ }
60776
+ const relatedTasks = Object.entries(dsl.tasks).filter(([id, t3]) => t3.workflow === workflowId || stepReferencedTaskIds.has(id)).map(([id, t3]) => ({ ...t3, id }));
60698
60777
  const agentIds = /* @__PURE__ */ new Set();
60699
60778
  for (const task of relatedTasks) {
60700
60779
  agentIds.add(task.target_agent);
@@ -60703,7 +60782,9 @@ function buildWorkflowContext(dsl, workflowId) {
60703
60782
  }
60704
60783
  }
60705
60784
  for (const step of wfDef.steps) {
60706
- if (step.type === "handoff" && step.from_agent) {
60785
+ if (step.type === "delegate") {
60786
+ agentIds.add(step.from_agent);
60787
+ } else if (step.type === "handoff" && step.from_agent) {
60707
60788
  agentIds.add(step.from_agent);
60708
60789
  }
60709
60790
  if (step.type === "validation") {
@@ -60760,6 +60841,11 @@ function buildWorkflowContext(dsl, workflowId) {
60760
60841
  validationIds.add(step.validation);
60761
60842
  }
60762
60843
  }
60844
+ for (const task of relatedTasks) {
60845
+ for (const valId of task.validations ?? []) {
60846
+ validationIds.add(valId);
60847
+ }
60848
+ }
60763
60849
  const relatedValidations = {};
60764
60850
  for (const id of validationIds) {
60765
60851
  if (dsl.validations[id]) relatedValidations[id] = dsl.validations[id];
@@ -60930,33 +61016,34 @@ function collectReferencedIds(workflow, dsl, relatedTasks) {
60930
61016
  const artifacts = /* @__PURE__ */ new Set();
60931
61017
  const taskMap = /* @__PURE__ */ new Map();
60932
61018
  for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
61019
+ function collectTaskIds(task) {
61020
+ addAgent(task.target_agent);
61021
+ for (const es of task.execution_steps ?? []) {
61022
+ collectExecutionStepIds(es, tools, artifacts);
61023
+ }
61024
+ }
61025
+ function collectRetryIds(retry) {
61026
+ const fixTask = taskMap.get(retry.fix_task);
61027
+ if (fixTask) collectTaskIds(fixTask);
61028
+ if (retry.revalidate_task) {
61029
+ const revalTask = taskMap.get(retry.revalidate_task);
61030
+ if (revalTask) addAgent(revalTask.target_agent);
61031
+ }
61032
+ }
60933
61033
  for (const step of workflow.steps) {
60934
- if (step.type === "handoff") {
61034
+ if (step.type === "delegate") {
61035
+ addAgent(step.from_agent);
61036
+ const task = taskMap.get(step.task);
61037
+ if (task) collectTaskIds(task);
61038
+ if (step.retry) collectRetryIds(step.retry);
61039
+ } else if (step.type === "gate") {
61040
+ } else if (step.type === "handoff") {
60935
61041
  if (step.from_agent) addAgent(step.from_agent);
60936
61042
  if (step.task) {
60937
61043
  const task = taskMap.get(step.task);
60938
- if (task) {
60939
- addAgent(task.target_agent);
60940
- for (const es of task.execution_steps ?? []) {
60941
- collectExecutionStepIds(es, tools, artifacts);
60942
- }
60943
- }
60944
- }
60945
- if (step.retry) {
60946
- const fixTask = taskMap.get(step.retry.fix_task);
60947
- if (fixTask) {
60948
- addAgent(fixTask.target_agent);
60949
- for (const es of fixTask.execution_steps ?? []) {
60950
- collectExecutionStepIds(es, tools, artifacts);
60951
- }
60952
- }
60953
- if (step.retry.revalidate_task) {
60954
- const revalTask = taskMap.get(step.retry.revalidate_task);
60955
- if (revalTask) {
60956
- addAgent(revalTask.target_agent);
60957
- }
60958
- }
61044
+ if (task) collectTaskIds(task);
60959
61045
  }
61046
+ if (step.retry) collectRetryIds(step.retry);
60960
61047
  } else if (step.type === "validation") {
60961
61048
  const val = dsl.validations[step.validation];
60962
61049
  if (val) {
@@ -61144,16 +61231,33 @@ function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
61144
61231
  }
61145
61232
  lines.push(`${indent}end`);
61146
61233
  }
61147
- function emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent) {
61148
- const retry = step.retry;
61149
- if (!retry) return;
61234
+ function emitDelegateStep(step, participants, dsl, relatedTasks, lines, indent) {
61235
+ const taskMap = /* @__PURE__ */ new Map();
61236
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
61237
+ const task = taskMap.get(step.task);
61238
+ if (!task) return;
61239
+ const fromAlias = participantAlias(participants, step.from_agent);
61240
+ const targetAlias = participantAlias(participants, task.target_agent);
61241
+ lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
61242
+ for (const es of task.execution_steps ?? []) {
61243
+ emitExecutionStep(es, targetAlias, participants, lines, indent);
61244
+ }
61245
+ lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
61246
+ }
61247
+ function emitGateStep(step, participants, lastFromAgent, lines, indent) {
61248
+ if (lastFromAgent) {
61249
+ const agentAl = participantAlias(participants, lastFromAgent);
61250
+ lines.push(`${indent}${agentAl}->>${agentAl}: ${step.gate_kind}`);
61251
+ }
61252
+ }
61253
+ function emitRetryBlock(fromAgent, retry, participants, relatedTasks, lines, indent) {
61150
61254
  const taskMap = /* @__PURE__ */ new Map();
61151
61255
  for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
61152
61256
  lines.push(`${indent}opt ${retry.condition}`);
61153
61257
  const innerIndent = indent + " ";
61154
61258
  const fixTask = taskMap.get(retry.fix_task);
61155
61259
  if (fixTask) {
61156
- const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
61260
+ const fromAlias = fromAgent ? participantAlias(participants, fromAgent) : null;
61157
61261
  const targetAlias = participantAlias(participants, fixTask.target_agent);
61158
61262
  if (fromAlias) {
61159
61263
  lines.push(`${innerIndent}${fromAlias}->>${targetAlias}: fix ${retry.fix_task}`);
@@ -61168,7 +61272,7 @@ function emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent) {
61168
61272
  if (retry.revalidate_task) {
61169
61273
  const revalTask = taskMap.get(retry.revalidate_task);
61170
61274
  if (revalTask) {
61171
- const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
61275
+ const fromAlias = fromAgent ? participantAlias(participants, fromAgent) : null;
61172
61276
  const revalAlias = participantAlias(participants, revalTask.target_agent);
61173
61277
  if (fromAlias) {
61174
61278
  lines.push(`${innerIndent}${fromAlias}->>${revalAlias}: revalidate ${retry.revalidate_task}`);
@@ -61255,11 +61359,19 @@ function generateSequenceDiagram(workflow, relatedTasks, dsl) {
61255
61359
  return lines.join("\n");
61256
61360
  }
61257
61361
  function emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, setLastFromAgent) {
61258
- if (step.type === "handoff") {
61362
+ if (step.type === "delegate") {
61363
+ setLastFromAgent(step.from_agent);
61364
+ emitDelegateStep(step, participants, dsl, relatedTasks, lines, indent);
61365
+ if (step.retry) {
61366
+ emitRetryBlock(step.from_agent, step.retry, participants, relatedTasks, lines, indent);
61367
+ }
61368
+ } else if (step.type === "gate") {
61369
+ emitGateStep(step, participants, lastFromAgent, lines, indent);
61370
+ } else if (step.type === "handoff") {
61259
61371
  if (step.from_agent) setLastFromAgent(step.from_agent);
61260
61372
  emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
61261
61373
  if (step.retry) {
61262
- emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent);
61374
+ emitRetryBlock(step.from_agent, step.retry, participants, relatedTasks, lines, indent);
61263
61375
  }
61264
61376
  } else if (step.type === "validation") {
61265
61377
  emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
@@ -61280,28 +61392,34 @@ function collectPhaseOps(dsl, wfId) {
61280
61392
  map.get(id).add(op);
61281
61393
  }
61282
61394
  const taskMap = new Map(ctx.relatedTasks.map((t3) => [t3.id, t3]));
61395
+ function collectTaskOps(task) {
61396
+ addOp(agentOps, task.target_agent, "execute");
61397
+ for (const es of task.execution_steps ?? []) {
61398
+ if (es.reads_artifact) addOp(artifactOps, es.reads_artifact, "R");
61399
+ if (es.produces_artifact) addOp(artifactOps, es.produces_artifact, "W");
61400
+ if (es.uses_tool) {
61401
+ const tool = dsl.tools[es.uses_tool];
61402
+ if (tool) {
61403
+ const cats = tool.commands.map((c2) => c2.category).filter((v2, i3, a3) => a3.indexOf(v2) === i3);
61404
+ for (const cat of cats) addOp(toolOps, es.uses_tool, cat);
61405
+ if (cats.length === 0) addOp(toolOps, es.uses_tool, "\u2713");
61406
+ } else {
61407
+ addOp(toolOps, es.uses_tool, "\u2713");
61408
+ }
61409
+ }
61410
+ }
61411
+ }
61283
61412
  for (const step of wf.steps) {
61284
- if (step.type === "handoff") {
61413
+ if (step.type === "delegate") {
61414
+ addOp(agentOps, step.from_agent, "delegate");
61415
+ const task = taskMap.get(step.task);
61416
+ if (task) collectTaskOps(task);
61417
+ } else if (step.type === "gate") {
61418
+ } else if (step.type === "handoff") {
61285
61419
  if (step.from_agent) addOp(agentOps, step.from_agent, "delegate");
61286
61420
  if (step.task) {
61287
61421
  const task = taskMap.get(step.task);
61288
- if (task) {
61289
- addOp(agentOps, task.target_agent, "execute");
61290
- for (const es of task.execution_steps ?? []) {
61291
- if (es.reads_artifact) addOp(artifactOps, es.reads_artifact, "R");
61292
- if (es.produces_artifact) addOp(artifactOps, es.produces_artifact, "W");
61293
- if (es.uses_tool) {
61294
- const tool = dsl.tools[es.uses_tool];
61295
- if (tool) {
61296
- const cats = tool.commands.map((c2) => c2.category).filter((v2, i3, a3) => a3.indexOf(v2) === i3);
61297
- for (const cat of cats) addOp(toolOps, es.uses_tool, cat);
61298
- if (cats.length === 0) addOp(toolOps, es.uses_tool, "\u2713");
61299
- } else {
61300
- addOp(toolOps, es.uses_tool, "\u2713");
61301
- }
61302
- }
61303
- }
61304
- }
61422
+ if (task) collectTaskOps(task);
61305
61423
  }
61306
61424
  } else if (step.type === "validation") {
61307
61425
  const val = dsl.validations[step.validation];