agent-contracts 0.7.0 → 0.8.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/index.js CHANGED
@@ -58399,6 +58399,7 @@ var ExecutionStepSchema = z6.object({
58399
58399
  abort_on_failure: z6.boolean().optional(),
58400
58400
  uses_tool: z6.string().optional(),
58401
58401
  produces_artifact: z6.string().optional(),
58402
+ reads_artifact: z6.string().optional(),
58402
58403
  depends_on: z6.array(z6.string()).optional(),
58403
58404
  skip_condition: z6.string().optional(),
58404
58405
  wait_for_approval: z6.boolean().optional()
@@ -58423,13 +58424,21 @@ var TaskSchema = z6.object({
58423
58424
 
58424
58425
  // src/schema/tool.ts
58425
58426
  import { z as z7 } from "zod";
58427
+ var CommandSchema = z7.object({
58428
+ command: z7.string(),
58429
+ category: z7.string(),
58430
+ reads: z7.array(z7.string()).default([]),
58431
+ writes: z7.array(z7.string()).default([]),
58432
+ purpose: z7.string().optional()
58433
+ });
58426
58434
  var ToolSchema = z7.object({
58427
58435
  kind: z7.string(),
58428
58436
  description: z7.string().optional(),
58429
58437
  input_artifacts: z7.array(z7.string()).default([]),
58430
58438
  output_artifacts: z7.array(z7.string()).default([]),
58431
58439
  invokable_by: z7.array(z7.string()),
58432
- side_effects: z7.array(z7.string()).default([])
58440
+ side_effects: z7.array(z7.string()).default([]),
58441
+ commands: z7.array(CommandSchema).default([])
58433
58442
  }).passthrough();
58434
58443
 
58435
58444
  // src/schema/validation.ts
@@ -58445,23 +58454,38 @@ var ValidationSchema = z8.object({
58445
58454
 
58446
58455
  // src/schema/workflow.ts
58447
58456
  import { z as z9 } from "zod";
58457
+ var RetrySchema = z9.object({
58458
+ condition: z9.string(),
58459
+ fix_task: z9.string(),
58460
+ revalidate_task: z9.string().optional()
58461
+ });
58462
+ var ExternalParticipantSchema = z9.object({
58463
+ id: z9.string(),
58464
+ kind: z9.enum(["actor", "participant"]),
58465
+ label: z9.string(),
58466
+ description: z9.string().optional()
58467
+ });
58448
58468
  var WorkflowHandoffStepSchema = z9.object({
58449
58469
  type: z9.literal("handoff"),
58450
58470
  description: z9.string().optional(),
58451
58471
  handoff_kind: z9.string(),
58452
58472
  task: z9.string().optional(),
58453
- from_agent: z9.string().optional()
58473
+ from_agent: z9.string().optional(),
58474
+ group: z9.string().optional(),
58475
+ retry: RetrySchema.optional()
58454
58476
  }).passthrough();
58455
58477
  var WorkflowValidationStepSchema = z9.object({
58456
58478
  type: z9.literal("validation"),
58457
58479
  description: z9.string().optional(),
58458
- validation: z9.string()
58480
+ validation: z9.string(),
58481
+ group: z9.string().optional()
58459
58482
  }).passthrough();
58460
58483
  var WorkflowDecisionStepSchema = z9.object({
58461
58484
  type: z9.literal("decision"),
58462
58485
  description: z9.string().optional(),
58463
58486
  on: z9.string(),
58464
- branches: z9.record(z9.string(), z9.array(z9.string()))
58487
+ branches: z9.record(z9.string(), z9.array(z9.string())),
58488
+ group: z9.string().optional()
58465
58489
  }).passthrough();
58466
58490
  var WorkflowStepSchema = z9.discriminatedUnion("type", [
58467
58491
  WorkflowHandoffStepSchema,
@@ -58469,9 +58493,11 @@ var WorkflowStepSchema = z9.discriminatedUnion("type", [
58469
58493
  WorkflowDecisionStepSchema
58470
58494
  ]);
58471
58495
  var WorkflowSchema = z9.object({
58496
+ description: z9.string().optional(),
58472
58497
  entry_conditions: z9.array(z9.string()).default([]),
58473
58498
  trigger: z9.string().optional(),
58474
- steps: z9.array(WorkflowStepSchema)
58499
+ steps: z9.array(WorkflowStepSchema),
58500
+ external_participants: z9.array(ExternalParticipantSchema).default([])
58475
58501
  }).passthrough();
58476
58502
 
58477
58503
  // src/schema/dsl.ts
@@ -59553,6 +59579,16 @@ var taskAgentBindingRule = {
59553
59579
  });
59554
59580
  }
59555
59581
  }
59582
+ if (step.reads_artifact) {
59583
+ if (!targetAgent.can_read_artifacts.includes(step.reads_artifact)) {
59584
+ diagnostics.push({
59585
+ ruleId: "task-agent-binding",
59586
+ severity: "error",
59587
+ path: `tasks.${taskId}.execution_steps`,
59588
+ message: `Task "${taskId}" step reads_artifact "${step.reads_artifact}" not in target agent "${task.target_agent}" can_read_artifacts`
59589
+ });
59590
+ }
59591
+ }
59556
59592
  }
59557
59593
  }
59558
59594
  return diagnostics;
@@ -59582,12 +59618,100 @@ var mergeIntegrityRule = {
59582
59618
  }
59583
59619
  };
59584
59620
 
59621
+ // src/linter/rules/artifact-ownership.ts
59622
+ var artifactOwnershipRule = {
59623
+ id: "artifact-ownership",
59624
+ description: "Ensure execution_step produces/reads operations are consistent with artifact producers/editors/consumers",
59625
+ run(dsl) {
59626
+ const diagnostics = [];
59627
+ for (const [taskId, task] of Object.entries(dsl.tasks)) {
59628
+ if (!task.execution_steps) continue;
59629
+ const agentId = task.target_agent;
59630
+ for (const step of task.execution_steps) {
59631
+ if (step.produces_artifact) {
59632
+ const artifact = dsl.artifacts[step.produces_artifact];
59633
+ if (artifact) {
59634
+ const canWrite = artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
59635
+ if (!canWrite) {
59636
+ diagnostics.push({
59637
+ ruleId: "artifact-ownership",
59638
+ severity: "warning",
59639
+ path: `tasks.${taskId}.execution_steps`,
59640
+ message: `Agent "${agentId}" produces artifact "${step.produces_artifact}" but is not listed in its producers or editors`
59641
+ });
59642
+ }
59643
+ }
59644
+ }
59645
+ if (step.reads_artifact) {
59646
+ const artifact = dsl.artifacts[step.reads_artifact];
59647
+ if (artifact) {
59648
+ const canRead = artifact.consumers.includes(agentId) || artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
59649
+ if (!canRead) {
59650
+ diagnostics.push({
59651
+ ruleId: "artifact-ownership",
59652
+ severity: "warning",
59653
+ path: `tasks.${taskId}.execution_steps`,
59654
+ message: `Agent "${agentId}" reads artifact "${step.reads_artifact}" but is not listed in its producers, editors, or consumers`
59655
+ });
59656
+ }
59657
+ }
59658
+ }
59659
+ }
59660
+ }
59661
+ return diagnostics;
59662
+ }
59663
+ };
59664
+
59665
+ // src/linter/rules/tool-commands.ts
59666
+ var toolCommandsRule = {
59667
+ id: "tool-commands",
59668
+ description: "Validate tool commands: reads/writes reference existing artifacts; writes align with output_artifacts",
59669
+ run(dsl) {
59670
+ const diagnostics = [];
59671
+ for (const [toolId, tool] of Object.entries(dsl.tools)) {
59672
+ for (const cmd of tool.commands) {
59673
+ for (const ref of cmd.reads) {
59674
+ if (!dsl.artifacts[ref]) {
59675
+ diagnostics.push({
59676
+ ruleId: "tool-commands",
59677
+ severity: "error",
59678
+ path: `tools.${toolId}.commands`,
59679
+ message: `Command "${cmd.command}" reads artifact "${ref}" which does not exist`
59680
+ });
59681
+ }
59682
+ }
59683
+ for (const ref of cmd.writes) {
59684
+ if (!dsl.artifacts[ref]) {
59685
+ diagnostics.push({
59686
+ ruleId: "tool-commands",
59687
+ severity: "error",
59688
+ path: `tools.${toolId}.commands`,
59689
+ message: `Command "${cmd.command}" writes artifact "${ref}" which does not exist`
59690
+ });
59691
+ }
59692
+ if (dsl.artifacts[ref] && !tool.output_artifacts.includes(ref)) {
59693
+ diagnostics.push({
59694
+ ruleId: "tool-commands",
59695
+ severity: "warning",
59696
+ path: `tools.${toolId}.commands`,
59697
+ message: `Command "${cmd.command}" writes artifact "${ref}" but tool's output_artifacts does not include it`
59698
+ });
59699
+ }
59700
+ }
59701
+ }
59702
+ }
59703
+ return diagnostics;
59704
+ }
59705
+ };
59706
+
59585
59707
  // src/linter/linter.ts
59586
59708
  var builtinRules = [
59587
59709
  validationCoverageRule,
59588
59710
  toolExecutionRule,
59589
59711
  taskAgentBindingRule,
59590
- mergeIntegrityRule
59712
+ mergeIntegrityRule,
59713
+ artifactOwnershipRule,
59714
+ toolCommandsRule
59591
59715
  ];
59592
59716
  function lint(dsl, rules = builtinRules) {
59593
59717
  const diagnostics = [];
@@ -60315,6 +60439,11 @@ function buildWorkflowContext(dsl, workflowId) {
60315
60439
  }
60316
60440
  }
60317
60441
  }
60442
+ for (const task of relatedTasks) {
60443
+ for (const step of task.execution_steps ?? []) {
60444
+ if (step.uses_tool) toolIds.add(step.uses_tool);
60445
+ }
60446
+ }
60318
60447
  const relatedTools = {};
60319
60448
  for (const id of toolIds) {
60320
60449
  if (dsl.tools[id]) relatedTools[id] = dsl.tools[id];
@@ -60322,6 +60451,10 @@ function buildWorkflowContext(dsl, workflowId) {
60322
60451
  const artifactIds = /* @__PURE__ */ new Set();
60323
60452
  for (const task of relatedTasks) {
60324
60453
  for (const artId of task.input_artifacts) artifactIds.add(artId);
60454
+ for (const step of task.execution_steps ?? []) {
60455
+ if (step.produces_artifact) artifactIds.add(step.produces_artifact);
60456
+ if (step.reads_artifact) artifactIds.add(step.reads_artifact);
60457
+ }
60325
60458
  }
60326
60459
  for (const id of agentIds) {
60327
60460
  const agent = dsl.agents[id];
@@ -60465,6 +60598,508 @@ function buildPerAgentContext(dsl, agent) {
60465
60598
  };
60466
60599
  }
60467
60600
 
60601
+ // src/renderer/sequence-diagram.ts
60602
+ function hashToColor(s2, saturation, lightness) {
60603
+ let hash = 0;
60604
+ for (const ch of s2) hash = (hash << 5) - hash + ch.charCodeAt(0) | 0;
60605
+ const h2 = (hash % 360 + 360) % 360;
60606
+ const c2 = (1 - Math.abs(2 * lightness - 1)) * saturation;
60607
+ const x3 = c2 * (1 - Math.abs(h2 / 60 % 2 - 1));
60608
+ const m2 = lightness - c2 / 2;
60609
+ let r3 = 0, g2 = 0, b3 = 0;
60610
+ if (h2 < 60) {
60611
+ r3 = c2;
60612
+ g2 = x3;
60613
+ } else if (h2 < 120) {
60614
+ r3 = x3;
60615
+ g2 = c2;
60616
+ } else if (h2 < 180) {
60617
+ g2 = c2;
60618
+ b3 = x3;
60619
+ } else if (h2 < 240) {
60620
+ g2 = x3;
60621
+ b3 = c2;
60622
+ } else if (h2 < 300) {
60623
+ r3 = x3;
60624
+ b3 = c2;
60625
+ } else {
60626
+ r3 = c2;
60627
+ b3 = x3;
60628
+ }
60629
+ return `rgb(${Math.round((r3 + m2) * 255)},${Math.round((g2 + m2) * 255)},${Math.round((b3 + m2) * 255)})`;
60630
+ }
60631
+ function sanitizeAlias(id) {
60632
+ return id.replace(/[^a-zA-Z0-9_]/g, "_");
60633
+ }
60634
+ function agentAlias(id, agent) {
60635
+ const words = agent.role_name.split(/\s+/);
60636
+ if (words.length === 1) return sanitizeAlias(words[0].slice(0, 4));
60637
+ return sanitizeAlias(words.map((w2) => w2[0]).join(""));
60638
+ }
60639
+ function collectReferencedIds(workflow, dsl, relatedTasks) {
60640
+ const agents = /* @__PURE__ */ new Set();
60641
+ const auditAgents = /* @__PURE__ */ new Set();
60642
+ const tools = /* @__PURE__ */ new Set();
60643
+ const artifacts = /* @__PURE__ */ new Set();
60644
+ const taskMap = /* @__PURE__ */ new Map();
60645
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60646
+ for (const step of workflow.steps) {
60647
+ if (step.type === "handoff") {
60648
+ if (step.from_agent) addAgent(step.from_agent);
60649
+ if (step.task) {
60650
+ const task = taskMap.get(step.task);
60651
+ if (task) {
60652
+ addAgent(task.target_agent);
60653
+ for (const es of task.execution_steps ?? []) {
60654
+ collectExecutionStepIds(es, tools, artifacts);
60655
+ }
60656
+ }
60657
+ }
60658
+ if (step.retry) {
60659
+ const fixTask = taskMap.get(step.retry.fix_task);
60660
+ if (fixTask) {
60661
+ addAgent(fixTask.target_agent);
60662
+ for (const es of fixTask.execution_steps ?? []) {
60663
+ collectExecutionStepIds(es, tools, artifacts);
60664
+ }
60665
+ }
60666
+ if (step.retry.revalidate_task) {
60667
+ const revalTask = taskMap.get(step.retry.revalidate_task);
60668
+ if (revalTask) {
60669
+ addAgent(revalTask.target_agent);
60670
+ }
60671
+ }
60672
+ }
60673
+ } else if (step.type === "validation") {
60674
+ const val = dsl.validations[step.validation];
60675
+ if (val) {
60676
+ if (val.executor_type === "agent") addAgent(val.executor);
60677
+ else tools.add(val.executor);
60678
+ artifacts.add(val.target_artifact);
60679
+ }
60680
+ }
60681
+ }
60682
+ function addAgent(agentId) {
60683
+ const agent = dsl.agents[agentId];
60684
+ if (agent?.mode === "read-only") {
60685
+ auditAgents.add(agentId);
60686
+ } else {
60687
+ agents.add(agentId);
60688
+ }
60689
+ }
60690
+ return { agents, auditAgents, tools, artifacts };
60691
+ }
60692
+ function collectExecutionStepIds(es, tools, artifacts) {
60693
+ if (es.uses_tool) tools.add(es.uses_tool);
60694
+ if (es.produces_artifact) artifacts.add(es.produces_artifact);
60695
+ if (es.reads_artifact) artifacts.add(es.reads_artifact);
60696
+ }
60697
+ function buildParticipants(ids, externals, dsl) {
60698
+ const participants = [];
60699
+ const usedAliases = /* @__PURE__ */ new Set();
60700
+ function uniqueAlias(preferred) {
60701
+ let alias = preferred;
60702
+ let i3 = 2;
60703
+ while (usedAliases.has(alias)) {
60704
+ alias = `${preferred}${i3}`;
60705
+ i3++;
60706
+ }
60707
+ usedAliases.add(alias);
60708
+ return alias;
60709
+ }
60710
+ for (const ep of externals) {
60711
+ const alias = uniqueAlias(sanitizeAlias(ep.id));
60712
+ participants.push({ id: ep.id, alias, label: ep.label, group: "external" });
60713
+ }
60714
+ for (const id of ids.agents) {
60715
+ const agent = dsl.agents[id];
60716
+ if (!agent) continue;
60717
+ const alias = uniqueAlias(agentAlias(id, agent));
60718
+ participants.push({ id, alias, label: agent.role_name, group: "agents" });
60719
+ }
60720
+ for (const id of ids.auditAgents) {
60721
+ const agent = dsl.agents[id];
60722
+ if (!agent) continue;
60723
+ const alias = uniqueAlias(agentAlias(id, agent));
60724
+ participants.push({ id, alias, label: agent.role_name, group: "audit" });
60725
+ }
60726
+ for (const id of ids.tools) {
60727
+ const tool = dsl.tools[id];
60728
+ if (!tool) continue;
60729
+ const alias = uniqueAlias(sanitizeAlias(id));
60730
+ participants.push({ id, alias, label: id, group: "toolchain" });
60731
+ }
60732
+ for (const id of ids.artifacts) {
60733
+ const art = dsl.artifacts[id];
60734
+ if (!art) continue;
60735
+ const alias = uniqueAlias(sanitizeAlias(id));
60736
+ participants.push({ id, alias, label: id, group: "artifacts" });
60737
+ }
60738
+ return participants;
60739
+ }
60740
+ function participantAlias(participants, id) {
60741
+ const p2 = participants.find((pp) => pp.id === id);
60742
+ return p2 ? p2.alias : sanitizeAlias(id);
60743
+ }
60744
+ function emitParticipants(participants, externals, lines, indent) {
60745
+ const groups = {
60746
+ external: [],
60747
+ agents: [],
60748
+ audit: [],
60749
+ toolchain: [],
60750
+ artifacts: []
60751
+ };
60752
+ for (const p2 of participants) groups[p2.group].push(p2);
60753
+ const externalMap = /* @__PURE__ */ new Map();
60754
+ for (const ep of externals) externalMap.set(ep.id, ep);
60755
+ if (groups.external.length > 0) {
60756
+ lines.push(`${indent}box rgb(255,245,230) External`);
60757
+ for (const p2 of groups.external) {
60758
+ const ep = externalMap.get(p2.id);
60759
+ const keyword = ep?.kind === "actor" ? "actor" : "participant";
60760
+ if (p2.alias === p2.label) {
60761
+ lines.push(`${indent}${keyword} ${p2.alias}`);
60762
+ } else {
60763
+ lines.push(`${indent}${keyword} ${p2.alias} as ${p2.label}`);
60764
+ }
60765
+ }
60766
+ lines.push(`${indent}end`);
60767
+ }
60768
+ const groupConfig = [
60769
+ { key: "agents", label: "Agents", color: "rgb(200,220,255)" },
60770
+ { key: "audit", label: "Audit", color: "rgb(255,220,220)" },
60771
+ { key: "toolchain", label: "Toolchain", color: "rgb(220,255,220)" },
60772
+ { key: "artifacts", label: "Artifacts", color: "rgb(255,230,210)" }
60773
+ ];
60774
+ for (const { key, label, color } of groupConfig) {
60775
+ const members = groups[key];
60776
+ if (members.length === 0) continue;
60777
+ lines.push(`${indent}box ${color} ${label}`);
60778
+ for (const p2 of members) {
60779
+ if (p2.alias === p2.label) {
60780
+ lines.push(`${indent}participant ${p2.alias}`);
60781
+ } else {
60782
+ lines.push(`${indent}participant ${p2.alias} as ${p2.label}`);
60783
+ }
60784
+ }
60785
+ lines.push(`${indent}end`);
60786
+ }
60787
+ }
60788
+ function emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent) {
60789
+ const taskMap = /* @__PURE__ */ new Map();
60790
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60791
+ if (!step.task) {
60792
+ if (step.from_agent) {
60793
+ const fromAlias2 = participantAlias(participants, step.from_agent);
60794
+ lines.push(`${indent}${fromAlias2}->>${fromAlias2}: ${step.handoff_kind}`);
60795
+ }
60796
+ return;
60797
+ }
60798
+ const task = taskMap.get(step.task);
60799
+ if (!task) return;
60800
+ const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
60801
+ const targetAlias = participantAlias(participants, task.target_agent);
60802
+ if (fromAlias) {
60803
+ lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
60804
+ }
60805
+ for (const es of task.execution_steps ?? []) {
60806
+ emitExecutionStep(es, targetAlias, participants, lines, indent);
60807
+ }
60808
+ if (fromAlias) {
60809
+ lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
60810
+ }
60811
+ }
60812
+ function emitExecutionStep(es, agentAlias2, participants, lines, indent) {
60813
+ if (es.reads_artifact) {
60814
+ const artAlias = participantAlias(participants, es.reads_artifact);
60815
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [R] ${es.action}`);
60816
+ }
60817
+ if (es.produces_artifact) {
60818
+ const artAlias = participantAlias(participants, es.produces_artifact);
60819
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [W] ${es.action}`);
60820
+ }
60821
+ if (es.uses_tool) {
60822
+ const toolAlias = participantAlias(participants, es.uses_tool);
60823
+ lines.push(`${indent}${agentAlias2}->>${toolAlias}: ${es.action}`);
60824
+ }
60825
+ if (!es.reads_artifact && !es.produces_artifact && !es.uses_tool) {
60826
+ lines.push(`${indent}${agentAlias2}->>${agentAlias2}: ${es.action}`);
60827
+ }
60828
+ }
60829
+ function emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent) {
60830
+ const val = dsl.validations[step.validation];
60831
+ if (!val) return;
60832
+ const executorAlias = participantAlias(participants, val.executor);
60833
+ const artifactAlias = participantAlias(participants, val.target_artifact);
60834
+ const fromAlias = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
60835
+ if (fromAlias && fromAlias !== executorAlias) {
60836
+ lines.push(`${indent}${fromAlias}->>${executorAlias}: ${step.validation}`);
60837
+ }
60838
+ lines.push(`${indent}${executorAlias}->>${artifactAlias}: [R] ${val.target_artifact}`);
60839
+ if (fromAlias && fromAlias !== executorAlias) {
60840
+ lines.push(`${indent}${executorAlias}-->>${fromAlias}: results`);
60841
+ }
60842
+ }
60843
+ function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
60844
+ const branches = Object.entries(step.branches);
60845
+ if (branches.length === 0) return;
60846
+ const agentAl = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
60847
+ for (let i3 = 0; i3 < branches.length; i3++) {
60848
+ const [key, values] = branches[i3];
60849
+ if (i3 === 0) {
60850
+ lines.push(`${indent}alt ${key}`);
60851
+ } else {
60852
+ lines.push(`${indent}else ${key}`);
60853
+ }
60854
+ if (agentAl) {
60855
+ lines.push(`${indent} Note over ${agentAl}: ${values.join(", ")}`);
60856
+ }
60857
+ }
60858
+ lines.push(`${indent}end`);
60859
+ }
60860
+ function emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent) {
60861
+ const retry = step.retry;
60862
+ if (!retry) return;
60863
+ const taskMap = /* @__PURE__ */ new Map();
60864
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60865
+ lines.push(`${indent}opt ${retry.condition}`);
60866
+ const innerIndent = indent + " ";
60867
+ const fixTask = taskMap.get(retry.fix_task);
60868
+ if (fixTask) {
60869
+ const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
60870
+ const targetAlias = participantAlias(participants, fixTask.target_agent);
60871
+ if (fromAlias) {
60872
+ lines.push(`${innerIndent}${fromAlias}->>${targetAlias}: fix ${retry.fix_task}`);
60873
+ }
60874
+ for (const es of fixTask.execution_steps ?? []) {
60875
+ emitExecutionStep(es, targetAlias, participants, lines, innerIndent);
60876
+ }
60877
+ if (fromAlias) {
60878
+ lines.push(`${innerIndent}${targetAlias}-->>${fromAlias}: ${fixTask.result_handoff}`);
60879
+ }
60880
+ }
60881
+ if (retry.revalidate_task) {
60882
+ const revalTask = taskMap.get(retry.revalidate_task);
60883
+ if (revalTask) {
60884
+ const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
60885
+ const revalAlias = participantAlias(participants, revalTask.target_agent);
60886
+ if (fromAlias) {
60887
+ lines.push(`${innerIndent}${fromAlias}->>${revalAlias}: revalidate ${retry.revalidate_task}`);
60888
+ lines.push(`${innerIndent}${revalAlias}-->>${fromAlias}: ${revalTask.result_handoff}`);
60889
+ }
60890
+ }
60891
+ }
60892
+ lines.push(`${indent}end`);
60893
+ }
60894
+ function groupSteps(steps) {
60895
+ const result = [];
60896
+ let currentGroup = null;
60897
+ for (let i3 = 0; i3 < steps.length; i3++) {
60898
+ const step = steps[i3];
60899
+ const group = "group" in step ? step.group : void 0;
60900
+ if (group) {
60901
+ if (currentGroup && currentGroup.group === group) {
60902
+ currentGroup.steps.push({ step, index: i3 });
60903
+ } else {
60904
+ if (currentGroup) result.push(currentGroup);
60905
+ currentGroup = { group, steps: [{ step, index: i3 }] };
60906
+ }
60907
+ } else {
60908
+ if (currentGroup) {
60909
+ result.push(currentGroup);
60910
+ currentGroup = null;
60911
+ }
60912
+ result.push({ group: null, steps: [{ step, index: i3 }] });
60913
+ }
60914
+ }
60915
+ if (currentGroup) result.push(currentGroup);
60916
+ return result;
60917
+ }
60918
+ function generateSequenceDiagram(workflow, relatedTasks, dsl) {
60919
+ const ids = collectReferencedIds(workflow, dsl, relatedTasks);
60920
+ const externals = workflow.external_participants ?? [];
60921
+ const participants = buildParticipants(ids, externals, dsl);
60922
+ const lines = [];
60923
+ const indent = " ";
60924
+ lines.push("sequenceDiagram");
60925
+ emitParticipants(participants, externals, lines, indent);
60926
+ lines.push("");
60927
+ lines.push(`${indent}rect ${hashToColor(workflow.id, 0.15, 0.95)}`);
60928
+ const firstP = participants[0];
60929
+ const lastP = participants[participants.length - 1];
60930
+ if (firstP && lastP) {
60931
+ const noteLabel = workflow.description ? `${workflow.id} \u2014 ${workflow.description}` : workflow.id;
60932
+ lines.push(`${indent}Note over ${firstP.alias},${lastP.alias}: ${noteLabel}`);
60933
+ }
60934
+ if (workflow.trigger && externals.some((ep) => ep.kind === "actor")) {
60935
+ const actor = externals.find((ep) => ep.kind === "actor");
60936
+ const actorAlias = participantAlias(participants, actor.id);
60937
+ const firstAgent = participants.find((p2) => p2.group === "agents" || p2.group === "audit");
60938
+ if (firstAgent) {
60939
+ lines.push(`${indent}${actorAlias}->>${firstAgent.alias}: ${workflow.trigger}`);
60940
+ }
60941
+ }
60942
+ let lastFromAgent;
60943
+ const grouped = groupSteps(workflow.steps);
60944
+ for (const g2 of grouped) {
60945
+ if (g2.group && g2.steps.length > 1) {
60946
+ lines.push("");
60947
+ lines.push(`${indent}par ${g2.group}`);
60948
+ const parIndent = indent + " ";
60949
+ for (let i3 = 0; i3 < g2.steps.length; i3++) {
60950
+ const { step } = g2.steps[i3];
60951
+ if (i3 > 0) lines.push(`${indent}and`);
60952
+ emitStep(step, participants, dsl, relatedTasks, lines, parIndent, lastFromAgent, (a3) => {
60953
+ lastFromAgent = a3;
60954
+ });
60955
+ }
60956
+ lines.push(`${indent}end`);
60957
+ } else {
60958
+ for (const { step } of g2.steps) {
60959
+ lines.push("");
60960
+ emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, (a3) => {
60961
+ lastFromAgent = a3;
60962
+ });
60963
+ }
60964
+ }
60965
+ }
60966
+ lines.push("");
60967
+ lines.push(`${indent}end`);
60968
+ return lines.join("\n");
60969
+ }
60970
+ function emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, setLastFromAgent) {
60971
+ if (step.type === "handoff") {
60972
+ if (step.from_agent) setLastFromAgent(step.from_agent);
60973
+ emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
60974
+ if (step.retry) {
60975
+ emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent);
60976
+ }
60977
+ } else if (step.type === "validation") {
60978
+ emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
60979
+ } else if (step.type === "decision") {
60980
+ emitDecisionStep(step, participants, lastFromAgent, lines, indent);
60981
+ }
60982
+ }
60983
+
60984
+ // src/renderer/overview-flowchart.ts
60985
+ function collectPhaseOps(dsl, wfId) {
60986
+ const ctx = buildWorkflowContext(dsl, wfId);
60987
+ const wf = dsl.workflow[wfId];
60988
+ const agentOps = /* @__PURE__ */ new Map();
60989
+ const artifactOps = /* @__PURE__ */ new Map();
60990
+ const toolOps = /* @__PURE__ */ new Map();
60991
+ function addOp(map, id, op) {
60992
+ if (!map.has(id)) map.set(id, /* @__PURE__ */ new Set());
60993
+ map.get(id).add(op);
60994
+ }
60995
+ const taskMap = new Map(ctx.relatedTasks.map((t3) => [t3.id, t3]));
60996
+ for (const step of wf.steps) {
60997
+ if (step.type === "handoff") {
60998
+ if (step.from_agent) addOp(agentOps, step.from_agent, "delegate");
60999
+ if (step.task) {
61000
+ const task = taskMap.get(step.task);
61001
+ if (task) {
61002
+ addOp(agentOps, task.target_agent, "execute");
61003
+ for (const es of task.execution_steps ?? []) {
61004
+ if (es.reads_artifact) addOp(artifactOps, es.reads_artifact, "R");
61005
+ if (es.produces_artifact) addOp(artifactOps, es.produces_artifact, "W");
61006
+ if (es.uses_tool) {
61007
+ const tool = dsl.tools[es.uses_tool];
61008
+ if (tool) {
61009
+ const cats = tool.commands.map((c2) => c2.category).filter((v2, i3, a3) => a3.indexOf(v2) === i3);
61010
+ for (const cat of cats) addOp(toolOps, es.uses_tool, cat);
61011
+ if (cats.length === 0) addOp(toolOps, es.uses_tool, "\u2713");
61012
+ } else {
61013
+ addOp(toolOps, es.uses_tool, "\u2713");
61014
+ }
61015
+ }
61016
+ }
61017
+ }
61018
+ }
61019
+ } else if (step.type === "validation") {
61020
+ const val = dsl.validations[step.validation];
61021
+ if (val) {
61022
+ if (val.executor_type === "agent") {
61023
+ addOp(agentOps, val.executor, "validate");
61024
+ } else {
61025
+ addOp(toolOps, val.executor, "verification");
61026
+ }
61027
+ addOp(artifactOps, val.target_artifact, "V");
61028
+ }
61029
+ }
61030
+ }
61031
+ return { agentOps, artifactOps, toolOps };
61032
+ }
61033
+ function formatOps(ops) {
61034
+ if (!ops || ops.size === 0) return "\u2014";
61035
+ return [...ops].join(", ");
61036
+ }
61037
+ function buildTable(header, rows) {
61038
+ const lines = [];
61039
+ lines.push("| " + header.join(" | ") + " |");
61040
+ lines.push("|" + header.map(() => "---").join("|") + "|");
61041
+ for (const row of rows) {
61042
+ lines.push("| " + row.join(" | ") + " |");
61043
+ }
61044
+ return lines.join("\n");
61045
+ }
61046
+ function generateOverviewFlowchart(dsl) {
61047
+ const workflowOrder = dsl.system.default_workflow_order ?? Object.keys(dsl.workflow);
61048
+ const phases = workflowOrder.filter((id) => dsl.workflow[id]);
61049
+ const phaseData = /* @__PURE__ */ new Map();
61050
+ for (const wfId of phases) {
61051
+ phaseData.set(wfId, collectPhaseOps(dsl, wfId));
61052
+ }
61053
+ const allAgentIds = /* @__PURE__ */ new Set();
61054
+ const allArtifactIds = /* @__PURE__ */ new Set();
61055
+ const allToolIds = /* @__PURE__ */ new Set();
61056
+ for (const ops of phaseData.values()) {
61057
+ for (const id of ops.agentOps.keys()) allAgentIds.add(id);
61058
+ for (const id of ops.artifactOps.keys()) allArtifactIds.add(id);
61059
+ for (const id of ops.toolOps.keys()) allToolIds.add(id);
61060
+ }
61061
+ const sections = [];
61062
+ if (allAgentIds.size > 0) {
61063
+ const header = ["Agent", ...phases];
61064
+ const rows = [];
61065
+ for (const agentId of allAgentIds) {
61066
+ const agent = dsl.agents[agentId];
61067
+ const label = agent ? agent.role_name : agentId;
61068
+ const row = [label];
61069
+ for (const wfId of phases) {
61070
+ row.push(formatOps(phaseData.get(wfId).agentOps.get(agentId)));
61071
+ }
61072
+ rows.push(row);
61073
+ }
61074
+ sections.push("#### Agent \xD7 Phase\n\n" + buildTable(header, rows));
61075
+ }
61076
+ if (allArtifactIds.size > 0) {
61077
+ const header = ["Artifact", ...phases];
61078
+ const rows = [];
61079
+ for (const artId of allArtifactIds) {
61080
+ const row = [artId];
61081
+ for (const wfId of phases) {
61082
+ row.push(formatOps(phaseData.get(wfId).artifactOps.get(artId)));
61083
+ }
61084
+ rows.push(row);
61085
+ }
61086
+ sections.push("#### Artifact \xD7 Phase\n\n" + buildTable(header, rows));
61087
+ }
61088
+ if (allToolIds.size > 0) {
61089
+ const header = ["Tool", ...phases];
61090
+ const rows = [];
61091
+ for (const toolId of allToolIds) {
61092
+ const row = [toolId];
61093
+ for (const wfId of phases) {
61094
+ row.push(formatOps(phaseData.get(wfId).toolOps.get(toolId)));
61095
+ }
61096
+ rows.push(row);
61097
+ }
61098
+ sections.push("#### Tool \xD7 Phase\n\n" + buildTable(header, rows));
61099
+ }
61100
+ return sections.join("\n\n");
61101
+ }
61102
+
60468
61103
  // src/renderer/renderer.ts
