agent-contracts 0.23.2 → 0.24.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
@@ -49713,15 +49713,20 @@ import { z as z2 } from "zod";
49713
49713
  var ArtifactSchema = z2.object({
49714
49714
  type: z2.string(),
49715
49715
  description: z2.string().optional(),
49716
- owner: z2.string(),
49717
- producers: z2.array(z2.string()),
49718
- editors: z2.array(z2.string()),
49719
- consumers: z2.array(z2.string()),
49720
- states: z2.array(z2.string()),
49716
+ owner: z2.string().optional(),
49717
+ producers: z2.array(z2.string()).default([]),
49718
+ editors: z2.array(z2.string()).default([]),
49719
+ consumers: z2.array(z2.string()).default([]),
49720
+ states: z2.array(z2.string()).default([]),
49721
49721
  required_validations: z2.array(z2.string()).default([]),
49722
49722
  visibility: z2.string().optional(),
49723
49723
  classification: z2.string().optional(),
49724
- guardrails: z2.array(z2.string()).optional()
49724
+ guardrails: z2.array(z2.string()).optional(),
49725
+ authority: z2.enum(["canonical", "derived", "generated", "control"]).optional(),
49726
+ path_patterns: z2.array(z2.string()).optional(),
49727
+ exclude_patterns: z2.array(z2.string()).optional(),
49728
+ manual_edit: z2.enum(["allowed", "discouraged", "forbidden"]).optional(),
49729
+ change_control: z2.enum(["none", "approval-required", "regeneration-required"]).optional()
49725
49730
  }).passthrough();
49726
49731
 
49727
49732
  // src/schema/binding.ts
