agent-contracts 0.19.3 → 0.19.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 +56 -19
- package/dist/cli.js +48 -29
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/cli-contract.yaml
CHANGED
|
@@ -3,7 +3,7 @@ cliContracts: 0.1.0
|
|
|
3
3
|
|
|
4
4
|
info:
|
|
5
5
|
title: agent-contracts CLI
|
|
6
|
-
version: 0.19.
|
|
6
|
+
version: 0.19.4
|
|
7
7
|
description: >-
|
|
8
8
|
Declarative YAML DSL toolkit for defining, validating, and rendering
|
|
9
9
|
multi-agent development workflows. Provides static validation,
|
|
@@ -625,44 +625,81 @@ commandSets:
|
|
|
625
625
|
schema:
|
|
626
626
|
type: string
|
|
627
627
|
|
|
628
|
+
- name: fail-on
|
|
629
|
+
description: >-
|
|
630
|
+
Minimum finding severity that causes exit 10
|
|
631
|
+
(info|warning|error|critical).
|
|
632
|
+
valueName: level
|
|
633
|
+
schema:
|
|
634
|
+
type: string
|
|
635
|
+
enum: [info, warning, error, critical]
|
|
636
|
+
default: critical
|
|
637
|
+
|
|
638
|
+
- name: output
|
|
639
|
+
aliases: [o]
|
|
640
|
+
description: Write result to a file instead of stdout.
|
|
641
|
+
valueName: file
|
|
642
|
+
schema:
|
|
643
|
+
type: string
|
|
644
|
+
file:
|
|
645
|
+
mode: write
|
|
646
|
+
encoding: utf-8
|
|
647
|
+
|
|
648
|
+
- name: report-format
|
|
649
|
+
description: >-
|
|
650
|
+
Alias for --format. When both are specified, --report-format
|
|
651
|
+
takes precedence.
|
|
652
|
+
valueName: fmt
|
|
653
|
+
schema:
|
|
654
|
+
type: string
|
|
655
|
+
enum: [text, json, markdown]
|
|
656
|
+
default: text
|
|
657
|
+
|
|
628
658
|
exits:
|
|
629
659
|
'0':
|
|
630
|
-
description: No
|
|
660
|
+
description: Audit succeeded. No findings at or above --fail-on threshold.
|
|
631
661
|
stdout:
|
|
632
662
|
format: '{options.format}'
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
output. Format depends on --format option (text, json, or
|
|
636
|
-
markdown).
|
|
663
|
+
schema:
|
|
664
|
+
$ref: './dsl_base/components.yaml#/schemas/agent-audit-result'
|
|
637
665
|
|
|
638
666
|
'1':
|
|
639
|
-
description:
|
|
667
|
+
description: Unexpected error (invalid input, config error, or internal failure).
|
|
640
668
|
stderr:
|
|
641
669
|
format: text
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
670
|
+
|
|
671
|
+
'10':
|
|
672
|
+
description: Findings at or above --fail-on severity threshold detected.
|
|
645
673
|
stdout:
|
|
646
674
|
format: '{options.format}'
|
|
675
|
+
schema:
|
|
676
|
+
$ref: './dsl_base/components.yaml#/schemas/agent-audit-result'
|
|
677
|
+
stderr:
|
|
678
|
+
format: text
|
|
647
679
|
schemaNote: >-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
are valid structured data, not error messages.
|
|
680
|
+
Summary diagnostic on stderr. Structured findings are
|
|
681
|
+
emitted on stdout in the requested format.
|
|
651
682
|
|
|
652
|
-
'
|
|
653
|
-
description:
|
|
683
|
+
'11':
|
|
684
|
+
description: >-
|
|
685
|
+
Runtime dependency missing (agent-contracts-runtime not installed).
|
|
654
686
|
stderr:
|
|
655
687
|
format: text
|
|
656
688
|
|
|
657
|
-
'
|
|
658
|
-
description: LLM adapter error (API failure,
|
|
689
|
+
'12':
|
|
690
|
+
description: LLM provider or adapter error (API failure, auth error).
|
|
659
691
|
stderr:
|
|
660
692
|
format: text
|
|
661
693
|
|
|
662
694
|
x-agent:
|
|
663
695
|
riskLevel: medium
|
|
664
696
|
requiresConfirmation: false
|
|
665
|
-
idempotent:
|
|
697
|
+
idempotent: false
|
|
698
|
+
idempotentNote: >-
|
|
699
|
+
Safe to repeat (no persistent side effects beyond network calls),
|
|
700
|
+
but LLM inference is non-deterministic — identical inputs may
|
|
701
|
+
produce different findings, severity assignments, and
|
|
702
|
+
recommendation text across runs.
|
|
666
703
|
sideEffects:
|
|
667
704
|
- network
|
|
668
705
|
sideEffectNote: >-
|
|
@@ -671,7 +708,7 @@ commandSets:
|
|
|
671
708
|
cost and sends DSL content to the LLM provider.
|
|
672
709
|
safeDryRunOption: dry-run
|
|
673
710
|
expectedDurationMs: 120000
|
|
674
|
-
retryableExitCodes: [
|
|
711
|
+
retryableExitCodes: [12]
|
|
675
712
|
recommendedBeforeUse:
|
|
676
713
|
- Ensure agent-contracts.config.yaml exists with render targets.
|
|
677
714
|
- Run validate first to confirm DSL is valid.
|
package/dist/cli.js
CHANGED
|
@@ -55898,6 +55898,7 @@ ${issues}
|
|
|
55898
55898
|
);
|
|
55899
55899
|
|
|
55900
55900
|
// src/cli/commands/audit.ts
|
|
55901
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
55901
55902
|
import { Command as Command8 } from "commander";
|
|
55902
55903
|
|
|
55903
55904
|
// src/auditor/context-builder.ts
|
|
@@ -56632,16 +56633,22 @@ function formatAuditResults(results, format2) {
|
|
|
56632
56633
|
}
|
|
56633
56634
|
return results.map((r3) => formatAuditResult(r3, format2)).join("\n\n");
|
|
56634
56635
|
}
|
|
56635
|
-
function computeExitCode(results) {
|
|
56636
|
+
function computeExitCode(results, failOn) {
|
|
56636
56637
|
for (const r3 of results) {
|
|
56637
56638
|
if (r3.status === "error") {
|
|
56638
|
-
if (r3.errorMessage?.includes("not installed")
|
|
56639
|
-
return
|
|
56639
|
+
if (r3.errorMessage?.includes("not installed")) return 11;
|
|
56640
|
+
if (r3.errorMessage?.includes("adapter") || r3.errorMessage?.includes("API")) return 12;
|
|
56641
|
+
return 1;
|
|
56640
56642
|
}
|
|
56641
56643
|
}
|
|
56644
|
+
const severityRank = { info: 0, warning: 1, error: 2, critical: 3 };
|
|
56645
|
+
const threshold = severityRank[failOn ?? "critical"] ?? 3;
|
|
56642
56646
|
for (const r3 of results) {
|
|
56643
|
-
if (r3.data?.critical_gaps
|
|
56644
|
-
|
|
56647
|
+
if (r3.data?.critical_gaps) {
|
|
56648
|
+
for (const gap of r3.data.critical_gaps) {
|
|
56649
|
+
const rank = severityRank[gap.severity ?? ""] ?? 0;
|
|
56650
|
+
if (rank >= threshold) return 10;
|
|
56651
|
+
}
|
|
56645
56652
|
}
|
|
56646
56653
|
}
|
|
56647
56654
|
return 0;
|
|
@@ -56659,13 +56666,13 @@ function parseAuditConfig(config) {
|
|
|
56659
56666
|
cache_dir: audit.cache_dir
|
|
56660
56667
|
};
|
|
56661
56668
|
}
|
|
56662
|
-
async function runAuditForDsl(dslPath, vars, configObj, auditType, opts) {
|
|
56669
|
+
async function runAuditForDsl(dslPath, vars, configObj, auditType, opts, failOn) {
|
|
56663
56670
|
const resolved = await resolve4(dslPath);
|
|
56664
56671
|
const data = vars ? substituteVars(resolved.data, vars) : resolved.data;
|
|
56665
56672
|
const schemaResult = validateSchema(data);
|
|
56666
56673
|
if (!schemaResult.success) {
|
|
56667
56674
|
process.stderr.write("Schema validation failed. Run 'agent-contracts validate' first.\n");
|
|
56668
|
-
return
|
|
56675
|
+
return { exitCode: 1, output: "" };
|
|
56669
56676
|
}
|
|
56670
56677
|
const auditConfig = parseAuditConfig(
|
|
56671
56678
|
configObj.audit
|
|
@@ -56678,17 +56685,18 @@ async function runAuditForDsl(dslPath, vars, configObj, auditType, opts) {
|
|
|
56678
56685
|
scope: opts.scope,
|
|
56679
56686
|
dryRun: opts.dryRun
|
|
56680
56687
|
});
|
|
56688
|
+
let output2;
|
|
56681
56689
|
if (opts.dryRun) {
|
|
56682
|
-
|
|
56683
|
-
|
|
56690
|
+
output2 = results.map(
|
|
56691
|
+
(r3) => `
|
|
56684
56692
|
--- Audit prompt: ${r3.auditType} ---
|
|
56685
|
-
|
|
56686
|
-
|
|
56687
|
-
|
|
56693
|
+
${r3.prompt}
|
|
56694
|
+
`
|
|
56695
|
+
).join("");
|
|
56688
56696
|
} else {
|
|
56689
|
-
|
|
56697
|
+
output2 = formatAuditResults(results, opts.format) + "\n";
|
|
56690
56698
|
}
|
|
56691
|
-
return computeExitCode(results);
|
|
56699
|
+
return { exitCode: computeExitCode(results, failOn), output: output2 };
|
|
56692
56700
|
}
|
|
56693
56701
|
const result = await runAudit(schemaResult.data, configObj, auditConfig, {
|
|
56694
56702
|
auditType,
|
|
@@ -56696,67 +56704,78 @@ async function runAuditForDsl(dslPath, vars, configObj, auditType, opts) {
|
|
|
56696
56704
|
scope: opts.scope,
|
|
56697
56705
|
dryRun: opts.dryRun
|
|
56698
56706
|
});
|
|
56707
|
+
let output;
|
|
56699
56708
|
if (opts.dryRun) {
|
|
56700
|
-
|
|
56709
|
+
output = result.prompt + "\n";
|
|
56701
56710
|
} else {
|
|
56702
|
-
|
|
56711
|
+
output = formatAuditResult(result, opts.format) + "\n";
|
|
56703
56712
|
}
|
|
56704
|
-
return computeExitCode([result]);
|
|
56713
|
+
return { exitCode: computeExitCode([result], failOn), output };
|
|
56705
56714
|
}
|
|
56706
|
-
var auditCommand = new Command8("audit").description("Run LLM-based semantic audit on DSL definitions and generated outputs").argument("[type]", `Audit type: ${AUDIT_TYPES.join(", ")}`, "all").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--format <format>", "Output format (text|json|markdown)", "text").option("--scope <entities>", "Limit audit scope (e.g. agents:architect,implementer)").option("--dry-run", "Output the audit prompt without calling LLM", false).option("--adapter <name>", "SDK adapter to use (default from config)").option("--model <name>", "LLM model override").action(
|
|
56715
|
+
var auditCommand = new Command8("audit").description("Run LLM-based semantic audit on DSL definitions and generated outputs").argument("[type]", `Audit type: ${AUDIT_TYPES.join(", ")}`, "all").option("-c, --config <path>", "Path to agent-contracts.config.yaml").option("--team <id>", "Limit to one team (multi-team config only)").option("--format <format>", "Output format (text|json|markdown)", "text").option("--scope <entities>", "Limit audit scope (e.g. agents:architect,implementer)").option("--dry-run", "Output the audit prompt without calling LLM", false).option("--adapter <name>", "SDK adapter to use (default from config)").option("--model <name>", "LLM model override").option("--fail-on <level>", "Minimum severity that causes exit 10 (info|warning|error|critical)", "critical").option("-o, --output <file>", "Write result to a file instead of stdout").option("--report-format <fmt>", "Alias for --format (for cli-contracts standard conformance)").action(
|
|
56707
56716
|
async (type, opts) => {
|
|
56708
56717
|
if (!AUDIT_TYPES.includes(type)) {
|
|
56709
56718
|
process.stderr.write(
|
|
56710
56719
|
`Unknown audit type: "${type}". Use one of: ${AUDIT_TYPES.join(", ")}
|
|
56711
56720
|
`
|
|
56712
56721
|
);
|
|
56713
|
-
process.exit(
|
|
56722
|
+
process.exit(1);
|
|
56714
56723
|
}
|
|
56715
|
-
const format2 = opts.format;
|
|
56724
|
+
const format2 = opts.reportFormat ?? opts.format;
|
|
56716
56725
|
try {
|
|
56717
56726
|
const config = await loadConfig(opts.config);
|
|
56718
56727
|
if (!config) {
|
|
56719
56728
|
process.stderr.write(
|
|
56720
56729
|
"Error: agent-contracts.config.yaml not found. Use --config to specify path.\n"
|
|
56721
56730
|
);
|
|
56722
|
-
process.exit(
|
|
56731
|
+
process.exit(1);
|
|
56723
56732
|
}
|
|
56724
56733
|
if (isMultiTeamConfig(config)) {
|
|
56725
56734
|
const teamEntries = getTeamEntries(config, opts.team);
|
|
56726
56735
|
let maxExit = 0;
|
|
56736
|
+
const allOutput = [];
|
|
56727
56737
|
for (const [teamId, teamConfig] of teamEntries) {
|
|
56728
56738
|
process.stderr.write(`
|
|
56729
56739
|
--- Team: ${teamId} ---
|
|
56730
56740
|
`);
|
|
56731
|
-
const
|
|
56741
|
+
const result2 = await runAuditForDsl(
|
|
56732
56742
|
teamConfig.dsl,
|
|
56733
56743
|
teamConfig.vars,
|
|
56734
56744
|
config,
|
|
56735
56745
|
type,
|
|
56736
|
-
{ format: format2, scope: opts.scope, dryRun: opts.dryRun, adapter: opts.adapter, model: opts.model }
|
|
56746
|
+
{ format: format2, scope: opts.scope, dryRun: opts.dryRun, adapter: opts.adapter, model: opts.model },
|
|
56747
|
+
opts.failOn
|
|
56737
56748
|
);
|
|
56738
|
-
|
|
56749
|
+
process.stdout.write(result2.output);
|
|
56750
|
+
allOutput.push(result2.output);
|
|
56751
|
+
if (result2.exitCode > maxExit) maxExit = result2.exitCode;
|
|
56739
56752
|
}
|
|
56753
|
+
if (opts.output) writeFileSync2(opts.output, allOutput.join(""), "utf8");
|
|
56740
56754
|
process.exit(maxExit);
|
|
56741
56755
|
}
|
|
56742
|
-
const
|
|
56756
|
+
const result = await runAuditForDsl(
|
|
56743
56757
|
config.dsl,
|
|
56744
56758
|
config.vars,
|
|
56745
56759
|
config,
|
|
56746
56760
|
type,
|
|
56747
|
-
{ format: format2, scope: opts.scope, dryRun: opts.dryRun, adapter: opts.adapter, model: opts.model }
|
|
56761
|
+
{ format: format2, scope: opts.scope, dryRun: opts.dryRun, adapter: opts.adapter, model: opts.model },
|
|
56762
|
+
opts.failOn
|
|
56748
56763
|
);
|
|
56749
|
-
process.
|
|
56764
|
+
process.stdout.write(result.output);
|
|
56765
|
+
if (opts.output) writeFileSync2(opts.output, result.output, "utf8");
|
|
56766
|
+
process.exit(result.exitCode);
|
|
56750
56767
|
} catch (err) {
|
|
56751
56768
|
if (err instanceof ConfigLoadError) {
|
|
56752
56769
|
process.stderr.write(`Config error: ${err.message}
|
|
56753
56770
|
`);
|
|
56754
|
-
process.exit(
|
|
56771
|
+
process.exit(1);
|
|
56755
56772
|
}
|
|
56756
56773
|
const msg = err instanceof Error ? err.message : String(err);
|
|
56757
56774
|
process.stderr.write(`Error: ${msg}
|
|
56758
56775
|
`);
|
|
56759
|
-
|
|
56776
|
+
if (msg.includes("not installed")) process.exit(11);
|
|
56777
|
+
if (msg.includes("adapter") || msg.includes("API")) process.exit(12);
|
|
56778
|
+
process.exit(1);
|
|
56760
56779
|
}
|
|
56761
56780
|
}
|
|
56762
56781
|
);
|