agent-contracts 0.19.2 → 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/README.md +1 -0
- package/cli-contract.yaml +56 -19
- package/dist/cli.js +58 -33
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +21 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -229,6 +229,7 @@ A **Workflow** defines a phase-level execution sequence:
|
|
|
229
229
|
Workflow steps support additional properties:
|
|
230
230
|
|
|
231
231
|
* `group` — consecutive steps with the same group are rendered as `par` (parallel) blocks in sequence diagrams
|
|
232
|
+
* `depends_on` — list of step task IDs that must complete before this step starts. When specified, the runtime can execute independent steps in parallel. When omitted, the step implicitly depends on all preceding steps (sequential execution)
|
|
232
233
|
* `max_retries` (delegate steps) — maximum number of full task re-executions (new sessions) allowed per step. Defaults to `0` (no retries), or `1` when a `retry` block is present
|
|
233
234
|
* `max_follow_ups` (delegate steps) — maximum number of lightweight same-session follow-up messages for output format corrections
|
|
234
235
|
* `retry` (delegate steps) — defines a conditional retry loop with `condition`, `fix_task`, and optional `revalidate_task`. These are rendered as recovery instructions in the LLM prompt
|
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
|
@@ -48983,6 +48983,7 @@ var WorkflowDelegateStepSchema = z14.object({
|
|
|
48983
48983
|
task: z14.string(),
|
|
48984
48984
|
from_agent: z14.string(),
|
|
48985
48985
|
group: z14.string().optional(),
|
|
48986
|
+
depends_on: z14.array(z14.string()).optional(),
|
|
48986
48987
|
max_retries: z14.number().int().min(0).optional(),
|
|
48987
48988
|
max_follow_ups: z14.number().int().min(0).optional(),
|
|
48988
48989
|
retry: RetrySchema.optional()
|
|
@@ -48991,7 +48992,8 @@ var WorkflowGateStepSchema = z14.object({
|
|
|
48991
48992
|
type: z14.literal("gate"),
|
|
48992
48993
|
description: z14.string().optional(),
|
|
48993
48994
|
gate_kind: z14.string(),
|
|
48994
|
-
group: z14.string().optional()
|
|
48995
|
+
group: z14.string().optional(),
|
|
48996
|
+
depends_on: z14.array(z14.string()).optional()
|
|
48995
48997
|
}).passthrough();
|
|
48996
48998
|
var WorkflowHandoffStepSchema = z14.object({
|
|
48997
48999
|
type: z14.literal("handoff"),
|
|
@@ -49000,13 +49002,15 @@ var WorkflowHandoffStepSchema = z14.object({
|
|
|
49000
49002
|
task: z14.string().optional(),
|
|
49001
49003
|
from_agent: z14.string().optional(),
|
|
49002
49004
|
group: z14.string().optional(),
|
|
49005
|
+
depends_on: z14.array(z14.string()).optional(),
|
|
49003
49006
|
retry: RetrySchema.optional()
|
|
49004
49007
|
}).passthrough();
|
|
49005
49008
|
var WorkflowValidationStepSchema = z14.object({
|
|
49006
49009
|
type: z14.literal("validation"),
|
|
49007
49010
|
description: z14.string().optional(),
|
|
49008
49011
|
validation: z14.string(),
|
|
49009
|
-
group: z14.string().optional()
|
|
49012
|
+
group: z14.string().optional(),
|
|
49013
|
+
depends_on: z14.array(z14.string()).optional()
|
|
49010
49014
|
}).passthrough();
|
|
49011
49015
|
var WorkflowDecisionStepSchema = z14.object({
|
|
49012
49016
|
type: z14.literal("decision"),
|
|
@@ -49015,7 +49019,8 @@ var WorkflowDecisionStepSchema = z14.object({
|
|
|
49015
49019
|
on: z14.string().optional(),
|
|
49016
49020
|
routing_key: z14.string().optional(),
|
|
49017
49021
|
branches: z14.record(z14.string(), z14.array(z14.string())),
|
|
49018
|
-
group: z14.string().optional()
|
|
49022
|
+
group: z14.string().optional(),
|
|
49023
|
+
depends_on: z14.array(z14.string()).optional()
|
|
49019
49024
|
}).passthrough();
|
|
49020
49025
|
var WorkflowTeamTaskStepSchema = z14.object({
|
|
49021
49026
|
type: z14.literal("team_task"),
|
|
@@ -49024,7 +49029,8 @@ var WorkflowTeamTaskStepSchema = z14.object({
|
|
|
49024
49029
|
workflow: z14.string(),
|
|
49025
49030
|
handoff: z14.string(),
|
|
49026
49031
|
expects: z14.string(),
|
|
49027
|
-
group: z14.string().optional()
|
|
49032
|
+
group: z14.string().optional(),
|
|
49033
|
+
depends_on: z14.array(z14.string()).optional()
|
|
49028
49034
|
}).passthrough();
|
|
49029
49035
|
var WorkflowStepSchema = z14.discriminatedUnion("type", [
|
|
49030
49036
|
WorkflowDelegateStepSchema,
|
|
@@ -55892,6 +55898,7 @@ ${issues}
|
|
|
55892
55898
|
);
|
|
55893
55899
|
|
|
55894
55900
|
// src/cli/commands/audit.ts
|
|
55901
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
55895
55902
|
import { Command as Command8 } from "commander";
|
|
55896
55903
|
|
|
55897
55904
|
// src/auditor/context-builder.ts
|
|
@@ -56626,16 +56633,22 @@ function formatAuditResults(results, format2) {
|
|
|
56626
56633
|
}
|
|
56627
56634
|
return results.map((r3) => formatAuditResult(r3, format2)).join("\n\n");
|
|
56628
56635
|
}
|
|
56629
|
-
function computeExitCode(results) {
|
|
56636
|
+
function computeExitCode(results, failOn) {
|
|
56630
56637
|
for (const r3 of results) {
|
|
56631
56638
|
if (r3.status === "error") {
|
|
56632
|
-
if (r3.errorMessage?.includes("not installed")
|
|
56633
|
-
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;
|
|
56634
56642
|
}
|
|
56635
56643
|
}
|
|
56644
|
+
const severityRank = { info: 0, warning: 1, error: 2, critical: 3 };
|
|
56645
|
+
const threshold = severityRank[failOn ?? "critical"] ?? 3;
|
|
56636
56646
|
for (const r3 of results) {
|
|
56637
|
-
if (r3.data?.critical_gaps
|
|
56638
|
-
|
|
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
|
+
}
|
|
56639
56652
|
}
|
|
56640
56653
|
}
|
|
56641
56654
|
return 0;
|
|
@@ -56653,13 +56666,13 @@ function parseAuditConfig(config) {
|
|
|
56653
56666
|
cache_dir: audit.cache_dir
|
|
56654
56667
|
};
|
|
56655
56668
|
}
|
|
56656
|
-
async function runAuditForDsl(dslPath, vars, configObj, auditType, opts) {
|
|
56669
|
+
async function runAuditForDsl(dslPath, vars, configObj, auditType, opts, failOn) {
|
|
56657
56670
|
const resolved = await resolve4(dslPath);
|
|
56658
56671
|
const data = vars ? substituteVars(resolved.data, vars) : resolved.data;
|
|
56659
56672
|
const schemaResult = validateSchema(data);
|
|
56660
56673
|
if (!schemaResult.success) {
|
|
56661
56674
|
process.stderr.write("Schema validation failed. Run 'agent-contracts validate' first.\n");
|
|
56662
|
-
return
|
|
56675
|
+
return { exitCode: 1, output: "" };
|
|
56663
56676
|
}
|
|
56664
56677
|
const auditConfig = parseAuditConfig(
|
|
56665
56678
|
configObj.audit
|
|
@@ -56672,17 +56685,18 @@ async function runAuditForDsl(dslPath, vars, configObj, auditType, opts) {
|
|
|
56672
56685
|
scope: opts.scope,
|
|
56673
56686
|
dryRun: opts.dryRun
|
|
56674
56687
|
});
|
|
56688
|
+
let output2;
|
|
56675
56689
|
if (opts.dryRun) {
|
|
56676
|
-
|
|
56677
|
-
|
|
56690
|
+
output2 = results.map(
|
|
56691
|
+
(r3) => `
|
|
56678
56692
|
--- Audit prompt: ${r3.auditType} ---
|
|
56679
|
-
|
|
56680
|
-
|
|
56681
|
-
|
|
56693
|
+
${r3.prompt}
|
|
56694
|
+
`
|
|
56695
|
+
).join("");
|
|
56682
56696
|
} else {
|
|
56683
|
-
|
|
56697
|
+
output2 = formatAuditResults(results, opts.format) + "\n";
|
|
56684
56698
|
}
|
|
56685
|
-
return computeExitCode(results);
|
|
56699
|
+
return { exitCode: computeExitCode(results, failOn), output: output2 };
|
|
56686
56700
|
}
|
|
56687
56701
|
const result = await runAudit(schemaResult.data, configObj, auditConfig, {
|
|
56688
56702
|
auditType,
|
|
@@ -56690,67 +56704,78 @@ async function runAuditForDsl(dslPath, vars, configObj, auditType, opts) {
|
|
|
56690
56704
|
scope: opts.scope,
|
|
56691
56705
|
dryRun: opts.dryRun
|
|
56692
56706
|
});
|
|
56707
|
+
let output;
|
|
56693
56708
|
if (opts.dryRun) {
|
|
56694
|
-
|
|
56709
|
+
output = result.prompt + "\n";
|
|
56695
56710
|
} else {
|
|
56696
|
-
|
|
56711
|
+
output = formatAuditResult(result, opts.format) + "\n";
|
|
56697
56712
|
}
|
|
56698
|
-
return computeExitCode([result]);
|
|
56713
|
+
return { exitCode: computeExitCode([result], failOn), output };
|
|
56699
56714
|
}
|
|
56700
|
-
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(
|
|
56701
56716
|
async (type, opts) => {
|
|
56702
56717
|
if (!AUDIT_TYPES.includes(type)) {
|
|
56703
56718
|
process.stderr.write(
|
|
56704
56719
|
`Unknown audit type: "${type}". Use one of: ${AUDIT_TYPES.join(", ")}
|
|
56705
56720
|
`
|
|
56706
56721
|
);
|
|
56707
|
-
process.exit(
|
|
56722
|
+
process.exit(1);
|
|
56708
56723
|
}
|
|
56709
|
-
const format2 = opts.format;
|
|
56724
|
+
const format2 = opts.reportFormat ?? opts.format;
|
|
56710
56725
|
try {
|
|
56711
56726
|
const config = await loadConfig(opts.config);
|
|
56712
56727
|
if (!config) {
|
|
56713
56728
|
process.stderr.write(
|
|
56714
56729
|
"Error: agent-contracts.config.yaml not found. Use --config to specify path.\n"
|
|
56715
56730
|
);
|
|
56716
|
-
process.exit(
|
|
56731
|
+
process.exit(1);
|
|
56717
56732
|
}
|
|
56718
56733
|
if (isMultiTeamConfig(config)) {
|
|
56719
56734
|
const teamEntries = getTeamEntries(config, opts.team);
|
|
56720
56735
|
let maxExit = 0;
|
|
56736
|
+
const allOutput = [];
|
|
56721
56737
|
for (const [teamId, teamConfig] of teamEntries) {
|
|
56722
56738
|
process.stderr.write(`
|
|
56723
56739
|
--- Team: ${teamId} ---
|
|
56724
56740
|
`);
|
|
56725
|
-
const
|
|
56741
|
+
const result2 = await runAuditForDsl(
|
|
56726
56742
|
teamConfig.dsl,
|
|
56727
56743
|
teamConfig.vars,
|
|
56728
56744
|
config,
|
|
56729
56745
|
type,
|
|
56730
|
-
{ 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
|
|
56731
56748
|
);
|
|
56732
|
-
|
|
56749
|
+
process.stdout.write(result2.output);
|
|
56750
|
+
allOutput.push(result2.output);
|
|
56751
|
+
if (result2.exitCode > maxExit) maxExit = result2.exitCode;
|
|
56733
56752
|
}
|
|
56753
|
+
if (opts.output) writeFileSync2(opts.output, allOutput.join(""), "utf8");
|
|
56734
56754
|
process.exit(maxExit);
|
|
56735
56755
|
}
|
|
56736
|
-
const
|
|
56756
|
+
const result = await runAuditForDsl(
|
|
56737
56757
|
config.dsl,
|
|
56738
56758
|
config.vars,
|
|
56739
56759
|
config,
|
|
56740
56760
|
type,
|
|
56741
|
-
{ 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
|
|
56742
56763
|
);
|
|
56743
|
-
process.
|
|
56764
|
+
process.stdout.write(result.output);
|
|
56765
|
+
if (opts.output) writeFileSync2(opts.output, result.output, "utf8");
|
|
56766
|
+
process.exit(result.exitCode);
|
|
56744
56767
|
} catch (err) {
|
|
56745
56768
|
if (err instanceof ConfigLoadError) {
|
|
56746
56769
|
process.stderr.write(`Config error: ${err.message}
|
|
56747
56770
|
`);
|
|
56748
|
-
process.exit(
|
|
56771
|
+
process.exit(1);
|
|
56749
56772
|
}
|
|
56750
56773
|
const msg = err instanceof Error ? err.message : String(err);
|
|
56751
56774
|
process.stderr.write(`Error: ${msg}
|
|
56752
56775
|
`);
|
|
56753
|
-
|
|
56776
|
+
if (msg.includes("not installed")) process.exit(11);
|
|
56777
|
+
if (msg.includes("adapter") || msg.includes("API")) process.exit(12);
|
|
56778
|
+
process.exit(1);
|
|
56754
56779
|
}
|
|
56755
56780
|
}
|
|
56756
56781
|
);
|