decodeBarcodes(imageData, formats) bekommt die zu suchenden Codearten
uebergeben; ohne Angabe unveraendertes Verhalten (Code128 + DataMatrix).
buildRecognitionAdapters() baut daraus und aus dem echten OCR-Adapter
die an recognize() (pipeline.js, unveraendert) uebergebenen Adapter:
in Strichcode/QR-Code liefert die Texterkennung sofort leeren Text ohne
Tesseract anzustossen, in Text-erkennen liefert die Barcode-Dekodierung
sofort eine leere Liste ohne zxing-wasm anzustossen.
Kennung, deutsche Beschriftung, Codearten, laufende Suche und
Texterkennung je Funktion an einer einzigen Stelle (src/scan-modes.js),
ohne Browser-Zugriff und damit unter Node pruefbar. Funktion "QR-Code"
enthaelt bewusst kein DataMatrix.
Der rote Dialog zeigte bisher immer "Nicht eindeutig", auch wenn die
Erkennung schlicht nichts Verwertbares geliefert hat (kein Barcode, kein
brauchbarer Klartext). Das verwirrt: es klingt nach mehreren Kandidaten,
obwohl gar keine Erkennung stattfand.
askForStack() bekommt einen expliziten Parameter nothingRecognized, da
sich die beiden Lagen nicht zweifelsfrei aus spec/candidates ableiten
lassen (main.js reicht bei "nichts erkannt" als Rueckfall alle
vorhandenen Stapel als candidates durch). main.js setzt ihn anhand von
plan.kind === 'ambiguous' (echte Mehrdeutigkeit) vs. allem anderen
(nur wegen roter Konfidenz im Dialog).
Signatur, Rueckgabeform, Schaltflaechen, Klassennamen, die
Mehrfachausloese-Sperre und die inert-Handhabung bleiben unveraendert.
Solange Kamera laeuft und keine Erkennung/kein Dialog/keine
Sitzungsliste im Weg steht, sucht die App ~5x/s im Zielrahmen nach
Barcodes. Ein gefundener Code durchlaeuft denselben Weg wie der
Knopfdruck (processCapture). Sperrzeit von 2s plus Codevergleich
verhindert, dass ein laenger vor die Kamera gehaltenes Modul mehrfach
gebucht wird, ohne einen zuegigen Modulwechsel auszubremsen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
scan-view.js setzt die Rahmenlage jetzt aus camera.js' FRAME_INSET
statt aus einem im Stilblatt duplizierten Wert. Neue Methode
setFrameDetected() faerbt den Rahmen gruen, sobald die Dauersuche
einen Barcode im Ausschnitt findet - schlichte Farbaenderung, keine
Animation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
FRAME_INSET und frameRect() legen die Rahmenmasse einmalig fest, statt
sie nur im Stilblatt zu duplizieren. grabFrameRegion() liefert den
Zielrahmen unskaliert aus dem Kamerabild - grabFrame() (fuer OCR)
bleibt unveraendert. Ein Code-128 auf kleinem Etikett braucht die
volle Aufloesung, sonst verschmieren die Striche unlesbar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ohne gueltiges Passwort gibt der Server weder Seite noch Skript heraus.
Das Passwort kommt aus APP_PASSWORD; fehlt die Variable, startet der Server
absichtlich nicht. /healthz bleibt passwortfrei, damit die Ueberwachung den
geschuetzten Dienst nicht faelschlich fuer ausgefallen haelt.
README beschreibt jetzt, dass ein Codetreffer einen Widerspruch der
technischen Angaben nicht mehr ueberstimmt (Fehler 1) und dass die
Codemenge eines Stapels ein abgeleiteter statt angesammelter Wert ist
(Fehler 2). Neue Grenze dokumentiert: ein gelesener Barcode-Inhalt ist exakt
gelesen, aber nicht garantiert eine Teilenummer - eine geteilte Los- oder
Wiederverkaeufer-Kennung kann zwei verschiedene Module verbinden, wogegen
die neue Widerspruchspruefung schuetzt. Testanzahl auf 124 aktualisiert.
Ergaenzt src/session.js aus dem vorigen Commit: Da stack.codes jetzt aus
entry.codes abgeleitet wird statt angesammelt zu werden, muss loadSession
denselben Ansatz verfolgen (wie bereits bei stack.count) - sonst wuerde ein
gesicherter, zwischenzeitlich per Umsortieren/Entfernen bereinigter Stand beim
Wiederherstellen einen laengst nicht mehr zutreffenden Code zurueckbringen.
entry.codes ist wie stack.codes optional, ein Stand ohne dieses Feld gilt
weiterhin nicht als unstimmig (Abwaertsvertraeglichkeit bleibt erhalten).
Ein gelesener Rohcode ist nicht garantiert eine Teilenummer: teilen sich
zwei technisch verschiedene Module z.B. denselben Los-Tag, hat der bisherige
Codeabgleich sie ohne Rueckfrage auf denselben Stapel gezogen. proposeAssignment
verlangt fuer einen Codekandidaten jetzt zusaetzlich specsCompatible; widerspricht
der einzige Treffer, faellt die Zuordnung auf den Vergleich der technischen
Angaben zurueck und im Zweifel auf einen eigenen Stapel.
TDD: Test zuerst rot gesehen (Los-Tag-Fall aus der Beanstandung), dann die
Filterung ergaenzt.
Beschreibt die neue Vorrangregel (bekannter Barcode-Inhalt entscheidet vor
dem Vergleich der technischen Angaben), dass eine exakt gelesene Teilenummer
allein fuer Gruen genuegt, und den OCR-Kurzschluss bei bereits bekanntem
Code. Ergaenzt entsprechende Pruefpunkte im Abschnitt "Am Gerät noch zu
pruefen" und aktualisiert die Testanzahl auf 121.
processCapture() reicht der Pipeline jetzt eine isKnownCode-Abhaengigkeit
herein, die gegen die Codes der Stapel der aktuellen Sitzung prueft, und
gibt die von recognize() gelieferten Rohcodes an proposeAssignment und
commitAssignment weiter, damit ein bereits bekannter Barcode-Inhalt die
Stapelzuordnung entscheidet.
Jeder Stapel fuehrt jetzt die Menge der Barcode-Zeichenketten, die bei
seinen Modulen gelesen wurden (stack.codes). Traegt ein gescanntes Modul
einen Code, den ein Stapel bereits kennt, hat das Vorrang vor dem Vergleich
der technischen Angaben - ein Barcode ist exakt gelesen, abgeleitete Angaben
koennen fehlerbehaftet sein. Genau ein Stapel ueber einen bekannten Code
-> Zuweisung, auch bei unvollstaendigen Angaben; mehrere -> weiterhin
mehrdeutig, der Nutzer entscheidet; kein passender Code -> unveraendert die
bisherige Regel. Eine Seriennummer, die bei jedem Modul anders ist, laeuft
dabei einfach ins Leere, ohne die Zuordnung ueber die Teilenummer zu
verhindern.
proposeAssignment und commitAssignment bekommen dafuer einen neuen, optional
en codes-Parameter (Vorgabe []); bestehende Aufrufe ohne diesen Parameter
verhalten sich unveraendert.
storage.js sichert und prueft stack.codes jetzt mit: fehlt das Feld (Stand
aus einer aelteren Fassung), gilt der Stapel als ohne bekannte Codes statt
den ganzen Stand zu verwerfen; ist es vorhanden, muss es eine Liste von
Zeichenketten sein wie jedes andere Feld auch.
Der Teilenummer-Decoder kennt bislang nur das Samsung-Schema; ein Hynix-Modul
mit einwandfrei gelesenem, aber unbekanntem Barcode-Schema endete deshalb in
Rot. Zum Sortieren muss keine Kapazitaet bekannt sein - eine exakt gelesene
Teilenummer genuegt, um ein Modul wiederzuerkennen. recognize() greift jetzt
erst dann auf Rot zurueck, wenn auch die Texterkennung keine Kapazitaet und
keine eindeutige Teilenummer liefert; die bestehende Vorsicht bei
widerspruechlichen unverwertbaren Barcodes bleibt dabei unangetastet.
Zusaetzlich kann recognize() jetzt ueber deps.isKnownCode (optional) erfahren,
dass ein gelesener Code bereits einem Stapel bekannt ist, und die bis zu 20
Sekunden dauernde Texterkennung dann ueberspringen. Ohne diese Abhaengigkeit
verhaelt sich die Pipeline unveraendert. recognize() liefert zusaetzlich die
rohen gelesenen Barcode-Inhalte (codes), damit session.js sie einem Stapel
zuordnen kann.
- Benenne REFERENZ in test/ocr-extract.test.js zu REFERENCE um
(Bezeichner auf Englisch, Kommentare/Texte auf Deutsch)
- Entferne »main«: "index.js" (Datei existiert nicht, nicht relevant für Anwendung)
- Entferne »directories«: { "doc": "docs" } (nicht relevant)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Wurde versehentlich nicht mit "Konsolidiere Spec-Kurzbeschreibung..."
committet, obwohl main.js dort bereits auf den Export umgestellt wurde.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Entfernt zwei nie existierende Statusmeldungen ("Kamera laeuft", "kein
Barcode gefunden"). Ergaenzt die seit final-fix-1 geltende, bisher
unerwaehnte Kandidaten-Regel fuer Stapel (sharesSetField), sowie zwei seit
final-fix-1 vorhandene, aber nirgends dokumentierte Funktionen:
Sitzungsfortsetzung beim Start und Ersatzweg ohne Kamera. Korrigiert einen
seit final-fix-1 falschen Pruefpunkt (automatische statt tatsaechlicher,
per Dialog bestaetigter Sitzungswiederherstellung nach Neuladen). Ergaenzt
die Dateistruktur-Tabelle um die bisher fehlenden src/ui/*.js-Dateien
(resume-dialog.js, describe-spec.js) und aktualisiert die veraltete
Testanzahl auf den aktuellen Stand.
Fuegt den Abschlussbericht dieser Aufraeumrunde hinzu.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
private als Wahrheitswert statt Zeichenkette "true"; description war noch
der unveraenderte Vorlagen-Platzhalter, jetzt ein kurzer deutscher Satz
passend zur App.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
src/ocr-extract.js: RANK_PATTERN enthielt [Xx], obwohl der Text an dieser
Stelle bereits vollstaendig grossgeschrieben ist (normalizeToken laeuft
vorher) - das kleine x konnte nie ankommen. Auf X reduziert, mit Kommentar
begruendet. Die uebrigen Muster im Modul (CAPACITY_PATTERN, SPEED_PATTERN,
PART_NUMBER_PATTERN, das formFactor-Muster, DATE_CODE_PATTERN) geprueft:
keine weiteren unerreichbaren Zweige, alle nutzen bereits ausschliesslich
Grossbuchstaben-Zeichenklassen bzw. Ziffern.
test/ocr-extract.test.js: Testname behauptete "nur einer plausibel", der
Referenztext enthaelt aber zwei plausible Datumscode-Kandidaten (1234 und
1908) - der Test belegt tatsaechlich, dass bei mehreren plausiblen
Kandidaten der zuletzt vorkommende gewinnt. Umbenannt entsprechend.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
test/storage.test.js: wieder -> reloaded, kaputt -> broken, zweiterEintrag
-> secondEntry, vorschlag -> proposal (Bezeichner, nicht die deutschen
Testbeschreibungen).
Neuer Test deckt die bislang nur mit einem einzigen Stapel geprueften
Stapelzaehler-Neuberechnung beim Laden ab: drei gespeicherte Stapel mit
absichtlich falschem count, davon einer (C) ganz ohne zugeordnete
Eintraege - alle drei muessen unabhaengig voneinander korrekt aus den
tatsaechlichen Eintraegen neu berechnet werden (A=2, B=1, C=0).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Projektvorgabe: Kommentare und Oberflaechentexte deutsch, Bezeichner im Code
englisch. Betroffen: src/barcode.js (vorbereitungsPromise -> readyPromise,
inkl. Verweis-Kommentar in ocr.js), sowie lokale Variablen in
test/spec-match.test.js, test/session.test.js und test/pipeline.test.js
(u.a. ocrAufgerufen -> ocrCalled, gefunden bei vollstaendigem Durchgang
aller Test-Dateien). Testbeschreibungen (Prosa) und Kommentare bleiben
unangetastet - nur echte Bezeichner wurden umbenannt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
main.js, result-overlay.js und session-list.js loesten dieselbe Aufgabe
(Spec-Felder zu einer Lesehilfe zusammenfassen) bislang mit drei leicht
unterschiedlichen Implementierungen - unterschiedliche Feldauswahl und
unterschiedlicher Umgang mit fehlenden Werten. Neues src/ui/describe-spec.js
buendelt das in describeSpec(spec, { placeholders }): ohne Platzhalter fuer
die kurze Treffer-Rueckmeldung und die "Zuletzt"-Zeile, mit Platzhalter fuer
die Sitzungsliste, wo feste Feldreihenfolge Wiedererkennung schafft.
Nutzt bei main.js zugleich die bereits vorhandene, jetzt exportierte
nextStackId aus session.js statt einer Zeile-fuer-Zeile-Kopie derselben
Buchstaben-Vergabe (nextFreeStackId entfaellt komplett).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commitAssignment speichert je Eintrag bereits, ob per Barcode oder
Texterkennung erkannt wurde - das wurde bisher nirgends angezeigt. Die
Sitzungsliste zeigt es jetzt knapp neben jedem Eintrag, weil der
Unterschied beim Sortieren wertvoll ist: Barcode ist exakt, Texterkennung
fehleranfälliger.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drei zusammenhängende Verhaltensfehler rund um main.js behoben:
- Kamerafehler ruft die Dateiauswahl nicht mehr ohne Nutzergeste auf
(Handy-Browser blockieren das). Stattdessen zeigt scan-view.js eine
sichtbare, dauerhaft eingeblendete Schaltfläche "Bild auswählen"; der
Kamera-Hinweis wird nicht mehr von der OCR-Verfügbarkeitsanzeige
überschrieben.
- Eine beim Start gefundene, gesicherte Sitzung wird nicht mehr
stillschweigend übernommen, sondern über den neuen Dialog
askResumeSession (resume-dialog.js, nach dem Muster von
ambiguous-dialog.js) zur Fortsetzung angeboten. Fortsetzen zeigt den
tatsächlich letzten Eintrag, Verwerfen löscht den gesicherten Stand.
- Während einer laufenden Erkennung sind Sitzungsliste und Rückgängig-
Fläche gesperrt; zusätzlich bucht ein durch einen zwischenzeitlichen
Sitzungswechsel verspätetes Erkennungsergebnis nicht mehr in die neue,
leere Sitzung (targetSession-Vergleich in processCapture).
- Auch ohne erfasste Stapel bleibt die Sitzungsliste (und damit "Sitzung
beenden") über eine Schaltfläche in der Stapel-Leiste erreichbar.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
proposeAssignment verlangt jetzt zusätzlich zur bisherigen
Verträglichkeitsprüfung, dass Stapel und Modul mindestens ein Merkmal
gemeinsam belegt haben. Ein Stapel mit vollständig leerem Spec (Rot-Fall,
"neuer Stapel") hatte sonst mit jedem Modul null gemeinsame Felder und
galt fälschlich als verträglich mit allem.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- README/.vch-description overstated the stacking rule as a hard
"identical specs AND identical part number" requirement. In reality
specsCompatible (src/spec.js) only compares fields known on both
sides, so an unread part number is skipped rather than compared;
proposeAssignment (src/session.js) only prompts when multiple stacks
match. Documented the actual rule and its deliberate trade-off.
- Added a sentence on how pipeline.js handles multiple barcodes with
an unknown numbering scheme that disagree: no part number is taken
over and OCR alone decides, without prompting.
- Added src/styles.css to the "Aufbau" file table.
- Added the two barcode-adapter device checks from
.superpowers/sdd/task-9-report.md (first-load timing, reload after
an interrupted first load) to "Am Gerät noch zu prüfen"; reviewed
task-8 and task-10..13 reports and confirmed their other device
checks were already present.
README und .vch-description an den tatsaechlichen Code angeglichen: Otsu-
Schwellwert statt fester Kontrastspreizung fuer OCR, Zeitgrenzen und
Mehrdeutigkeitsbehandlung in der Pipeline, gruendliche Zustandspruefung in
storage.js, 97 Tests. Herstellertabellen-Validierung (Step 3) bleibt
blockiert, da sie reale Module vom Nutzer braucht - pn-tables.js unveraendert.
Ehrlicher Beleg-Stand der Tabellen sowie Erweiterungsanleitung in der README,
plus konsolidierte Liste dessen, was mangels Handy/Browser noch am Geraet zu
pruefen ist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
openSessionList() now closes any already-open overlay itself before
rendering, so a double-tap on the stack bar (which has no lock) can no
longer stack two session lists with duplicate handlers. The onMove/
onRemove callbacks no longer need their own closeOverlays() call since
openSessionList() does it unconditionally now.
onEndSession no longer calls syncView() after clearSession(), which
was writing the freshly emptied session straight back into storage and
undoing the clear. It now only refreshes the visible stacks, so ending
a session actually leaves nothing saved, while a subsequent scan still
saves normally via syncView().
Ersetzt das Sichtpruefungs-Geruest in main.js durch die vollstaendige
Verdrahtung aus Kamera, Barcode/OCR-Erkennung, Sitzungsverwaltung,
Speicherung und Oberflaeche. Neu: session-list.js fuer die
Sitzungsliste zum Umsortieren/Entfernen/Beenden.
Gegenueber dem urspruenglichen Plan an den seither geaenderten
Schnittstellen ausgerichtet: commitAssignment erhaelt die tatsaechliche
Erkennungsquelle (source) statt der Konfidenz als drittes Argument, und
die OCR-Verfuegbarkeitsanzeige ueberschreibt keine noch zu lesende
Fehlermeldung mehr. Bezeichner in beiden Dateien auf Englisch
umgestellt, damit sie der bereits etablierten Projektkonvention
entsprechen.
Beanstandung 1: .overlay bekommt overflow-y:auto, overscroll-behavior:
contain und justify-content:safe center, damit bei vielen Kandidaten-
Stapeln (Rot-Fall bietet alle Stapel der Sitzung an) keine Schaltfläche
mehr unerreichbar aus dem Bildschirm waechst, ohne dass die Seite
dahinter mitrollt oder sich die Optik bei wenigen Stapeln aendert.
Beanstandung 2: askForStack setzt inert auf die Geschwisterelemente von
root, solange der Dialog offen ist, und hebt es beim Schliessen (ueber
jeden der drei Wege) nur fuer selbst gesetzte Elemente wieder auf.
Fokus kehrt nach dem Schliessen zum vorherigen Element zurueck statt auf
dem entfernten Dialog haengen zu bleiben.
When a new scan result displaces a previously visible overlay, the promise
of the displaced overlay was never resolved. This caused the caller waiting
on that promise to block indefinitely, freezing the app.
Now the resolve function is stored in the WeakMap alongside the overlay
and timer. When a new overlay displaces the previous one, the displaced
overlay's promise is resolved immediately with resolve(), signifying that
it is no longer visible.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- .stacks-Buttons auf min-height 56px angehoben, Leiste auf 76px
vergrößert, damit die Buttons vollständig hineinpassen
- Datei-Input bleibt dauerhaft hidden statt nach dem ersten Öffnen
sichtbar zu bleiben und den Kamerabereich zu verkleinern
- Rückgängig-Knopf erhält aria-label für Screenreader
- showResult entfernt eine noch sichtbare vorherige Rückmeldung und
deren Zeitgeber, bevor die neue eingeblendet wird
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ein einzelnes Reflexpixel (Normalfall bei glaenzenden Metalletiketten)
dominierte bisher Minimum/Maximum der Kontrastspreizung und drueckte
Schrift und Untergrund gemeinsam unter den festen Schwellwert 128 - die
Schrift verschwand. Der Schwellwert wird jetzt per Otsu-Verfahren aus dem
Helligkeits-Histogramm des Bildes selbst bestimmt und bleibt dadurch gegen
einzelne Ausreisser unempfindlich. Ausserdem: fehlendes Kleinbuchstaben-x
in der Tesseract-Zeichenliste ergaenzt (Bestueckungsangabe "4DRx4").
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
preprocess() rechnet rein (Graustufen, Kontrastspreizung, Schwellwert) ohne
DOM-Zugriff und ist damit ohne Browser testbar. runOcr() ist der Browser-
Adapter, cacht den Tesseract-Arbeiter und laesst isOcrAvailable() sich nach
einem Fehlschlag wieder erholen statt dauerhaft einzufrieren - analog zum
ensureReady()-Muster in barcode.js.
Dekodiert Code-128 und DataMatrix aus einem Einzelbild ueber zxing-wasm.
Statt eines einfachen Boolean-Merkers wird die einmalige WASM-Vorbereitung
per gecachtem Promise realisiert (verhindert doppelte Vorbereitung bei
schnell aufeinanderfolgenden Aufrufen) und im Fehlerfall via
purgeZXingModule() zurueckgesetzt, damit ein spaeterer Versuch echt neu
startet statt eine intern gecachte Ablehnung zu wiederholen.
main.js: Klick-Handler zeigt die dekodierten Codes an und faengt jetzt
auch den Fehler ab, den grabFrame wirft, wenn das Kamerabild noch nicht
bereit ist.
- startCamera: schlaegt play() fehl, werden Tracks gestoppt und srcObject
geloest, bevor der Fehler weitergereicht wird (Kamera-LED erlischt statt
dauerhaft aktiv zu bleiben).
- grabFrame/imageDataFromFile: pruefen vor dem Verkleinern, ob Breite und
Hoehe > 0 sind, und werfen sonst eine verstaendliche deutsche Meldung
statt eines technischen Fehlers aus getImageData.
- Fuegt isPositiveInteger() hinzu fuer Validierung von Eintragsnummern
- nextEntryId und entry.entryId muessen ganze Zahlen >= 1 sein
- Akzeptiert nicht mehr negative, gebrochene oder Null-Werte
- Vier neue Tests pruefen die verstaerkten Anforderungen
- Alle bestehenden Tests bleiben gruen
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Stapelzähler wird beim Laden immer aus den zugeordneten Einträgen neu
berechnet statt aus dem gespeicherten Wert übernommen. Zusätzlich wird
verworfen (null): Einträge mit unbekannter Stapelkennung, doppelte
Eintragsnummern, doppelte Stapelkennungen und ein nextEntryId, der nicht
größer als jede vorhandene Eintragsnummer ist.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
loadSession pruefte bisher nur, ob stacks/entries Arrays sind, nicht
deren Inhalt. Ein fremder oder verfaelschter Eintrag unter dem
gleichen Schluessel kam dadurch als vermeintlich gueltige Sitzung
durch und liess die App beim naechsten Scan mit TypeError abstuerzen
(stack.spec fehlte). Falsch typisierte Felder (nextEntryId als String,
stack.count als String) wurden ebenfalls durchgereicht und verdarben
die Sitzung lautlos (doppelte entryIds, "3" + 1 = "31").
loadSession verlangt jetzt, dass nextEntryId eine endliche Zahl ist
und dass jeder Stapel/Eintrag ein echtes Objekt (kein Array, nicht
null) mit den Feldern ist, die session.js tatsaechlich weiterverwendet.
Schlaegt eine Pruefung fehl, liefert loadSession null - ein halb
brauchbarer Zustand wird nicht repariert oder teilweise uebernommen.
Mehrere Barcodes ohne bekanntes Nummernschema, die sich in der
Teilenummer widersprechen, durften bisher nicht mehr Vorrang vor der
per OCR gelesenen Teilenummer erhalten als ein einzelner Treffer -
der erste gewann ungeprueft. Jetzt gilt derselbe Massstab wie bei
verwertbaren Treffern: Vorrang nur bei Eindeutigkeit (ein Code, oder
mehrere mit derselben - via canonical() verwechslungstolerant
verglichenen - Teilenummer). Widersprechen sie sich, stuetzt sich das
Ergebnis allein auf die Texterkennung.
Zusaetzlich: ungueltige @param-Zeile fuer deps in recognize() korrigiert.
Die Barcode-Dekodierung selbst ist normalerweise schnell, doch beim ersten
Scan einer Sitzung muss der Barcode-Adapter sein WebAssembly-Modul laden,
was auf einem Handy mehrere Sekunden dauern kann. Die Zeitgrenze dient nicht
als Leistungserwartung, sondern als Absicherung gegen einen dauerhaft
hängenden Adapter — sie muss deshalb auch das einmalige Laden abdecken.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Barcode- und OCR-Adapter erhalten je eine eigene, ueberschreibbare
Zeitobergrenze (deps.barcodeTimeoutMs / deps.ocrTimeoutMs). Ein
Adapter, der nie einloest, blockiert recognize() damit nicht mehr
dauerhaft und faellt stattdessen auf den Ersatzwert zurueck, genau
wie bei einem geworfenen Fehler. Kein offener Timer bleibt zurueck.
- mergeCompatibleSpecs entfernt: vertraegliche verwertbare
Barcode-Treffer sind wegen der Kopplung von partNumber und den
uebrigen Feldern ohnehin identisch, der erste Treffer genuegt.
Test entsprechend umbenannt, um das tatsaechlich gepruefte
Verhalten zu benennen statt eine nicht mehr vorhandene
Auffuell-Semantik zu behaupten.
- Kommentar in pn-tables.js von einer inhaltlichen Wiederholung
befreit.
recognize() stuerzte ab, wenn decodeBarcodes() etwas anderes als eine Liste
zurueckgab (null/undefined/Objekt), da die for...of-Schleife nicht iterierbare
Werte nicht abfaengt. Nicht-Listen werden nun wie eine leere Liste behandelt,
ebenso wird eine nicht-string-wertige runOcr()-Rueckgabe wie leerer Text
behandelt.
Ausserdem gewann bei mehreren verwertbaren Barcodes im selben Bild bisher
ungeprueft der erste Treffer mit gruener Ampel. Jetzt werden alle verwertbaren
Codes gesammelt: genau einer bleibt gruen wie bisher, mehrere untereinander
vertraegliche werden zusammengefuehrt (spaeterer Treffer ueberschreibt kein
bereits gesetztes Feld) und bleiben gruen, mehrere unvertraegliche ergeben rot
mit leerem Spec statt eines geratenen Ergebnisses.
Korrigiert ausserdem den irrefuehrenden Warnkommentar in pn-tables.js: ein
falscher Tabelleneintrag faellt auf dem Barcode-Weg nicht automatisch auf, da
dort keine Texterkennung zum Abgleich laeuft.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>