agent-contracts 0.30.4 → 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/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: {}
@@ -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/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: z6.enum(["block", "warn", "shadow", "info"]),
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,