agent-contracts 0.10.0 → 0.11.1

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
@@ -228,6 +228,23 @@ Workflow steps support additional properties:
228
228
  * `group` — consecutive steps with the same group are rendered as `par` (parallel) blocks in sequence diagrams
229
229
  * `retry` (handoff steps only) — defines a conditional retry loop with `condition`, `fix_task`, and optional `revalidate_task`
230
230
 
231
+ ### Guardrail
232
+
233
+ A **Guardrail** declares a cross-cutting constraint:
234
+
235
+ * description — what is protected
236
+ * scope — which DSL entities it applies to (agents, tasks, tools, artifacts, workflows)
237
+ * rationale — why the constraint exists
238
+ * tags — classification for filtering
239
+ * exemptions — glob patterns or entity IDs exempt from the guardrail
240
+
241
+ ### Guardrail Policy
242
+
243
+ A **Guardrail Policy** defines enforcement strategy for guardrails:
244
+
245
+ * rules — array of enforcement rules mapping guardrails to actions
246
+ * Each rule specifies: severity (`critical`/`mandatory`/`warning`/`info`), action (`block`/`warn`/`shadow`/`info`), override permissions
247
+
231
248
  ### Handoff Type
232
249
 
233
250
  A **Handoff Type** defines the schema for inter-agent messages:
@@ -283,6 +300,10 @@ Design regressions become testable.
283
300
  * **Config-driven prompt rendering**
284
301
  * **Variable substitution** via `${vars.xxx}` in DSL values
285
302
  * **Inheritance with merge operators via `extends`**
303
+ * **Guardrail definitions** for cross-cutting process constraints
304
+ * **Guardrail policies** with configurable enforcement (block/warn/shadow/info)
305
+ * **Software bindings** (DI) for tool-specific guardrail implementation (Cursor, Git, GitHub)
306
+ * **Guardrail generation** from DSL + policy + bindings via `generate guardrails`
286
307
  * **Flexible file splitting** via `$ref` (replacement), `$refs` (import + deep-merge), and JSON Pointer `$ref` (in-document)
287
308
  * **JSON Schema for editor support and external tooling**
288
309
  * **CI-friendly workflow checks**
@@ -317,6 +338,8 @@ validations: {}
317
338
  handoff_types: {}
318
339
  workflow: {}
319
340
  policies: {}
341
+ guardrails: {}
342
+ guardrail_policies: {}
320
343
  components:
321
344
  schemas: {}
322
345
  ````
@@ -790,6 +813,7 @@ npx agent-contracts
790
813
  | `agent-contracts validate [path]` | Validate schema and references |
791
814
  | `agent-contracts lint [path]` | Run semantic lint |
792
815
  | `agent-contracts render` | Render outputs from config |
816
+ | `agent-contracts generate guardrails` | Generate guardrail artifacts from bindings |
793
817
  | `agent-contracts check` | Run resolve → validate → lint → render --check |
794
818
 
795
819
  The `[path]` argument defaults to `agent-contracts.yaml` in the current directory.
@@ -856,6 +880,8 @@ Each `context` type provides a different rendering scope:
856
880
  | `handoff_type` | Per handoff type | `{handoff_type.id}` in output path | `handoff_type`, `relatedTasks`, `dsl` |
857
881
  | `workflow` | Per workflow phase | `{workflow.id}` in output path | `workflow`, `relatedAgents`, `relatedTasks`, `relatedTools`, `relatedArtifacts`, `relatedValidations`, `dsl` |
858
882
  | `policy` | Per policy | `{policy.id}` in output path | `policy`, `dsl` |
883
+ | `guardrail` | Per guardrail | `{guardrail.id}` in output path | `guardrail`, `dsl` |
884
+ | `guardrail_policy` | Per guardrail policy | `{guardrail_policy.id}` in output path | `guardrail_policy`, `dsl` |
859
885
 
860
886
  #### Enriched context details
861
887
 
@@ -906,6 +932,172 @@ Templates can use these built-in helpers:
906
932
 
907
933
  ---
908
934
 
