# Ist-Abgleich V2-Spezifikation gegen vorhandenen Code

**Stand:** 31.07.2026, Session 8eefcbe1
**Bezug:** `spec/SupplierPulse_QAF_Compare_JSON_V2_Spezifikation.md`
**Geprüfter Code:** `~/work/kadi-v2` auf `main` = `2f0e146` (31.07. 19:18)

## Belastbarkeit dieses Dokuments

Grundlage sind Modul-Header, Export-Listen und gezielte Greps — **nicht** die vollständige
Lektüre der großen Dateien (`business-rules.ts` 40 KB, `reconciliation.ts` 41 KB,
`canonical-fields.ts` 153 KB). Jede Zeile trägt deshalb eine Konfidenz. Alles mit
Konfidenz „mittel" ist vor der Umsetzung der jeweiligen Phase nachzulesen, nicht zu glauben.

## Vorbemerkung 1: R-01 existiert nicht

Die Spezifikation vergibt Anforderungs-IDs **R-02 bis R-24**. Ein `R-01` kommt in der
gesamten Datei nicht vor (verifiziert per Grep über alle Nennungen). Der Auftrag lautete
„R-01 bis R-24" — abgeglichen sind die real existierenden 23 Anforderungen.

## Vorbemerkung 2: Modul-Zuordnung (korrigiert Kap. 13 der Spec)

Die drei bewerteten V1-Läufe stammen aus **`components/qaf-differences/export-utils.ts:43`**
(`buildViewModelExport`, `format: 'supplierpulse-qaf-compare'`, `version: 1`, Dateiname
`SupplierPulse_QAF_Compare_Result_<part>_<date>.json`). Die Sektionen werden in
`lib/qaf-differences/internal/summary-view.ts` und `components/qaf-differences/qaf-comparison-detail.tsx`
gebildet — verifiziert gegen die Sektionsliste eines echten Laufs (kpis, formLines, buckets,
bridge, metricsTable, movers, negotiation, levers, oneTimePayments).

Kap. 13 nimmt an, QAF-Differences sei ein separates, von der Spec nicht berührtes Modul.
Es ist dasselbe Modul. Die Namensdrift erklärt den Irrtum: das Modul heißt intern
`qaf-differences`, seine Exporte heißen `QAF_Compare`.

Folge für die Planung: V2 ist **kein Neubau neben** dem Bestand, sondern ein Umbau **im**
Modul, in dem auch das Multi-QAF-Programm (P0–P5) und der Lieferanten-Benchmark liegen.

## Vorbemerkung 3: die zweite Achse — Standard-Paarvergleich vs. Multi-QAF

Das Modul hat zwei Zweige mit sehr unterschiedlichem Reifegrad:

- **Standard-Paarvergleich** (`comparison_mode: 'summary'`) — das ist, was die Spec als V1
  bewertet: Summenzeilen, Bridge, keine Positionsebene.
- **Multi-QAF-Zweig** (`multi_qaf`, `multi_qaf_variant_vs_standard`, `supplier_benchmark`) —
  hat Mapping, Effekt-Klassen, Reconciliation, Abdeckungs-Matrix.

Die Fähigkeiten, die die Spec fordert, existieren also teilweise — **im anderen Zweig**.
Das ist der zentrale Hebel: Vieles ist Portierung + Verallgemeinerung statt Neuentwicklung.

---

## Abgleichstabelle

Legende Status: **vorhanden** · **teilweise** (Kern da, Spec-Vertrag fehlt) · **fehlt**

