Riorganizzazione: Nuova struttura orto-suite/ - No more .skill zips, pronto per copia diretta

This commit is contained in:
Noe 2026-03-07 02:00:05 +01:00
parent 1d2401e647
commit c729f59621
29 changed files with 5642 additions and 135 deletions

View file

@ -0,0 +1,362 @@
# 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)