agent-contracts 0.30.3 → 0.31.0
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/LICENSE +1 -1
- package/README.md +13 -3
- package/cli-contract.yaml +2 -2
- package/dist/cli.js +75 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +99 -16
- package/dist/index.js +78 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -278,6 +278,8 @@ A **Guardrail Policy** defines enforcement strategy for guardrails:
|
|
|
278
278
|
|
|
279
279
|
* rules — array of enforcement rules mapping guardrails to actions
|
|
280
280
|
* Each rule specifies: severity (`critical`/`mandatory`/`warning`/`info`), action (`block`/`warn`/`shadow`/`info`), override permissions
|
|
281
|
+
* `action` supports a conditional form for state-dependent enforcement: `{ default: "block", when: { maintenance: "shadow" } }`
|
|
282
|
+
* Available states are declared system-wide via `system.states`
|
|
281
283
|
|
|
282
284
|
### Handoff Type
|
|
283
285
|
|
|
@@ -337,6 +339,7 @@ Design regressions become testable.
|
|
|
337
339
|
* **Inheritance with merge operators via `extends`**
|
|
338
340
|
* **Guardrail definitions** for cross-cutting process constraints
|
|
339
341
|
* **Guardrail policies** with configurable enforcement (block/warn/shadow/info)
|
|
342
|
+
* **State-dependent guardrail action** — `action` accepts a conditional form `{ default, when }` keyed by `system.states` for workspace-mode-aware enforcement
|
|
340
343
|
* **Software bindings** (DI) for tool-specific guardrail implementation (Cursor, Git, GitHub)
|
|
341
344
|
* **Guardrail generation** from DSL + policy + bindings via `generate guardrails`
|
|
342
345
|
* **Navigation index** — compile-time artifact-centric model mapping artifacts to operations, agent permissions, relations, and action routes
|
|
@@ -374,6 +377,7 @@ system:
|
|
|
374
377
|
- audit
|
|
375
378
|
- release
|
|
376
379
|
- reflect
|
|
380
|
+
states: [] # optional — named workspace states for conditional guardrail action
|
|
377
381
|
|
|
378
382
|
agents: {}
|
|
379
383
|
tasks: {}
|
|
@@ -711,7 +715,7 @@ artifacts:
|
|
|
711
715
|
|
|
712
716
|
## artifact-contracts integration
|
|
713
717
|
|
|
714
|
-
agent-contracts integrates with [artifact-contracts](https://github.com/foo-
|
|
718
|
+
agent-contracts integrates with [artifact-contracts](https://github.com/foo-log-inc/artifact-contracts) and [cli-contracts](https://github.com/foo-log-inc/cli-contracts) to provide a unified artifact governance model.
|
|
715
719
|
|
|
716
720
|
### Design principle
|
|
717
721
|
|
|
@@ -1106,7 +1110,7 @@ VarsSubstitutionError: Undefined variable "repo_url" in value "Repository: ${var
|
|
|
1106
1110
|
|
|
1107
1111
|
For the full CLI reference with all commands, options, arguments, exit codes, and AI agent policies, see the [CLI Reference](docs/cli-reference.md).
|
|
1108
1112
|
|
|
1109
|
-
The CLI contract specification is defined in [`cli-contract.yaml`](cli-contract.yaml) using [CLI Contracts](https://github.com/foo-
|
|
1113
|
+
The CLI contract specification is defined in [`cli-contract.yaml`](cli-contract.yaml) using [CLI Contracts](https://github.com/foo-log-inc/cli-contracts). Commands that have side effects declare structured `effects` metadata, and the `--introspect` global option outputs the derived policy as JSON without executing the command.
|
|
1110
1114
|
|
|
1111
1115
|
### Installation
|
|
1112
1116
|
|
|
@@ -1149,7 +1153,7 @@ agent-contracts audit --introspect
|
|
|
1149
1153
|
agent-contracts validate --introspect
|
|
1150
1154
|
````
|
|
1151
1155
|
|
|
1152
|
-
The output follows the [CLI Contracts](https://github.com/foo-
|
|
1156
|
+
The output follows the [CLI Contracts](https://github.com/foo-log-inc/cli-contracts) `IntrospectionResult` shape:
|
|
1153
1157
|
|
|
1154
1158
|
````json
|
|
1155
1159
|
{
|
|
@@ -1536,6 +1540,12 @@ guardrail_policies:
|
|
|
1536
1540
|
- guardrail: no-force-push
|
|
1537
1541
|
severity: critical
|
|
1538
1542
|
action: block
|
|
1543
|
+
- guardrail: branch-lock
|
|
1544
|
+
severity: critical
|
|
1545
|
+
action:
|
|
1546
|
+
default: block
|
|
1547
|
+
when:
|
|
1548
|
+
maintenance: shadow
|
|
1539
1549
|
- guardrail: english-only-code
|
|
1540
1550
|
severity: warning
|
|
1541
1551
|
action: warn
|
package/cli-contract.yaml
CHANGED
package/dist/cli.js
CHANGED
|
@@ -49099,10 +49099,16 @@ var GuardrailPolicyRuleEscalationSchema = z6.object({
|
|
|
49099
49099
|
target: z6.string(),
|
|
49100
49100
|
condition: z6.string().optional()
|
|
49101
49101
|
}).passthrough();
|
|
49102
|
+
var ActionEnum = z6.enum(["block", "warn", "shadow", "info"]);
|
|
49103
|
+
var ConditionalActionSchema = z6.object({
|
|
49104
|
+
default: ActionEnum,
|
|
49105
|
+
when: z6.record(z6.string(), ActionEnum)
|
|
49106
|
+
});
|
|
49107
|
+
var ActionSchema = z6.union([ActionEnum, ConditionalActionSchema]);
|
|
49102
49108
|
var GuardrailPolicyRuleSchema = z6.object({
|
|
49103
49109
|
guardrail: z6.string(),
|
|
49104
49110
|
severity: z6.enum(["critical", "mandatory", "warning", "info"]),
|
|
49105
|
-
action:
|
|
49111
|
+
action: ActionSchema,
|
|
49106
49112
|
allow_override: z6.boolean().default(false),
|
|
49107
49113
|
override_requires: z6.array(z6.string()).optional(),
|
|
49108
49114
|
escalation: GuardrailPolicyRuleEscalationSchema.optional()
|
|
@@ -49134,7 +49140,8 @@ var SystemSchema = z8.object({
|
|
|
49134
49140
|
name: z8.string(),
|
|
49135
49141
|
default_workflow_order: z8.array(z8.string()),
|
|
49136
49142
|
sections: z8.array(SectionSchema).optional(),
|
|
49137
|
-
context_loading: ContextLoadingSchema
|
|
49143
|
+
context_loading: ContextLoadingSchema,
|
|
49144
|
+
states: z8.array(z8.string()).default([])
|
|
49138
49145
|
}).passthrough();
|
|
49139
49146
|
|
|
49140
49147
|
// src/schema/task.ts
|
|
@@ -52246,6 +52253,70 @@ var guardrailPolicyCoverageRule = {
|
|
|
52246
52253
|
}
|
|
52247
52254
|
};
|
|
52248
52255
|
|
|
52256
|
+
// src/linter/rules/guardrail-policy-action-state.ts
|
|
52257
|
+
function isConditionalAction(action) {
|
|
52258
|
+
return typeof action === "object" && action !== null && "default" in action;
|
|
52259
|
+
}
|
|
52260
|
+
function collectReferencedWhenStates(dsl) {
|
|
52261
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
52262
|
+
for (const policy of Object.values(dsl.guardrail_policies)) {
|
|
52263
|
+
for (const rule of policy.rules) {
|
|
52264
|
+
if (isConditionalAction(rule.action)) {
|
|
52265
|
+
for (const state of Object.keys(rule.action.when)) {
|
|
52266
|
+
referenced.add(state);
|
|
52267
|
+
}
|
|
52268
|
+
}
|
|
52269
|
+
}
|
|
52270
|
+
}
|
|
52271
|
+
return referenced;
|
|
52272
|
+
}
|
|
52273
|
+
var guardrailPolicyActionStateUndefinedRule = {
|
|
52274
|
+
id: "guardrail-policy-action-state-undefined",
|
|
52275
|
+
description: "Policy rule action.when keys must reference states declared in system.states",
|
|
52276
|
+
run(dsl) {
|
|
52277
|
+
const diagnostics = [];
|
|
52278
|
+
const systemStates = new Set(dsl.system.states ?? []);
|
|
52279
|
+
for (const [policyId, policy] of Object.entries(dsl.guardrail_policies)) {
|
|
52280
|
+
for (let ruleIndex = 0; ruleIndex < policy.rules.length; ruleIndex++) {
|
|
52281
|
+
const rule = policy.rules[ruleIndex];
|
|
52282
|
+
if (!isConditionalAction(rule.action)) continue;
|
|
52283
|
+
for (const state of Object.keys(rule.action.when)) {
|
|
52284
|
+
if (!systemStates.has(state)) {
|
|
52285
|
+
diagnostics.push({
|
|
52286
|
+
ruleId: "guardrail-policy-action-state-undefined",
|
|
52287
|
+
severity: "error",
|
|
52288
|
+
path: `guardrail_policies.${policyId}.rules[${ruleIndex}].action.when.${state}`,
|
|
52289
|
+
message: `Policy rule references state "${state}" in action.when, but it is not declared in system.states`
|
|
52290
|
+
});
|
|
52291
|
+
}
|
|
52292
|
+
}
|
|
52293
|
+
}
|
|
52294
|
+
}
|
|
52295
|
+
return diagnostics;
|
|
52296
|
+
}
|
|
52297
|
+
};
|
|
52298
|
+
var systemStatesUnusedRule = {
|
|
52299
|
+
id: "system-states-unused",
|
|
52300
|
+
description: "Each state in system.states should be referenced by at least one policy rule action.when",
|
|
52301
|
+
run(dsl) {
|
|
52302
|
+
const diagnostics = [];
|
|
52303
|
+
const states = dsl.system.states ?? [];
|
|
52304
|
+
if (states.length === 0) return diagnostics;
|
|
52305
|
+
const referenced = collectReferencedWhenStates(dsl);
|
|
52306
|
+
for (const state of states) {
|
|
52307
|
+
if (!referenced.has(state)) {
|
|
52308
|
+
diagnostics.push({
|
|
52309
|
+
ruleId: "system-states-unused",
|
|
52310
|
+
severity: "info",
|
|
52311
|
+
path: `system.states`,
|
|
52312
|
+
message: `State "${state}" is declared in system.states but not referenced by any policy rule action.when`
|
|
52313
|
+
});
|
|
52314
|
+
}
|
|
52315
|
+
}
|
|
52316
|
+
return diagnostics;
|
|
52317
|
+
}
|
|
52318
|
+
};
|
|
52319
|
+
|
|
52249
52320
|
// src/linter/rules/yaml-reserved-key-safety.ts
|
|
52250
52321
|
var YAML_11_RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
52251
52322
|
"on",
|
|
@@ -53055,6 +53126,8 @@ var builtinRules = [
|
|
|
53055
53126
|
artifactOwnershipRule,
|
|
53056
53127
|
toolCommandsRule,
|
|
53057
53128
|
guardrailPolicyCoverageRule,
|
|
53129
|
+
guardrailPolicyActionStateUndefinedRule,
|
|
53130
|
+
systemStatesUnusedRule,
|
|
53058
53131
|
yamlReservedKeySafetyRule,
|
|
53059
53132
|
artifactRequiredValidationWiringRule,
|
|
53060
53133
|
taskOutputValidationCompletenessRule,
|