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/index.d.ts CHANGED
@@ -106,15 +106,33 @@ type Agent = z.infer<typeof AgentSchema>;
106
106
  declare const ArtifactSchema: z.ZodObject<{
107
107
  type: z.ZodString;
108
108
  description: z.ZodOptional<z.ZodString>;
109
- owner: z.ZodString;
110
- producers: z.ZodArray<z.ZodString>;
111
- editors: z.ZodArray<z.ZodString>;
112
- consumers: z.ZodArray<z.ZodString>;
113
- states: z.ZodArray<z.ZodString>;
109
+ owner: z.ZodOptional<z.ZodString>;
110
+ producers: z.ZodDefault<z.ZodArray<z.ZodString>>;
111
+ editors: z.ZodDefault<z.ZodArray<z.ZodString>>;
112
+ consumers: z.ZodDefault<z.ZodArray<z.ZodString>>;
113
+ states: z.ZodDefault<z.ZodArray<z.ZodString>>;
114
114
  required_validations: z.ZodDefault<z.ZodArray<z.ZodString>>;
115
115
  visibility: z.ZodOptional<z.ZodString>;
116
116
  classification: z.ZodOptional<z.ZodString>;
117
117
  guardrails: z.ZodOptional<z.ZodArray<z.ZodString>>;
118
+ authority: z.ZodOptional<z.ZodEnum<{
119
+ canonical: "canonical";
120
+ derived: "derived";
121
+ generated: "generated";
122
+ control: "control";
123
+ }>>;
124
+ path_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
125
+ exclude_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
126
+ manual_edit: z.ZodOptional<z.ZodEnum<{
127
+ allowed: "allowed";
128
+ discouraged: "discouraged";
129
+ forbidden: "forbidden";
130
+ }>>;
131
+ change_control: z.ZodOptional<z.ZodEnum<{
132
+ none: "none";
133
+ "approval-required": "approval-required";
134
+ "regeneration-required": "regeneration-required";
135
+ }>>;
118
136
  }, z.core.$loose>;
119
137
  type Artifact = z.infer<typeof ArtifactSchema>;
120
138
 
@@ -501,22 +519,40 @@ declare const DslSchema: z.ZodObject<{
501
519
  artifacts: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
502
520
  type: z.ZodString;
503
521
  description: z.ZodOptional<z.ZodString>;
504
- owner: z.ZodString;
505
- producers: z.ZodArray<z.ZodString>;
506
- editors: z.ZodArray<z.ZodString>;
507
- consumers: z.ZodArray<z.ZodString>;
508
- states: z.ZodArray<z.ZodString>;
522
+ owner: z.ZodOptional<z.ZodString>;
523
+ producers: z.ZodDefault<z.ZodArray<z.ZodString>>;
524
+ editors: z.ZodDefault<z.ZodArray<z.ZodString>>;
525
+ consumers: z.ZodDefault<z.ZodArray<z.ZodString>>;
526
+ states: z.ZodDefault<z.ZodArray<z.ZodString>>;
509
527
  required_validations: z.ZodDefault<z.ZodArray<z.ZodString>>;
510
528
  visibility: z.ZodOptional<z.ZodString>;
511
529
  classification: z.ZodOptional<z.ZodString>;
512
530
  guardrails: z.ZodOptional<z.ZodArray<z.ZodString>>;
531
+ authority: z.ZodOptional<z.ZodEnum<{
532
+ canonical: "canonical";
533
+ derived: "derived";
534
+ generated: "generated";
535
+ control: "control";
536
+ }>>;
537
+ path_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
538
+ exclude_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
539
+ manual_edit: z.ZodOptional<z.ZodEnum<{
540
+ allowed: "allowed";
541
+ discouraged: "discouraged";
542
+ forbidden: "forbidden";
543
+ }>>;
544
+ change_control: z.ZodOptional<z.ZodEnum<{
545
+ none: "none";
546
+ "approval-required": "approval-required";
547
+ "regeneration-required": "regeneration-required";
548
+ }>>;
513
549
  }, z.core.$loose>>>;
514
550
  tools: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
515
551
  kind: z.ZodString;
