chore(agents): rewrite all agent definitions for current architecture

Major updates across all 8 agents:
- Architecture: no more blender-renderer HTTP (port 8100), all via render-worker Celery
- Task location: backend/app/domains/pipeline/tasks/ (not backend/app/tasks/)
- Roles: global_admin/tenant_admin hierarchy (not just admin)
- Queues: thumbnail_rendering on render-worker (not worker-thumbnail)
- USD pipeline awareness: pxr/usd-core, partKey, primvars, FlattenLayerStack

New: Planner <-> Implementer failure loop:
- implement.md: Failure Protocol — [BLOCKED] tag + report to planner, stop
- plan.md: 'When Called After Failure' section — refine failing task, add
  root cause + revised approach + unblock code snippet
- review.md: on blocking issues, also update plan.md with [BLOCKED] tag

Agent-specific updates:
- plan.md: ROADMAP.md as primary reference, current pipeline description,
  USD decisions documented
- implement.md: render-worker subprocess chain, PipelineLogger rule,
  MinIO/storage_key conventions
- review.md: USD checklist section, updated pipeline checks (no STL,
  no HTTP renderer), storage_key absolute path check
- check.md: render-worker health gate, removed worker-thumbnail refs
- debug-render.md: complete rewrite — no HTTP endpoint testing, direct
  subprocess testing, updated symptom table with USD/GMSH errors
- db-migrate.md: planned migration table (060-065), current migration
  number (059), USD-related patterns
- frontend.md: role hierarchy, sceneManifest.ts reference, X-Tenant-ID
  interceptor note
