agent-contracts 0.22.3 → 0.22.5

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
@@ -48949,6 +48949,7 @@ var ArtifactSchema = z2.object({
48949
48949
  states: z2.array(z2.string()),
48950
48950
  required_validations: z2.array(z2.string()).default([]),
48951
48951
  visibility: z2.string().optional(),
48952
+ classification: z2.string().optional(),
48952
48953
  guardrails: z2.array(z2.string()).optional()
48953
48954
  }).passthrough();
48954
48955
 
@@ -49153,7 +49154,7 @@ var ExecutionStepSchema = z9.object({
49153
49154
  var TaskSchema = z9.object({
49154
49155
  description: z9.string(),
49155
49156
  target_agent: z9.string(),
49156
- allowed_from_agents: z9.array(z9.string()),
49157
+ allowed_from_agents: z9.array(z9.string()).default([]),
49157
49158
  workflow: z9.string(),
49158
49159
  input_artifacts: z9.array(z9.string()),
49159
49160
  invocation_handoff: z9.string(),
@@ -49226,7 +49227,8 @@ var ValidationSchema = z13.object({
49226
49227
  executor_type: z13.enum(["tool", "agent"]),
49227
49228
  executor: z13.string(),
49228
49229
  blocking: z13.boolean(),
49229
- produces_evidence: z13.string().optional()
49230
+ produces_evidence: z13.string().optional(),
49231
+ description: z13.string().optional()
49230
49232
  }).passthrough();
49231
49233
 
49232
49234
  // src/schema/workflow.ts
@@ -49371,13 +49373,13 @@ var DslSchema = z15.object({
49371
49373
  // src/schema/json-schema-utils.ts
49372
49374
  function resolveAllOf(schema) {
49373
49375
  const allOf = schema["allOf"];
49374
- if (!Array.isArray(allOf)) return schema;
49376
+ if (!Array.isArray(allOf)) return resolveNestedProperties(schema);
49375
49377
  let mergedProperties = {};
49376
49378
  let mergedRequired = [];
49377
49379
  const mergedTop = {};
49378
49380
  for (const sub of allOf) {
49379
49381
  if (typeof sub !== "object" || sub === null || Array.isArray(sub)) continue;
49380
- const subSchema = sub;
49382
+ const subSchema = resolveAllOf(sub);
49381
49383
  if (subSchema["properties"] && typeof subSchema["properties"] === "object") {
49382
49384
  mergedProperties = {
49383
49385
  ...mergedProperties,
@@ -49408,13 +49410,30 @@ function resolveAllOf(schema) {
49408
49410
  }
49409
49411
  const result = { ...mergedTop };
49410
49412
  if (Object.keys(mergedProperties).length > 0) {
49411
- result["properties"] = mergedProperties;
49413
+ result["properties"] = resolvePropertySchemas(mergedProperties);
49412
49414
  }
49413
49415
  if (mergedRequired.length > 0) {
49414
49416
  result["required"] = [...new Set(mergedRequired)];
49415
49417
  }
49416
49418
  return result;
49417
49419
  }
49420
+ function resolveNestedProperties(schema) {
49421
+ const props = schema["properties"];
49422
+ if (!props || typeof props !== "object") return schema;
49423
+ return { ...schema, properties: resolvePropertySchemas(props) };
49424
+ }
49425
+ function resolvePropertySchemas(properties) {
49426
+ const result = {};
49427
+ for (const [key, value] of Object.entries(properties)) {
49428
+ if (value && typeof value === "object" && !Array.isArray(value)) {
49429
+ const propSchema = value;
49430
+ result[key] = propSchema["allOf"] ? resolveAllOf(propSchema) : propSchema;
49431
+ } else {
49432
+ result[key] = value;
49433
+ }
49434
+ }
49435
+ return result;
49436
+ }
49418
49437
 
49419
49438
  // src/schema/merge-operators.ts
49420
49439
  import { z as z16 } from "zod";
@@ -49462,7 +49481,7 @@ function deepClone(value) {
49462
49481
  }
49463
49482
  return result;
49464
49483
  }
49465
- function resolveJsonPointer(root, pointer) {
49484
+ function tryResolveJsonPointer(root, pointer) {
49466
49485
  const path = pointer.slice(2);
49467
49486
  const segments = path.split("/").map(
49468
49487
  (s2) => s2.replace(/~1/g, "/").replace(/~0/g, "~")
@@ -49476,12 +49495,19 @@ function resolveJsonPointer(root, pointer) {
49476
49495
  }
49477
49496
  current = current[segment];
49478
49497
  if (current === void 0) {
49479
- throw new DslLoadError(
49480
- `Cannot resolve JSON Pointer "${pointer}": path segment "${segment}" not found`
49481
- );
49498
+ return { found: false };
49482
49499
  }
49483
49500
  }
49484
- return current;
49501
+ return { found: true, value: current };
49502
+ }
49503
+ function resolveJsonPointer(root, pointer) {
49504
+ const result = tryResolveJsonPointer(root, pointer);
49505
+ if (!result.found) {
49506
+ throw new DslLoadError(
49507
+ `Cannot resolve JSON Pointer "${pointer}": target not found`
49508
+ );
49509
+ }
49510
+ return result.value;
49485
49511
  }
49486
49512
  function hasRefs(value) {
49487
49513
  if (!("$refs" in value)) return false;
@@ -49525,7 +49551,7 @@ function deepMergeRefs(a3, b3, sourcePath) {
49525
49551
  }
49526
49552
  return result;
49527
49553
  }
49528
- async function loadRefsSource(refPath, baseDir, resolving, rootDoc) {
49554
+ async function loadRefsSource(refPath, baseDir, resolving) {
49529
49555
  const target = resolve(baseDir, refPath);
49530
49556
  const s2 = await fsStat(target).catch(() => null);
49531
49557
  if (s2?.isDirectory()) {
@@ -49533,7 +49559,7 @@ async function loadRefsSource(refPath, baseDir, resolving, rootDoc) {
49533
49559
  throw new DslLoadError(`Circular $refs detected: ${target}`, target);
49534
49560
  }
49535
49561
  resolving.add(target);
49536
- const result = await loadDirectoryAsMap(target, resolving, rootDoc);
49562
+ const result = await loadDirectoryAsMap(target, resolving);
49537
49563
  resolving.delete(target);
49538
49564
  return result;
49539
49565
  }
@@ -49551,16 +49577,16 @@ async function loadRefsSource(refPath, baseDir, resolving, rootDoc) {
49551
49577
  target
49552
49578
  );
49553
49579
  }
49554
- const resolved = await resolveRefsDeep(
49580
+ const resolved = await assembleRefs(
49555
49581
  content,
49556
49582
  dirname(target),
49557
49583
  resolving,
49558
- rootDoc
49584
+ content
49559
49585
  );
49560
49586
  resolving.delete(target);
49561
49587
  return resolved;
49562
49588
  }
49563
- async function loadDirectoryAsMap(dirPath, resolving, rootDoc) {
49589
+ async function loadDirectoryAsMap(dirPath, resolving) {
49564
49590
  let entries;
49565
49591
  try {
49566
49592
  entries = await readdir(dirPath);
@@ -49587,17 +49613,17 @@ async function loadDirectoryAsMap(dirPath, resolving, rootDoc) {
49587
49613
  filePath
49588
49614
  );
49589
49615
  }
49590
- const resolved = await resolveRefsDeep(
49616
+ const resolved = await assembleRefs(
49591
49617
  content,
49592
49618
  dirPath,
49593
49619
  resolving,
49594
- rootDoc
49620
+ content
49595
49621
  );
49596
49622
  merged = deepMergeRefs(merged, resolved, filePath);
49597
49623
  }
49598
49624
  return merged;
49599
49625
  }
49600
- async function processRefs(obj, baseDir, resolving, rootDoc) {
49626
+ async function processRefs(obj, baseDir, resolving) {
49601
49627
  const refPaths = obj["$refs"];
49602
49628
  const inline = {};
49603
49629
  for (const [key, value] of Object.entries(obj)) {
@@ -49607,17 +49633,17 @@ async function processRefs(obj, baseDir, resolving, rootDoc) {
49607
49633
  }
49608
49634
  let merged = {};
49609
49635
  for (const refPath of refPaths) {
49610
- const loaded = await loadRefsSource(refPath, baseDir, resolving, rootDoc);
49636
+ const loaded = await loadRefsSource(refPath, baseDir, resolving);
49611
49637
  merged = deepMergeRefs(merged, loaded, refPath);
49612
49638
  }
49613
49639
  merged = deepMergeRefs(merged, inline, "(inline)");
49614
49640
  return merged;
49615
49641
  }
49616
- async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49642
+ async function assembleRefs(data, baseDir, resolving, fileRoot) {
49617
49643
  if (typeof data !== "object" || data === null) return data;
49618
49644
  if (Array.isArray(data)) {
49619
49645
  return Promise.all(
49620
- data.map((item) => resolveRefsDeep(item, baseDir, resolving, rootDoc))
49646
+ data.map((item) => assembleRefs(item, baseDir, resolving, fileRoot))
49621
49647
  );
49622
49648
  }
49623
49649
  if (isRef(data)) {
@@ -49626,13 +49652,16 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49626
49652
  if (resolving.has(refValue)) {
49627
49653
  throw new DslLoadError(`Circular $ref detected: ${refValue}`);
49628
49654
  }
49655
+ const result2 = tryResolveJsonPointer(fileRoot, refValue);
49656
+ if (!result2.found) {
49657
+ return data;
49658
+ }
49629
49659
  resolving.add(refValue);
49630
- const target = resolveJsonPointer(rootDoc, refValue);
49631
- const resolved = await resolveRefsDeep(
49632
- deepClone(target),
49660
+ const resolved = await assembleRefs(
49661
+ deepClone(result2.value),
49633
49662
  baseDir,
49634
49663
  resolving,
49635
- rootDoc
49664
+ fileRoot
49636
49665
  );
49637
49666
  resolving.delete(refValue);
49638
49667
  return resolved;
@@ -49656,7 +49685,7 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49656
49685
  );
49657
49686
  }
49658
49687
  resolving.add(refTarget);
49659
- const result2 = await loadDirectoryAsMap(refTarget, resolving, rootDoc);
49688
+ const result2 = await loadDirectoryAsMap(refTarget, resolving);
49660
49689
  resolving.delete(refTarget);
49661
49690
  return result2;
49662
49691
  }
@@ -49671,12 +49700,12 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49671
49700
  }
49672
49701
  resolving.add(refTarget);
49673
49702
  const content = await readYaml(refTarget);
49674
- const fileRoot = fragment ? content : rootDoc;
49675
- let fileData = await resolveRefsDeep(
49703
+ const newFileRoot = isRecord(content) ? content : fileRoot;
49704
+ let fileData = await assembleRefs(
49676
49705
  content,
49677
49706
  dirname(refTarget),
49678
49707
  resolving,
49679
- fileRoot
49708
+ newFileRoot
49680
49709
  );
49681
49710
  resolving.delete(refTarget);
49682
49711
  if (fragment && fragment.startsWith("#/")) {
@@ -49692,11 +49721,31 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49692
49721
  }
49693
49722
  let obj = data;
49694
49723
  if (hasRefs(obj)) {
49695
- obj = await processRefs(obj, baseDir, resolving, rootDoc);
49724
+ obj = await processRefs(obj, baseDir, resolving);
49696
49725
  }
49697
49726
  const result = {};
49698
49727
  for (const [key, value] of Object.entries(obj)) {
49699
- result[key] = await resolveRefsDeep(value, baseDir, resolving, rootDoc);
49728
+ result[key] = await assembleRefs(value, baseDir, resolving, fileRoot);
49729
+ }
49730
+ return result;
49731
+ }
49732
+ function linkDocPointers(data, rootDoc) {
49733
+ if (typeof data !== "object" || data === null) return data;
49734
+ if (Array.isArray(data)) {
49735
+ return data.map((item) => linkDocPointers(item, rootDoc));
49736
+ }
49737
+ if (isRef(data)) {
49738
+ const refValue = data.$ref;
49739
+ if (refValue.startsWith("#/")) {
49740
+ const target = resolveJsonPointer(rootDoc, refValue);
49741
+ return linkDocPointers(deepClone(target), rootDoc);
49742
+ }
49743
+ return data;
49744
+ }
49745
+ const obj = data;
49746
+ const result = {};
49747
+ for (const [key, value] of Object.entries(obj)) {
49748
+ result[key] = linkDocPointers(value, rootDoc);
49700
49749
  }
49701
49750
  return result;
49702
49751
  }
@@ -49727,13 +49776,16 @@ async function loadDsl(entryPath) {
49727
49776
  const data = raw;
49728
49777
  checkVersion(data, absPath);
49729
49778
  const baseDir = dirname(absPath);
49730
- const resolving = /* @__PURE__ */ new Set([absPath]);
49731
- const resolved = await resolveRefsDeep(
49779
+ const assembled = await assembleRefs(
49732
49780
  data,
49733
49781
  baseDir,
49734
- resolving,
49782
+ /* @__PURE__ */ new Set([absPath]),
49735
49783
  data
49736
49784
  );
49785
+ const resolved = linkDocPointers(
49786
+ assembled,
49787
+ assembled
49788
+ );
49737
49789
  return { data: resolved, filePath: absPath };
49738
49790
  }
49739
49791
 
@@ -51342,6 +51394,7 @@ var taskAgentBindingRule = {
51342
51394
  }
51343
51395
  for (const [taskId, task] of Object.entries(dsl.tasks)) {
51344
51396
  for (const fromAgentId of task.allowed_from_agents) {
51397
+ if (fromAgentId === task.target_agent) continue;
51345
51398
  const fromAgent = dsl.agents[fromAgentId];
51346
51399
  if (fromAgent && !fromAgent.can_invoke_agents.includes(task.target_agent)) {
51347
51400
  diagnostics.push({
@@ -51916,6 +51969,176 @@ var validationExecutorNoContextRule = {
51916
51969
  }
51917
51970
  };
51918
51971
 
51972
+ // src/linter/rules/extension-consumption.ts
51973
+ function isRecord4(v2) {
51974
+ return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
51975
+ }
51976
+ function collectXUsages(dsl) {
51977
+ const usages = /* @__PURE__ */ new Map();
51978
+ function record(key, path, nodeType) {
51979
+ let list = usages.get(key);
51980
+ if (!list) {
51981
+ list = [];
51982
+ usages.set(key, list);
51983
+ }
51984
+ list.push({ path, nodeType });
51985
+ }
51986
+ function walkObj(obj, path, nodeType) {
51987
+ for (const key of Object.keys(obj)) {
51988
+ if (key.startsWith("x-") && key !== "x-extensions" && key !== "x-extensions-strict") {
51989
+ record(key, path ? `${path}.${key}` : key, nodeType);
51990
+ }
51991
+ }
51992
+ }
51993
+ walkObj(dsl, "", "root");
51994
+ if (isRecord4(dsl.system)) {
51995
+ walkObj(dsl.system, "system", "system");
51996
+ }
51997
+ for (const [id, agent] of Object.entries(dsl.agents)) {
51998
+ const agentObj = agent;
51999
+ walkObj(agentObj, `agents.${id}`, "agent");
52000
+ if (Array.isArray(agentObj["rules"])) {
52001
+ for (let i3 = 0; i3 < agentObj["rules"].length; i3++) {
52002
+ const r3 = agentObj["rules"][i3];
52003
+ if (isRecord4(r3)) walkObj(r3, `agents.${id}.rules[${i3}]`, "rule");
52004
+ }
52005
+ }
52006
+ if (Array.isArray(agentObj["escalation_criteria"])) {
52007
+ for (let i3 = 0; i3 < agentObj["escalation_criteria"].length; i3++) {
52008
+ const e3 = agentObj["escalation_criteria"][i3];
52009
+ if (isRecord4(e3)) walkObj(e3, `agents.${id}.escalation_criteria[${i3}]`, "escalation_criterion");
52010
+ }
52011
+ }
52012
+ if (Array.isArray(agentObj["prerequisites"])) {
52013
+ for (let i3 = 0; i3 < agentObj["prerequisites"].length; i3++) {
52014
+ const p2 = agentObj["prerequisites"][i3];
52015
+ if (isRecord4(p2)) walkObj(p2, `agents.${id}.prerequisites[${i3}]`, "prerequisite");
52016
+ }
52017
+ }
52018
+ }
52019
+ for (const [id, task] of Object.entries(dsl.tasks)) {
52020
+ const taskObj = task;
52021
+ walkObj(taskObj, `tasks.${id}`, "task");
52022
+ if (Array.isArray(taskObj["execution_steps"])) {
52023
+ for (let i3 = 0; i3 < taskObj["execution_steps"].length; i3++) {
52024
+ const s2 = taskObj["execution_steps"][i3];
52025
+ if (isRecord4(s2)) walkObj(s2, `tasks.${id}.execution_steps[${i3}]`, "execution_step");
52026
+ }
52027
+ }
52028
+ }
52029
+ for (const [id, art] of Object.entries(dsl.artifacts)) {
52030
+ walkObj(art, `artifacts.${id}`, "artifact");
52031
+ }
52032
+ for (const [id, tool] of Object.entries(dsl.tools)) {
52033
+ const toolObj = tool;
52034
+ walkObj(toolObj, `tools.${id}`, "tool");
52035
+ if (Array.isArray(toolObj["commands"])) {
52036
+ for (let i3 = 0; i3 < toolObj["commands"].length; i3++) {
52037
+ const c2 = toolObj["commands"][i3];
52038
+ if (isRecord4(c2)) walkObj(c2, `tools.${id}.commands[${i3}]`, "tool_command");
52039
+ }
52040
+ }
52041
+ }
52042
+ for (const [id, val] of Object.entries(dsl.validations)) {
52043
+ walkObj(val, `validations.${id}`, "validation");
52044
+ }
52045
+ for (const [id, ht] of Object.entries(dsl.handoff_types)) {
52046
+ walkObj(ht, `handoff_types.${id}`, "handoff_type");
52047
+ }
52048
+ for (const [id, wf] of Object.entries(dsl.workflow)) {
52049
+ const wfObj = wf;
52050
+ walkObj(wfObj, `workflow.${id}`, "workflow");
52051
+ if (Array.isArray(wfObj["steps"])) {
52052
+ for (let i3 = 0; i3 < wfObj["steps"].length; i3++) {
52053
+ const s2 = wfObj["steps"][i3];
52054
+ if (isRecord4(s2)) walkObj(s2, `workflow.${id}.steps[${i3}]`, "workflow_step");
52055
+ }
52056
+ }
52057
+ }
52058
+ for (const [id, pol] of Object.entries(dsl.policies)) {
52059
+ walkObj(pol, `policies.${id}`, "policy");
52060
+ }
52061
+ for (const [id, gr] of Object.entries(dsl.guardrails)) {
52062
+ walkObj(gr, `guardrails.${id}`, "guardrail");
52063
+ }
52064
+ for (const [id, gp] of Object.entries(dsl.guardrail_policies)) {
52065
+ walkObj(gp, `guardrail_policies.${id}`, "guardrail_policy");
52066
+ }
52067
+ return usages;
52068
+ }
52069
+ var extensionDeclaredButUnusedRule = {
52070
+ id: "extension-declared-unused",
52071
+ description: "Declared extension in `extensions` is never used on any entity",
52072
+ run(dsl) {
52073
+ const diagnostics = [];
52074
+ const declaredKeys = Object.keys(dsl.extensions);
52075
+ if (declaredKeys.length === 0) return diagnostics;
52076
+ const usages = collectXUsages(dsl);
52077
+ for (const key of declaredKeys) {
52078
+ if (!usages.has(key)) {
52079
+ diagnostics.push({
52080
+ ruleId: "extension-declared-unused",
52081
+ severity: "warning",
52082
+ path: `extensions.${key}`,
52083
+ message: `Extension "${key}" is declared but never used on any entity`
52084
+ });
52085
+ }
52086
+ }
52087
+ return diagnostics;
52088
+ }
52089
+ };
52090
+ var extensionScopeMismatchRule = {
52091
+ id: "extension-scope-mismatch",
52092
+ description: "Extension used on a node type outside its declared scope",
52093
+ run(dsl) {
52094
+ const diagnostics = [];
52095
+ const extensions = dsl.extensions;
52096
+ if (Object.keys(extensions).length === 0) return diagnostics;
52097
+ const usages = collectXUsages(dsl);
52098
+ for (const [key, decl] of Object.entries(extensions)) {
52099
+ const scope = decl.scope;
52100
+ if (!scope || scope.length === 0) continue;
52101
+ const scopeSet = new Set(scope);
52102
+ const keyUsages = usages.get(key);
52103
+ if (!keyUsages) continue;
52104
+ for (const usage of keyUsages) {
52105
+ if (!scopeSet.has(usage.nodeType)) {
52106
+ diagnostics.push({
52107
+ ruleId: "extension-scope-mismatch",
52108
+ severity: "warning",
52109
+ path: usage.path,
52110
+ message: `Extension "${key}" is used on ${usage.nodeType} but declared scope is [${scope.join(", ")}]`
52111
+ });
52112
+ }
52113
+ }
52114
+ }
52115
+ return diagnostics;
52116
+ }
52117
+ };
52118
+ var extensionUndeclaredUsageRule = {
52119
+ id: "extension-undeclared-usage",
52120
+ description: "Entity uses x-* property that is not declared in extensions (when extensions section exists)",
52121
+ run(dsl) {
52122
+ const diagnostics = [];
52123
+ const extensions = dsl.extensions;
52124
+ if (Object.keys(extensions).length === 0) return diagnostics;
52125
+ const declaredKeys = new Set(Object.keys(extensions));
52126
+ const usages = collectXUsages(dsl);
52127
+ for (const [key, keyUsages] of usages) {
52128
+ if (declaredKeys.has(key)) continue;
52129
+ for (const usage of keyUsages) {
52130
+ diagnostics.push({
52131
+ ruleId: "extension-undeclared-usage",
52132
+ severity: "info",
52133
+ path: usage.path,
52134
+ message: `Extension "${key}" is used but not declared in extensions \u2014 consider adding a declaration`
52135
+ });
52136
+ }
52137
+ }
52138
+ return diagnostics;
52139
+ }
52140
+ };
52141
+
51919
52142
  // src/linter/linter.ts
51920
52143
  var builtinRules = [
51921
52144
  validationCoverageRule,
@@ -51932,7 +52155,10 @@ var builtinRules = [
51932
52155
  entityGuardrailUndefinedRule,
51933
52156
  entityNoGuardrailsRule,
51934
52157
  guardrailOrphanedRule,
51935
- validationExecutorNoContextRule
52158
+ validationExecutorNoContextRule,
52159
+ extensionDeclaredButUnusedRule,
52160
+ extensionScopeMismatchRule,
52161
+ extensionUndeclaredUsageRule
51936
52162
  ];
51937
52163
  function lint(dsl, rules = builtinRules) {
51938
52164
  const diagnostics = [];
@@ -54167,7 +54393,8 @@ ${issues}`,
54167
54393
  bindings: [],
54168
54394
  activeGuardrailPolicy: void 0,
54169
54395
  paths: void 0,
54170
- teams: resolveTeamConfigs(config.teams, configDir)
54396
+ teams: resolveTeamConfigs(config.teams, configDir),
54397
+ audit: config.audit ?? void 0
54171
54398
  };
54172
54399
  }
54173
54400
  return {
@@ -54177,7 +54404,8 @@ ${issues}`,
54177
54404
  configDir,
54178
54405
  bindings: (config.bindings ?? []).map((b3) => resolve4(configDir, b3)),
54179
54406
  activeGuardrailPolicy: config.active_guardrail_policy,
54180
- paths: config.paths
54407
+ paths: config.paths,
54408
+ audit: config.audit ?? void 0
54181
54409
  };
54182
54410
  }
54183
54411
  function resolveDslPath(dirArg, dirArgDefault, config) {
@@ -54191,7 +54419,7 @@ function resolveDslPath(dirArg, dirArgDefault, config) {
54191
54419
  }
54192
54420
 
54193
54421
  // src/config/binding-merger.ts
54194
- function isRecord4(v2) {
54422
+ function isRecord5(v2) {
54195
54423
  return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
54196
54424
  }
54197
54425
  var BINDING_MAP_MERGE_SECTIONS = ["guardrail_impl", "outputs"];
@@ -54205,7 +54433,7 @@ function mergeBinding(base, project) {
54205
54433
  if (projVal === void 0) {
54206
54434
  continue;
54207
54435
  }
54208
- const baseMap = isRecord4(baseVal) ? baseVal : {};
54436
+ const baseMap = isRecord5(baseVal) ? baseVal : {};
54209
54437
  result[section] = mergeEntityMaps(
54210
54438
  baseMap,
54211
54439
  projVal,
@@ -54221,7 +54449,7 @@ function mergeBinding(base, project) {
54221
54449
  const projArr = Array.isArray(projVal) ? projVal : [];
54222
54450
  result[section] = [...baseArr, ...projArr];
54223
54451
  }
54224
- if (project["reporting"] !== void 0 && isRecord4(base["reporting"]) && isRecord4(project["reporting"])) {
54452
+ if (project["reporting"] !== void 0 && isRecord5(base["reporting"]) && isRecord5(project["reporting"])) {
54225
54453
  result["reporting"] = deepMergeEntities(
54226
54454
  base["reporting"],
54227
54455
  project["reporting"],
@@ -54717,6 +54945,121 @@ function formatDslOverview(dsl) {
54717
54945
  `- Validations: ${Object.keys(dsl.validations).join(", ")}`
54718
54946
  ].join("\n");
54719
54947
  }
54948
+ function isRecord6(v2) {
54949
+ return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
54950
+ }
54951
+ function collectAllXUsages(dsl) {
54952
+ const entries = [];
54953
+ function walk(obj, path, nodeType) {
54954
+ for (const key of Object.keys(obj)) {
54955
+ if (key.startsWith("x-") && key !== "x-extensions" && key !== "x-extensions-strict") {
54956
+ entries.push({ path: path ? `${path}.${key}` : key, nodeType, key });
54957
+ }
54958
+ }
54959
+ }
54960
+ walk(dsl, "", "root");
54961
+ if (isRecord6(dsl.system)) walk(dsl.system, "system", "system");
54962
+ for (const [id, a3] of Object.entries(dsl.agents))
54963
+ walk(a3, `agents.${id}`, "agent");
54964
+ for (const [id, t3] of Object.entries(dsl.tasks))
54965
+ walk(t3, `tasks.${id}`, "task");
54966
+ for (const [id, a3] of Object.entries(dsl.artifacts))
54967
+ walk(a3, `artifacts.${id}`, "artifact");
54968
+ for (const [id, t3] of Object.entries(dsl.tools))
54969
+ walk(t3, `tools.${id}`, "tool");
54970
+ for (const [id, v2] of Object.entries(dsl.validations))
54971
+ walk(v2, `validations.${id}`, "validation");
54972
+ for (const [id, h2] of Object.entries(dsl.handoff_types))
54973
+ walk(h2, `handoff_types.${id}`, "handoff_type");
54974
+ for (const [id, w2] of Object.entries(dsl.workflow))
54975
+ walk(w2, `workflow.${id}`, "workflow");
54976
+ for (const [id, p2] of Object.entries(dsl.policies))
54977
+ walk(p2, `policies.${id}`, "policy");
54978
+ for (const [id, g2] of Object.entries(dsl.guardrails))
54979
+ walk(g2, `guardrails.${id}`, "guardrail");
54980
+ for (const [id, gp] of Object.entries(dsl.guardrail_policies))
54981
+ walk(gp, `guardrail_policies.${id}`, "guardrail_policy");
54982
+ return entries;
54983
+ }
54984
+ function extractTemplateXReferences(config) {
54985
+ const refs = [];
54986
+ try {
54987
+ const { readFileSync } = __require("fs");
54988
+ for (const target of config.renders) {
54989
+ try {
54990
+ const content = readFileSync(target.template, "utf8");
54991
+ const matches = content.matchAll(/\{\{[^}]*?(x-[\w-]+)[^}]*?\}\}/g);
54992
+ for (const m2 of matches) refs.push(m2[1]);
54993
+ } catch {
54994
+ }
54995
+ }
54996
+ } catch {
54997
+ }
54998
+ return [...new Set(refs)];
54999
+ }
55000
+ function buildExtensionsContext(dsl, config) {
55001
+ const parts = [];
55002
+ parts.push("## Extension Declarations");
55003
+ const declaredKeys = Object.keys(dsl.extensions);
55004
+ if (declaredKeys.length === 0) {
55005
+ parts.push("(No extensions declared in `extensions` section)");
55006
+ } else {
55007
+ parts.push("```yaml\n" + yaml.stringify({ extensions: dsl.extensions }) + "```");
55008
+ }
55009
+ parts.push("## x-* Usage Map");
55010
+ const usages = collectAllXUsages(dsl);
55011
+ if (usages.length === 0) {
55012
+ parts.push("(No x-* properties found on any entity)");
55013
+ } else {
55014
+ const byKey = /* @__PURE__ */ new Map();
55015
+ for (const u2 of usages) {
55016
+ let list = byKey.get(u2.key);
55017
+ if (!list) {
55018
+ list = [];
55019
+ byKey.set(u2.key, list);
55020
+ }
55021
+ list.push(u2);
55022
+ }
55023
+ const lines = ["| Extension | Node Type | Path |", "|-----------|-----------|------|"];
55024
+ for (const [key, entries] of byKey) {
55025
+ for (const e3 of entries) {
55026
+ lines.push(`| ${key} | ${e3.nodeType} | ${e3.path} |`);
55027
+ }
55028
+ }
55029
+ parts.push(lines.join("\n"));
55030
+ }
55031
+ parts.push("## Template x-* References");
55032
+ const templateRefs = extractTemplateXReferences(config);
55033
+ if (templateRefs.length === 0) {
55034
+ parts.push("(No x-* references found in render templates, or no templates configured)");
55035
+ } else {
55036
+ parts.push(templateRefs.map((r3) => `- ${r3}`).join("\n"));
55037
+ }
55038
+ parts.push("## Runtime Codegen Fixed Fields");
55039
+ parts.push(
55040
+ "The agent-contracts-runtime codegen templates emit only these fixed fields (x-* properties are not included in generated TypeScript contracts):\n- **AgentContract**: id, role_name, purpose, mode, dispatch_only, can_read_artifacts, can_write_artifacts, can_execute_tools, can_invoke_agents, can_return_handoffs, responsibilities, constraints, rules, escalation_criteria\n- **TaskContract**: id, description, target_agent, allowed_from_agents, workflow, invocation_handoff, result_handoff, input_artifacts, responsibilities, completion_criteria, optional\n- **WorkflowContract**: id, description, trigger, entry_conditions, steps"
55041
+ );
55042
+ const declaredSet = new Set(declaredKeys);
55043
+ const usedKeys = new Set(usages.map((u2) => u2.key));
55044
+ const templateRefSet = new Set(templateRefs);
55045
+ parts.push("## Gap Summary");
55046
+ const gaps = [];
55047
+ for (const key of declaredKeys) {
55048
+ if (!usedKeys.has(key)) gaps.push(`- **${key}**: declared but never populated on any entity`);
55049
+ }
55050
+ for (const key of usedKeys) {
55051
+ if (declaredKeys.length > 0 && !declaredSet.has(key))
55052
+ gaps.push(`- **${key}**: used on entities but not declared in extensions`);
55053
+ if (!templateRefSet.has(key))
55054
+ gaps.push(`- **${key}**: populated on entities but not referenced in any render template`);
55055
+ }
55056
+ if (gaps.length === 0) {
55057
+ parts.push("(No obvious gaps detected by static analysis)");
55058
+ } else {
55059
+ parts.push(gaps.join("\n"));
55060
+ }
55061
+ return parts.join("\n\n");
55062
+ }
54720
55063
  async function buildAuditContext(auditType, dsl, config) {
54721
55064
  const sections = [];
54722
55065
  sections.push(formatDslOverview(dsl));
@@ -54737,6 +55080,9 @@ ${entry.content}`);
54737
55080
  sections.push("(No rendered agent prompt files found. Run `agent-contracts render` first.)");
54738
55081
  }
54739
55082
  }
55083
+ if (auditType === "extensions") {
55084
+ sections.push(buildExtensionsContext(dsl, config));
55085
+ }
54740
55086
  if (auditType === "dsl") {
54741
55087
  sections.push("## Agent Definitions");
54742
55088
  for (const [agentId, agentDef] of Object.entries(dsl.agents)) {
@@ -54803,7 +55149,8 @@ var dslAuditor = {
54803
55149
  "Prioritize improvement recommendations (P0/P1/P2) with concrete fix proposals",
54804
55150
  "Report score-based improvement areas as audit recommendations (read-only; consumes dsl-score-report produced by dsl-designer)",
54805
55151
  "Review DSL design for semantic coherence (role overlap, scope breadth, gate placement)",
54806
- "Verify generated prompts faithfully represent DSL intent (no hallucinated permissions)"
55152
+ "Verify generated prompts faithfully represent DSL intent (no hallucinated permissions)",
55153
+ "Audit x-* extension consumption across render templates and runtime codegen paths"
54807
55154
  ],
54808
55155
  constraints: [
54809
55156
  "Do not directly modify DSL definitions (read-only analysis)",
@@ -55064,12 +55411,14 @@ var auditSemanticDesign = {
55064
55411
  "Verify handoff schemas carry sufficient fields for task completion_criteria",
55065
55412
  "Check workflow gates are placed effectively",
55066
55413
  "Detect guardrails declared but absent from execution path",
55067
- "Check semantic validations are distributed across phases"
55414
+ "Check semantic validations are distributed across phases",
55415
+ "Detect custom x- properties that replicate standard DSL control-flow features (gate, decision, entry_conditions)"
55068
55416
  ],
55069
55417
  completion_criteria: [
55070
55418
  "All agents reviewed for scope and overlap",
55071
55419
  "Workflow gate placement analyzed",
55072
55420
  "Guardrail enforcement path verified",
55421
+ "Custom x- property misuse flagged",
55073
55422
  "Findings classified with severity and category"
55074
55423
  ],
55075
55424
  optional: false
@@ -55102,6 +55451,35 @@ var auditGeneratedPrompts = {
55102
55451
  ],
55103
55452
  optional: false
55104
55453
  };
55454
+ var auditExtensionConsumption = {
55455
+ id: "audit-extension-consumption",
55456
+ description: "Audit declared x-* extensions for consumption gaps across render and runtime paths",
55457
+ target_agent: "dsl-auditor",
55458
+ allowed_from_agents: [
55459
+ "dsl-auditor"
55460
+ ],
55461
+ workflow: "dsl-audit",
55462
+ invocation_handoff: "dsl-task-request",
55463
+ result_handoff: "dsl-audit-result",
55464
+ input_artifacts: [
55465
+ "dsl-source",
55466
+ "dsl-generated-output"
55467
+ ],
55468
+ responsibilities: [
55469
+ "Cross-check extensions declarations against entity x-* usage",
55470
+ "Identify x-* properties populated in DSL but not consumed by any render template",
55471
+ "Detect semantic overlap between x-* extensions and standard DSL features",
55472
+ "Report runtime codegen reachability for each extension",
55473
+ "Distinguish intentional metadata-only extensions from consumption gaps"
55474
+ ],
55475
+ completion_criteria: [
55476
+ "All declared extensions checked for template and runtime consumption",
55477
+ "Unused extensions flagged with suggested action (remove, migrate to standard, or add template support)",
55478
+ "Runtime-unreachable extensions documented with explanation",
55479
+ "Findings classified with severity and category"
55480
+ ],
55481
+ optional: false
55482
+ };
55105
55483
  var taskRegistry = {
55106
55484
  "update-dsl-definitions": updateDslDefinitions,
55107
55485
  "update-dsl-binding": updateDslBinding,
@@ -55109,7 +55487,8 @@ var taskRegistry = {
55109
55487
  "check-dsl-score": checkDslScore,
55110
55488
  "audit-dsl-completeness": auditDslCompleteness,
55111
55489
  "audit-semantic-design": auditSemanticDesign,
55112
- "audit-generated-prompts": auditGeneratedPrompts
55490
+ "audit-generated-prompts": auditGeneratedPrompts,
55491
+ "audit-extension-consumption": auditExtensionConsumption
55113
55492
  };
55114
55493
 
55115
55494
  // src/generated/dsl-base/handoffs.ts
@@ -55131,8 +55510,44 @@ var DslTaskResultSchema = z20.object({
55131
55510
  score_dimensions: z20.record(z20.string(), z20.unknown()).optional(),
55132
55511
  notes: z20.string().optional()
55133
55512
  });
55513
+ var AuditResultSchema = z20.object({
55514
+ summary: z20.string(),
55515
+ riskLevel: z20.enum(["low", "medium", "high", "critical"]),
55516
+ findings: z20.array(z20.object({
55517
+ id: z20.string().optional(),
55518
+ severity: z20.enum(["info", "warning", "error", "critical"]),
55519
+ category: z20.string(),
55520
+ target: z20.string().optional(),
55521
+ location: z20.string().optional(),
55522
+ message: z20.string(),
55523
+ recommendation: z20.string().optional(),
55524
+ confidence: z20.number().optional(),
55525
+ evidence: z20.array(z20.object({
55526
+ kind: z20.enum(["file", "command", "schema", "diff", "stdout", "stderr", "text"]),
55527
+ target: z20.string().optional(),
55528
+ location: z20.string().optional(),
55529
+ excerpt: z20.string().optional()
55530
+ })).optional(),
55531
+ details: z20.record(z20.string(), z20.unknown()).optional()
55532
+ })),
55533
+ recommendedActions: z20.array(z20.object({
55534
+ kind: z20.enum(["run_command", "edit_file", "review", "confirm", "block", "ignore"]),
55535
+ title: z20.string(),
55536
+ command: z20.string().optional(),
55537
+ target: z20.string().optional(),
55538
+ rationale: z20.string().optional()
55539
+ })).optional(),
55540
+ metadata: z20.object({
55541
+ tool: z20.string().optional(),
55542
+ command: z20.string().optional(),
55543
+ version: z20.string().optional(),
55544
+ generatedAt: z20.string().optional(),
55545
+ adapter: z20.string().optional(),
55546
+ model: z20.string().optional()
55547
+ }).optional()
55548
+ });
55134
55549
  var DslAuditResultSchema = z20.object({
55135
- audit_type: z20.enum(["completeness", "semantic", "prompt"]),
55550
+ audit_type: z20.enum(["completeness", "semantic", "prompt", "extensions"]),
55136
55551
  total_dimensions: z20.number(),
55137
55552
  pass_count: z20.number(),
55138
55553
  miss_count: z20.number(),
@@ -55156,6 +55571,7 @@ var DslAuditResultSchema = z20.object({
55156
55571
  var handoffSchemas = {
55157
55572
  "dsl-task-request": DslTaskRequestSchema,
55158
55573
  "dsl-task-result": DslTaskResultSchema,
55574
+ "audit-result": AuditResultSchema,
55159
55575
  "dsl-audit-result": DslAuditResultSchema
55160
55576
  };
55161
55577
 
@@ -55208,7 +55624,8 @@ async function createAdapter(runtimePkg, name, config) {
55208
55624
  var AUDIT_TYPE_TO_TASK = {
55209
55625
  render: "audit-dsl-completeness",
55210
55626
  dsl: "audit-semantic-design",
55211
- prompt: "audit-generated-prompts"
55627
+ prompt: "audit-generated-prompts",
55628
+ extensions: "audit-extension-consumption"
55212
55629
  };
55213
55630
  async function runAudit(dsl, config, auditConfig, options) {
55214
55631
  const taskId = AUDIT_TYPE_TO_TASK[options.auditType];
@@ -55262,7 +55679,7 @@ async function runAudit(dsl, config, auditConfig, options) {
55262
55679
  };
55263
55680
  }
55264
55681
  async function runAllAudits(dsl, config, auditConfig, options) {
55265
- const types = ["render", "dsl", "prompt"];
55682
+ const types = ["render", "dsl", "prompt", "extensions"];
55266
55683
  const results = [];
55267
55684
  for (const auditType of types) {
55268
55685
  results.push(await runAudit(dsl, config, auditConfig, { ...options, auditType }));