Skip to content

fix(ai-service): confirm units quoted across a table cell border (#50) - #55

Merged
Fluory merged 4 commits into
mainfrom
claude/fix-verifier-cell-border-50
Sep 24, 2026
Merged

Fluory merged 4 commits into
mainfrom
claude/fix-verifier-cell-border-50

Conversation

@Fluory

@Fluory Fluory commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Warum

Fixes #50 · Eval-Fall t03: Eine Einheit, deren Zitat über eine Tabellen-Zellgrenze geht (60 | Stk.), blieb „unsicher“, obwohl das Zitat wörtlich im Segment steht.

Arbeitsstand

  • Ziel: Einheiten in Tabellenzeilen werden bestätigt, wenn eine Zelle des Zitats exakt eine bekannte Einheit ist und keine andere Zelle eine andere Einheit nennt.
  • Nicht-Ziele: Zitatprüfung lockern; Aufteilen an Leerzeichenfolgen (würde Werkstoff St 52 als Einheit werten – ADR-0001 D8); Spaltenwissen im Verifier.
  • Erledigt: Fix in values.py, Regressions- und Negativtests, Eval-Replay, Baseline über --update-baseline, README, CHANGELOG, frischer Review eingearbeitet (mehrdeutige Zeilen-Zitate zählen nicht), CI grün.
  • Offen: Review/Merge durch den Orchestrator.
  • Annahmen: Zellgrenzen sind | und Tab.
  • Nächster kleinster Schritt: Review und Merge durch den Orchestrator.

Was ist passiert (Klartext)

Die KI zitiert bei Tabellen manchmal über eine Spaltengrenze hinweg, etwa „60 | Stk.“. Das Zitat stand korrekt im Dokument, aber die Einheitenprüfung erwartete die Einheit direkt hinter einer Zahl – der Strich dazwischen hat sie gestört. Jetzt zählt auch eine Tabellenzelle, die genau eine bekannte Einheit enthält – aber nur, wenn das Zitat nicht gleichzeitig eine andere Einheit nennt (eine ganze Zeile mit „Stk.“ und „kg“ beweist keins von beiden). Die strenge Regel „gefunden nur mit wörtlich bestätigtem Zitat“ bleibt unverändert; Negativtests belegen, dass nichts gelockert wurde. Ergebnis im Eval: Einheiten der Positionen 86 % → 97 % richtig, Belegquote 89 % → 100 %, alle anderen Werte gleich.

Plan-Pflicht (SYSTEM.md §4)

  • Kein Auslöser – keine Modulgrenze, öffentliche API, Migration, Auth/Rechte, kein Zahlungs-/Daten-/Infrapfad, höchstens zwei Module, keine Architekturvarianten, umkehrbar
  • Auslöser zutreffend – Impact Manifest ausgefüllt (Plan vor Code)

Geändert

  • services/ai/src/requestflow_ai/grounding/values.py: Einheit auch als exakte Zelle (|, Tab) des Zitats, wenn keine Zelle eine andere Einheit nennt
  • services/ai/tests/test_grounding_verifier.py, test_grounding_values.py: Regression t03 + Negativfälle (u. a. ganze Zeile | 60 | Stk. | 12 | kg |)
  • services/ai/evals/baseline.json: line_items.unit (nur verbessert)
  • services/ai/README.md (inkl. bekannter Grenze), CHANGELOG.md

Nachweis (SYSTEM.md §11)

  • verify:changed: grün – ruff, ruff format, pyright 0 Fehler, pytest 435 passed / 2 skipped (docling-Modelle fehlen lokal)
  • verify: grün (CI check auf 3fca181, inkl. AI-Service-Verify und Eval-Gate); TS unberührt
  • verify:full / E2E-Spec: Eval-Gate im Replay grün (15 Fälle, kein Schlüsselfeld schlechter)
  • Manueller Prüfnachweis: vor dem Fix 4 rote neue Positivtests; die neuen Zeilen-Negativfälle sind mit dem ersten Stand rot
  • Frischer Review (P1 vor Ready-for-review; Architektur/API/DB immer): fix(ai-service): confirm units quoted across a table cell border (#50) #55 (comment) – nichts blockierend, should behoben

Doku-Entscheidung (genau eine)

  • Keine langlebige Doku betroffen – Begründung: –
  • Doku betroffen und im selben PR aktualisiert:
    • Produktdoku (P0: README): –
    • Technische Doku: services/ai/README.md
    • Architekturkarte: –
    • ADR: –
    • CHANGELOG [Unreleased] (sichtbares Feature oder Verhalten – im selben PR, nie „später")

Entferntes oder Umbenanntes: docs/ + README gegrept, Treffer bereinigt: nichts entfernt

Dateigrößen und neue Bausteine (SYSTEM.md §7)

Dateien über 500 Zeilen im Diff (Ausnahmen: generierter Code, Lockfiles, Fixtures, Migrationen, Schemas, Ressourcen, Doku, Konfiguration):

  • keine
  • bewusst belassen – Begründung: –
  • im selben PR nach fachlicher Verantwortung geteilt
  • Folge-Issue –

Über 800 Zeilen mit neuer Fachlogik oder über 1000 Zeilen (P1/P2): nicht betroffen

Neue Shared-Komponente, Utility-Datei, Adapter oder fachlicher Service:

  • nein
  • ja – gesucht nach: –

Subagent-Einsätze

  • Umsetzungs-Subagent (Worktree) – Fix, Tests, Eval-Replay.
  • Frischer Review-Subagent (read-only) – nichts blockierend, 1 should (behoben), 1 nit (begründet belassen).

Risiken / offene Punkte

  • Bekannte Grenze: ein Zitat nur der falschen Spaltenzelle (12 | kg) besteht weiterhin – wie ein nacktes kg schon vorher.
  • CHANGELOG-Konflikt mit parallelen PRs möglich (nur Textzeilen).

🤖 Generated with Claude Code

https://claude.ai/code/session_01DJ5vaKvTYiMvdngT4d3xo1

The unit check accepted a known unit only directly after a number or as
the whole quote, so a quote spanning a pipe-table cell border such as
"60    | Stk." (eval t03) left a correct unit unverified. A known unit now
also counts when one cell of the quote (split on "|" and tabs) is exactly
the unit. The quote-in-segment check is unchanged, so quotes that differ
from the segment in real characters are still rejected.

Eval replay: line_items.unit found_accuracy 86.21 -> 96.55, grounding
89.29 -> 100; no other metric moved. Baseline updated via
--update-baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJ5vaKvTYiMvdngT4d3xo1
…nit (#50 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJ5vaKvTYiMvdngT4d3xo1

Fluory commented Sep 24, 2026

Copy link
Copy Markdown
Owner Author

Frischer Review (read-only Subagent) – Ergebnis und Umgang

Nichts blockierend. Belegt: die neuen Tests scheitern mit values.py von main (4 rot); die Zitatprüfung im Segment bleibt bindend; baseline.json ändert nur line_items.unit nach oben, falsch-„found“ bleibt 0.

Befund Umgang
should – eine Einheit-Zelle aus einer anderen Spalte zählt (Zitat der ganzen Zeile | 60 | Stk. | 12 | kg | bestätigt kg für ein Stück-Item) behoben in 3fca181: nennen die Zellen verschiedene Einheiten, zählt keine; zwei Negativfälle ergänzt (mit dem alten Stand rot). Rest-Grenze (12 | kg allein) als bekannte Grenze im README – genau wie ein nacktes kg-Zitat schon vorher
nit – Kopfzellen wie Pos | m | Werkstoff zählen für m bleibt: dieselbe vorbestehende Grenze wie ein reines m-Zitat; der Verifier kennt keine Spalten

Nach der Änderung: ruff/format/pyright sauber, pytest 435 passed / 2 skipped, Eval-Replay grün (unverändert gegenüber der Baseline dieses PRs).


Generated by Claude Code

@Fluory
Fluory marked this pull request as ready for review September 24, 2026 11:19
@Fluory
Fluory merged commit 4d4ea2a into main Sep 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(ai-service): grounding verifier rejects quotes that span a table cell border

2 participants