935
+ ## Guardrail DI system
936
+
937
+ `agent-contracts` includes a dependency injection system for guardrails that separates **what to protect** from **how to enforce** and **where to output**.
938
+
939
+ ### Architecture
940
+
941
+ ```text
942
+ agent-contracts.yaml (DSL) agent-contracts.config.yaml
943
+ ├─ guardrails: (what + why) ├─ bindings: [cursor.yaml, git.yaml, ...]
944
+ ├─ guardrail_policies: (how) ├─ active_guardrail_policy: default
945
+ └─ agents, tasks, ... ├─ paths: {cursor_root: .cursor, ...}
946
+ └─ vars, renders (existing)
947
+ ```
948
+
949
+ ### Guardrail definition
950
+
951
+ Guardrails declare constraints in the DSL without any implementation details:
952
+
953
+ ````yaml
954
+ guardrails:
955
+ no-force-push:
956
+ description: "Force push to protected branches is forbidden"
957
+ scope:
958
+ tools: [git]
959
+ rationale: "Force push destroys commit history"
960
+ tags: [branch-protection, safety]
961
+ ````
962
+
963
+ ### Guardrail policy
964
+
965
+ Policies define enforcement strategies:
966
+
967
+ ````yaml
968
+ guardrail_policies:
969
+ default-enforcement:
970
+ rules:
971
+ - guardrail: no-force-push
972
+ severity: critical
973
+ action: block
974
+ - guardrail: english-only-code
975
+ severity: warning
976
+ action: warn
977
+ allow_override: true
978
+ ````
979
+
980
+ ### Software bindings
981
+
982
+ Bindings define software-specific check implementations:
983
+
984
+ ````yaml
985
+ # bindings/cursor.yaml
986
+ software: cursor
987
+ version: 1
988
+
989
+ guardrail_impl:
990
+ no-force-push:
991
+ checks:
992
+ - hook_event: beforeShellExecution
993
+ matcher:
994
+ type: command_regex
995
+ pattern: "git\\s+push\\s+.*--force"
996
+ message: "Force push is forbidden"
997
+
998
+ outputs:
999
+ hook-script:
1000
+ target: "{cursor_root}/hooks/evaluate-hook.sh"
1001
+ mode: write
1002
+ executable: true
1003
+ template: ./templates/cursor-hook-wrapper.sh.hbs
1004
+ ````
1005
+
1006
+ ### Binding inheritance
1007
+
1008
+ Binding files support `extends` for inheriting and extending a base binding, using the same mechanism as DSL-level `extends`.
1009
+
1010
+ A base binding defines shared guardrail implementations and outputs:
1011
+
1012
+ ````yaml
1013
+ # skeleton/bindings/cursor.yaml (base)
1014
+ software: cursor
1015
+ version: 1
1016
+
1017
+ guardrail_impl:
1018
+ no-force-push:
1019
+ checks:
1020
+ - hook_event: beforeShellExecution
1021
+ matcher:
1022
+ type: command_regex
1023
+ pattern: "git\\s+push\\s+.*--force"
1024
+ message: "Force push is forbidden"
1025
+
1026
+ outputs:
1027
+ policy-bundle:
1028
+ target: "{cursor_root}/guardrails/policy.json"
1029
+ mode: write
1030
+ inline_template: "{{json resolved_checks}}"
1031
+ ````
1032
+
1033
+ A project binding extends the base and adds project-specific guardrail implementations:
1034
+
1035
+ ````yaml
1036
+ # project/bindings/cursor.yaml
1037
+ extends: ../../skeleton/bindings/cursor.yaml
1038
+ software: cursor
1039
+ version: 1
1040
+
1041
+ guardrail_impl:
1042
+ lint-on-save:
1043
+ checks:
1044
+ - hook_event: afterFileEdit
1045
+ matcher:
1046
+ type: file_glob
1047
+ pattern: "**/*.{ts,tsx}"
1048
+ message: "TS file edited — lint results attached."
1049
+ ````
1050
+
1051
+ The result is a single merged binding with all guardrail implementations from both base and project.
1052
+
1053
+ Merge behavior:
1054
+
1055
+ | Field | Behavior |
1056
+ |-------|----------|
1057
+ | `software` | Project wins |
1058
+ | `guardrail_impl` | Map merge by guardrail ID (new IDs added; same ID deep-merged) |
1059
+ | `outputs` | Map merge by output ID (project overrides base) |
1060
+ | `reporting` | Deep merge (project fields override base) |
1061
+ | passthrough fields | Project wins |
1062
+
1063
+ All merge operators (`$append`, `$prepend`, `$insert_after`, `$replace`, `$remove`) work within binding `extends`, the same as DSL `extends`.
1064
+
1065
+ Chained inheritance (grandparent → parent → child) and both local path (`./`, `../`) and npm package references are supported. Circular extends are detected and rejected.
1066
+
1067
+ When using binding `extends`, the config only needs to list the child binding:
1068
+
1069
+ ````yaml
1070
+ # agent-contracts.config.yaml
1071
+ bindings:
1072
+ - ./bindings/cursor.yaml # extends base internally
1073
+ - ./bindings/git.yaml
1074
+ ````
1075
+
1076
+ ### Config
1077
+
1078
+ ````yaml
1079
+ # agent-contracts.config.yaml
1080
+ bindings:
1081
+ - ./bindings/cursor.yaml
1082
+ - ./bindings/git.yaml
1083
+
1084
+ active_guardrail_policy: default-enforcement
1085
+
1086
+ paths:
1087
+ cursor_root: .cursor
1088
+ git_hooks_root: scripts/git-hooks
1089
+ ````
1090
+
1091
+ ### Generate command
1092
+
1093
+ ````bash
1094
+ agent-contracts generate guardrails -c agent-contracts.config.yaml
1095
+ agent-contracts generate guardrails -c agent-contracts.config.yaml --binding cursor
1096
+ agent-contracts generate guardrails -c agent-contracts.config.yaml --dry-run
1097
+ ````
1098
+
1099
+ ---
1100
+
909
1101
  ## Validation model
910
1102
 
911
1103
  `agent-contracts` validates your system in multiple layers.