@@ -49984,7 +49989,7 @@ var ToolSchema = z12.object({
49984
49989
  description: z12.string().optional(),
49985
49990
  input_artifacts: z12.array(z12.string()).default([]),
49986
49991
  output_artifacts: z12.array(z12.string()).default([]),
49987
- invokable_by: z12.array(z12.string()),
49992
+ invokable_by: z12.array(z12.string()).default([]),
49988
49993
  side_effects: z12.array(z12.string()).default([]),
49989
49994
  commands: z12.array(CommandSchema).default([]),
49990
49995
  guardrails: z12.array(z12.string()).optional()
@@ -52118,28 +52123,38 @@ function checkReferences(dsl) {
52118
52123
  }
52119
52124
  }
52120
52125
  for (const [id, art] of Object.entries(dsl.artifacts)) {
52121
- checkExists(art.owner, agentIds, "agents", `artifacts.${id}.owner`);
52122
- for (const ref of art.producers) {
52123
- checkExists(ref, agentIds, "agents", `artifacts.${id}.producers`);
52126
+ if (art.owner) {
52127
+ checkExists(art.owner, agentIds, "agents", `artifacts.${id}.owner`);
52124
52128
  }
52125
- for (const ref of art.editors) {
52126
- checkExists(ref, agentIds, "agents", `artifacts.${id}.editors`);
52129
+ if (art.producers.length > 0) {
52130
+ for (const ref of art.producers) {
52131
+ checkExists(ref, agentIds, "agents", `artifacts.${id}.producers`);
52132
+ }
52127
52133
  }
52128
- for (const ref of art.consumers) {
52129
- checkExists(ref, agentIds, "agents", `artifacts.${id}.consumers`);
52134
+ if (art.editors.length > 0) {
52135
+ for (const ref of art.editors) {
52136
+ checkExists(ref, agentIds, "agents", `artifacts.${id}.editors`);
52137
+ }
52138
+ }
52139
+ if (art.consumers.length > 0) {
52140
+ for (const ref of art.consumers) {
52141
+ checkExists(ref, agentIds, "agents", `artifacts.${id}.consumers`);
52142
+ }
52130
52143
  }
52131
52144
  for (const ref of art.required_validations) {
52132
52145
  checkExists(ref, validationIds, "validations", `artifacts.${id}.required_validations`);
52133
52146
  }
52134
52147
  }
52135
52148
  for (const [id, art] of Object.entries(dsl.artifacts)) {
52136
- const ownerAgent = dsl.agents[art.owner];
52137
- if (ownerAgent && !ownerAgent.can_read_artifacts.includes(id)) {
52138
- diagnostics.push({
52139
- path: `artifacts.${id}.owner`,
52140
- message: `Agent "${art.owner}" owns artifact "${id}" but cannot read it (missing from can_read_artifacts)`,
52141
- code: "artifact-owner-no-read"
52142
- });
52149
+ if (art.owner) {
52150
+ const ownerAgent = dsl.agents[art.owner];
52151
+ if (ownerAgent && !ownerAgent.can_read_artifacts.includes(id)) {
52152
+ diagnostics.push({
52153
+ path: `artifacts.${id}.owner`,
52154
+ message: `Agent "${art.owner}" owns artifact "${id}" but cannot read it (missing from can_read_artifacts)`,
52155
+ code: "artifact-owner-no-read"
52156
+ });
52157
+ }
52143
52158
  }
52144
52159
  for (const valId of art.required_validations) {
52145
52160
  const validation = dsl.validations[valId];
@@ -52156,8 +52171,10 @@ function checkReferences(dsl) {
52156
52171
  }
52157
52172
  }
52158
52173
  for (const [id, tool] of Object.entries(dsl.tools)) {
52159
- for (const ref of tool.invokable_by) {
52160
- checkExists(ref, agentIds, "agents", `tools.${id}.invokable_by`);
52174
+ if (tool.invokable_by.length > 0) {
52175
+ for (const ref of tool.invokable_by) {
52176
+ checkExists(ref, agentIds, "agents", `tools.${id}.invokable_by`);
52177
+ }
52161
52178
  }
52162
52179
  }
52163
52180
  for (const [id, val] of Object.entries(dsl.validations)) {
@@ -52750,7 +52767,7 @@ var artifactOwnershipRule = {
52750
52767
  for (const step of task.execution_steps) {
52751
52768
  if (step.produces_artifact) {
52752
52769
  const artifact = dsl.artifacts[step.produces_artifact];
52753
- if (artifact) {
52770
+ if (artifact && (artifact.producers.length > 0 || artifact.editors.length > 0)) {
52754
52771
  const canWrite = artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
52755
52772
  if (!canWrite) {
52756
52773
  diagnostics.push({
@@ -52764,7 +52781,7 @@ var artifactOwnershipRule = {
52764
52781
  }
52765
52782
  if (step.reads_artifact) {
52766
52783
  const artifact = dsl.artifacts[step.reads_artifact];
52767
- if (artifact) {
52784
+ if (artifact && (artifact.consumers.length > 0 || artifact.producers.length > 0 || artifact.editors.length > 0)) {
52768
52785
  const canRead = artifact.consumers.includes(agentId) || artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
52769
52786
  if (!canRead) {
52770
52787
  diagnostics.push({
@@ -53663,9 +53680,9 @@ var ruleset = {
53663
53680
  }
53664
53681
  },
53665
53682
  "artifact-producers-ref": {
53666
- description: "Artifact producers must reference existing agents",
53683
+ description: "(deprecated) Artifact producers must reference existing agents",
53667
53684
  message: "{{error}}",
53668
- severity: "error",
53685
+ severity: "warn",
53669
53686
  given: "$.artifacts.*",
53670
53687
  then: {
53671
53688
  field: "producers",
@@ -53674,9 +53691,9 @@ var ruleset = {
53674
53691
  }
53675
53692
  },
53676
53693
  "artifact-editors-ref": {
53677
- description: "Artifact editors must reference existing agents",
53694
+ description: "(deprecated) Artifact editors must reference existing agents",
53678
53695
  message: "{{error}}",
53679
- severity: "error",
53696
+ severity: "warn",
53680
53697
  given: "$.artifacts.*",
53681
53698
  then: {
53682
53699
  field: "editors",
@@ -53685,9 +53702,9 @@ var ruleset = {
53685
53702
  }
53686
53703
  },
53687
53704
  "artifact-consumers-ref": {
53688
- description: "Artifact consumers must reference existing agents",
53705
+ description: "(deprecated) Artifact consumers must reference existing agents",
53689
53706
  message: "{{error}}",
53690
- severity: "error",
53707
+ severity: "warn",
53691
53708
  given: "$.artifacts.*",
53692
53709
  then: {
53693
53710
  field: "consumers",
@@ -53862,9 +53879,9 @@ var ruleset = {
53862
53879
  },
53863
53880
  // ========== 15.2.2 Artifact responsibility integrity ==========
53864
53881
  "artifact-editors-not-empty": {
53865
- description: "Artifact editors must not be empty (15.2.2)",
53882
+ description: "(deprecated) Artifact editors must not be empty (15.2.2)",
53866
53883
  message: "{{error}}",
53867
- severity: "error",
53884
+ severity: "info",
53868
53885
  given: "$.artifacts.*.editors",
53869
53886
  then: {
53870
53887
  function: editors_not_empty_default
@@ -55310,6 +55327,12 @@ function expandOutputPath(pattern, context, entityId, entity) {
55310
55327
  }
55311
55328
  );
55312
55329
  }
55330
+ var CONTEXT_TYPE_PATTERN = new RegExp(
55331
+ `\\{(${CONTEXT_TYPES.join("|")})\\.[^}]+\\}`
55332
+ );
55333
+ function hasUnresolvedPathVars(path) {
55334
+ return CONTEXT_TYPE_PATTERN.test(path);
55335
+ }
55313
55336
  function buildEntityContext(dsl, context, entityId) {
55314
55337
  switch (context) {
55315
55338
  case "agent": {
@@ -55375,6 +55398,7 @@ async function renderFromConfig(dsl, renderTargets, options) {
55375
55398
  const output = compiled(ctx);
55376
55399
  const entity = section[entityId];
55377
55400
  const outputPath = expandOutputPath(target.output, target.context, entityId, entity);
55401
+ if (hasUnresolvedPathVars(outputPath)) continue;
55378
55402
  if (target.skip_empty && isEffectivelyEmpty(output)) {
55379
55403
  await removeIfExists(outputPath);
55380
55404
  continue;
@@ -55425,6 +55449,7 @@ async function checkDriftFromConfig(dsl, renderTargets, options) {
55425
55449
  const expected = compiled(ctx);
55426
55450
  const entity = section[entityId];
55427
55451
  const outputPath = expandOutputPath(target.output, target.context, entityId, entity);
55452
+ if (hasUnresolvedPathVars(outputPath)) continue;
55428
55453
  await checkExpectedVsExisting(expected, outputPath, target.skip_empty, diffs);
55429
55454
  }
55430
55455
  }
@@ -55587,60 +55612,6 @@ function schemaCompleteness(dsl) {
55587
55612
  recommendations: lowSections.length > 0 ? [`Low optional field coverage in: ${lowSections.join(", ")}`] : []
55588
55613
  };
55589
55614
  }
55590
- function crossReferenceBidirectionality(dsl) {
55591
- let totalChecks = 0;
55592
- let passedChecks = 0;
55593
- const issues = [];
55594
- for (const [agentId, agent] of Object.entries(dsl.agents)) {
55595
- for (const toolId of agent.can_execute_tools) {
55596
- totalChecks++;
55597
- const tool = dsl.tools[toolId];
55598
- if (tool && tool.invokable_by.includes(agentId)) {
55599
- passedChecks++;
55600
- } else {
55601
- issues.push(`agent ${agentId} \u2192 tool ${toolId}`);
55602
- }
55603
- }
55604
- for (const artId of agent.can_write_artifacts) {
55605
- totalChecks++;
55606
- const art = dsl.artifacts[artId];
55607
- if (art && (art.producers.includes(agentId) || art.editors.includes(agentId))) {
55608
- passedChecks++;
55609
- } else {
55610
- issues.push(`agent ${agentId} \u2192 artifact ${artId} (write)`);
55611
- }
55612
- }
55613
- for (const artId of agent.can_read_artifacts) {
55614
- totalChecks++;
55615
- const art = dsl.artifacts[artId];
55616
- if (art && (art.consumers.includes(agentId) || art.producers.includes(agentId) || art.editors.includes(agentId))) {
55617
- passedChecks++;
55618
- } else {
55619
- issues.push(`agent ${agentId} \u2192 artifact ${artId} (read)`);
55620
- }
55621
- }
55622
- }
55623
- for (const [toolId, tool] of Object.entries(dsl.tools)) {
55624
- for (const agentId of tool.invokable_by) {
55625
- totalChecks++;
55626
- const agent = dsl.agents[agentId];
55627
- if (agent && agent.can_execute_tools.includes(toolId)) {
55628
- passedChecks++;
55629
- } else {
55630
- issues.push(`tool ${toolId} \u2192 agent ${agentId}`);
55631
- }
55632
- }
55633
- }
55634
- return {
55635
- id: "cross-reference-bidirectionality",
55636
- label: "Cross-reference bidirectionality",
55637
- score: passedChecks,
55638
- total: totalChecks,
55639
- percent: pct(passedChecks, totalChecks),
55640
- weight: 2,
55641
- recommendations: issues.length > 0 ? [`${issues.length} unreciprocated cross-references: ${issues.slice(0, 5).join(", ")}${issues.length > 5 ? `, ... (${issues.length - 5} more)` : ""}`] : []
55642
- };
55643
- }
55644
55615
  function entityGuardrailCoverage(dsl) {
55645
55616
  const entitySections = [
55646
55617
  { name: "agents", entities: dsl.agents },
@@ -55731,7 +55702,6 @@ function score(dsl) {
55731
55702
  guardrailPolicyCoverage(dsl),
55732
55703
  workflowValidationIntegration(dsl),
55733
55704
  schemaCompleteness(dsl),
55734
- crossReferenceBidirectionality(dsl),
55735
55705
  guardrailScopeResolution(dsl),
55736
55706
  entityGuardrailCoverage(dsl)
55737
55707
  ];
@@ -56147,10 +56117,9 @@ async function generateGuardrails(options) {
56147
56117
  const mergedCtx = { ...entityCtx, vars, paths, binding, resolved_checks: checkResult.resolved };
56148
56118
  const rendered = compiled(mergedCtx);
56149
56119
  const entity = section[entityId];
56150
- const resolvedOutput = resolveBindingRenderOutputPath(
56151
- expandOutputPath(renderTarget.output, context, entityId, entity),
56152
- paths
56153
- );
56120
+ const expandedOutput = expandOutputPath(renderTarget.output, context, entityId, entity);
56121
+ if (hasUnresolvedPathVars(expandedOutput)) continue;
56122
+ const resolvedOutput = resolveBindingRenderOutputPath(expandedOutput, paths);
56154
56123
  const outputPath = resolve6(config.configDir, resolvedOutput);
56155
56124
  if (shouldSkipEmpty && rendered.trim().length === 0) {
56156
56125
  if (!dryRun) {