- 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
308 lines
7.5 KiB
Markdown
308 lines
7.5 KiB
Markdown
# 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
|