yui-agent-guard 0.1.0__tar.gz

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.
Files changed (27) hide show
  1. yui_agent_guard-0.1.0/.github/workflows/ci.yml +65 -0
  2. yui_agent_guard-0.1.0/.github/workflows/release.yml +84 -0
  3. yui_agent_guard-0.1.0/.gitignore +8 -0
  4. yui_agent_guard-0.1.0/PKG-INFO +277 -0
  5. yui_agent_guard-0.1.0/README.md +248 -0
  6. yui_agent_guard-0.1.0/examples/ai_resilience_path_policy.yaml +32 -0
  7. yui_agent_guard-0.1.0/examples/architecture_policy.yaml +20 -0
  8. yui_agent_guard-0.1.0/examples/content_security_policy.yaml +19 -0
  9. yui_agent_guard-0.1.0/pyproject.toml +66 -0
  10. yui_agent_guard-0.1.0/scripts/check_pypi_release_state.py +65 -0
  11. yui_agent_guard-0.1.0/scripts/check_release_version.py +46 -0
  12. yui_agent_guard-0.1.0/src/agent_guard/__init__.py +27 -0
  13. yui_agent_guard-0.1.0/src/agent_guard/api_guard.py +137 -0
  14. yui_agent_guard-0.1.0/src/agent_guard/cli.py +255 -0
  15. yui_agent_guard-0.1.0/src/agent_guard/content_guard.py +343 -0
  16. yui_agent_guard-0.1.0/src/agent_guard/digest_guard.py +132 -0
  17. yui_agent_guard-0.1.0/src/agent_guard/path_guard.py +182 -0
  18. yui_agent_guard-0.1.0/src/agent_guard/py.typed +0 -0
  19. yui_agent_guard-0.1.0/tests/test_api_guard.py +121 -0
  20. yui_agent_guard-0.1.0/tests/test_check_pypi_release_state.py +48 -0
  21. yui_agent_guard-0.1.0/tests/test_check_release_version.py +53 -0
  22. yui_agent_guard-0.1.0/tests/test_cli.py +208 -0
  23. yui_agent_guard-0.1.0/tests/test_content_guard.py +266 -0
  24. yui_agent_guard-0.1.0/tests/test_digest_guard.py +142 -0
  25. yui_agent_guard-0.1.0/tests/test_packaging.py +31 -0
  26. yui_agent_guard-0.1.0/tests/test_path_guard.py +121 -0
  27. yui_agent_guard-0.1.0/tests/test_public_api.py +20 -0