516
552
  description: z.ZodOptional<z.ZodString>;
517
553
  input_artifacts: z.ZodDefault<z.ZodArray<z.ZodString>>;
518
554
  output_artifacts: z.ZodDefault<z.ZodArray<z.ZodString>>;
519
- invokable_by: z.ZodArray<z.ZodString>;
555
+ invokable_by: z.ZodDefault<z.ZodArray<z.ZodString>>;
520
556
  side_effects: z.ZodDefault<z.ZodArray<z.ZodString>>;
521
557
  commands: z.ZodDefault<z.ZodArray<z.ZodObject<{
522
558
  command: z.ZodString;
@@ -1035,7 +1071,7 @@ declare const ToolSchema: z.ZodObject<{
1035
1071
  description: z.ZodOptional<z.ZodString>;
1036
1072
  input_artifacts: z.ZodDefault<z.ZodArray<z.ZodString>>;
1037
1073
  output_artifacts: z.ZodDefault<z.ZodArray<z.ZodString>>;
1038
- invokable_by: z.ZodArray<z.ZodString>;
1074
+ invokable_by: z.ZodDefault<z.ZodArray<z.ZodString>>;
1039
1075
  side_effects: z.ZodDefault<z.ZodArray<z.ZodString>>;
1040
1076
  commands: z.ZodDefault<z.ZodArray<z.ZodObject<{
1041
1077
  command: z.ZodString;
package/dist/index.js CHANGED
@@ -48942,15 +48942,20 @@ import { z as z2 } from "zod";
48942
48942
  var ArtifactSchema = z2.object({
48943
48943
  type: z2.string(),
48944
48944
  description: z2.string().optional(),
48945
- owner: z2.string(),
48946
- producers: z2.array(z2.string()),
48947
- editors: z2.array(z2.string()),
48948
- consumers: z2.array(z2.string()),
48949
- states: z2.array(z2.string()),
48945
+ owner: z2.string().optional(),
48946
+ producers: z2.array(z2.string()).default([]),
48947
+ editors: z2.array(z2.string()).default([]),
48948
+ consumers: z2.array(z2.string()).default([]),
48949
+ states: z2.array(z2.string()).default([]),
48950
48950
  required_validations: z2.array(z2.string()).default([]),
48951
48951
  visibility: z2.string().optional(),
48952
48952
  classification: z2.string().optional(),
48953
- guardrails: z2.array(z2.string()).optional()
48953
+ guardrails: z2.array(z2.string()).optional(),
48954
+ authority: z2.enum(["canonical", "derived", "generated", "control"]).optional(),
48955
+ path_patterns: z2.array(z2.string()).optional(),
48956
+ exclude_patterns: z2.array(z2.string()).optional(),
48957
+ manual_edit: z2.enum(["allowed", "discouraged", "forbidden"]).optional(),
48958
+ change_control: z2.enum(["none", "approval-required", "regeneration-required"]).optional()
48954
48959
  }).passthrough();
48955
48960
 
48956
48961
  // src/schema/binding.ts
@@ -49213,7 +49218,7 @@ var ToolSchema = z12.object({
49213
49218
  description: z12.string().optional(),
49214
49219
  input_artifacts: z12.array(z12.string()).default([]),
49215
49220
  output_artifacts: z12.array(z12.string()).default([]),
49216
- invokable_by: z12.array(z12.string()),
49221
+ invokable_by: z12.array(z12.string()).default([]),
49217
49222
  side_effects: z12.array(z12.string()).default([]),
49218
49223
  commands: z12.array(CommandSchema).default([]),
49219
49224
  guardrails: z12.array(z12.string()).optional()
@@ -50974,28 +50979,38 @@ function checkReferences(dsl) {
50974
50979
  }
50975
50980
  }
50976
50981
  for (const [id, art] of Object.entries(dsl.artifacts)) {
50977
- checkExists(art.owner, agentIds, "agents", `artifacts.${id}.owner`);
50978
- for (const ref of art.producers) {
50979
- checkExists(ref, agentIds, "agents", `artifacts.${id}.producers`);
50982
+ if (art.owner) {
50983
+ checkExists(art.owner, agentIds, "agents", `artifacts.${id}.owner`);
50980
50984
  }
50981
- for (const ref of art.editors) {
50982
- checkExists(ref, agentIds, "agents", `artifacts.${id}.editors`);
50985
+ if (art.producers.length > 0) {
50986
+ for (const ref of art.producers) {
50987
+ checkExists(ref, agentIds, "agents", `artifacts.${id}.producers`);
50988
+ }
50983
50989
  }
50984
- for (const ref of art.consumers) {
50985
- checkExists(ref, agentIds, "agents", `artifacts.${id}.consumers`);
50990
+ if (art.editors.length > 0) {
50991
+ for (const ref of art.editors) {
50992
+ checkExists(ref, agentIds, "agents", `artifacts.${id}.editors`);
50993
+ }
50994
+ }
50995
+ if (art.consumers.length > 0) {
50996
+ for (const ref of art.consumers) {
50997
+ checkExists(ref, agentIds, "agents", `artifacts.${id}.consumers`);
50998
+ }
50986
50999
  }
50987
51000
  for (const ref of art.required_validations) {
50988
51001
  checkExists(ref, validationIds, "validations", `artifacts.${id}.required_validations`);
50989
51002
  }
50990
51003
  }
50991
51004
  for (const [id, art] of Object.entries(dsl.artifacts)) {
50992
- const ownerAgent = dsl.agents[art.owner];
50993
- if (ownerAgent && !ownerAgent.can_read_artifacts.includes(id)) {
50994
- diagnostics.push({
50995
- path: `artifacts.${id}.owner`,
50996
- message: `Agent "${art.owner}" owns artifact "${id}" but cannot read it (missing from can_read_artifacts)`,
50997
- code: "artifact-owner-no-read"
50998
- });
51005
+ if (art.owner) {
51006
+ const ownerAgent = dsl.agents[art.owner];
51007
+ if (ownerAgent && !ownerAgent.can_read_artifacts.includes(id)) {
51008
+ diagnostics.push({
51009
+ path: `artifacts.${id}.owner`,
51010
+ message: `Agent "${art.owner}" owns artifact "${id}" but cannot read it (missing from can_read_artifacts)`,
51011
+ code: "artifact-owner-no-read"
51012
+ });
51013
+ }
50999
51014
  }
51000
51015
  for (const valId of art.required_validations) {
51001
51016
  const validation = dsl.validations[valId];
@@ -51012,8 +51027,10 @@ function checkReferences(dsl) {
51012
51027
  }
51013
51028
  }
51014
51029
  for (const [id, tool] of Object.entries(dsl.tools)) {
51015
- for (const ref of tool.invokable_by) {
51016
- checkExists(ref, agentIds, "agents", `tools.${id}.invokable_by`);
51030
+ if (tool.invokable_by.length > 0) {
51031
+ for (const ref of tool.invokable_by) {
51032
+ checkExists(ref, agentIds, "agents", `tools.${id}.invokable_by`);
51033
+ }
51017
51034
  }
51018
51035
  }
51019
51036
  for (const [id, val] of Object.entries(dsl.validations)) {
@@ -51606,7 +51623,7 @@ var artifactOwnershipRule = {
51606
51623
  for (const step of task.execution_steps) {
51607
51624
  if (step.produces_artifact) {
51608
51625
  const artifact = dsl.artifacts[step.produces_artifact];
51609
- if (artifact) {
51626
+ if (artifact && (artifact.producers.length > 0 || artifact.editors.length > 0)) {
51610
51627
  const canWrite = artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
51611
51628
  if (!canWrite) {
51612
51629
  diagnostics.push({
@@ -51620,7 +51637,7 @@ var artifactOwnershipRule = {
51620
51637
  }
51621
51638
  if (step.reads_artifact) {
51622
51639
  const artifact = dsl.artifacts[step.reads_artifact];
51623
- if (artifact) {
51640
+ if (artifact && (artifact.consumers.length > 0 || artifact.producers.length > 0 || artifact.editors.length > 0)) {
51624
51641
  const canRead = artifact.consumers.includes(agentId) || artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
51625
51642
  if (!canRead) {
51626
51643
  diagnostics.push({
@@ -52519,9 +52536,9 @@ var ruleset = {
52519
52536
  }
52520
52537
  },
52521
52538
  "artifact-producers-ref": {
52522
- description: "Artifact producers must reference existing agents",
52539
+ description: "(deprecated) Artifact producers must reference existing agents",
52523
52540
  message: "{{error}}",
52524
- severity: "error",
52541
+ severity: "warn",
52525
52542
  given: "$.artifacts.*",
52526
52543
  then: {
52527
52544
  field: "producers",
@@ -52530,9 +52547,9 @@ var ruleset = {
52530
52547
  }
52531
52548
  },
52532
52549
  "artifact-editors-ref": {
52533
- description: "Artifact editors must reference existing agents",
52550
+ description: "(deprecated) Artifact editors must reference existing agents",
52534
52551
  message: "{{error}}",
52535
- severity: "error",
52552
+ severity: "warn",
52536
52553
  given: "$.artifacts.*",
52537
52554
  then: {
52538
52555
  field: "editors",
@@ -52541,9 +52558,9 @@ var ruleset = {
52541
52558
  }
52542
52559
  },
52543
52560
  "artifact-consumers-ref": {
52544
- description: "Artifact consumers must reference existing agents",
52561
+ description: "(deprecated) Artifact consumers must reference existing agents",
52545
52562
  message: "{{error}}",
52546
- severity: "error",
52563
+ severity: "warn",
52547
52564
  given: "$.artifacts.*",
52548
52565
  then: {
52549
52566
  field: "consumers",
@@ -52718,9 +52735,9 @@ var ruleset = {
52718
52735
  },
52719
52736
  // ========== 15.2.2 Artifact responsibility integrity ==========
52720
52737
  "artifact-editors-not-empty": {
52721
- description: "Artifact editors must not be empty (15.2.2)",
52738
+ description: "(deprecated) Artifact editors must not be empty (15.2.2)",
52722
52739
  message: "{{error}}",
52723
- severity: "error",
52740
+ severity: "info",
52724
52741
  given: "$.artifacts.*.editors",
52725
52742
  then: {
52726
52743
  function: editors_not_empty_default
@@ -54181,6 +54198,12 @@ function expandOutputPath(pattern, context, entityId, entity) {
54181
54198
  }
54182
54199
  );
54183
54200
  }
54201
+ var CONTEXT_TYPE_PATTERN = new RegExp(
54202
+ `\\{(${CONTEXT_TYPES.join("|")})\\.[^}]+\\}`
54203
+ );
54204
+ function hasUnresolvedPathVars(path) {
54205
+ return CONTEXT_TYPE_PATTERN.test(path);
54206
+ }
54184
54207
  function buildEntityContext(dsl, context, entityId) {
54185
54208
  switch (context) {
54186
54209
  case "agent": {
@@ -54246,6 +54269,7 @@ async function renderFromConfig(dsl, renderTargets, options) {
54246
54269
  const output = compiled(ctx);
54247
54270
  const entity = section[entityId];
54248
54271
  const outputPath = expandOutputPath(target.output, target.context, entityId, entity);
54272
+ if (hasUnresolvedPathVars(outputPath)) continue;
54249
54273
  if (target.skip_empty && isEffectivelyEmpty(output)) {
54250
54274
  await removeIfExists(outputPath);
54251
54275
  continue;
@@ -54296,6 +54320,7 @@ async function checkDriftFromConfig(dsl, renderTargets, options) {
54296
54320
  const expected = compiled(ctx);
54297
54321
  const entity = section[entityId];
54298
54322
  const outputPath = expandOutputPath(target.output, target.context, entityId, entity);
54323
+ if (hasUnresolvedPathVars(outputPath)) continue;
54299
54324
  await checkExpectedVsExisting(expected, outputPath, target.skip_empty, diffs);
54300
54325
  }
54301
54326
  }
@@ -54791,60 +54816,6 @@ function schemaCompleteness(dsl) {
54791
54816
  recommendations: lowSections.length > 0 ? [`Low optional field coverage in: ${lowSections.join(", ")}`] : []
54792
54817
  };
54793
54818
  }
54794
- function crossReferenceBidirectionality(dsl) {
54795
- let totalChecks = 0;
54796
- let passedChecks = 0;
54797
- const issues = [];
54798
- for (const [agentId, agent] of Object.entries(dsl.agents)) {
54799
- for (const toolId of agent.can_execute_tools) {
54800
- totalChecks++;
54801
- const tool = dsl.tools[toolId];
54802
- if (tool && tool.invokable_by.includes(agentId)) {
54803
- passedChecks++;
54804
- } else {
54805
- issues.push(`agent ${agentId} \u2192 tool ${toolId}`);
54806
- }
54807
- }
54808
- for (const artId of agent.can_write_artifacts) {
54809
- totalChecks++;
54810
- const art = dsl.artifacts[artId];
54811
- if (art && (art.producers.includes(agentId) || art.editors.includes(agentId))) {
54812
- passedChecks++;
54813
- } else {
54814
- issues.push(`agent ${agentId} \u2192 artifact ${artId} (write)`);
54815
- }
54816
- }
54817
- for (const artId of agent.can_read_artifacts) {
54818
- totalChecks++;
54819
- const art = dsl.artifacts[artId];
54820
- if (art && (art.consumers.includes(agentId) || art.producers.includes(agentId) || art.editors.includes(agentId))) {
54821
- passedChecks++;
54822
- } else {
54823
- issues.push(`agent ${agentId} \u2192 artifact ${artId} (read)`);
54824
- }
54825
- }
54826
- }
54827
- for (const [toolId, tool] of Object.entries(dsl.tools)) {
54828
- for (const agentId of tool.invokable_by) {
54829
- totalChecks++;
54830
- const agent = dsl.agents[agentId];
54831
- if (agent && agent.can_execute_tools.includes(toolId)) {
54832
- passedChecks++;
54833
- } else {
54834
- issues.push(`tool ${toolId} \u2192 agent ${agentId}`);
54835
- }
54836
- }
54837
- }
54838
- return {
54839
- id: "cross-reference-bidirectionality",
54840
- label: "Cross-reference bidirectionality",
54841
- score: passedChecks,
54842
- total: totalChecks,
54843
- percent: pct(passedChecks, totalChecks),
54844
- weight: 2,
54845
- recommendations: issues.length > 0 ? [`${issues.length} unreciprocated cross-references: ${issues.slice(0, 5).join(", ")}${issues.length > 5 ? `, ... (${issues.length - 5} more)` : ""}`] : []
54846
- };
54847
- }
54848
54819
  function entityGuardrailCoverage(dsl) {
54849
54820
  const entitySections = [
54850
54821
  { name: "agents", entities: dsl.agents },
@@ -54935,7 +54906,6 @@ function score(dsl) {
54935
54906
  guardrailPolicyCoverage(dsl),
54936
54907
  workflowValidationIntegration(dsl),
54937
54908
  schemaCompleteness(dsl),
54938
- crossReferenceBidirectionality(dsl),
54939
54909
  guardrailScopeResolution(dsl),
54940
54910
  entityGuardrailCoverage(dsl)
54941
54911
  ];
@@ -56294,10 +56264,9 @@ async function generateGuardrails(options) {
56294
56264
  const mergedCtx = { ...entityCtx, vars, paths, binding, resolved_checks: checkResult.resolved };
56295
56265
  const rendered = compiled(mergedCtx);
56296
56266
  const entity = section[entityId];
56297
- const resolvedOutput = resolveBindingRenderOutputPath(
56298
- expandOutputPath(renderTarget.output, context, entityId, entity),
56299
- paths
56300
- );
56267
+ const expandedOutput = expandOutputPath(renderTarget.output, context, entityId, entity);
56268
+ if (hasUnresolvedPathVars(expandedOutput)) continue;
56269
+ const resolvedOutput = resolveBindingRenderOutputPath(expandedOutput, paths);
56301
56270
  const outputPath = resolve6(config.configDir, resolvedOutput);
56302
56271
  if (shouldSkipEmpty && rendered.trim().length === 0) {
56303
56272
  if (!dryRun) {