agent-contracts 0.22.3 → 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/cli-contract.yaml +11 -8
- package/dist/cli.js +442 -42
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.js +443 -43
- package/dist/index.js.map +1 -1
- package/dsl_base/agents/dsl-auditor.yaml +31 -2
- package/dsl_base/agents/dsl-designer.yaml +0 -2
- package/dsl_base/artifacts.yaml +1 -1
- package/dsl_base/handoff-types.yaml +33 -11
- package/dsl_base/tasks.yaml +43 -14
- package/dsl_base/validations.yaml +6 -6
- package/dsl_base/workflow.yaml +30 -8
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
49563
|
+
const resolved = await assembleRefs(
|
|
49555
49564
|
content,
|
|
49556
49565
|
dirname(target),
|
|
49557
49566
|
resolving,
|
|
49558
|
-
|
|
49567
|
+
content
|
|
49559
49568
|
);
|
|
49560
49569
|
resolving.delete(target);
|
|
49561
49570
|
return resolved;
|
|
49562
49571
|
}
|
|
49563
|
-
async function loadDirectoryAsMap(dirPath, resolving
|
|
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
|
|
49599
|
+
const resolved = await assembleRefs(
|
|
49591
49600
|
content,
|
|
49592
49601
|
dirPath,
|
|
49593
49602
|
resolving,
|
|
49594
|
-
|
|
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
|
|
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
|
|
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
|
|
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) =>
|
|
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
|
|
49631
|
-
|
|
49632
|
-
deepClone(target),
|
|
49643
|
+
const resolved = await assembleRefs(
|
|
49644
|
+
deepClone(result2.value),
|
|
49633
49645
|
baseDir,
|
|
49634
49646
|
resolving,
|
|
49635
|
-
|
|
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
|
|
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
|
|
49675
|
-
let fileData = await
|
|
49686
|
+
const newFileRoot = isRecord(content) ? content : fileRoot;
|
|
49687
|
+
let fileData = await assembleRefs(
|
|
49676
49688
|
content,
|
|
49677
49689
|
dirname(refTarget),
|
|
49678
49690
|
resolving,
|
|
49679
|
-
|
|
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
|
|
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
|
|
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
|
|
49731
|
-
const resolved = await resolveRefsDeep(
|
|
49762
|
+
const assembled = await assembleRefs(
|
|
49732
49763
|
data,
|
|
49733
49764
|
baseDir,
|
|
49734
|
-
|
|
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
|
|
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 =
|
|
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 &&
|
|
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 }));
|