orto-skills/references/qa_checklist.md

362 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# QA Checklist — Validazione PlanBundle
Criteri e checklist per validare completezza e coerenza di piano prima della pubblicazione.
---
## QA Score Calculation
**Formula:**
```
QA_Score = (Checks_Pass / Total_Checks) × Weight_Pass
0.90-1.00: ✅ Excellent (publish)
0.70-0.89: ✅ Good (publish with warnings)
0.50-0.69: ⚠️ Marginal (request review/improvements)
< 0.50: ❌ Fail (do not publish; request major fixes)
```
---
## Sezione 1: Data Completeness
### 1.1 Garden Configuration
- [ ] **orto_id** non vuoto, univoco in registry
- [ ] **Location** (provincia + regione) valide (Italia)
- [ ] **Coordinates** (lat/lon) within bounds (-90 a 90, -180 a 180)
- [ ] **Area (m²)** positivo, > 0.1 m² (sensible)
- [ ] **Clima zone** inferito correttamente (nord/centro/sud)
- [ ] **Soil type** documentato (se possibile)
- [ ] **Sun exposure** documentato (ore/giorno)
- [ ] **Drainage** valutato (buono/mediocre/scarso)
**Validation:**
```python
if not (lat >= -90 and lat <= 90): error = "Invalid latitude"
if not (lon >= -180 and lon <= 180): error = "Invalid longitude"
if area <= 0: error = "Area must be positive"
```
**Impact:** ⭐⭐⭐ (critical for all downstream skills)
---
### 1.2 Community Profile
- [ ] **n_persone** > 0
- [ ] **Dieta** definita (vegano/vegetariano/onnivoro/altro)
- [ ] **Preferenze colture** lista non vuota (min. 3)
- [ ] **Colture evitamento** lista (se allergie)
- [ ] **Esperienza** livello segnato (nessuna/dilettante/esperto)
- [ ] **Tempo disponibile** (ore/settimana) > 0
- [ ] **Accessibility requirements** documentati (se disabilità)
**Validation:**
```python
if n_persone <= 0: error = "Zero people"
if not any(diet in ["vegano", "vegetariano", "onnivoro"]):
warning = "Unknown diet"
if not preferenze_colture: error = "No crop preference"
```
**Impact:** ⭐⭐ (affect crop selection, layout)
---
## Sezione 2: Agronomic Consistency
### 2.1 Crop Diversity
**Rule:** Min. 4 gruppi botanici rappresentati (spread nutritivo)
| Gruppo | Colture Tipiche | Min Presenti |
|--------|---|---|
| Solanaceae | Pomodoro, Peperone, Melanzana | 1+ |
| Brassicaceae | Cavolo, Broccoli, Cavolfiore | 1+ |
| Leguminosae | Fagiolo, Pisello, Fava | 1+ |
| Cucurbitaceae | Zucchina, Melone, Cocomero | 1+ |
| Leafy/Erbette | Lattuga, Spinacio, Cavolo riccio | 1+ |
| Aromatiche | Basilico, Parsley, Oregano | 0+ (opzionale) |
| Root | Carota, Cipolla, Barbabietola | 1+ |
**Check:**
```python
groups_present = len([g for g in GROUPS if count[g] > 0])
if groups_present < 4: flag = "⚠️ Low diversity"
```
**Impact:** ⭐⭐⭐ (nutritional balance, pest management)
---
### 2.2 Rotation Consistency
**Rule:** No stessa famiglia botanica per 2+ anni su stessa aiuola
**Check:**
```python
for aiuola in layout:
for year in [year1, year2, year3]:
crops = layout[aiuola][year]
families = [get_family(c) for c in crops]
if len(families) != len(set(families)): # Duplicates
error = f"Rotation fail {aiuola} year {year}"
```
**Fallback:** Se spazio piccolo (< 20 m²), tollerare 2 anni (vs. 3)
**Impact:** ⭐⭐⭐ (disease/pest control)
---
### 2.3 Nutritional Coverage
**Rule:** Piano colture deve coprire 80% fabbisogno dieta user
**Calcolo:**
```
For each dietary group (proteins, carbs, vit, minerals):
estimated_supply = sum(crop_yield × nutritional_contribution)
target = user_daily × days_season
coverage = estimated_supply / target
if coverage >= 0.80: ✅ OK
elif coverage >= 0.60: ⚠️ Marginal
else: ❌ Insufficient
```
**Example (Vegano, 3 persone, estate):**
```
Proteins (legumi):
Fagiolo 10 kg × 25g protein/100g = 2.5 kg protein
Target (3pp × 60g/gg × 90gg) = 16.2 kg
Coverage = 2.5 / 16.2 = 15% ❌ INSUFFICIENT
Recommendation: Aggiungere 2ª coltura legume (Pisello autunno)
```
**Impact:** ⭐⭐ (user satisfaction, sustainability)
---
## Sezione 3: Spatial Consistency
### 3.1 Layout Coherence
- [ ] **Tutte colture** da piano_colture_annuale sono assegnate a aiuole
- [ ] **No overlaps:** Stessa aiuola non ha > 100% area
- [ ] **Consociazioni:** % positive > antagonismi nella stessa aiuola
- [ ] **Accessibilità:** Sentieri >= min requirement (0.5-0.7 m)
- [ ] **Sun exposure:** Colture assegnate a zone corrette (pieno sole, ombra, ecc.)
**Check:**
```python
total_assigned = sum(area for crop in layout)
if total_assigned > available_area:
error = f"Over-allocated: {total_assigned} > {available_area}"
for aiuola in layout:
positives = count_positive_consociations(aiuola)
negatives = count_negative_consociations(aiuola)
if positives < negatives:
warning = f"Aiuola {aiuola}: more antagonismi than positive"
```
**Impact:** ⭐⭐⭐ (physical feasibility, crop performance)
---
### 3.2 Water Zone Coherence
- [ ] **Zone ALTA (MEDIA, BASSA)** assegnate coerentemente da layout
- [ ] **No mix:** Stessa zona irrigazione non ha mix ALTA + BASSA
- [ ] **Emitters**: Ciascuna zona ha emitter assegnato
**Check:**
```python
for zone in irrigation_zones:
crops_zone = [c for c in layout if zone_assigned(c) == zone]
water_classes = [get_water_class(c) for c in crops_zone]
if len(set(water_classes)) > 2: # More than 2 different classes
warning = f"Zone {zone}: mixed water needs (may need adjustment)"
```
**Impact:** ⭐⭐⭐ (irrigation efficiency, cost)
---
## Sezione 4: Water & Irrigation
### 4.1 Water Adequacy
**Rule:** Total water demand ≤ 110% source capacity (buffer 10%)
**Calc:**
```
Demand (mm/season) = sum(ET0 × Kc for each month × area_m2)
Rainfall (mm) = avg rainfall region × season_length
Irrigation_deficit = Demand - Rainfall
Source capacity (L/day) × season_length (days) × 1000 (L to mm on area)
/ area_m2
= Max available (mm/season)
if Irrigation_deficit <= Max_available: ✅ OK
elif Irrigation_deficit <= 1.1 × Max_available: ⚠️ Tight (need mulch)
else: ❌ INSUFFICIENT
```
**Mitigation (if deficit):**
- Mulching pesante (-20-30% ET)
- Raccolta pluviale (add 50-100 L)
- Shift crops (meno ALTA, più BASSA)
**Impact:** ⭐⭐⭐ (feasibility, cost)
---
### 4.2 System Pressure
**Rule:** Pressione sistema deve essere 0.5-1.5 bar (goccia) o 2-3 bar (sprinkler)
**Check:**
```python
emitters_per_zone = plan.irrigation[zone].emitters
total_flow = sum(e.flow for e in emitters_per_zone)
if source_pressure < min_required:
warning = "Low pressure: may need pump or regulator"
elif source_pressure > max_required:
warning = "High pressure: may damage emitters"
```
**Impact:** ⭐⭐ (durability, efficiency)
---
## Sezione 5: Temporal (Calendar)
### 5.1 Seasonal Alignment
- [ ] **Tutte colture** hanno semina/trapianto entro frost windows
- [ ] **Raccolta** prima di gelo primo (se sensitive)
- [ ] **Successioni** (es. Lattuga 3x) scheduled con spacing
- [ ] **Task frequency** total time ≤ available hours/week
**Check:**
```python
for crop in piano_colture:
if sowing_date < last_frost and crop_is_frost_sensitive:
error = f"{crop} planted before frost date"
if harvest_date > first_frost and crop_is_frost_sensitive:
error = f"{crop} harvest after frost"
# Time check
total_weekly_hours = sum(task.hours for task in calendario)
if total_weekly_hours > user_available_hours:
warning = f"Tasks exceed available time by {excess} hours/week"
suggestion = "Reduce scope or automate irrigation"
```
**Impact:** ⭐⭐⭐ (feasibility, success)
---
### 5.2 Meteo Sensitivity Tagging
- [ ] **Trapianti** tagged METEO_CRITICA
- [ ] **Trattamenti fogliari** tagged METEO_DEFER
- [ ] **Raccolta** no tag (non-deferent)
- [ ] **Irrigazione** tagged METEO_SKIP
**Check:**
```python
for task in calendario:
if task.type == "trapianto":
if not task.meteo_tag: warning = "Trapianto non taggato"
if task.type == "spray_fogliare":
if task.meteo_tag != "METEO_DEFER": error = "Wrong tag"
```
**Impact:** ⭐⭐ (weather adaptation)
---
## Sezione 6: Disease & Safety
### 6.1 Preventive Coverage
- [ ] **Alto-risk crops** (Pomodoro, Melanzana, Cavolo) hanno piano preventivo
- [ ] **Treatments** (rame, zolfo, bio) sono autorizzati Italia
- [ ] **DPI** richiesti documentati
- [ ] **Carenza** (raccolta timing) rispettate
**Check:**
```python
high_risk = ["Pomodoro", "Melanzana", "Cavolo"]
for crop in piano_colture:
if crop in high_risk:
if not plan_fitopatologo[crop].preventive:
warning = f"No preventive plan for high-risk {crop}"
```
**Impact:** ⭐⭐⭐ (disease management, safety)
---
### 6.2 DPI & Safety
- [ ] **Treatments** sono bio-authorized (D.M. 18527/2012) o IPM
- [ ] **DPI required** documentati (guanti, respiratore, ecc.)
- [ ] **Warnings** per allergie/sensibilità registrati
**Check:**
```python
for treatment in piano_fitopatologo.treatments:
if treatment not in APPROVED_BIO_LIST:
error = f"Unapproved treatment: {treatment}"
```
**Impact:** ⭐⭐⭐ (legal, health)
---
## Sezione 7: QA Summary Report
**Output Model:**
```markdown
# QA Report — [ORTO_ID]
## Score Card
| Check | Status | Weight | Result |
|-------|--------|--------|--------|
| Data Completeness | ✅ 10/10 | 15% | 1.5 |
| Agronomic | ✅ 8/9 | 20% | 1.78 |
| Spatial | ✅ 9/10 | 15% | 1.35 |
| Water | ⚠️ 7/10 | 20% | 1.4 |
| Temporal | ✅ 10/10 | 15% | 1.5 |
| Disease | ✅ 8/9 | 15% | 1.33 |
| **OVERALL** | | | **0.91** |
## Recommendations
1. ⚠️ Water tight (105% capacity) → Apply mulch (-25% ET)
2. ✅ Crop diversity excellent (6 groups)
3. ✅ Rotation coherent 3-year
4. ⚠️ Time: Weekly tasks 6.5 hrs (vs. 5 available) → Automate irrigation
## Decision
**APPROVED** (Score 0.91 — Excellent)
→ Publish to user with water mitigation note
---
```
---
**Ultima revisione:** 2026-03-06
**Integrazione:** orto-orchestratore Phase 3 (Data Validation)