mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 16:35:18 -05:00
179 lines
5.8 KiB
Markdown
179 lines
5.8 KiB
Markdown
# Agent Rules
|
|
|
|
**These rules are MANDATORY and MUST be followed without exception by all agents working on this codebase.**
|
|
|
|
---
|
|
|
|
## 1. Entity Versioning MUST Be Automatic
|
|
|
|
> [!CAUTION]
|
|
> **NON-NEGOTIABLE REQUIREMENT**
|
|
|
|
All versioned entities (Parks, Rides, Companies, etc.) MUST have their version history created **automatically via Django signals**—NEVER manually in views, serializers, or management commands.
|
|
|
|
### Why This Rule Exists
|
|
|
|
Manual version creation is fragile and error-prone. If any code path modifies a versioned entity without explicitly calling "create version," history is lost forever. Signal-based versioning guarantees that **every single modification** is captured, regardless of where the change originates.
|
|
|
|
### Required Implementation Pattern
|
|
|
|
```python
|
|
# apps/{entity}/signals.py - REQUIRED for all versioned entities
|
|
|
|
from django.db.models.signals import pre_save
|
|
from django.dispatch import receiver
|
|
from .models import Park, ParkVersion
|
|
from .serializers import ParkSerializer
|
|
|
|
@receiver(pre_save, sender=Park)
|
|
def auto_create_park_version(sender, instance, **kwargs):
|
|
"""
|
|
Automatically snapshot the entity BEFORE any modification.
|
|
This signal fires for ALL save operations, ensuring no history is ever lost.
|
|
"""
|
|
if not instance.pk:
|
|
return # Skip for initial creation
|
|
|
|
try:
|
|
old_instance = sender.objects.get(pk=instance.pk)
|
|
ParkVersion.objects.create(
|
|
park=instance,
|
|
data=ParkSerializer(old_instance).data,
|
|
changed_by=getattr(instance, '_changed_by', None),
|
|
change_summary=getattr(instance, '_change_summary', 'Auto-versioned')
|
|
)
|
|
except sender.DoesNotExist:
|
|
pass # Edge case: concurrent deletion
|
|
```
|
|
|
|
### Passing Context to Signals
|
|
|
|
When updating entities, attach metadata to the instance before saving:
|
|
|
|
```python
|
|
# In views/serializers - attach context, DON'T create versions manually
|
|
park._changed_by = request.user
|
|
park._change_summary = submission_note or "Updated via API"
|
|
park.save() # Signal handles versioning automatically
|
|
```
|
|
|
|
### What Is FORBIDDEN
|
|
|
|
The following patterns are **strictly prohibited** and will be flagged as non-compliant:
|
|
|
|
```python
|
|
# ❌ FORBIDDEN: Manual version creation in views
|
|
def update(self, request, slug=None):
|
|
park = self.get_object()
|
|
# ... update logic ...
|
|
ParkVersion.objects.create(park=park, ...) # VIOLATION!
|
|
park.save()
|
|
|
|
# ❌ FORBIDDEN: Manual version creation in serializers
|
|
def update(self, instance, validated_data):
|
|
ParkVersion.objects.create(park=instance, ...) # VIOLATION!
|
|
return super().update(instance, validated_data)
|
|
|
|
# ❌ FORBIDDEN: Manual version creation in management commands
|
|
def handle(self, *args, **options):
|
|
for park in Park.objects.all():
|
|
ParkVersion.objects.create(park=park, ...) # VIOLATION!
|
|
park.status = 'updated'
|
|
park.save()
|
|
```
|
|
|
|
### Compliance Checklist
|
|
|
|
For every versioned entity, verify:
|
|
|
|
- [ ] A `pre_save` signal receiver exists in `signals.py`
|
|
- [ ] The signal is connected in `apps.py` via `ready()` method
|
|
- [ ] No manual `{Entity}Version.objects.create()` calls exist in views
|
|
- [ ] No manual `{Entity}Version.objects.create()` calls exist in serializers
|
|
- [ ] No manual `{Entity}Version.objects.create()` calls exist in management commands
|
|
|
|
---
|
|
|
|
## 2. Error Handling MUST Use Capture Utilities
|
|
|
|
> [!CAUTION]
|
|
> **NON-NEGOTIABLE REQUIREMENT**
|
|
|
|
All error-prone code on both backend AND frontend MUST use the error capture utilities. Errors should flow to the admin dashboard (`/admin/errors`) for monitoring.
|
|
|
|
### Backend Requirements
|
|
|
|
Use the utilities from `apps.core.utils`:
|
|
|
|
```python
|
|
from apps.core.utils import capture_errors, error_context, capture_and_log
|
|
|
|
# ✅ REQUIRED: Decorator on views and critical functions
|
|
@capture_errors(source='api', severity='high')
|
|
def create_park(request, data):
|
|
return ParkService.create(data)
|
|
|
|
# ✅ REQUIRED: Context manager for critical operations
|
|
with error_context('Processing payment', severity='critical'):
|
|
process_payment()
|
|
|
|
# ✅ ACCEPTABLE: Manual capture when you need the error ID
|
|
except Exception as e:
|
|
error_id = capture_and_log(e, 'Operation failed', severity='high')
|
|
```
|
|
|
|
### Frontend Requirements
|
|
|
|
Use the composables and utilities:
|
|
|
|
```typescript
|
|
// ✅ REQUIRED: Component-level error boundary
|
|
const { wrap, error, retry } = useErrorBoundary({ componentName: 'RideCard' })
|
|
const ride = await wrap(() => api.get('/rides/1'), 'Loading ride')
|
|
|
|
// ✅ REQUIRED: tryCatch for async operations
|
|
const [data, error] = await tryCatch(fetchData(), 'Fetching data')
|
|
|
|
// ✅ REQUIRED: Report caught errors
|
|
const { reportError } = useReportError()
|
|
try { ... } catch (e) { reportError(e, { action: 'Operation' }) }
|
|
```
|
|
|
|
### What Is FORBIDDEN
|
|
|
|
```python
|
|
# ❌ FORBIDDEN: Silent exception swallowing
|
|
except Exception:
|
|
pass # VIOLATION! Error lost forever
|
|
|
|
# ❌ FORBIDDEN: Logging without dashboard capture
|
|
except Exception as e:
|
|
logger.error(e) # VIOLATION! Not visible in dashboard
|
|
```
|
|
|
|
```typescript
|
|
// ❌ FORBIDDEN: Silent catch
|
|
catch (e) { console.error(e) } // VIOLATION! Not in dashboard
|
|
|
|
// ❌ FORBIDDEN: Uncaptured async errors
|
|
await riskyOperation() // VIOLATION! No error handling
|
|
```
|
|
|
|
### Compliance Checklist
|
|
|
|
- [ ] All API views decorated with `@capture_errors`
|
|
- [ ] All critical service methods use `error_context`
|
|
- [ ] All frontend async operations use `tryCatch` or `useErrorBoundary`
|
|
- [ ] No silent exception swallowing (`except: pass`)
|
|
- [ ] All caught exceptions reported via utilities
|
|
|
|
### Documentation
|
|
|
|
Full usage guide: [docs/ERROR_HANDLING.md](file:///Volumes/macminissd/Projects/thrillwiki_django_no_react/docs/ERROR_HANDLING.md)
|
|
|
|
---
|
|
|
|
## Document Authority
|
|
|
|
This document has the same authority as all other `source_docs/` files. Per the `/comply` workflow, these specifications are **immutable law** and must be enforced immediately upon detection of any violation.
|