| ID | Anforderung | Status | Fundstelle / Befund | Konfidenz |
|---|---|---|---|---|
| R-02 | Dual-Pass-Extraktion (Formeltext + Wert + `value_state`) | teilweise | `formula-engine.ts` erkennt Formeländerung bei gleichem Wert (`formel_geaendert_wert_gleich`, `differ.ts:164`) — die schwierigste Hälfte ist da. `workbook-safety.ts:530` liefert `externalLinksPresent` (= Detektor D04). **Lücke:** kein `value_state`-Vokabular je Zelle; versteckte **Spalten** nirgends gelesen (nur versteckte Blätter, `multi-qaf/container-assembly.ts:171`) → D05 nicht erfüllbar | hoch |
| R-03 | `identity_and_premises` + `comparability_status` | teilweise | Prämissen-/Identitätsfelder werden gelesen (`summary-parser.ts`, `canonical-fields.ts`), `plausibility.ts` prüft Sachnummer/Währung kreuzweise. **Lücke:** kein Gate-Objekt mit `unchanged_essential`/`changed`/`empty_in_both` und keine Herabstufung nachgelagerter Aussagen | mittel |
| R-04 | Label aus der Datei lesen, gegen Registry validieren | **teilweise — Ursache von F-02 lokalisiert** | `summary-metrics.ts` macht bereits Label-Anchoring mit Synonymtabelle (Z. 126–139) und Confidence (Z. 283–285: 1 Treffer → `labelMatch`/1,0; **0 Treffer → `fixedRow`-Fallback auf die erwartete Zeile mit Confidence 0,6**). Genau dieser stille Fallback erzeugt F-02: G27 trägt „JIS", der Synonymeintrag lautet `'Zölle Lieferant - BMW'` (Z. 139), also 0 Treffer → Zeile 27 wird trotzdem gelesen (Z. 218) und mit dem Config-Label `'Zölle Lieferant → BMW'` (Z. 166) angezeigt. **Lücke:** Datei-Label wird nicht mitgeführt, `label_verified` fehlt, Confidence 0,6 erzeugt kein DQ-Finding | hoch |
| R-05 | Additivitäts-Registry (`row_role`) | fehlt | Keine Rollen-Auszeichnung der Preisblockzeilen. Die V1-`formLines` kennen nur `same`/`total`-Flags | hoch |
| R-06 | Brücke ohne Residual-Step, vollqualifizierte Quellen | teilweise | `SourceRef` existiert als Typ (`types.ts:22`: file/sheet/row/column/cell) und wird laut Modul-Header durchgehend mitgeführt („Every value keeps its A1 provenance"). **Lücke:** kein `value_state`; Brücke selbst hat den Residual-Step (F-01) | hoch |
| R-07 | Eine kanonische Blockdefinition | fehlt | `buckets` (4 Blöcke) und `bridge.endComposition` divergieren im Ist-Lauf nachweislich | hoch |
| R-08 | Kern vs. `derived_views` mit `source_ref` | fehlt | V1 hält `quotationPrice` 4× redundant | hoch |
| R-09 | Material-Analyse mit Mapping + Effekt-Buckets | teilweise | `material-parser.ts` (38 KB) parst BOM inkl. RMR-Split-Zeilen sauber. `matcher.ts` hat eine 5-stufige Matching-Kaskade **für Prozessschritte**, mit `scoreCandidate` (Jaccard) und Cross-Language-Behandlung. **Lücke:** kein Material-Mapping, keine Match-Typen, keine Effekt-Buckets im Standard-Zweig. Die Bausteine sind übertragbar, der Kaskaden-Aufbau ist eine andere Domäne | hoch |
| R-10 | Fertigungs-Analyse (Stationen, Parameteridentität, Takt) | teilweise | `matcher.ts` ist genau dafür gebaut. Takt/Kapazität: im G60-Zweig vorhanden (`g60/calculator.ts`), im Standard-Zweig nicht. **Lücke:** Stationsbegriff (Spec 7.4: kostenwirksam vs. beschreibend), `parallel_needed`, Sub-Ops | mittel |
| R-11 | SBM-/Werkzeug-Analyse | teilweise | `sbm-parser.ts` (44 KB) parst SBM. **Lücke:** Werkzeug-Mapping, Klassifikation (`new_scope`/`second_tool`/…), Einmal-Brücke, Spec-Removal-Detektion | mittel |
| R-12 | DQ-Detektorkatalog D01–D17 | teilweise | **Drei** Findings-Schichten mit Severity existieren bereits: `plausibility.ts` (Cross-File-Sanity), `rule-engine.ts` (R1–R6, empirisch aus der Fehlerreport-Analyse), `business-rules.ts` (40 KB). **Lücke:** kein einheitlicher, ID-stabiler Katalog D01–D17; eher Konsolidierung als Neubau | mittel |
| R-13 | `difference_id` + `traceability_index` | fehlt | Keine stabilen Differenz-IDs im Modul gefunden | hoch |
| R-14 | Pflicht-`validation`-Sektion | fehlt | Nur die Fach-Parser (`co2e`, `lccn`, `logistics`, `rmr`) haben eigene Checks; keine Lauf-Validation mit `pass`/`fail` und Limits | hoch |
| R-15 | Status/Schwellen als versionierte Config | **teilweise, näher dran als die Spec annimmt** | `differ.ts:19–36`: `DifferBandsConfig` mit `auffaellig10/auffaellig25/kritisch50` ist bereits benannte Config mit Defaults (KAR-896). **Lücke:** die Schwelle steckt weiterhin im Status-**Namen** (F-18), und `thresholds_applied` wird nicht ausgegeben | hoch |
| R-16 | Reconciliation-Pflicht je Ebene | teilweise | `reconciliation.ts` (41 KB) prüft Summary ↔ Fertigungskosten-Detailzeilen (`fk_detail_sum`, `scrap_manufacturing_detail_sum`) und die interne Kostenkaskade — aber **pro Datei**, nicht als Δ-Reconciliation über Mappings. Die Mechanik und Toleranz-Doktrin sind da, die Delta-Achse fehlt | hoch |
| R-17 | Kanonische Serialisierung/Rundung | fehlt | Rundung passiert verteilt; keine Serialisierungsschicht mit Einheiten-Rundungstabelle | mittel |
| R-18 | `unit`-Feld je Wertegruppe | fehlt | Einheiten sind implizit | hoch |
| R-19 | `content_hash` / Determinismus-Nachweis | teilweise | Hash-Infrastruktur existiert (`template-fingerprint.ts` 46 KB, `capability/not-a-qaf-detector.ts`), aber nicht als Ergebnis-Hash über kanonisches JSON | hoch |
| R-20 | `movers` als deklarierte, rekonsilierende Sicht | teilweise | `movers.ts` existiert (2,6 KB, `buildMovers`/`topMovers`/`TopN`) — dünn, wie F-16 beschreibt. **Lücke:** `of_total`, `shown_sum`, `residual_sum`, `reconciles_to` | hoch |
| R-21 | `levers` mit EUR-Wirkung, Quellen, IDs | teilweise | `levers.ts` (2,5 KB) mit `buildLevers`, `LEVER_KPI_DEFS`, `hasLeverKpiSignal` — die Regelkatalog-Idee ist angelegt. **Lücke:** `cost_effect_eur_per_piece`, `sources[]`, `difference_ids[]` | hoch |
| R-22 | Schema-Stabilitäts-Garantie | fehlt | Im Ist nachweislich verletzt: 14/15/13 `metricsTable`-Zeilen über drei Läufe | hoch |
| R-23 | `comparison_type` mit fachlicher Taxonomie | **teilweise — aber andere Achse** | `comparison-mode.ts` hat `QafComparisonModeKey` (7 Modi) plus zentrale `COMPARISON_MODE_RULES`-Registry mit Exhaustiveness-Prüfung (KAR-943). Das ist jedoch der **Betriebsmodus** (welche Dateiarten gepaart werden), nicht die fachliche Taxonomie der Spec (`temporal_same_project`, `cross_site_same_part`, …). Der Modus `'summary'` deckt zeitlichen Vergleich und Objektvergleich ununterschieden ab — exakt F-20. Die Registry ist der richtige Ort für das neue Feld | hoch |
| R-24 | `section_state` je Sektion | teilweise | `module-degradation.ts` implementiert bereits die Doktrin „nicht still leer" für degradierte Detail-Blätter, mit ausdrücklichem Bezug auf „Do not hide uncertainty behind a single green status". **Lücke:** nur für Detail-Sheet-Parsing, nicht als generisches `section_state` mit `not_computed` | hoch |

## Bilanz

- **fehlt vollständig:** R-05, R-07, R-08, R-13, R-14, R-17, R-18, R-22 → 8 von 23
- **teilweise vorhanden:** R-02, R-03, R-04, R-06, R-09, R-10, R-11, R-12, R-15, R-16, R-19, R-20, R-21, R-23, R-24 → 15 von 23
- **vollständig vorhanden:** keine

Kein Punkt der Spezifikation ist erledigt. Aber **zwei Drittel der Anforderungen haben einen
tragfähigen Kern im Repo**, und die acht echten Lücken sind überwiegend Struktur- und
Vertragsarbeit (IDs, Envelope, Serialisierung, Rollen), nicht Analytik.

## Was das für die Phasenplanung heißt

Phase 1 der Spec (Kap. 14 + 20) ist damit realistisch als **Vertrags-Phase** zu lesen, nicht
als Extraktions-Neubau:

1. `row_role`/Additivitäts-Registry für den Preisblock (R-05) — Voraussetzung für die strenge Brücke
2. Label-Verifikation härten (R-04): Datei-Label mitführen, `label_verified`, den 0-Treffer-Fallback
   in ein DQ-Finding überführen statt still Zeile 27 zu lesen
3. `summary_lines` vollständig aus der Registry (R-22) statt der heutigen 13–15 Zeilen
4. Strenge `summary_bridge` ohne „Übrige"-Step (R-06), Residual gegen Toleranz (R-14-Grundgerüst)
5. Envelope, `conventions`, `unit` (R-18), Serialisierung + `content_hash` (R-17/R-19)
6. `section_state` (R-24) generalisieren, `comparison_type` (R-23) in `COMPARISON_MODE_RULES` ergänzen

Die Positionsebene (R-09/R-10/R-11) ist Phase 2–4 und der eigentliche Aufwandsblock — dort
entscheidet, wie viel aus dem Multi-QAF-Zweig portierbar ist. Diese Frage ist mit dem
vorliegenden Abgleich **nicht** beantwortet; sie braucht eine gezielte Lektüre von
`multi-qaf/` gegen Spec 8.4/8.5.

## Offene Punkte

- Golden-Case-Regression: Inputs und Referenz enthalten echte Lieferanten-Kalkulationen und
  dürfen nicht ins Repo (Vertraulichkeits-Gate). Ohne Ablage außerhalb git ist die Abnahme
  aus Kap. 11 lokal ausführbar, aber nicht CI-fähig. Entscheidung steht aus.
- Die Regressionsfälle aus Kap. 19 C (61.35-8736421, 5A5C5D7) haben keine Quelldateien.
