Initial commit: Cloudflare infrastructure with WAF Intelligence
- Complete Cloudflare Terraform configuration (DNS, WAF, tunnels, access) - WAF Intelligence MCP server with threat analysis and ML classification - GitOps automation with PR workflows and drift detection - Observatory monitoring stack with Prometheus/Grafana - IDE operator rules for governed development - Security playbooks and compliance frameworks - Autonomous remediation and state reconciliation
This commit is contained in:
307
AGENT_GUARDRAILS.md
Normal file
307
AGENT_GUARDRAILS.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# AGENT GUARDRAILS for CLOUDFLARE Project
|
||||
|
||||
**Purpose:** Prevent common coding mistakes when using autonomous agents (Cline, Claude, etc.)
|
||||
|
||||
**Governed by:** [RED-BOOK.md](RED-BOOK.md) — See Appendix A for agent constraints
|
||||
|
||||
**Copy this into your agent prompt before asking for code changes.**
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ CRITICAL RULES
|
||||
|
||||
### 1. NO BLIND PATCHING
|
||||
|
||||
**When you need to modify a Python file:**
|
||||
|
||||
1. ✅ **FIRST:** Use the Read tool to read the ENTIRE file (all lines)
|
||||
2. ✅ **THEN:** Check if your change already exists
|
||||
3. ✅ **THEN:** Check for duplicates
|
||||
4. ✅ **THEN:** Rewrite the WHOLE function/block (not line-by-line insertion)
|
||||
5. ❌ **NEVER:** Append code without reading the full file
|
||||
|
||||
### 2. ARGPARSE IS SPECIAL
|
||||
|
||||
**When modifying `argparse` code:**
|
||||
|
||||
- ❌ DO NOT add arguments in multiple places
|
||||
- ❌ DO NOT call `parser.add_argument()` twice for the same option
|
||||
- ✅ DO rewrite the entire `build_parser()` function
|
||||
- ✅ DO check the file for existing argument definitions FIRST
|
||||
- ✅ DO verify no conflicting option strings (like `--question`)
|
||||
|
||||
**Example of WRONG approach:**
|
||||
```python
|
||||
# ❌ BAD: Adding same arg in two places
|
||||
parser.add_argument("--question", required=True) # Line 50
|
||||
parser.add_argument("--question", required=False) # Line 100
|
||||
# ^ This will throw: argparse.ArgumentError: argument --question: conflicting option string
|
||||
```
|
||||
|
||||
**Example of RIGHT approach:**
|
||||
```python
|
||||
# ✅ GOOD: Single source of truth
|
||||
def build_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--question", required=False)
|
||||
parser.add_argument("--frameworks", nargs="+")
|
||||
parser.add_argument("--verbose", action="store_true")
|
||||
return parser
|
||||
```
|
||||
|
||||
### 3. NO DUPLICATES
|
||||
|
||||
**Before writing any function:**
|
||||
|
||||
1. Search the file for function with the same name
|
||||
2. If it exists, rewrite it (don't add another one)
|
||||
3. Check for similar function names (typos, variations)
|
||||
4. Delete the old one if rewriting
|
||||
|
||||
### 4. IMPORTS AT TOP
|
||||
|
||||
**Never import mid-function:**
|
||||
|
||||
```python
|
||||
# ✅ CORRECT: Imports at top
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def main():
|
||||
result = sys.exit(0) # OK to use here
|
||||
|
||||
# ❌ WRONG: Import inside function
|
||||
def main():
|
||||
import sys # No! Import at top
|
||||
import random_library # No!
|
||||
```
|
||||
|
||||
### 5. TYPE HINTS REQUIRED
|
||||
|
||||
**Every function must have type hints:**
|
||||
|
||||
```python
|
||||
# ✅ CORRECT
|
||||
def answer(self, question: str, frameworks: Optional[List[str]] = None) -> ToolResponse:
|
||||
...
|
||||
|
||||
# ❌ WRONG (missing types)
|
||||
def answer(self, question, frameworks=None):
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 CHECKLIST BEFORE WRITING CODE
|
||||
|
||||
Before you generate or modify any code file:
|
||||
|
||||
- [ ] Have I read the ENTIRE file first?
|
||||
- [ ] Does this function already exist?
|
||||
- [ ] Are there duplicates I should remove?
|
||||
- [ ] Does this follow SRP (single responsibility)?
|
||||
- [ ] Are all functions type-hinted?
|
||||
- [ ] Are imports at the top?
|
||||
- [ ] Is there a docstring?
|
||||
- [ ] Will this create new test failures?
|
||||
|
||||
---
|
||||
|
||||
## 🔍 FILE-SPECIFIC RULES
|
||||
|
||||
### For oracle_answer_mcp.py
|
||||
|
||||
**CRITICAL:** This file had duplicate argparse definitions. If you modify it:
|
||||
|
||||
1. Read the ENTIRE build_parser() function
|
||||
2. Look for ANY parser.add_argument() calls
|
||||
3. If --question is defined MORE than once, DELETE all but one
|
||||
4. Check for conflicting flags (argparse won't allow duplicates)
|
||||
|
||||
---
|
||||
|
||||
### For oracle_runner.py
|
||||
|
||||
**This is stable.** Only modify if:
|
||||
- Bug fix required
|
||||
- New compliance framework needed
|
||||
- Performance issue
|
||||
|
||||
When modifying:
|
||||
1. Keep the `run()` method signature the same
|
||||
2. Keep `OracleAnswer` dataclass schema consistent
|
||||
3. Update COMPLIANCE_LEDGER.jsonl format in docstring
|
||||
|
||||
---
|
||||
|
||||
### For Terraform files
|
||||
|
||||
**Cloudflare provider is v4.52.5.** If updating:
|
||||
1. Check `.terraform.lock.hcl` first
|
||||
2. Run `terraform validate` after changes
|
||||
3. Run `terraform plan` before commit
|
||||
4. Don't modify resource names (breaks state)
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ COMMON MISTAKES (Don't Make These)
|
||||
|
||||
| Mistake | Symptom | Fix |
|
||||
|---------|---------|-----|
|
||||
| Duplicate argparse args | `ArgumentError: conflicting option string` | Delete duplicate definition |
|
||||
| Missing type hints | Type checker errors | Add `: Type` to all params |
|
||||
| Append instead of rewrite | Multiple similar functions | Read file, rewrite once |
|
||||
| Import mid-function | Code style error | Move imports to top |
|
||||
| Subscript None | `TypeError: 'NoneType' not subscriptable` | Check for None first |
|
||||
| Missing docstrings | Code review failure | Add docstrings to all functions |
|
||||
|
||||
---
|
||||
|
||||
## 🧪 TESTING AFTER CHANGES
|
||||
|
||||
After modifying code, run:
|
||||
|
||||
```bash
|
||||
# 1. Quick sanity check
|
||||
bash TEST_WORKFLOW.sh quick
|
||||
|
||||
# 2. Test the specific script you changed
|
||||
python3 oracle_runner.py "test question?"
|
||||
|
||||
# 3. Run any affected tests
|
||||
python3 oracle_answer_mcp.py --tool-info
|
||||
|
||||
# 4. Look for errors
|
||||
python3 -m py_compile oracle_runner.py # Syntax check
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚫 FORBIDDEN PATTERNS
|
||||
|
||||
### ❌ Pattern 1: Blind Appending
|
||||
|
||||
```python
|
||||
# NO! Never do this:
|
||||
# Read part of file, then append without seeing rest
|
||||
parser.add_argument("--json") # Line 200
|
||||
|
||||
# ... 100 lines away somewhere:
|
||||
parser.add_argument("--json") # DUPLICATE! Conflict!
|
||||
```
|
||||
|
||||
### ❌ Pattern 2: Nested Imports
|
||||
|
||||
```python
|
||||
# NO! Never do this:
|
||||
def process_data():
|
||||
import csv # Should be at top
|
||||
import json # Should be at top
|
||||
# ... code
|
||||
```
|
||||
|
||||
### ❌ Pattern 3: Type-Free Parameters
|
||||
|
||||
```python
|
||||
# NO! Never do this:
|
||||
def answer(self, question, frameworks, verbose): # No types!
|
||||
pass
|
||||
|
||||
# YES! Do this:
|
||||
def answer(self, question: str, frameworks: Optional[List[str]], verbose: bool) -> ToolResponse:
|
||||
pass
|
||||
```
|
||||
|
||||
### ❌ Pattern 4: Patch Editing
|
||||
|
||||
```python
|
||||
# NO! Don't patch one line:
|
||||
oldString: "def main():\n ..."
|
||||
newString: "def main():\n print('new line')" # This breaks the function
|
||||
|
||||
# YES! Rewrite whole function:
|
||||
# Read the full main()
|
||||
# Rewrite it completely
|
||||
# Replace the entire function
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ CORRECT WORKFLOW
|
||||
|
||||
When asked to modify code:
|
||||
|
||||
**Step 1: Understand**
|
||||
- What is broken?
|
||||
- What file needs changing?
|
||||
- What is the whole context?
|
||||
|
||||
**Step 2: Read**
|
||||
```
|
||||
Use the Read tool:
|
||||
read /path/to/file.py # Read ENTIRE file
|
||||
```
|
||||
|
||||
**Step 3: Analyze**
|
||||
- Where is the problem?
|
||||
- Is it already fixed?
|
||||
- Are there duplicates?
|
||||
- What is the function signature?
|
||||
|
||||
**Step 4: Rewrite**
|
||||
```
|
||||
Use the Edit tool:
|
||||
- oldString: [ENTIRE function]
|
||||
- newString: [Fixed ENTIRE function]
|
||||
```
|
||||
|
||||
**Step 5: Test**
|
||||
```bash
|
||||
python3 file.py --test
|
||||
bash TEST_WORKFLOW.sh quick
|
||||
```
|
||||
|
||||
**Step 6: Verify**
|
||||
- No new errors?
|
||||
- No duplicates?
|
||||
- Tests passing?
|
||||
|
||||
---
|
||||
|
||||
## 📞 SUMMARY
|
||||
|
||||
| Rule | Critical? | Check Before |
|
||||
|------|-----------|------------|
|
||||
| Read entire file | ✅ Yes | Edit anything |
|
||||
| No duplicate defs | ✅ Yes | Add any function |
|
||||
| Argparse centralized | ✅ Yes | Modify argparse |
|
||||
| Type hints required | ✅ Yes | Write any function |
|
||||
| Docstrings needed | ✅ Yes | Finish any function |
|
||||
| Imports at top | 🟡 High | Write imports |
|
||||
| Tests passing | 🟡 High | Commit code |
|
||||
|
||||
---
|
||||
|
||||
## 🆘 If Something Goes Wrong
|
||||
|
||||
**You see: `argparse.ArgumentError: argument --question: conflicting option string`**
|
||||
1. Read `oracle_answer_mcp.py` line-by-line
|
||||
2. Find ALL instances of `parser.add_argument("--question"...)`
|
||||
3. Keep ONE, delete the others
|
||||
4. Test: `python3 oracle_answer_mcp.py --tool-info`
|
||||
|
||||
**You see: `TypeError: 'NoneType' object is not subscriptable`**
|
||||
1. Find the line with `[...]` or `.get(...)`
|
||||
2. Add null check: `if result: result['key']`
|
||||
3. Test the fix
|
||||
|
||||
**You see: `Import "x" could not be resolved`**
|
||||
1. Check if module exists: `ls mcp/oracle_answer/*.py`
|
||||
2. Check imports are correct: `from .tool import X`
|
||||
3. Check __init__.py exists
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** December 8, 2025
|
||||
**Status:** 🟢 Active
|
||||
**Apply To:** All code modifications by agents
|
||||
Reference in New Issue
Block a user