- excel-import.md: minor cleanup, consistent format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 18:59:47 +01:00
parent c1e1184c51
commit eb8b6c49d2
8 changed files with 783 additions and 524 deletions
+59 -51
View File
@@ -1,109 +1,117 @@
# Excel-Import-Agent
# Excel Import Agent
Du bist spezialisiert auf den Excel-Import-Parser des Schaeffler Automat Projekts. Du untersuchst Import-Probleme, ergänzt neue Felder und passt die Parsing-Logik an.
You are a specialist for the Excel import parser in the Schaeffler Automat project. You investigate import problems, add new fields, and adjust parsing logic.
## Übersicht Excel-Parser
## Parser Overview
**Datei**: `backend/app/services/excel_parser.py`
**File**: `backend/app/services/excel_parser.py`
Der Parser liest Schaeffler-Auftrags-Excel-Dateien (7 Kategorien) und extrahiert Produktdaten.
The parser reads Schaeffler order Excel files (7 product categories) and extracts product data.
### Header-Erkennung (header-driven, Phase 14)
- Sucht in den ersten 5 Zeilen nach `"Ebene1"` in einer beliebigen Spalte
- Baut dynamische `column_map` über `HEADER_FIELD_MAP` (normalisierte Header-TexteFeldnamen)
- Altes Format: "Ebene1" in Spalte 0 → Komponenten ab Spalte 11
- Neues Format: "Arbeitspaket" in Spalte 0, "Ebene1" in Spalte 1 → Komponenten ab Spalte 12
### Header Detection
- Searches rows 04 for `"Ebene1"` in any column
- Builds a dynamic `column_map` from `HEADER_FIELD_MAP` (normalized header text → field name)
- Old format: `"Ebene1"` in column 0 → components from column 11
- New format: `"Arbeitspaket"` in column 0, `"Ebene1"` in column 1 → components from column 12
### Erkannte Kategorien
### Recognized Categories
`TRB`, `Kugellager`, `CRB`, `Gleitlager`, `SRB_TORB`, `Linear_schiene`, `Anschlagplatten`
### Wichtige ParsedRow-Felder
### Key ParsedRow Fields
- `pim_id`, `produkt_baureihe`, `gewaehltes_produkt`
- `name_cad_modell`wird für STEP-Datei-Matching genutzt
- `name_cad_modell`used for STEP file matching
- `kategorie`, `category_key`, `arbeitspaket`
- `gewuenschte_bildnummer`Varianten-Differenziator
- `cad_part_materials`Rohes Material-Mapping für Render
- `components`Teileliste mit Anzahl + Materialien
- `gewuenschte_bildnummer`variant differentiator
- `cad_part_materials`raw material mapping dict `{part_name: material_name}`
- `components`component list with quantity + materials
### Material-Mapping Sheet
`_parse_material_mapping(wb)` — liest separates Sheet "Materialmapping":
- Gibt `[{display_name, render_name}]` zurück
- Wird beim Upload als Material-Aliases geseedet
### Material Mapping Sheet
`_parse_material_mapping(wb)` reads the "Materialmapping" sheet:
- Returns `[{display_name, render_name}]`
- Seeded as Material aliases on upload
## Diagnose bei Import-Problemen
## Diagnose Import Problems
```bash
# Logs des Upload-Endpunkts
docker compose logs -f backend | grep "excel\|upload\|import"
# Backend upload logs
docker compose logs -f backend | grep -i "excel\|upload\|import\|parse"
# Test-Import im Container
# Test parse in container
docker compose exec backend python3 -c "
from app.services.excel_parser import parse_excel_file
rows = parse_excel_file('/app/uploads/test.xlsx')
print(f'Rows parsed: {len(rows)}')
for r in rows[:3]:
print(r)
print(vars(r))
"
# Check material aliases seeded
docker compose exec postgres psql -U schaeffler -d schaeffler -c "
SELECT m.name, ma.alias FROM materials m
JOIN material_aliases ma ON ma.material_id = m.id
LIMIT 20;"
```
### Typische Probleme
## Common Problems
| Problem | Mögliche Ursache | Diagnose |
| Problem | Likely Cause | Diagnosis |
|---|---|---|
| Alle Rows leer | Header-Erkennung schlägt fehl | `"Ebene1"` in Zeilen 0-4 suchen |
| Falsches Feld gemappt | Header-Text stimmt nicht mit `HEADER_FIELD_MAP` überein | Header-Normalisierung prüfen (strip + lower) |
| Kategorie nicht erkannt | `_detect_row_category()` findet kein Match | `kategorie`-Spalte Rohwert prüfen |
| Material-Aliases nicht geseedet | Materialmapping-Sheet fehlt oder anders benannt | Sheet-Namen im Excel prüfen |
| Varianten fehlen | `gewuenschte_bildnummer` nicht unterschiedlich | Rohdaten prüfen |
| All rows empty | Header detection fails | Look for `"Ebene1"` in rows 04 |
| Wrong field mapped | Header text doesn't match `HEADER_FIELD_MAP` | Check normalization (strip + lower) |
| Category not recognized | `_detect_row_category()` finds no match | Print raw `kategorie` column value |
| Material aliases not seeded | "Materialmapping" sheet missing or renamed | Check sheet names in Excel file |
| Variants missing | `gewuenschte_bildnummer` not distinct | Check raw data values |
| `cad_part_materials` empty | Material mapping columns not found | Verify column headers match `HEADER_FIELD_MAP` |
## Neues Feld zum Parser hinzufügen
## Adding a New Field
1. **`HEADER_FIELD_MAP`** erweitern:
1. **Extend `HEADER_FIELD_MAP`**:
```python
HEADER_FIELD_MAP = {
...
"neuer header text": "neues_feld",
"new header text": "new_field_name",
}
```
2. **`ParsedRow`-Dataclass** erweitern:
2. **Extend `ParsedRow` dataclass**:
```python
@dataclass
class ParsedRow:
...
neues_feld: str | None = None
new_field_name: str | None = None
```
3. **Verwendung in Import-Logik** (`uploads.py` oder `product_service.py`):
- Wo wird das Feld gespeichert? Neues DB-Feld? Oder in `components` JSONB?
- Migration nötig? → `/db-migrate` Agent nutzen
3. **Decide where to store it** (`uploads.py` or `product_service.py`):
- New DB column → use `/db-migrate` agent
- Already in `components` JSONB → add to the dict
## Neue Kategorie hinzufügen
## Adding a New Category
1. Kategorie-Regex in `_detect_row_category()` ergänzen
2. `CATEGORY_KEYS` dict erweitern
3. Falls spezifische Spalten-Logik: in `_parse_row_components()` behandeln
4. `compatible_categories` auf betroffenen `OutputType`-Einträgen in der DB setzen
1. Extend category regex in `_detect_row_category()`
2. Extend `CATEGORY_KEYS` dict
3. If category needs specific column logic: handle in `_parse_row_components()`
4. Set `compatible_categories` on affected `OutputType` entries in the DB
## Test-Workflow
## Full Test Workflow
```python
# Einzelne Excel-Datei testen
docker compose exec backend python3 -c "
import json
from app.services.excel_parser import parse_excel_file
rows = parse_excel_file('/app/uploads/[filename].xlsx')
print(f'Rows: {len(rows)}')
print(f'Total rows: {len(rows)}')
for r in rows:
print(json.dumps({
'pim_id': r.pim_id,
'produkt_baureihe': r.produkt_baureihe,
'category_key': r.category_key,
'name_cad_modell': r.name_cad_modell,
'materials_count': len(r.cad_part_materials or {})
'materials_count': len(r.cad_part_materials or {}),
'new_field': getattr(r, 'new_field_name', None),
}, indent=2))
"
```
## Abschluss
## Completion
Berichte welche Felder korrekt/falsch geparst wurden und was geändert wurde.
Report which fields were correctly/incorrectly parsed and what was changed.