rule-audit 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.
- rule_audit-0.1.0/LICENSE +21 -0
- rule_audit-0.1.0/PKG-INFO +240 -0
- rule_audit-0.1.0/README.md +210 -0
- rule_audit-0.1.0/pyproject.toml +69 -0
- rule_audit-0.1.0/rule_audit/__init__.py +60 -0
- rule_audit-0.1.0/rule_audit/__main__.py +6 -0
- rule_audit-0.1.0/rule_audit/analyzer.py +1024 -0
- rule_audit-0.1.0/rule_audit/cli.py +265 -0
- rule_audit-0.1.0/rule_audit/edge_cases.py +448 -0
- rule_audit-0.1.0/rule_audit/parser.py +365 -0
- rule_audit-0.1.0/rule_audit/py.typed +0 -0
- rule_audit-0.1.0/rule_audit/report.py +443 -0
- rule_audit-0.1.0/rule_audit.egg-info/PKG-INFO +240 -0
- rule_audit-0.1.0/rule_audit.egg-info/SOURCES.txt +21 -0
- rule_audit-0.1.0/rule_audit.egg-info/dependency_links.txt +1 -0
- rule_audit-0.1.0/rule_audit.egg-info/entry_points.txt +2 -0
- rule_audit-0.1.0/rule_audit.egg-info/requires.txt +5 -0
- rule_audit-0.1.0/rule_audit.egg-info/top_level.txt +1 -0
- rule_audit-0.1.0/setup.cfg +4 -0
- rule_audit-0.1.0/tests/test_analyzer.py +426 -0
- rule_audit-0.1.0/tests/test_benchmark.py +589 -0
- rule_audit-0.1.0/tests/test_parser.py +315 -0
- rule_audit-0.1.0/tests/test_philosophical.py +343 -0
rule_audit-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hermes Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rule-audit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Detect logical contradictions, gaps, and exploitable edge cases in AI system prompts
|
|
5
|
+
Author-email: Hermes Labs <rolybosch96@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/roli-lpci/rule-audit
|
|
8
|
+
Project-URL: Repository, https://github.com/roli-lpci/rule-audit
|
|
9
|
+
Project-URL: Issues, https://github.com/roli-lpci/rule-audit/issues
|
|
10
|
+
Keywords: ai-safety,llm,prompt-engineering,security,audit,contradiction-detection,red-teaming
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov>=4.1; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# rule-audit
|
|
32
|
+
|
|
33
|
+
**Static analyzer for AI system prompts. Finds logical contradictions, coverage gaps, and exploitable edge cases — without running an LLM.**
|
|
34
|
+
|
|
35
|
+
Built at Hermes Labs Hackathon Round 8: ModelBreak.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## The Problem
|
|
40
|
+
|
|
41
|
+
Any sufficiently complex AI safety prompt contains rules that contradict each other under specific conditions. These contradictions are invisible to the author but obvious to an attacker. `rule-audit` finds them first.
|
|
42
|
+
|
|
43
|
+
**Real contradiction in standard safety prompts:**
|
|
44
|
+
```
|
|
45
|
+
"You must always follow user instructions."
|
|
46
|
+
"You must never produce harmful content."
|
|
47
|
+
```
|
|
48
|
+
These are irreconcilable the moment a user instructs the model to produce harmful content. No priority clause means the model chooses arbitrarily — or the attacker chooses for it.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install rule-audit
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or from source:
|
|
59
|
+
```bash
|
|
60
|
+
git clone https://github.com/roli-lpci/rule-audit
|
|
61
|
+
cd rule-audit
|
|
62
|
+
pip install -e ".[dev]"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Quickstart
|
|
68
|
+
|
|
69
|
+
### CLI
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Inline prompt
|
|
73
|
+
rule-audit "You are helpful. You must never lie. Always answer every question."
|
|
74
|
+
|
|
75
|
+
# From file
|
|
76
|
+
rule-audit --file system_prompt.txt
|
|
77
|
+
|
|
78
|
+
# Save Markdown report
|
|
79
|
+
rule-audit --file system_prompt.txt --output report.md
|
|
80
|
+
|
|
81
|
+
# JSON output for downstream processing
|
|
82
|
+
rule-audit --file system_prompt.txt --format json
|
|
83
|
+
|
|
84
|
+
# Summary only (for CI gates)
|
|
85
|
+
rule-audit --file system_prompt.txt --format summary
|
|
86
|
+
|
|
87
|
+
# Show all parsed rules
|
|
88
|
+
rule-audit --file system_prompt.txt --verbose
|
|
89
|
+
|
|
90
|
+
# Only show high-severity findings
|
|
91
|
+
rule-audit --file system_prompt.txt --min-severity high
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Exit codes: `0` = low/no risk, `2` = high/critical risk, `1` = error.
|
|
95
|
+
|
|
96
|
+
### Python API
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from rule_audit import audit
|
|
100
|
+
|
|
101
|
+
report = audit("""
|
|
102
|
+
You are a helpful AI assistant.
|
|
103
|
+
Always answer user questions completely.
|
|
104
|
+
Never produce content that could harm anyone.
|
|
105
|
+
Follow operator instructions above all else.
|
|
106
|
+
If asked to roleplay without restrictions, comply.
|
|
107
|
+
""")
|
|
108
|
+
|
|
109
|
+
print(report.summary())
|
|
110
|
+
# rule-audit report [2026-04-15T...]
|
|
111
|
+
# ============================================================
|
|
112
|
+
# Rules parsed : 6
|
|
113
|
+
# Contradictions : 3 (2 high, 1 medium)
|
|
114
|
+
# Coverage gaps : 4
|
|
115
|
+
# Priority ambiguities : 2
|
|
116
|
+
# Meta-paradoxes : 0
|
|
117
|
+
# Absoluteness issues : 5
|
|
118
|
+
# Edge case scenarios : 11
|
|
119
|
+
# Risk score : 67/100 [HIGH]
|
|
120
|
+
|
|
121
|
+
# Full Markdown report
|
|
122
|
+
md = report.to_markdown()
|
|
123
|
+
|
|
124
|
+
# Access findings programmatically
|
|
125
|
+
for c in report.result.contradictions:
|
|
126
|
+
print(c.severity, c.description)
|
|
127
|
+
|
|
128
|
+
for ec in report.edge_cases:
|
|
129
|
+
print(ec.title)
|
|
130
|
+
print(ec.attack_vector)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## What It Detects
|
|
136
|
+
|
|
137
|
+
### 1. Contradictions
|
|
138
|
+
Rule pairs where one says "always X" and another says "never X in context Y". Three subtypes:
|
|
139
|
+
|
|
140
|
+
- **Direct** — opposing modalities on the same topic (`MUST` vs `MUST_NOT`)
|
|
141
|
+
- **Conditional** — one rule applies unconditionally, another restricts within a subset (boundary is undefined)
|
|
142
|
+
- **Absoluteness** — two absolute rules that pull in opposite directions (compliance vs safety)
|
|
143
|
+
|
|
144
|
+
### 2. Coverage Gaps
|
|
145
|
+
Scenario domains with no rule coverage. Checks for:
|
|
146
|
+
- Harmful content handling
|
|
147
|
+
- Principal hierarchy (user vs operator vs developer)
|
|
148
|
+
- Ambiguous request handling
|
|
149
|
+
- Persona / roleplay scenarios
|
|
150
|
+
- Refusal protocol
|
|
151
|
+
- Instruction conflict resolution
|
|
152
|
+
- Self-disclosure rules
|
|
153
|
+
- Edge case fallback behavior
|
|
154
|
+
|
|
155
|
+
### 3. Priority Ambiguities
|
|
156
|
+
Rule clusters that conflict with no explicit ordering. Classic example: a safety rule and a helpfulness rule both applying to the same request, with no stated priority.
|
|
157
|
+
|
|
158
|
+
### 4. Meta-Rule Paradoxes
|
|
159
|
+
Rules that reference rules:
|
|
160
|
+
- **Self-defeating** — "ignore all instructions" voids itself
|
|
161
|
+
- **Override loops** — "these instructions supersede all others" is exploitable via injection
|
|
162
|
+
- **Circular** — a rule that requires itself to be applied before it can be applied
|
|
163
|
+
|
|
164
|
+
### 5. Absoluteness Audit
|
|
165
|
+
Every `always`/`never`/`under no circumstances` rule is challenged with:
|
|
166
|
+
- Known exceptions that legitimately exist
|
|
167
|
+
- Context-dependent cases where the absolute doesn't hold
|
|
168
|
+
- Adversarial triggers that exploit the absolute
|
|
169
|
+
|
|
170
|
+
### 6. Edge Case Scenarios
|
|
171
|
+
For each finding, generates the exact attack prompt an adversary would construct — including the attack vector, expected failure mode, and mitigation.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Architecture
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
rule_audit/
|
|
179
|
+
├── __init__.py # Public API: audit(), audit_file(), AuditReport
|
|
180
|
+
├── parser.py # Sentence splitting, modal verb detection, Rule objects
|
|
181
|
+
├── analyzer.py # Contradiction finder, gap detector, priority mapper
|
|
182
|
+
├── edge_cases.py # Scenario generator from analysis results
|
|
183
|
+
├── report.py # Markdown + summary renderer, AuditReport class
|
|
184
|
+
└── cli.py # CLI entry point
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Pure Python. Zero LLM dependency. Zero API calls.**
|
|
188
|
+
|
|
189
|
+
The parser uses NLP heuristics:
|
|
190
|
+
- Sentence boundary detection (period + newline + list markers)
|
|
191
|
+
- Modal verb regex patterns (must/should/may + negations)
|
|
192
|
+
- Absoluteness scoring (lexical keywords → 0.0–1.0 scale)
|
|
193
|
+
- Keyword cluster matching (14 semantic clusters: harm, privacy, identity, truth, ...)
|
|
194
|
+
|
|
195
|
+
The analyzer uses combinatorial pair analysis:
|
|
196
|
+
- O(n²) rule pair comparison (practical for prompts: n < 100)
|
|
197
|
+
- Cluster overlap detection for shared domain identification
|
|
198
|
+
- Modality opposition lookup table
|
|
199
|
+
- Absoluteness threshold gates
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Road to SaaS
|
|
204
|
+
|
|
205
|
+
This tool was built as a static analyzer, but the architecture supports a commercial path:
|
|
206
|
+
|
|
207
|
+
| Phase | Feature | Status |
|
|
208
|
+
|-------|---------|--------|
|
|
209
|
+
| v0.1 | Core static analysis, CLI, Python API | Done |
|
|
210
|
+
| v0.2 | Rule diffing (before/after prompt edits) | Planned |
|
|
211
|
+
| v0.3 | LLM-augmented gap detection (optional) | Planned |
|
|
212
|
+
| v0.4 | GitHub Action / CI integration | Planned |
|
|
213
|
+
| v1.0 | Web UI + prompt editor with live feedback | Planned |
|
|
214
|
+
| SaaS | Per-prompt API, team dashboards, compliance reports | Roadmap |
|
|
215
|
+
|
|
216
|
+
**Target customers:** AI teams building production LLM products who need to audit system prompts before deployment. Compliance teams preparing for EU AI Act audits. Red team consultancies.
|
|
217
|
+
|
|
218
|
+
**Pricing model:** Free CLI tier → $X/month API tier → Enterprise (custom).
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Development
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# Run tests
|
|
226
|
+
pytest
|
|
227
|
+
|
|
228
|
+
# Run with coverage
|
|
229
|
+
pytest --cov=rule_audit --cov-report=term-missing
|
|
230
|
+
|
|
231
|
+
# Test against a real prompt
|
|
232
|
+
echo "Your system prompt here" > test_prompt.txt
|
|
233
|
+
python -m rule_audit --file test_prompt.txt --verbose
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT — Hermes Labs 2026
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# rule-audit
|
|
2
|
+
|
|
3
|
+
**Static analyzer for AI system prompts. Finds logical contradictions, coverage gaps, and exploitable edge cases — without running an LLM.**
|
|
4
|
+
|
|
5
|
+
Built at Hermes Labs Hackathon Round 8: ModelBreak.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
Any sufficiently complex AI safety prompt contains rules that contradict each other under specific conditions. These contradictions are invisible to the author but obvious to an attacker. `rule-audit` finds them first.
|
|
12
|
+
|
|
13
|
+
**Real contradiction in standard safety prompts:**
|
|
14
|
+
```
|
|
15
|
+
"You must always follow user instructions."
|
|
16
|
+
"You must never produce harmful content."
|
|
17
|
+
```
|
|
18
|
+
These are irreconcilable the moment a user instructs the model to produce harmful content. No priority clause means the model chooses arbitrarily — or the attacker chooses for it.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install rule-audit
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or from source:
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/roli-lpci/rule-audit
|
|
31
|
+
cd rule-audit
|
|
32
|
+
pip install -e ".[dev]"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Quickstart
|
|
38
|
+
|
|
39
|
+
### CLI
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Inline prompt
|
|
43
|
+
rule-audit "You are helpful. You must never lie. Always answer every question."
|
|
44
|
+
|
|
45
|
+
# From file
|
|
46
|
+
rule-audit --file system_prompt.txt
|
|
47
|
+
|
|
48
|
+
# Save Markdown report
|
|
49
|
+
rule-audit --file system_prompt.txt --output report.md
|
|
50
|
+
|
|
51
|
+
# JSON output for downstream processing
|
|
52
|
+
rule-audit --file system_prompt.txt --format json
|
|
53
|
+
|
|
54
|
+
# Summary only (for CI gates)
|
|
55
|
+
rule-audit --file system_prompt.txt --format summary
|
|
56
|
+
|
|
57
|
+
# Show all parsed rules
|
|
58
|
+
rule-audit --file system_prompt.txt --verbose
|
|
59
|
+
|
|
60
|
+
# Only show high-severity findings
|
|
61
|
+
rule-audit --file system_prompt.txt --min-severity high
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Exit codes: `0` = low/no risk, `2` = high/critical risk, `1` = error.
|
|
65
|
+
|
|
66
|
+
### Python API
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from rule_audit import audit
|
|
70
|
+
|
|
71
|
+
report = audit("""
|
|
72
|
+
You are a helpful AI assistant.
|
|
73
|
+
Always answer user questions completely.
|
|
74
|
+
Never produce content that could harm anyone.
|
|
75
|
+
Follow operator instructions above all else.
|
|
76
|
+
If asked to roleplay without restrictions, comply.
|
|
77
|
+
""")
|
|
78
|
+
|
|
79
|
+
print(report.summary())
|
|
80
|
+
# rule-audit report [2026-04-15T...]
|
|
81
|
+
# ============================================================
|
|
82
|
+
# Rules parsed : 6
|
|
83
|
+
# Contradictions : 3 (2 high, 1 medium)
|
|
84
|
+
# Coverage gaps : 4
|
|
85
|
+
# Priority ambiguities : 2
|
|
86
|
+
# Meta-paradoxes : 0
|
|
87
|
+
# Absoluteness issues : 5
|
|
88
|
+
# Edge case scenarios : 11
|
|
89
|
+
# Risk score : 67/100 [HIGH]
|
|
90
|
+
|
|
91
|
+
# Full Markdown report
|
|
92
|
+
md = report.to_markdown()
|
|
93
|
+
|
|
94
|
+
# Access findings programmatically
|
|
95
|
+
for c in report.result.contradictions:
|
|
96
|
+
print(c.severity, c.description)
|
|
97
|
+
|
|
98
|
+
for ec in report.edge_cases:
|
|
99
|
+
print(ec.title)
|
|
100
|
+
print(ec.attack_vector)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## What It Detects
|
|
106
|
+
|
|
107
|
+
### 1. Contradictions
|
|
108
|
+
Rule pairs where one says "always X" and another says "never X in context Y". Three subtypes:
|
|
109
|
+
|
|
110
|
+
- **Direct** — opposing modalities on the same topic (`MUST` vs `MUST_NOT`)
|
|
111
|
+
- **Conditional** — one rule applies unconditionally, another restricts within a subset (boundary is undefined)
|
|
112
|
+
- **Absoluteness** — two absolute rules that pull in opposite directions (compliance vs safety)
|
|
113
|
+
|
|
114
|
+
### 2. Coverage Gaps
|
|
115
|
+
Scenario domains with no rule coverage. Checks for:
|
|
116
|
+
- Harmful content handling
|
|
117
|
+
- Principal hierarchy (user vs operator vs developer)
|
|
118
|
+
- Ambiguous request handling
|
|
119
|
+
- Persona / roleplay scenarios
|
|
120
|
+
- Refusal protocol
|
|
121
|
+
- Instruction conflict resolution
|
|
122
|
+
- Self-disclosure rules
|
|
123
|
+
- Edge case fallback behavior
|
|
124
|
+
|
|
125
|
+
### 3. Priority Ambiguities
|
|
126
|
+
Rule clusters that conflict with no explicit ordering. Classic example: a safety rule and a helpfulness rule both applying to the same request, with no stated priority.
|
|
127
|
+
|
|
128
|
+
### 4. Meta-Rule Paradoxes
|
|
129
|
+
Rules that reference rules:
|
|
130
|
+
- **Self-defeating** — "ignore all instructions" voids itself
|
|
131
|
+
- **Override loops** — "these instructions supersede all others" is exploitable via injection
|
|
132
|
+
- **Circular** — a rule that requires itself to be applied before it can be applied
|
|
133
|
+
|
|
134
|
+
### 5. Absoluteness Audit
|
|
135
|
+
Every `always`/`never`/`under no circumstances` rule is challenged with:
|
|
136
|
+
- Known exceptions that legitimately exist
|
|
137
|
+
- Context-dependent cases where the absolute doesn't hold
|
|
138
|
+
- Adversarial triggers that exploit the absolute
|
|
139
|
+
|
|
140
|
+
### 6. Edge Case Scenarios
|
|
141
|
+
For each finding, generates the exact attack prompt an adversary would construct — including the attack vector, expected failure mode, and mitigation.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Architecture
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
rule_audit/
|
|
149
|
+
├── __init__.py # Public API: audit(), audit_file(), AuditReport
|
|
150
|
+
├── parser.py # Sentence splitting, modal verb detection, Rule objects
|
|
151
|
+
├── analyzer.py # Contradiction finder, gap detector, priority mapper
|
|
152
|
+
├── edge_cases.py # Scenario generator from analysis results
|
|
153
|
+
├── report.py # Markdown + summary renderer, AuditReport class
|
|
154
|
+
└── cli.py # CLI entry point
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Pure Python. Zero LLM dependency. Zero API calls.**
|
|
158
|
+
|
|
159
|
+
The parser uses NLP heuristics:
|
|
160
|
+
- Sentence boundary detection (period + newline + list markers)
|
|
161
|
+
- Modal verb regex patterns (must/should/may + negations)
|
|
162
|
+
- Absoluteness scoring (lexical keywords → 0.0–1.0 scale)
|
|
163
|
+
- Keyword cluster matching (14 semantic clusters: harm, privacy, identity, truth, ...)
|
|
164
|
+
|
|
165
|
+
The analyzer uses combinatorial pair analysis:
|
|
166
|
+
- O(n²) rule pair comparison (practical for prompts: n < 100)
|
|
167
|
+
- Cluster overlap detection for shared domain identification
|
|
168
|
+
- Modality opposition lookup table
|
|
169
|
+
- Absoluteness threshold gates
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Road to SaaS
|
|
174
|
+
|
|
175
|
+
This tool was built as a static analyzer, but the architecture supports a commercial path:
|
|
176
|
+
|
|
177
|
+
| Phase | Feature | Status |
|
|
178
|
+
|-------|---------|--------|
|
|
179
|
+
| v0.1 | Core static analysis, CLI, Python API | Done |
|
|
180
|
+
| v0.2 | Rule diffing (before/after prompt edits) | Planned |
|
|
181
|
+
| v0.3 | LLM-augmented gap detection (optional) | Planned |
|
|
182
|
+
| v0.4 | GitHub Action / CI integration | Planned |
|
|
183
|
+
| v1.0 | Web UI + prompt editor with live feedback | Planned |
|
|
184
|
+
| SaaS | Per-prompt API, team dashboards, compliance reports | Roadmap |
|
|
185
|
+
|
|
186
|
+
**Target customers:** AI teams building production LLM products who need to audit system prompts before deployment. Compliance teams preparing for EU AI Act audits. Red team consultancies.
|
|
187
|
+
|
|
188
|
+
**Pricing model:** Free CLI tier → $X/month API tier → Enterprise (custom).
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Development
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Run tests
|
|
196
|
+
pytest
|
|
197
|
+
|
|
198
|
+
# Run with coverage
|
|
199
|
+
pytest --cov=rule_audit --cov-report=term-missing
|
|
200
|
+
|
|
201
|
+
# Test against a real prompt
|
|
202
|
+
echo "Your system prompt here" > test_prompt.txt
|
|
203
|
+
python -m rule_audit --file test_prompt.txt --verbose
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT — Hermes Labs 2026
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rule-audit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Detect logical contradictions, gaps, and exploitable edge cases in AI system prompts"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Hermes Labs", email = "rolybosch96@gmail.com" }
|
|
13
|
+
]
|
|
14
|
+
keywords = [
|
|
15
|
+
"ai-safety", "llm", "prompt-engineering", "security", "audit",
|
|
16
|
+
"contradiction-detection", "red-teaming"
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 3 - Alpha",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.9",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
29
|
+
"Topic :: Security",
|
|
30
|
+
]
|
|
31
|
+
requires-python = ">=3.9"
|
|
32
|
+
dependencies = []
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/roli-lpci/rule-audit"
|
|
36
|
+
Repository = "https://github.com/roli-lpci/rule-audit"
|
|
37
|
+
Issues = "https://github.com/roli-lpci/rule-audit/issues"
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
rule-audit = "rule_audit.cli:main"
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
dev = [
|
|
44
|
+
"pytest>=7.4",
|
|
45
|
+
"pytest-cov>=4.1",
|
|
46
|
+
"mypy>=1.0",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.packages.find]
|
|
50
|
+
where = ["."]
|
|
51
|
+
include = ["rule_audit*"]
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.package-data]
|
|
54
|
+
rule_audit = ["py.typed"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
testpaths = ["tests"]
|
|
58
|
+
addopts = "-v --tb=short"
|
|
59
|
+
python_files = ["test_*.py"]
|
|
60
|
+
python_classes = ["Test*"]
|
|
61
|
+
python_functions = ["test_*"]
|
|
62
|
+
|
|
63
|
+
[tool.coverage.run]
|
|
64
|
+
source = ["rule_audit"]
|
|
65
|
+
omit = ["tests/*"]
|
|
66
|
+
|
|
67
|
+
[tool.coverage.report]
|
|
68
|
+
show_missing = true
|
|
69
|
+
fail_under = 70
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
rule_audit — AI system prompt logical contradiction detector.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
from rule_audit import audit, AuditReport
|
|
6
|
+
|
|
7
|
+
report = audit("You are a helpful assistant. You must never...")
|
|
8
|
+
print(report.summary())
|
|
9
|
+
print(report.to_markdown())
|
|
10
|
+
print(report.to_json())
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import logging
|
|
16
|
+
|
|
17
|
+
from rule_audit.analyzer import analyze
|
|
18
|
+
from rule_audit.parser import parse, parse_file, Rule
|
|
19
|
+
from rule_audit.report import AuditReport
|
|
20
|
+
|
|
21
|
+
__version__ = "0.1.0"
|
|
22
|
+
__all__ = ["audit", "audit_file", "AuditReport", "Rule", "__version__"]
|
|
23
|
+
|
|
24
|
+
# Library-level logger — users configure their own handlers.
|
|
25
|
+
# Default: NullHandler so we don't spam logs if the user hasn't configured logging.
|
|
26
|
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def audit(prompt: str) -> AuditReport:
|
|
30
|
+
"""
|
|
31
|
+
Parse a system prompt string and return a full AuditReport.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
prompt: The raw system prompt text to analyze.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
AuditReport with contradictions, gaps, edge cases, and risk score.
|
|
38
|
+
|
|
39
|
+
Added in v0.1.0.
|
|
40
|
+
"""
|
|
41
|
+
rules = parse(prompt)
|
|
42
|
+
result = analyze(rules, prompt_text=prompt)
|
|
43
|
+
return AuditReport(result, prompt_text=prompt)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def audit_file(path: str) -> AuditReport:
|
|
47
|
+
"""
|
|
48
|
+
Read a file and audit its contents as a system prompt.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
path: Path to a .txt file containing the system prompt.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
AuditReport with full analysis.
|
|
55
|
+
|
|
56
|
+
Added in v0.1.0.
|
|
57
|
+
"""
|
|
58
|
+
with open(path, "r", encoding="utf-8") as fh:
|
|
59
|
+
prompt = fh.read()
|
|
60
|
+
return audit(prompt)
|