@@ -0,0 +1,65 @@
1
+ # Where: .github/workflows/ci.yml
2
+ # What: run workflow linting, tests, and packaging checks on every push to master and every PR.
3
+ # Why: keep the extracted guard package safe while the API surface is still moving.
4
+
5
+ name: ci
6
+
7
+ env:
8
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
9
+
10
+ on:
11
+ push:
12
+ branches: [master]
13
+ pull_request:
14
+
15
+ jobs:
16
+ actionlint:
17
+ name: actionlint
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v6
21
+ - uses: devops-actions/actionlint@v0.1.11
22
+
23
+ test:
24
+ name: pytest (py${{ matrix.python-version }})
25
+ runs-on: ubuntu-latest
26
+ strategy:
27
+ fail-fast: false
28
+ matrix:
29
+ python-version: ['3.11', '3.12']
30
+ steps:
31
+ - uses: actions/checkout@v6
32
+ - uses: actions/setup-python@v6
33
+ with:
34
+ python-version: ${{ matrix.python-version }}
35
+ - name: Install package + dev deps
36
+ run: pip install -e ".[dev]"
37
+ - name: Run tests
38
+ run: pytest -q
39
+ - name: Run CLI smoke tests
40
+ run: |
41
+ python -m agent_guard.cli content check --repo-root . --policy examples/content_security_policy.yaml --mode registered --scan-dir . --json
42
+ python -m agent_guard.cli path check --root . --policy examples/ai_resilience_path_policy.yaml --json
43
+ mkdir -p /tmp/agent-guard-digest-smoke
44
+ printf 'pinned\n' > /tmp/agent-guard-digest-smoke/pinned.txt
45
+ python - <<'PY'
46
+ import hashlib
47
+ from pathlib import Path
48
+
49
+ root = Path("/tmp/agent-guard-digest-smoke")
50
+ digest = hashlib.sha256((root / "pinned.txt").read_bytes()).hexdigest()
51
+ (root / "policy.yaml").write_text(
52
+ "checks:\n"
53
+ " - id: pinned_text\n"
54
+ " path: pinned.txt\n"
55
+ f" sha256: '{digest}'\n",
56
+ encoding="utf-8",
57
+ )
58
+ PY
59
+ python -m agent_guard.cli digest check --root /tmp/agent-guard-digest-smoke --policy /tmp/agent-guard-digest-smoke/policy.yaml --json
60
+ - name: Build sdist + wheel
61
+ if: matrix.python-version == '3.12'
62
+ run: python -m build
63
+ - name: Verify metadata (twine check)
64
+ if: matrix.python-version == '3.12'
65
+ run: python -m twine check dist/*
@@ -0,0 +1,84 @@
1
+ # Where: .github/workflows/release.yml
2
+ # What: build sdist+wheel and publish to PyPI on tag push, via Trusted Publishing.
3
+ # Why: make agent-guard consumable from downstream CI without long-lived PyPI tokens.
4
+
5
+ name: release
6
+
7
+ env:
8
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
9
+
10
+ on:
11
+ workflow_dispatch:
12
+ inputs:
13
+ publish:
14
+ description: 'Publish to PyPI instead of build-only dry run'
15
+ required: true
16
+ type: boolean
17
+ default: false
18
+ push:
19
+ tags:
20
+ - 'v*'
21
+
22
+ permissions:
23
+ contents: read
24
+
25
+ jobs:
26
+ validate-release-request:
27
+ name: validate release request
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - name: Validate manual publish ref
31
+ run: |
32
+ set -euo pipefail
33
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ] \
34
+ && [ "${{ inputs.publish }}" = "true" ] \
35
+ && [[ "${GITHUB_REF}" != refs/tags/v* ]]; then
36
+ echo "::error::manual publish=true must be run against a v* tag ref, not ${GITHUB_REF}"
37
+ exit 1
38
+ fi
39
+ echo "release request accepted for ${GITHUB_REF}"
40
+
41
+ build:
42
+ name: build sdist + wheel
43
+ needs: validate-release-request
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v6
47
+ - uses: actions/setup-python@v6
48
+ with:
49
+ python-version: '3.12'
50
+ - name: Assert tag matches package version
51
+ if: github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v')
52
+ env:
53
+ TAG_NAME: ${{ github.ref_name }}
54
+ run: python scripts/check_release_version.py "$TAG_NAME"
55
+ - name: Check PyPI release state
56
+ if: github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v')
57
+ run: python scripts/check_pypi_release_state.py
58
+ - name: Install build + twine
59
+ run: python -m pip install --upgrade build twine
60
+ - name: Build distributions
61
+ run: python -m build
62
+ - name: Verify metadata (twine check)
63
+ run: python -m twine check dist/*
64
+ - uses: actions/upload-artifact@v7
65
+ with:
66
+ name: dist
67
+ path: dist/
68
+
69
+ publish:
70
+ name: publish to PyPI (OIDC)
71
+ needs: build
72
+ if: github.event_name == 'push' || (inputs.publish && startsWith(github.ref, 'refs/tags/v'))
73
+ runs-on: ubuntu-latest
74
+ environment:
75
+ name: pypi
76
+ url: https://pypi.org/p/yui-agent-guard
77
+ permissions:
78
+ id-token: write
79
+ steps:
80
+ - uses: actions/download-artifact@v8
81
+ with:
82
+ name: dist
83
+ path: dist/
84
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ __pycache__/
3
+ .pytest_cache/
4
+ build/
5
+ dist/
6
+ *.egg-info/
7
+ .venv312/
8
+ .venv-py312/
@@ -0,0 +1,277 @@
1
+ Metadata-Version: 2.4
2
+ Name: yui-agent-guard
3
+ Version: 0.1.0
4
+ Summary: Static repository guardrails for agent-touched codebases.
5
+ Project-URL: Repository, https://github.com/yui-stingray/agent-guard
6
+ Project-URL: Issues, https://github.com/yui-stingray/agent-guard/issues
7
+ Author: yui-stingray
8
+ License-Expression: MIT
9
+ Keywords: agent,ai-agents,guardrails,policy,security
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: pyyaml<7,>=6
23
+ Provides-Extra: dev
24
+ Requires-Dist: build<2,>=1.2; extra == 'dev'
25
+ Requires-Dist: pytest-cov<7,>=5; extra == 'dev'
26
+ Requires-Dist: pytest<9,>=8; extra == 'dev'
27
+ Requires-Dist: twine<7,>=6; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # agent-guard
31
+
32
+ > Static repository guardrails for agent-touched codebases.
33
+ >
34
+ > `agent-policy` decides whether an agent should do something.
35
+ > `agent-guard` checks whether the repository content still obeys the rules.
36
+
37
+ **Status**: `0.1.0` alpha. The current MVP ships four scanners: `api`, `content`, `path`, and `digest`.
38
+
39
+ ## Why
40
+
41
+ `agent-guard` exists to enforce fail-closed static checks around agent-operated repositories without pulling in a full control plane.
42
+
43
+ The current extracted scanners are intentionally narrow:
44
+ - `api`: scan repository text files for URLs, allow approved API patterns, fail on forbidden API patterns
45
+ - `content`: scan Markdown or other configured text files for dangerous instruction patterns
46
+ - `path`: scan repository path names for private artifacts, env files, and other publish-time leaks
47
+ - `digest`: verify SHA-256 pins for governance docs and safety-critical scripts
48
+ - return stable JSON or text output for local hooks and CI
49
+
50
+ It does **not** manage approvals, logs, state, or UI. Those belong in higher layers.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pip install -e .
56
+ ```
57
+
58
+ Requires Python 3.11+. The only runtime dependency is `PyYAML`.
59
+
60
+ ## Quick start
61
+
62
+ API surface guard:
63
+
64
+ ```bash
65
+ agent-guard api check --root . --policy examples/architecture_policy.yaml
66
+ ```
67
+
68
+ Content security guard:
69
+
70
+ ```bash
71
+ agent-guard content check --repo-root . --policy examples/content_security_policy.yaml --mode registered --scan-dir skills
72
+ ```
73
+
74
+ Path-name guard:
75
+
76
+ ```bash
77
+ agent-guard path check --root . --policy examples/ai_resilience_path_policy.yaml
78
+ ```
79
+
80
+ Digest guard:
81
+
82
+ ```bash
83
+ agent-guard digest check --root . --policy digest_policy.yaml
84
+ ```
85
+
86
+ JSON mode is stable and intended for CI/wrappers:
87
+
88
+ ```bash
89
+ agent-guard api check --root . --policy examples/architecture_policy.yaml --json
90
+ agent-guard content check --repo-root . --policy examples/content_security_policy.yaml --mode registered --scan-dir skills --json
91
+ agent-guard path check --root . --policy examples/ai_resilience_path_policy.yaml --json
92
+ agent-guard digest check --root . --policy digest_policy.yaml --json
93
+ ```
94
+
95
+ ## Current scanners
96
+
97
+ ### API guard
98
+
99
+ The API guard scans configured paths for URLs and compares them against allow/deny regex lists.
100
+
101
+ Typical use case:
102
+ - keep a CLI-first repository from silently drifting into direct inference API calls
103
+
104
+ It returns:
105
+ - exit `0` on clean
106
+ - exit `1` on violation
107
+ - exit `2` on configuration/runtime error
108
+
109
+ ### Content guard
110
+
111
+ The content guard scans configured text content for forbidden regex patterns.
112
+
113
+ Supported modes:
114
+ - `registered`: scan a configured directory under the repo
115
+ - `preregister`: scan explicit file or directory targets
116
+ - `new`: scan changed files from git diff, optionally including untracked files
117
+
118
+ `new` mode uses two behaviors: with `--since-ref`, it scans files changed between that ref and `HEAD`; without `--since-ref`, it scans the current working tree diff and can optionally include untracked files.
119
+
120
+ Typical use cases:
121
+ - keep dangerous install instructions out of skills docs
122
+ - block hardcoded credential-like strings in agent-authored Markdown
123
+ - catch destructive command suggestions before they spread
124
+
125
+ It returns:
126
+ - exit `0` on clean
127
+ - exit `1` on violation
128
+ - exit `2` on configuration/runtime error
129
+
130
+ ### Path guard
131
+
132
+ The path guard scans file and directory names under configured roots. It uses
133
+ allowlist-first matching so narrow exceptions such as `.env.example` can be
134
+ allowed while broader deny patterns still block `.env`, `.env.local`, and
135
+ `.env.evil`.
136
+
137
+ Typical use cases:
138
+ - keep `artifacts/private/` out of publishable repository paths
139
+ - block bypass corpus files and red-team session logs by name
140
+ - catch env-file leaks even when contents are ignored or unreadable
141
+
142
+ It returns:
143
+ - exit `0` on clean
144
+ - exit `1` on violation
145
+ - exit `2` on configuration/runtime error
146
+
147
+ ### Digest guard
148
+
149
+ The digest guard verifies pinned SHA-256 values for files that should not
150
+ drift silently. Each check names a repository-relative path, an expected
151
+ digest, and an optional `start_line` when only the content body should be
152
+ hashed.
153
+
154
+ Typical use cases:
155
+ - detect unreviewed edits to governance documents
156
+ - pin verifier scripts that protect publication or release gates
157
+ - preserve B9-style constitution integrity checks without shell-specific logic
158
+
159
+ It returns:
160
+ - exit `0` on clean
161
+ - exit `1` on violation
162
+ - exit `2` on configuration/runtime error
163
+
164
+ ## Example policies
165
+
166
+ ### API guard policy
167
+
168
+ ```yaml
169
+ scan:
170
+ include:
171
+ - src
172
+ - scripts
173
+ exclude:
174
+ - scripts/build_instructions.sh
175
+
176
+ policy:
177
+ allowed_api_patterns:
178
+ - "^https://ntfy\.sh/"
179
+ forbidden_api_patterns:
180
+ - "^https://api\.openai\.com/"
181
+ - "^https://api\.anthropic\.com/"
182
+ ```
183
+
184
+ A ready-to-run copy lives in [`examples/architecture_policy.yaml`](examples/architecture_policy.yaml).
185
+
186
+ ### Content guard policy
187
+
188
+ ```yaml
189
+ file_globs:
190
+ - "**/*.md"
191
+ exclude_globs:
192
+ - "archive/**"
193
+ forbidden_patterns:
194
+ - id: pipe_to_shell
195
+ severity: high
196
+ pattern: '(?i)curl\s+[^\n|]+\|\s*(bash|sh)\b'
197
+ message: "pipe-to-shell pattern is forbidden"
198
+ exclude_globs:
199
+ - "fixtures/red-team/**"
200
+ ```
201
+
202
+ A ready-to-run copy lives in [`examples/content_security_policy.yaml`](examples/content_security_policy.yaml).
203
+
204
+ Content rules may define per-rule `include_globs` / `exclude_globs`. Use this
205
+ when a repository contains intentional adversarial fixtures that should stay
206
+ scannable for secrets but should not fail dangerous-command rules. For narrow
207
+ documented examples, append an inline suppression such as
208
+ `# agent-guard: allow pipe_to_shell` or `# agent-guard: allow all` on the same
209
+ line.
210
+
211
+ ### Path guard policy
212
+
213
+ ```yaml
214
+ scan:
215
+ include:
216
+ - "."
217
+ exclude:
218
+ - ".git"
219
+ - ".venv"
220
+ - "node_modules"
221
+
222
+ policy:
223
+ allowed_path_patterns:
224
+ - "(^|/)\\.env\\.example$"
225
+ forbidden_path_patterns:
226
+ - id: private_artifacts
227
+ severity: high
228
+ pattern: "(^|/)artifacts/private(/|$)"
229
+ message: "private artifact directory must stay outside published/tracked paths"
230
+ ```
231
+
232
+ A ready-to-run ai-resilience-style copy lives in
233
+ [`examples/ai_resilience_path_policy.yaml`](examples/ai_resilience_path_policy.yaml).
234
+
235
+ ### Digest guard policy
236
+
237
+ ```yaml
238
+ checks:
239
+ - id: constitution_full
240
+ path: agent-constitution-v0.md
241
+ sha256: "<64-char lowercase sha256>"
242
+ - id: constitution_content
243
+ path: agent-constitution-v0.md
244
+ sha256: "<64-char lowercase sha256>"
245
+ start_line: 15
246
+ ```
247
+
248
+ ## CLI
249
+
250
+ ```bash
251
+ agent-guard api check --root <repo> --policy <yaml> [--json]
252
+ agent-guard content check --repo-root <repo> --policy <yaml> --mode <registered|preregister|new> [--scan-dir <dir>] [--targets <paths...>] [--since-ref <ref>] [--no-untracked] [--json]
253
+ agent-guard path check --root <repo> --policy <yaml> [--json]
254
+ agent-guard digest check --root <repo> --policy <yaml> [--json]
255
+ ```
256
+
257
+ ## Roadmap
258
+
259
+ Planned next steps:
260
+ - shared result envelope helpers across scanners
261
+ - optional pre-commit examples
262
+
263
+ ## Releases
264
+
265
+ Tag-driven. Pushing a `vX.Y.Z` annotated tag triggers
266
+ [`.github/workflows/release.yml`](.github/workflows/release.yml), which first
267
+ verifies that the tag matches `[project].version` in `pyproject.toml`, checks
268
+ that the version is not already present on PyPI, then builds the sdist + wheel
269
+ and publishes to PyPI via Trusted Publishing (OIDC). No maintainer-side PyPI
270
+ token is required once the PyPI project environment is configured. Manual
271
+ `workflow_dispatch` with `publish=false` is a build-only dry run; it skips the
272
+ publish job. Manual `publish=true` must be run against a `v*` tag ref; running
273
+ it from a branch fails before build.
274
+
275
+ ## License
276
+
277
+ MIT.
@@ -0,0 +1,248 @@
1
+ # agent-guard
2
+
3
+ > Static repository guardrails for agent-touched codebases.
4
+ >
5
+ > `agent-policy` decides whether an agent should do something.
6
+ > `agent-guard` checks whether the repository content still obeys the rules.
7
+
8
+ **Status**: `0.1.0` alpha. The current MVP ships four scanners: `api`, `content`, `path`, and `digest`.
9
+
10
+ ## Why
11
+
12
+ `agent-guard` exists to enforce fail-closed static checks around agent-operated repositories without pulling in a full control plane.
13
+
14
+ The current extracted scanners are intentionally narrow:
15
+ - `api`: scan repository text files for URLs, allow approved API patterns, fail on forbidden API patterns
16
+ - `content`: scan Markdown or other configured text files for dangerous instruction patterns
17
+ - `path`: scan repository path names for private artifacts, env files, and other publish-time leaks
18
+ - `digest`: verify SHA-256 pins for governance docs and safety-critical scripts
19
+ - return stable JSON or text output for local hooks and CI
20
+
21
+ It does **not** manage approvals, logs, state, or UI. Those belong in higher layers.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install -e .
27
+ ```
28
+
29
+ Requires Python 3.11+. The only runtime dependency is `PyYAML`.
30
+
31
+ ## Quick start
32
+
33
+ API surface guard:
34
+
35
+ ```bash
36
+ agent-guard api check --root . --policy examples/architecture_policy.yaml
37
+ ```
38
+
39
+ Content security guard:
40
+
41
+ ```bash
42
+ agent-guard content check --repo-root . --policy examples/content_security_policy.yaml --mode registered --scan-dir skills
43
+ ```
44
+
45
+ Path-name guard:
46
+
47
+ ```bash
48
+ agent-guard path check --root . --policy examples/ai_resilience_path_policy.yaml
49
+ ```
50
+
51
+ Digest guard:
52
+
53
+ ```bash
54
+ agent-guard digest check --root . --policy digest_policy.yaml
55
+ ```
56
+
57
+ JSON mode is stable and intended for CI/wrappers:
58
+
59
+ ```bash
60
+ agent-guard api check --root . --policy examples/architecture_policy.yaml --json
61
+ agent-guard content check --repo-root . --policy examples/content_security_policy.yaml --mode registered --scan-dir skills --json
62
+ agent-guard path check --root . --policy examples/ai_resilience_path_policy.yaml --json
63
+ agent-guard digest check --root . --policy digest_policy.yaml --json
64
+ ```
65
+
66
+ ## Current scanners
67
+
68
+ ### API guard
69
+
70
+ The API guard scans configured paths for URLs and compares them against allow/deny regex lists.
71
+
72
+ Typical use case:
73
+ - keep a CLI-first repository from silently drifting into direct inference API calls
74
+
75
+ It returns:
76
+ - exit `0` on clean
77
+ - exit `1` on violation
78
+ - exit `2` on configuration/runtime error
79
+
80
+ ### Content guard
81
+
82
+ The content guard scans configured text content for forbidden regex patterns.
83
+
84
+ Supported modes:
85
+ - `registered`: scan a configured directory under the repo
86
+ - `preregister`: scan explicit file or directory targets
87
+ - `new`: scan changed files from git diff, optionally including untracked files
88
+
89
+ `new` mode uses two behaviors: with `--since-ref`, it scans files changed between that ref and `HEAD`; without `--since-ref`, it scans the current working tree diff and can optionally include untracked files.
90
+
91
+ Typical use cases:
92
+ - keep dangerous install instructions out of skills docs
93
+ - block hardcoded credential-like strings in agent-authored Markdown
94
+ - catch destructive command suggestions before they spread
95
+
96
+ It returns:
97
+ - exit `0` on clean
98
+ - exit `1` on violation
99
+ - exit `2` on configuration/runtime error
100
+
101
+ ### Path guard
102
+
103
+ The path guard scans file and directory names under configured roots. It uses
104
+ allowlist-first matching so narrow exceptions such as `.env.example` can be
105
+ allowed while broader deny patterns still block `.env`, `.env.local`, and
106
+ `.env.evil`.
107
+
108
+ Typical use cases:
109
+ - keep `artifacts/private/` out of publishable repository paths
110
+ - block bypass corpus files and red-team session logs by name
111
+ - catch env-file leaks even when contents are ignored or unreadable
112
+
113
+ It returns:
114
+ - exit `0` on clean
115
+ - exit `1` on violation
116
+ - exit `2` on configuration/runtime error
117
+
118
+ ### Digest guard
119
+
120
+ The digest guard verifies pinned SHA-256 values for files that should not
121
+ drift silently. Each check names a repository-relative path, an expected
122
+ digest, and an optional `start_line` when only the content body should be
123
+ hashed.
124
+
125
+ Typical use cases:
126
+ - detect unreviewed edits to governance documents
127
+ - pin verifier scripts that protect publication or release gates
128
+ - preserve B9-style constitution integrity checks without shell-specific logic
129
+
130
+ It returns:
131
+ - exit `0` on clean
132
+ - exit `1` on violation
133
+ - exit `2` on configuration/runtime error
134
+
135
+ ## Example policies
136
+
137
+ ### API guard policy
138
+
139
+ ```yaml
140
+ scan:
141
+ include:
142
+ - src
143
+ - scripts
144
+ exclude:
145
+ - scripts/build_instructions.sh
146
+
147
+ policy:
148
+ allowed_api_patterns:
149
+ - "^https://ntfy\.sh/"
150
+ forbidden_api_patterns:
151
+ - "^https://api\.openai\.com/"
152
+ - "^https://api\.anthropic\.com/"
153
+ ```
154
+
155
+ A ready-to-run copy lives in [`examples/architecture_policy.yaml`](examples/architecture_policy.yaml).
156
+
157
+ ### Content guard policy
158
+
159
+ ```yaml
160
+ file_globs:
161
+ - "**/*.md"
162
+ exclude_globs:
163
+ - "archive/**"
164
+ forbidden_patterns:
165
+ - id: pipe_to_shell
166
+ severity: high
167
+ pattern: '(?i)curl\s+[^\n|]+\|\s*(bash|sh)\b'
168
+ message: "pipe-to-shell pattern is forbidden"
169
+ exclude_globs:
170
+ - "fixtures/red-team/**"
171
+ ```
172
+
173
+ A ready-to-run copy lives in [`examples/content_security_policy.yaml`](examples/content_security_policy.yaml).
174
+
175
+ Content rules may define per-rule `include_globs` / `exclude_globs`. Use this
176
+ when a repository contains intentional adversarial fixtures that should stay
177
+ scannable for secrets but should not fail dangerous-command rules. For narrow
178
+ documented examples, append an inline suppression such as
179
+ `# agent-guard: allow pipe_to_shell` or `# agent-guard: allow all` on the same
180
+ line.
181
+
182
+ ### Path guard policy
183
+
184
+ ```yaml
185
+ scan:
186
+ include:
187
+ - "."
188
+ exclude:
189
+ - ".git"
190
+ - ".venv"
191
+ - "node_modules"
192
+
193
+ policy:
194
+ allowed_path_patterns:
195
+ - "(^|/)\\.env\\.example$"
196
+ forbidden_path_patterns:
197
+ - id: private_artifacts
198
+ severity: high
199
+ pattern: "(^|/)artifacts/private(/|$)"
200
+ message: "private artifact directory must stay outside published/tracked paths"
201
+ ```
202
+
203
+ A ready-to-run ai-resilience-style copy lives in
204
+ [`examples/ai_resilience_path_policy.yaml`](examples/ai_resilience_path_policy.yaml).
205
+
206
+ ### Digest guard policy
207
+
208
+ ```yaml
209
+ checks:
210
+ - id: constitution_full
211
+ path: agent-constitution-v0.md
212
+ sha256: "<64-char lowercase sha256>"
213
+ - id: constitution_content
214
+ path: agent-constitution-v0.md
215
+ sha256: "<64-char lowercase sha256>"
216
+ start_line: 15
217
+ ```
218
+
219
+ ## CLI
220
+
221
+ ```bash
222
+ agent-guard api check --root <repo> --policy <yaml> [--json]
223
+ agent-guard content check --repo-root <repo> --policy <yaml> --mode <registered|preregister|new> [--scan-dir <dir>] [--targets <paths...>] [--since-ref <ref>] [--no-untracked] [--json]
224
+ agent-guard path check --root <repo> --policy <yaml> [--json]
225
+ agent-guard digest check --root <repo> --policy <yaml> [--json]
226
+ ```
227
+
228
+ ## Roadmap
229
+
230
+ Planned next steps:
231
+ - shared result envelope helpers across scanners
232
+ - optional pre-commit examples
233
+
234
+ ## Releases
235
+
236
+ Tag-driven. Pushing a `vX.Y.Z` annotated tag triggers
237
+ [`.github/workflows/release.yml`](.github/workflows/release.yml), which first
238
+ verifies that the tag matches `[project].version` in `pyproject.toml`, checks
239
+ that the version is not already present on PyPI, then builds the sdist + wheel
240
+ and publishes to PyPI via Trusted Publishing (OIDC). No maintainer-side PyPI
241
+ token is required once the PyPI project environment is configured. Manual
242
+ `workflow_dispatch` with `publish=false` is a build-only dry run; it skips the
243
+ publish job. Manual `publish=true` must be run against a `v*` tag ref; running
244
+ it from a branch fails before build.
245
+
246
+ ## License
247
+
248
+ MIT.