60469
61104
  Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
60470
61105
  Handlebars.registerHelper("notEmpty", (obj) => {
@@ -60626,6 +61261,41 @@ Handlebars.registerHelper("size", (obj) => {
60626
61261
  if (obj && typeof obj === "object") return Object.keys(obj).length;
60627
61262
  return 0;
60628
61263
  });
61264
+ Handlebars.registerHelper(
61265
+ "sequenceDiagram",
61266
+ function(...args) {
61267
+ const opts = args[args.length - 1];
61268
+ const positionalArgs = args.slice(0, -1);
61269
+ if (typeof positionalArgs[0] === "string" && positionalArgs[1]) {
61270
+ const workflowId = positionalArgs[0];
61271
+ const dsl2 = positionalArgs[1];
61272
+ if (!dsl2.workflow[workflowId]) return "";
61273
+ const ctx = buildWorkflowContext(dsl2, workflowId);
61274
+ return generateSequenceDiagram(
61275
+ ctx.workflow,
61276
+ ctx.relatedTasks,
61277
+ dsl2
61278
+ );
61279
+ }
61280
+ const workflow = this["workflow"];
61281
+ const relatedTasks = this["relatedTasks"];
61282
+ const dsl = opts?.hash?.["dsl"] ?? this["dsl"];
61283
+ if (!workflow || !dsl) return "";
61284
+ return generateSequenceDiagram(workflow, relatedTasks ?? [], dsl);
61285
+ }
61286
+ );
61287
+ Handlebars.registerHelper(
61288
+ "overviewFlowchart",
61289
+ function(...args) {
61290
+ const positionalArgs = args.slice(0, -1);
61291
+ if (positionalArgs[0] && typeof positionalArgs[0] === "object") {
61292
+ return generateOverviewFlowchart(positionalArgs[0]);
61293
+ }
61294
+ const dsl = this["dsl"];
61295
+ if (!dsl) return "";
61296
+ return generateOverviewFlowchart(dsl);
61297
+ }
61298
+ );
60629
61299
  function getDslSection(dsl, context) {
60630
61300
  const sectionMap = {
60631
61301
  agent: dsl.agents,
@@ -60867,6 +61537,7 @@ export {
60867
61537
  ArtifactSchema,
60868
61538
  BaseResolveError,
60869
61539
  CONTEXT_TYPES,
61540
+ CommandSchema,
60870
61541
  ConfigLoadError,
60871
61542
  ContextTypeSchema,
60872
61543
  DslLoadError,