agent-contracts 0.22.2 → 0.22.4

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
@@ -49462,7 +49464,7 @@ function deepClone(value) {
49462
49464
  }
49463
49465
  return result;
49464
49466
  }
49465
- function resolveJsonPointer(root, pointer) {
49467
+ function tryResolveJsonPointer(root, pointer) {
49466
49468
  const path = pointer.slice(2);
49467
49469
  const segments = path.split("/").map(
49468
49470
  (s2) => s2.replace(/~1/g, "/").replace(/~0/g, "~")
@@ -49476,12 +49478,19 @@ function resolveJsonPointer(root, pointer) {
49476
49478
  }
49477
49479
  current = current[segment];
49478
49480
  if (current === void 0) {
49479
- throw new DslLoadError(
49480
- `Cannot resolve JSON Pointer "${pointer}": path segment "${segment}" not found`
49481
- );
49481
+ return { found: false };
49482
49482
  }
49483
49483
  }
49484
- return current;
49484
+ return { found: true, value: current };
49485
+ }
49486
+ function resolveJsonPointer(root, pointer) {
49487
+ const result = tryResolveJsonPointer(root, pointer);
49488
+ if (!result.found) {
49489
+ throw new DslLoadError(
49490
+ `Cannot resolve JSON Pointer "${pointer}": target not found`
49491
+ );
49492
+ }
49493
+ return result.value;
49485
49494
  }
49486
49495
  function hasRefs(value) {
49487
49496
  if (!("$refs" in value)) return false;
@@ -49525,7 +49534,7 @@ function deepMergeRefs(a3, b3, sourcePath) {
49525
49534
  }
49526
49535
  return result;
49527
49536
  }
49528
- async function loadRefsSource(refPath, baseDir, resolving, rootDoc) {
49537
+ async function loadRefsSource(refPath, baseDir, resolving) {
49529
49538
  const target = resolve(baseDir, refPath);
49530
49539
  const s2 = await fsStat(target).catch(() => null);
49531
49540
  if (s2?.isDirectory()) {
@@ -49533,7 +49542,7 @@ async function loadRefsSource(refPath, baseDir, resolving, rootDoc) {
49533
49542
  throw new DslLoadError(`Circular $refs detected: ${target}`, target);
49534
49543
  }
49535
49544
  resolving.add(target);
49536
- const result = await loadDirectoryAsMap(target, resolving, rootDoc);
49545
+ const result = await loadDirectoryAsMap(target, resolving);
49537
49546
  resolving.delete(target);
49538
49547
  return result;
49539
49548
  }
@@ -49551,16 +49560,16 @@ async function loadRefsSource(refPath, baseDir, resolving, rootDoc) {
49551
49560
  target
49552
49561
  );
49553
49562
  }
49554
- const resolved = await resolveRefsDeep(
49563
+ const resolved = await assembleRefs(
49555
49564
  content,
49556
49565
  dirname(target),
49557
49566
  resolving,
49558
- rootDoc
49567
+ content
49559
49568
  );
49560
49569
  resolving.delete(target);
49561
49570
  return resolved;
49562
49571
  }
49563
- async function loadDirectoryAsMap(dirPath, resolving, rootDoc) {
49572
+ async function loadDirectoryAsMap(dirPath, resolving) {
49564
49573
  let entries;
49565
49574
  try {
49566
49575
  entries = await readdir(dirPath);
@@ -49587,17 +49596,17 @@ async function loadDirectoryAsMap(dirPath, resolving, rootDoc) {
49587
49596
  filePath
49588
49597
  );
49589
49598
  }
49590
- const resolved = await resolveRefsDeep(
49599
+ const resolved = await assembleRefs(
49591
49600
  content,
49592
49601
  dirPath,
49593
49602
  resolving,
49594
- rootDoc
49603
+ content
49595
49604
  );
49596
49605
  merged = deepMergeRefs(merged, resolved, filePath);
49597
49606
  }
49598
49607
  return merged;
49599
49608
  }
49600
- async function processRefs(obj, baseDir, resolving, rootDoc) {
49609
+ async function processRefs(obj, baseDir, resolving) {
49601
49610
  const refPaths = obj["$refs"];
49602
49611
  const inline = {};
49603
49612
  for (const [key, value] of Object.entries(obj)) {
@@ -49607,17 +49616,17 @@ async function processRefs(obj, baseDir, resolving, rootDoc) {
49607
49616
  }
49608
49617
  let merged = {};
49609
49618
  for (const refPath of refPaths) {
49610
- const loaded = await loadRefsSource(refPath, baseDir, resolving, rootDoc);
49619
+ const loaded = await loadRefsSource(refPath, baseDir, resolving);
49611
49620
  merged = deepMergeRefs(merged, loaded, refPath);
49612
49621
  }
49613
49622
  merged = deepMergeRefs(merged, inline, "(inline)");
49614
49623
  return merged;
49615
49624
  }
49616
- async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49625
+ async function assembleRefs(data, baseDir, resolving, fileRoot) {
49617
49626
  if (typeof data !== "object" || data === null) return data;
49618
49627
  if (Array.isArray(data)) {
49619
49628
  return Promise.all(
49620
- data.map((item) => resolveRefsDeep(item, baseDir, resolving, rootDoc))
49629
+ data.map((item) => assembleRefs(item, baseDir, resolving, fileRoot))
49621
49630
  );
49622
49631
  }
49623
49632
  if (isRef(data)) {
@@ -49626,13 +49635,16 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49626
49635
  if (resolving.has(refValue)) {
49627
49636
  throw new DslLoadError(`Circular $ref detected: ${refValue}`);
49628
49637
  }
49638
+ const result2 = tryResolveJsonPointer(fileRoot, refValue);
49639
+ if (!result2.found) {
49640
+ return data;
49641
+ }
49629
49642
  resolving.add(refValue);
49630
- const target = resolveJsonPointer(rootDoc, refValue);
49631
- const resolved = await resolveRefsDeep(
49632
- deepClone(target),
49643
+ const resolved = await assembleRefs(
49644
+ deepClone(result2.value),
49633
49645
  baseDir,
49634
49646
  resolving,
49635
- rootDoc
49647
+ fileRoot
49636
49648
  );
49637
49649
  resolving.delete(refValue);
49638
49650
  return resolved;
@@ -49656,7 +49668,7 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49656
49668
  );
49657
49669
  }
49658
49670
  resolving.add(refTarget);
49659
- const result2 = await loadDirectoryAsMap(refTarget, resolving, rootDoc);
49671
+ const result2 = await loadDirectoryAsMap(refTarget, resolving);
49660
49672
  resolving.delete(refTarget);
49661
49673
  return result2;
49662
49674
  }
@@ -49671,12 +49683,12 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49671
49683
  }
49672
49684
  resolving.add(refTarget);
49673
49685
  const content = await readYaml(refTarget);
49674
- const fileRoot = fragment ? content : rootDoc;
49675
- let fileData = await resolveRefsDeep(
49686
+ const newFileRoot = isRecord(content) ? content : fileRoot;
49687
+ let fileData = await assembleRefs(
49676
49688
  content,
49677
49689
  dirname(refTarget),
49678
49690
  resolving,
49679
- fileRoot
49691
+ newFileRoot
49680
49692
  );
49681
49693
  resolving.delete(refTarget);
49682
49694
  if (fragment && fragment.startsWith("#/")) {
@@ -49692,11 +49704,31 @@ async function resolveRefsDeep(data, baseDir, resolving, rootDoc) {
49692
49704
  }
49693
49705
  let obj = data;
49694
49706
  if (hasRefs(obj)) {
49695
- obj = await processRefs(obj, baseDir, resolving, rootDoc);
49707
+ obj = await processRefs(obj, baseDir, resolving);
49696
49708
  }
49697
49709
  const result = {};
49698
49710
  for (const [key, value] of Object.entries(obj)) {
49699
- result[key] = await resolveRefsDeep(value, baseDir, resolving, rootDoc);
49711
+ result[key] = await assembleRefs(value, baseDir, resolving, fileRoot);
49712
+ }
49713
+ return result;
49714
+ }
49715
+ function linkDocPointers(data, rootDoc) {
49716
+ if (typeof data !== "object" || data === null) return data;
49717
+ if (Array.isArray(data)) {
49718
+ return data.map((item) => linkDocPointers(item, rootDoc));
49719
+ }
49720
+ if (isRef(data)) {
49721
+ const refValue = data.$ref;
49722
+ if (refValue.startsWith("#/")) {
49723
+ const target = resolveJsonPointer(rootDoc, refValue);
49724
+ return linkDocPointers(deepClone(target), rootDoc);
49725
+ }
49726
+ return data;
49727
+ }
49728
+ const obj = data;
49729
+ const result = {};
49730
+ for (const [key, value] of Object.entries(obj)) {
49731
+ result[key] = linkDocPointers(value, rootDoc);
49700
49732
  }
49701
49733
  return result;
49702
49734
  }
@@ -49727,13 +49759,16 @@ async function loadDsl(entryPath) {
49727
49759
  const data = raw;
49728
49760
  checkVersion(data, absPath);
49729
49761
  const baseDir = dirname(absPath);
49730
- const resolving = /* @__PURE__ */ new Set([absPath]);
49731
- const resolved = await resolveRefsDeep(
49762
+ const assembled = await assembleRefs(
49732
49763
  data,
49733
49764
  baseDir,
49734
- resolving,
49765
+ /* @__PURE__ */ new Set([absPath]),
49735
49766
  data
49736
49767
  );
49768
+ const resolved = linkDocPointers(
49769
+ assembled,
49770
+ assembled
49771
+ );
49737
49772
  return { data: resolved, filePath: absPath };
49738
49773
  }
49739
49774
 
@@ -51342,6 +51377,7 @@ var taskAgentBindingRule = {
51342
51377
  }
51343
51378
  for (const [taskId, task] of Object.entries(dsl.tasks)) {
51344
51379
  for (const fromAgentId of task.allowed_from_agents) {
51380
+ if (fromAgentId === task.target_agent) continue;
51345
51381
  const fromAgent = dsl.agents[fromAgentId];
51346
51382
  if (fromAgent && !fromAgent.can_invoke_agents.includes(task.target_agent)) {
51347
51383
  diagnostics.push({
@@ -51916,6 +51952,176 @@ var validationExecutorNoContextRule = {
51916
51952
  }
51917
51953
  };
51918
51954
 
51955
+ // src/linter/rules/extension-consumption.ts
51956
+ function isRecord4(v2) {
51957
+ return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
51958
+ }
51959
+ function collectXUsages(dsl) {
51960
+ const usages = /* @__PURE__ */ new Map();
51961
+ function record(key, path, nodeType) {
51962
+ let list = usages.get(key);
51963
+ if (!list) {
51964
+ list = [];
51965
+ usages.set(key, list);
51966
+ }
51967
+ list.push({ path, nodeType });
51968
+ }
51969
+ function walkObj(obj, path, nodeType) {
51970
+ for (const key of Object.keys(obj)) {
51971
+ if (key.startsWith("x-") && key !== "x-extensions" && key !== "x-extensions-strict") {
51972
+ record(key, path ? `${path}.${key}` : key, nodeType);
51973
+ }
51974
+ }
51975
+ }
51976
+ walkObj(dsl, "", "root");
51977
+ if (isRecord4(dsl.system)) {
51978
+ walkObj(dsl.system, "system", "system");
51979
+ }
51980
+ for (const [id, agent] of Object.entries(dsl.agents)) {
51981
+ const agentObj = agent;
51982
+ walkObj(agentObj, `agents.${id}`, "agent");
51983
+ if (Array.isArray(agentObj["rules"])) {
51984
+ for (let i3 = 0; i3 < agentObj["rules"].length; i3++) {
51985
+ const r3 = agentObj["rules"][i3];
51986
+ if (isRecord4(r3)) walkObj(r3, `agents.${id}.rules[${i3}]`, "rule");
51987
+ }
51988
+ }
51989
+ if (Array.isArray(agentObj["escalation_criteria"])) {
51990
+ for (let i3 = 0; i3 < agentObj["escalation_criteria"].length; i3++) {
51991
+ const e3 = agentObj["escalation_criteria"][i3];
51992
+ if (isRecord4(e3)) walkObj(e3, `agents.${id}.escalation_criteria[${i3}]`, "escalation_criterion");
51993
+ }
51994
+ }
51995
+ if (Array.isArray(agentObj["prerequisites"])) {
51996
+ for (let i3 = 0; i3 < agentObj["prerequisites"].length; i3++) {
51997
+ const p2 = agentObj["prerequisites"][i3];
51998
+ if (isRecord4(p2)) walkObj(p2, `agents.${id}.prerequisites[${i3}]`, "prerequisite");
51999
+ }
52000
+ }
52001
+ }
52002
+ for (const [id, task] of Object.entries(dsl.tasks)) {
52003
+ const taskObj = task;
52004
+ walkObj(taskObj, `tasks.${id}`, "task");
52005
+ if (Array.isArray(taskObj["execution_steps"])) {
52006
+ for (let i3 = 0; i3 < taskObj["execution_steps"].length; i3++) {
52007
+ const s2 = taskObj["execution_steps"][i3];
52008
+ if (isRecord4(s2)) walkObj(s2, `tasks.${id}.execution_steps[${i3}]`, "execution_step");
52009
+ }
52010
+ }
52011
+ }
52012
+ for (const [id, art] of Object.entries(dsl.artifacts)) {
52013
+ walkObj(art, `artifacts.${id}`, "artifact");
52014
+ }
52015
+ for (const [id, tool] of Object.entries(dsl.tools)) {
52016
+ const toolObj = tool;
52017
+ walkObj(toolObj, `tools.${id}`, "tool");
52018
+ if (Array.isArray(toolObj["commands"])) {
52019
+ for (let i3 = 0; i3 < toolObj["commands"].length; i3++) {
52020
+ const c2 = toolObj["commands"][i3];
52021
+ if (isRecord4(c2)) walkObj(c2, `tools.${id}.commands[${i3}]`, "tool_command");
52022
+ }
52023
+ }
52024
+ }
52025
+ for (const [id, val] of Object.entries(dsl.validations)) {
52026
+ walkObj(val, `validations.${id}`, "validation");
52027
+ }
52028
+ for (const [id, ht] of Object.entries(dsl.handoff_types)) {
52029
+ walkObj(ht, `handoff_types.${id}`, "handoff_type");
52030
+ }
52031
+ for (const [id, wf] of Object.entries(dsl.workflow)) {
52032
+ const wfObj = wf;
52033
+ walkObj(wfObj, `workflow.${id}`, "workflow");
52034
+ if (Array.isArray(wfObj["steps"])) {
52035
+ for (let i3 = 0; i3 < wfObj["steps"].length; i3++) {
52036
+ const s2 = wfObj["steps"][i3];
52037
+ if (isRecord4(s2)) walkObj(s2, `workflow.${id}.steps[${i3}]`, "workflow_step");
52038
+ }
52039
+ }
52040
+ }
52041
+ for (const [id, pol] of Object.entries(dsl.policies)) {
52042
+ walkObj(pol, `policies.${id}`, "policy");
52043
+ }
52044
+ for (const [id, gr] of Object.entries(dsl.guardrails)) {
52045
+ walkObj(gr, `guardrails.${id}`, "guardrail");
52046
+ }
52047
+ for (const [id, gp] of Object.entries(dsl.guardrail_policies)) {
52048
+ walkObj(gp, `guardrail_policies.${id}`, "guardrail_policy");
52049
+ }
52050
+ return usages;
52051
+ }
52052
+ var extensionDeclaredButUnusedRule = {
52053
+ id: "extension-declared-unused",
52054
+ description: "Declared extension in `extensions` is never used on any entity",
52055
+ run(dsl) {
52056
+ const diagnostics = [];
52057
+ const declaredKeys = Object.keys(dsl.extensions);
52058
+ if (declaredKeys.length === 0) return diagnostics;
52059
+ const usages = collectXUsages(dsl);
52060
+ for (const key of declaredKeys) {
52061
+ if (!usages.has(key)) {
52062
+ diagnostics.push({
52063
+ ruleId: "extension-declared-unused",
52064
+ severity: "warning",
52065
+ path: `extensions.${key}`,
52066
+ message: `Extension "${key}" is declared but never used on any entity`
52067
+ });
52068
+ }
52069
+ }
52070
+ return diagnostics;
52071
+ }
52072
+ };
52073
+ var extensionScopeMismatchRule = {
52074
+ id: "extension-scope-mismatch",
52075
+ description: "Extension used on a node type outside its declared scope",
52076
+ run(dsl) {
52077
+ const diagnostics = [];
52078
+ const extensions = dsl.extensions;
52079
+ if (Object.keys(extensions).length === 0) return diagnostics;
52080
+ const usages = collectXUsages(dsl);
52081
+ for (const [key, decl] of Object.entries(extensions)) {
52082
+ const scope = decl.scope;
52083
+ if (!scope || scope.length === 0) continue;
52084
+ const scopeSet = new Set(scope);
52085
+ const keyUsages = usages.get(key);
52086
+ if (!keyUsages) continue;
52087
+ for (const usage of keyUsages) {
52088
+ if (!scopeSet.has(usage.nodeType)) {
52089
+ diagnostics.push({
52090
+ ruleId: "extension-scope-mismatch",
52091
+ severity: "warning",
52092
+ path: usage.path,
52093
+ message: `Extension "${key}" is used on ${usage.nodeType} but declared scope is [${scope.join(", ")}]`
52094
+ });
52095
+ }
52096
+ }
52097
+ }
52098
+ return diagnostics;
52099
+ }
52100
+ };
52101
+ var extensionUndeclaredUsageRule = {
52102
+ id: "extension-undeclared-usage",
52103
+ description: "Entity uses x-* property that is not declared in extensions (when extensions section exists)",
52104
+ run(dsl) {
52105
+ const diagnostics = [];
52106
+ const extensions = dsl.extensions;
52107
+ if (Object.keys(extensions).length === 0) return diagnostics;
52108
+ const declaredKeys = new Set(Object.keys(extensions));
52109
+ const usages = collectXUsages(dsl);
52110
+ for (const [key, keyUsages] of usages) {
52111
+ if (declaredKeys.has(key)) continue;
52112
+ for (const usage of keyUsages) {
52113
+ diagnostics.push({
52114
+ ruleId: "extension-undeclared-usage",
52115
+ severity: "info",
52116
+ path: usage.path,
52117
+ message: `Extension "${key}" is used but not declared in extensions \u2014 consider adding a declaration`
52118
+ });
52119
+ }
52120
+ }
52121
+ return diagnostics;
52122
+ }
52123
+ };
52124
+
51919
52125
  // src/linter/linter.ts
51920
52126
  var builtinRules = [
51921
52127
  validationCoverageRule,
@@ -51932,7 +52138,10 @@ var builtinRules = [
51932
52138
  entityGuardrailUndefinedRule,
51933
52139
  entityNoGuardrailsRule,
51934
52140
  guardrailOrphanedRule,
51935
- validationExecutorNoContextRule
52141
+ validationExecutorNoContextRule,
52142
+ extensionDeclaredButUnusedRule,
52143
+ extensionScopeMismatchRule,
52144
+ extensionUndeclaredUsageRule
51936
52145
  ];
51937
52146
  function lint(dsl, rules = builtinRules) {
51938
52147
  const diagnostics = [];
@@ -54167,7 +54376,8 @@ ${issues}`,
54167
54376
  bindings: [],
54168
54377
  activeGuardrailPolicy: void 0,
54169
54378
  paths: void 0,
54170
- teams: resolveTeamConfigs(config.teams, configDir)
54379
+ teams: resolveTeamConfigs(config.teams, configDir),
54380
+ audit: config.audit ?? void 0
54171
54381
  };
54172
54382
  }
54173
54383
  return {
@@ -54177,7 +54387,8 @@ ${issues}`,
54177
54387
  configDir,
54178
54388
  bindings: (config.bindings ?? []).map((b3) => resolve4(configDir, b3)),
54179
54389
  activeGuardrailPolicy: config.active_guardrail_policy,
54180
- paths: config.paths
54390
+ paths: config.paths,
54391
+ audit: config.audit ?? void 0
54181
54392
  };
54182
54393
  }
54183
54394
  function resolveDslPath(dirArg, dirArgDefault, config) {
@@ -54191,7 +54402,7 @@ function resolveDslPath(dirArg, dirArgDefault, config) {
54191
54402
  }
54192
54403
 
54193
54404
  // src/config/binding-merger.ts
54194
- function isRecord4(v2) {
54405
+ function isRecord5(v2) {
54195
54406
  return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
54196
54407
  }
54197
54408
  var BINDING_MAP_MERGE_SECTIONS = ["guardrail_impl", "outputs"];
@@ -54205,7 +54416,7 @@ function mergeBinding(base, project) {
54205
54416
  if (projVal === void 0) {
54206
54417
  continue;
54207
54418
  }
54208
- const baseMap = isRecord4(baseVal) ? baseVal : {};
54419
+ const baseMap = isRecord5(baseVal) ? baseVal : {};
54209
54420
  result[section] = mergeEntityMaps(
54210
54421
  baseMap,
54211
54422
  projVal,
@@ -54221,7 +54432,7 @@ function mergeBinding(base, project) {
54221
54432
  const projArr = Array.isArray(projVal) ? projVal : [];
54222
54433
  result[section] = [...baseArr, ...projArr];
54223
54434
  }
54224
- if (project["reporting"] !== void 0 && isRecord4(base["reporting"]) && isRecord4(project["reporting"])) {
54435
+ if (project["reporting"] !== void 0 && isRecord5(base["reporting"]) && isRecord5(project["reporting"])) {
54225
54436
  result["reporting"] = deepMergeEntities(
54226
54437
  base["reporting"],
54227
54438
  project["reporting"],
@@ -54717,6 +54928,121 @@ function formatDslOverview(dsl) {
54717
54928
  `- Validations: ${Object.keys(dsl.validations).join(", ")}`
54718
54929
  ].join("\n");
54719
54930
  }
54931
+ function isRecord6(v2) {
54932
+ return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
54933
+ }
54934
+ function collectAllXUsages(dsl) {
54935
+ const entries = [];
54936
+ function walk(obj, path, nodeType) {
54937
+ for (const key of Object.keys(obj)) {
54938
+ if (key.startsWith("x-") && key !== "x-extensions" && key !== "x-extensions-strict") {
54939
+ entries.push({ path: path ? `${path}.${key}` : key, nodeType, key });
54940
+ }
54941
+ }
54942
+ }
54943
+ walk(dsl, "", "root");
54944
+ if (isRecord6(dsl.system)) walk(dsl.system, "system", "system");
54945
+ for (const [id, a3] of Object.entries(dsl.agents))
54946
+ walk(a3, `agents.${id}`, "agent");
54947
+ for (const [id, t3] of Object.entries(dsl.tasks))
54948
+ walk(t3, `tasks.${id}`, "task");
54949
+ for (const [id, a3] of Object.entries(dsl.artifacts))
54950
+ walk(a3, `artifacts.${id}`, "artifact");
54951
+ for (const [id, t3] of Object.entries(dsl.tools))
54952
+ walk(t3, `tools.${id}`, "tool");
54953
+ for (const [id, v2] of Object.entries(dsl.validations))
54954
+ walk(v2, `validations.${id}`, "validation");
54955
+ for (const [id, h2] of Object.entries(dsl.handoff_types))
54956
+ walk(h2, `handoff_types.${id}`, "handoff_type");
54957
+ for (const [id, w2] of Object.entries(dsl.workflow))
54958
+ walk(w2, `workflow.${id}`, "workflow");
54959
+ for (const [id, p2] of Object.entries(dsl.policies))
54960
+ walk(p2, `policies.${id}`, "policy");
54961
+ for (const [id, g2] of Object.entries(dsl.guardrails))
54962
+ walk(g2, `guardrails.${id}`, "guardrail");
54963
+ for (const [id, gp] of Object.entries(dsl.guardrail_policies))
54964
+ walk(gp, `guardrail_policies.${id}`, "guardrail_policy");
54965
+ return entries;
54966
+ }
54967
+ function extractTemplateXReferences(config) {
54968
+ const refs = [];
54969
+ try {
54970
+ const { readFileSync } = __require("fs");
54971
+ for (const target of config.renders) {
54972
+ try {
54973
+ const content = readFileSync(target.template, "utf8");
54974
+ const matches = content.matchAll(/\{\{[^}]*?(x-[\w-]+)[^}]*?\}\}/g);
54975
+ for (const m2 of matches) refs.push(m2[1]);
54976
+ } catch {
54977
+ }
54978
+ }
54979
+ } catch {
54980
+ }
54981
+ return [...new Set(refs)];
54982
+ }
54983
+ function buildExtensionsContext(dsl, config) {
54984
+ const parts = [];
54985
+ parts.push("## Extension Declarations");
54986
+ const declaredKeys = Object.keys(dsl.extensions);
54987
+ if (declaredKeys.length === 0) {
54988
+ parts.push("(No extensions declared in `extensions` section)");
54989
+ } else {
54990
+ parts.push("```yaml\n" + yaml.stringify({ extensions: dsl.extensions }) + "```");
54991
+ }
54992
+ parts.push("## x-* Usage Map");
54993
+ const usages = collectAllXUsages(dsl);
54994
+ if (usages.length === 0) {
54995
+ parts.push("(No x-* properties found on any entity)");
54996
+ } else {
54997
+ const byKey = /* @__PURE__ */ new Map();
54998
+ for (const u2 of usages) {
54999
+ let list = byKey.get(u2.key);
55000
+ if (!list) {
55001
+ list = [];
55002
+ byKey.set(u2.key, list);
55003
+ }
55004
+ list.push(u2);
55005
+ }
55006
+ const lines = ["| Extension | Node Type | Path |", "|-----------|-----------|------|"];
55007
+ for (const [key, entries] of byKey) {
55008
+ for (const e3 of entries) {
55009
+ lines.push(`| ${key} | ${e3.nodeType} | ${e3.path} |`);
55010
+ }
55011
+ }
55012
+ parts.push(lines.join("\n"));
55013
+ }
55014
+ parts.push("## Template x-* References");
55015
+ const templateRefs = extractTemplateXReferences(config);
55016
+ if (templateRefs.length === 0) {
55017
+ parts.push("(No x-* references found in render templates, or no templates configured)");
55018
+ } else {
55019
+ parts.push(templateRefs.map((r3) => `- ${r3}`).join("\n"));
55020
+ }
55021
+ parts.push("## Runtime Codegen Fixed Fields");
55022
+ parts.push(
55023
+ "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"
55024
+ );
55025
+ const declaredSet = new Set(declaredKeys);
55026
+ const usedKeys = new Set(usages.map((u2) => u2.key));
55027
+ const templateRefSet = new Set(templateRefs);
55028
+ parts.push("## Gap Summary");
55029
+ const gaps = [];
55030
+ for (const key of declaredKeys) {
55031
+ if (!usedKeys.has(key)) gaps.push(`- **${key}**: declared but never populated on any entity`);
55032
+ }
55033
+ for (const key of usedKeys) {
55034
+ if (declaredKeys.length > 0 && !declaredSet.has(key))
55035
+ gaps.push(`- **${key}**: used on entities but not declared in extensions`);
55036
+ if (!templateRefSet.has(key))
55037
+ gaps.push(`- **${key}**: populated on entities but not referenced in any render template`);
55038
+ }
55039
+ if (gaps.length === 0) {
55040
+ parts.push("(No obvious gaps detected by static analysis)");
55041
+ } else {
55042
+ parts.push(gaps.join("\n"));
55043
+ }
55044
+ return parts.join("\n\n");
55045
+ }
54720
55046
  async function buildAuditContext(auditType, dsl, config) {
54721
55047
  const sections = [];
54722
55048
  sections.push(formatDslOverview(dsl));
@@ -54737,6 +55063,9 @@ ${entry.content}`);
54737
55063
  sections.push("(No rendered agent prompt files found. Run `agent-contracts render` first.)");
54738
55064
  }
54739
55065
  }
55066
+ if (auditType === "extensions") {
55067
+ sections.push(buildExtensionsContext(dsl, config));
55068
+ }
54740
55069
  if (auditType === "dsl") {
54741
55070
  sections.push("## Agent Definitions");
54742
55071
  for (const [agentId, agentDef] of Object.entries(dsl.agents)) {
@@ -54803,7 +55132,8 @@ var dslAuditor = {
54803
55132
  "Prioritize improvement recommendations (P0/P1/P2) with concrete fix proposals",
54804
55133
  "Report score-based improvement areas as audit recommendations (read-only; consumes dsl-score-report produced by dsl-designer)",
54805
55134
  "Review DSL design for semantic coherence (role overlap, scope breadth, gate placement)",
54806
- "Verify generated prompts faithfully represent DSL intent (no hallucinated permissions)"
55135
+ "Verify generated prompts faithfully represent DSL intent (no hallucinated permissions)",
55136
+ "Audit x-* extension consumption across render templates and runtime codegen paths"
54807
55137
  ],
54808
55138
  constraints: [
54809
55139
  "Do not directly modify DSL definitions (read-only analysis)",
@@ -55064,12 +55394,14 @@ var auditSemanticDesign = {
55064
55394
  "Verify handoff schemas carry sufficient fields for task completion_criteria",
55065
55395
  "Check workflow gates are placed effectively",
55066
55396
  "Detect guardrails declared but absent from execution path",
55067
- "Check semantic validations are distributed across phases"
55397
+ "Check semantic validations are distributed across phases",
55398
+ "Detect custom x- properties that replicate standard DSL control-flow features (gate, decision, entry_conditions)"
55068
55399
  ],
55069
55400
  completion_criteria: [
55070
55401
  "All agents reviewed for scope and overlap",
55071
55402
  "Workflow gate placement analyzed",
55072
55403
  "Guardrail enforcement path verified",
55404
+ "Custom x- property misuse flagged",
55073
55405
  "Findings classified with severity and category"
55074
55406
  ],
55075
55407
  optional: false
@@ -55102,6 +55434,35 @@ var auditGeneratedPrompts = {
55102
55434
  ],
55103
55435
  optional: false
55104
55436
  };
55437
+ var auditExtensionConsumption = {
55438
+ id: "audit-extension-consumption",
55439
+ description: "Audit declared x-* extensions for consumption gaps across render and runtime paths",
55440
+ target_agent: "dsl-auditor",
55441
+ allowed_from_agents: [
55442
+ "dsl-auditor"
55443
+ ],
55444
+ workflow: "dsl-audit",
55445
+ invocation_handoff: "dsl-task-request",
55446
+ result_handoff: "dsl-audit-result",
55447
+ input_artifacts: [
55448
+ "dsl-source",
55449
+ "dsl-generated-output"
55450
+ ],
55451
+ responsibilities: [
55452
+ "Cross-check extensions declarations against entity x-* usage",
55453
+ "Identify x-* properties populated in DSL but not consumed by any render template",
55454
+ "Detect semantic overlap between x-* extensions and standard DSL features",
55455
+ "Report runtime codegen reachability for each extension",
55456
+ "Distinguish intentional metadata-only extensions from consumption gaps"
55457
+ ],
55458
+ completion_criteria: [
55459
+ "All declared extensions checked for template and runtime consumption",
55460
+ "Unused extensions flagged with suggested action (remove, migrate to standard, or add template support)",
55461
+ "Runtime-unreachable extensions documented with explanation",
55462
+ "Findings classified with severity and category"
55463
+ ],
55464
+ optional: false
55465
+ };
55105
55466
  var taskRegistry = {
55106
55467
  "update-dsl-definitions": updateDslDefinitions,
55107
55468
  "update-dsl-binding": updateDslBinding,
@@ -55109,7 +55470,8 @@ var taskRegistry = {
55109
55470
  "check-dsl-score": checkDslScore,
55110
55471
  "audit-dsl-completeness": auditDslCompleteness,
55111
55472
  "audit-semantic-design": auditSemanticDesign,
55112
- "audit-generated-prompts": auditGeneratedPrompts
55473
+ "audit-generated-prompts": auditGeneratedPrompts,
55474
+ "audit-extension-consumption": auditExtensionConsumption
55113
55475
  };
55114
55476
 
55115
55477
  // src/generated/dsl-base/handoffs.ts
@@ -55131,8 +55493,44 @@ var DslTaskResultSchema = z20.object({
55131
55493
  score_dimensions: z20.record(z20.string(), z20.unknown()).optional(),
55132
55494
  notes: z20.string().optional()
55133
55495
  });
55496
+ var AuditResultSchema = z20.object({
55497
+ summary: z20.string(),
55498
+ riskLevel: z20.enum(["low", "medium", "high", "critical"]),
55499
+ findings: z20.array(z20.object({
55500
+ id: z20.string().optional(),
55501
+ severity: z20.enum(["info", "warning", "error", "critical"]),
55502
+ category: z20.string(),
55503
+ target: z20.string().optional(),
55504
+ location: z20.string().optional(),
55505
+ message: z20.string(),
55506
+ recommendation: z20.string().optional(),
55507
+ confidence: z20.number().optional(),
55508
+ evidence: z20.array(z20.object({
55509
+ kind: z20.enum(["file", "command", "schema", "diff", "stdout", "stderr", "text"]),
55510
+ target: z20.string().optional(),
55511
+ location: z20.string().optional(),
55512
+ excerpt: z20.string().optional()
55513
+ })).optional(),
55514
+ details: z20.record(z20.string(), z20.unknown()).optional()
55515
+ })),
55516
+ recommendedActions: z20.array(z20.object({
55517
+ kind: z20.enum(["run_command", "edit_file", "review", "confirm", "block", "ignore"]),
55518
+ title: z20.string(),
55519
+ command: z20.string().optional(),
55520
+ target: z20.string().optional(),
55521
+ rationale: z20.string().optional()
55522
+ })).optional(),
55523
+ metadata: z20.object({
55524
+ tool: z20.string().optional(),
55525
+ command: z20.string().optional(),
55526
+ version: z20.string().optional(),
55527
+ generatedAt: z20.string().optional(),
55528
+ adapter: z20.string().optional(),
55529
+ model: z20.string().optional()
55530
+ }).optional()
55531
+ });
55134
55532
  var DslAuditResultSchema = z20.object({
55135
- audit_type: z20.enum(["completeness", "semantic", "prompt"]),
55533
+ audit_type: z20.enum(["completeness", "semantic", "prompt", "extensions"]),
55136
55534
  total_dimensions: z20.number(),
55137
55535
  pass_count: z20.number(),
55138
55536
  miss_count: z20.number(),
@@ -55156,6 +55554,7 @@ var DslAuditResultSchema = z20.object({
55156
55554
  var handoffSchemas = {
55157
55555
  "dsl-task-request": DslTaskRequestSchema,
55158
55556
  "dsl-task-result": DslTaskResultSchema,
55557
+ "audit-result": AuditResultSchema,
55159
55558
  "dsl-audit-result": DslAuditResultSchema
55160
55559
  };
55161
55560
 
@@ -55208,7 +55607,8 @@ async function createAdapter(runtimePkg, name, config) {
55208
55607
  var AUDIT_TYPE_TO_TASK = {
55209
55608
  render: "audit-dsl-completeness",
55210
55609
  dsl: "audit-semantic-design",
55211
- prompt: "audit-generated-prompts"
55610
+ prompt: "audit-generated-prompts",
55611
+ extensions: "audit-extension-consumption"
55212
55612
  };
55213
55613
  async function runAudit(dsl, config, auditConfig, options) {
55214
55614
  const taskId = AUDIT_TYPE_TO_TASK[options.auditType];
@@ -55262,7 +55662,7 @@ async function runAudit(dsl, config, auditConfig, options) {
55262
55662
  };
55263
55663
  }
55264
55664
  async function runAllAudits(dsl, config, auditConfig, options) {
55265
- const types = ["render", "dsl", "prompt"];
55665
+ const types = ["render", "dsl", "prompt", "extensions"];
55266
55666
  const results = [];
55267
55667
  for (const auditType of types) {
55268
55668
  results.push(await runAudit(dsl, config, auditConfig, { ...options, auditType }));