From 5d42b4cfc5d611559fbbdedbc9e57ee22ab15bdc Mon Sep 17 00:00:00 2001 From: team3 Date: Wed, 29 Jul 2026 15:19:41 +0200 Subject: [PATCH] update --- LEARNINGS.md | 451 +++ backend/agents.py | 15 +- backend/chat.py | 292 ++ backend/config.py | 7 + backend/features.py | 67 +- backend/inhalt.py | 748 ----- backend/k1-1024.png | Bin 0 -> 31742 bytes backend/k1-1280.png | Bin 0 -> 32992 bytes backend/k1-1600.png | Bin 0 -> 34587 bytes backend/k1-390.png | Bin 0 -> 28532 bytes backend/k1-640.png | Bin 0 -> 30416 bytes backend/k1-820.png | Bin 0 -> 31811 bytes backend/komfort.png | Bin 0 -> 22217 bytes backend/ledger.py | 6 +- backend/offen.png | Bin 0 -> 26027 bytes backend/parser.py | 14 +- backend/planung.py | 163 + backend/projekte.py | 23 +- backend/pruefung.py | 120 +- backend/quellcode.py | 189 -- backend/routes.py | 105 +- backend/stil/allgemein.md | 3 + backend/stil/funktion-testen.md | 11 + backend/stil/funktion-titel.md | 4 +- backend/struktur.py | 60 +- backend/tests/test_inhalt.py | 60 - backend/tests/test_ledger.py | 499 +-- backend/tests/test_parser.py | 23 +- backend/tests/test_planung.py | 201 ++ backend/tests/test_pruefung.py | 3 +- backend/tests/test_struktur.py | 93 + .../.planung/.pruefung.json | 537 ++++ .../.planung/.verlauf.json | 122 + .../.planung/auswahl-anstossen.md | 49 + .../.planung/beratung-anbieten.md | 47 + .../.planung/layout-zuweisen.md | 69 + .../.planung/option-ansehen.md | 51 + .../.planung/schritt-zeigen.md | 49 + .../.planung/varianten-waehlen.md | 109 + .../.planung/vorschau-zeigen.md | 53 + daten/MtoVariantConfigurator/.pruefung.json | 537 ++++ .../auswahl-anstossen.md | 49 + .../beratung-anbieten.md | 47 + .../MtoVariantConfigurator/layout-zuweisen.md | 69 + .../MtoVariantConfigurator/option-ansehen.md | 51 + .../MtoVariantConfigurator/schritt-zeigen.md | 49 + .../varianten-waehlen.md | 109 + .../MtoVariantConfigurator/vorschau-zeigen.md | 53 + daten/PLANER2GEN/.pruefung.json | 1024 ++++++ daten/PLANER2GEN/ansicht.md | 53 + daten/PLANER2GEN/chat.md | 83 + daten/PLANER2GEN/features.md | 260 ++ daten/PLANER2GEN/funktionen.md | 102 + daten/PLANER2GEN/pruefung.md | 92 + daten/PLANER2GEN/verlauf.md | 62 + daten/PLANER2GEN/vorschlaege.md | 55 + daten/Planer/.planung/.pruefung.json | 928 ++++++ daten/Planer/.planung/darkmode.md | 23 + daten/Planer/.planung/design.md | 44 + daten/Planer/.planung/features.md | 109 + daten/Planer/.planung/funktionen.md | 98 + daten/Planer/.planung/k1-1024.png | Bin 0 -> 31445 bytes daten/Planer/.planung/k1-1280.png | Bin 0 -> 32564 bytes daten/Planer/.planung/k1-1600.png | Bin 0 -> 34370 bytes daten/Planer/.planung/k1-390.png | Bin 0 -> 28243 bytes daten/Planer/.planung/k1-640.png | Bin 0 -> 30111 bytes daten/Planer/.planung/k1-820.png | Bin 0 -> 31558 bytes daten/Planer/.planung/karten-besprechen.md | 61 + daten/Planer/.planung/karten-pruefen.md | 82 + daten/Planer/.planung/komfort.png | Bin 0 -> 21904 bytes daten/Planer/.planung/offen.png | Bin 0 -> 25795 bytes daten/Planer/.planung/projekte.md | 53 + daten/Planer/.planung/vision-festhalten.md | 53 + daten/Planer/.planung/vision.md | 19 + daten/Planer/.pruefung.json | 726 ++++- daten/Planer/darkmode.md | 2 +- daten/Planer/design.md | 13 + daten/Planer/features.md | 25 +- daten/Planer/funktionen.md | 28 +- daten/Planer/k1-1024.png | Bin 0 -> 31445 bytes daten/Planer/k1-1280.png | Bin 0 -> 32564 bytes daten/Planer/k1-1600.png | Bin 0 -> 34370 bytes daten/Planer/k1-390.png | Bin 0 -> 28243 bytes daten/Planer/k1-640.png | Bin 0 -> 30111 bytes daten/Planer/k1-820.png | Bin 0 -> 31558 bytes daten/Planer/karten-besprechen.md | 61 + daten/Planer/karten-pruefen.md | 22 +- daten/Planer/komfort.png | Bin 0 -> 21904 bytes daten/Planer/offen.png | Bin 0 -> 25795 bytes daten/Planer/vision.md | 2 +- daten/RAG/.pruefung.json | 2735 +++++++++++++++++ daten/RAG/admin.md | 93 + daten/RAG/agenten.md | 286 ++ daten/RAG/anleitungen.md | 43 + daten/RAG/auftraege.md | 94 + daten/RAG/backup.md | 97 + daten/RAG/benutzer.md | 89 + daten/RAG/berichte.md | 90 + daten/RAG/chat.md | 53 + daten/RAG/diagnose.md | 386 +++ daten/RAG/dokumente.md | 127 + daten/RAG/evaluation.md | 100 + daten/RAG/faelle.md | 74 + daten/RAG/feedback.md | 128 + daten/RAG/knowledge-raeume.md | 141 + daten/RAG/konfiguration.md | 129 + daten/RAG/logs.md | 46 + daten/RAG/sonstiges.md | 64 + daten/RAG/system.md | 304 ++ daten/RAG/tags.md | 63 + daten/RAG/titel.md | 40 + daten/RAG/uploads.md | 75 + daten/RAG/verlauf.md | 57 + daten/RAG/versionen.md | 75 + daten/TFT/.pruefung.json | 317 ++ daten/TFT/analyse.md | 61 + daten/TFT/einheit.md | 35 + daten/TFT/pipeline.md | 60 + daten/TFT/shop.md | 83 + daten/TFT/spiel.md | 98 + frontend/k1-1024.png | Bin 0 -> 31614 bytes frontend/k1-1280.png | Bin 0 -> 32737 bytes frontend/k1-1600.png | Bin 0 -> 34471 bytes frontend/k1-390.png | Bin 0 -> 28294 bytes frontend/k1-640.png | Bin 0 -> 30163 bytes frontend/k1-820.png | Bin 0 -> 31744 bytes frontend/komfort.png | Bin 0 -> 22205 bytes frontend/offen.png | Bin 0 -> 26127 bytes frontend/src/App.vue | 173 +- frontend/src/api.js | 23 +- frontend/src/components/ChatPanel.vue | 170 + frontend/src/components/FeatureKarte.vue | 148 +- frontend/src/components/FeatureListe.vue | 194 +- frontend/src/components/ModalBox.vue | 16 +- frontend/src/components/PruefPanel.vue | 2 - frontend/src/components/SeitenLeiste.vue | 28 +- frontend/src/components/k1-1024.png | Bin 0 -> 31798 bytes frontend/src/components/k1-1280.png | Bin 0 -> 32941 bytes frontend/src/components/k1-1600.png | Bin 0 -> 34726 bytes frontend/src/components/k1-390.png | Bin 0 -> 28557 bytes frontend/src/components/k1-640.png | Bin 0 -> 30441 bytes frontend/src/components/k1-820.png | Bin 0 -> 31909 bytes frontend/src/components/komfort.png | Bin 0 -> 22299 bytes frontend/src/components/offen.png | Bin 0 -> 26186 bytes frontend/src/composables/kontextmenue.js | 6 + frontend/src/composables/planung.js | 104 + frontend/src/composables/pruefung.js | 24 +- k1-1024.png | Bin 0 -> 30383 bytes k1-1280.png | Bin 0 -> 31504 bytes k1-1600.png | Bin 0 -> 33294 bytes k1-390.png | Bin 0 -> 27112 bytes k1-640.png | Bin 0 -> 28938 bytes k1-820.png | Bin 0 -> 30512 bytes komfort.png | Bin 0 -> 20865 bytes offen.png | Bin 0 -> 24629 bytes 155 files changed, 14482 insertions(+), 1736 deletions(-) create mode 100644 LEARNINGS.md create mode 100644 backend/chat.py delete mode 100644 backend/inhalt.py create mode 100644 backend/k1-1024.png create mode 100644 backend/k1-1280.png create mode 100644 backend/k1-1600.png create mode 100644 backend/k1-390.png create mode 100644 backend/k1-640.png create mode 100644 backend/k1-820.png create mode 100644 backend/komfort.png create mode 100644 backend/offen.png create mode 100644 backend/planung.py delete mode 100644 backend/quellcode.py delete mode 100644 backend/tests/test_inhalt.py create mode 100644 backend/tests/test_planung.py create mode 100644 daten/MtoVariantConfigurator/.planung/.pruefung.json create mode 100644 daten/MtoVariantConfigurator/.planung/.verlauf.json create mode 100644 daten/MtoVariantConfigurator/.planung/auswahl-anstossen.md create mode 100644 daten/MtoVariantConfigurator/.planung/beratung-anbieten.md create mode 100644 daten/MtoVariantConfigurator/.planung/layout-zuweisen.md create mode 100644 daten/MtoVariantConfigurator/.planung/option-ansehen.md create mode 100644 daten/MtoVariantConfigurator/.planung/schritt-zeigen.md create mode 100644 daten/MtoVariantConfigurator/.planung/varianten-waehlen.md create mode 100644 daten/MtoVariantConfigurator/.planung/vorschau-zeigen.md create mode 100644 daten/MtoVariantConfigurator/.pruefung.json create mode 100644 daten/MtoVariantConfigurator/auswahl-anstossen.md create mode 100644 daten/MtoVariantConfigurator/beratung-anbieten.md create mode 100644 daten/MtoVariantConfigurator/layout-zuweisen.md create mode 100644 daten/MtoVariantConfigurator/option-ansehen.md create mode 100644 daten/MtoVariantConfigurator/schritt-zeigen.md create mode 100644 daten/MtoVariantConfigurator/varianten-waehlen.md create mode 100644 daten/MtoVariantConfigurator/vorschau-zeigen.md create mode 100644 daten/PLANER2GEN/.pruefung.json create mode 100644 daten/PLANER2GEN/ansicht.md create mode 100644 daten/PLANER2GEN/chat.md create mode 100644 daten/PLANER2GEN/features.md create mode 100644 daten/PLANER2GEN/funktionen.md create mode 100644 daten/PLANER2GEN/pruefung.md create mode 100644 daten/PLANER2GEN/verlauf.md create mode 100644 daten/PLANER2GEN/vorschlaege.md create mode 100644 daten/Planer/.planung/.pruefung.json create mode 100644 daten/Planer/.planung/darkmode.md create mode 100644 daten/Planer/.planung/design.md create mode 100644 daten/Planer/.planung/features.md create mode 100644 daten/Planer/.planung/funktionen.md create mode 100644 daten/Planer/.planung/k1-1024.png create mode 100644 daten/Planer/.planung/k1-1280.png create mode 100644 daten/Planer/.planung/k1-1600.png create mode 100644 daten/Planer/.planung/k1-390.png create mode 100644 daten/Planer/.planung/k1-640.png create mode 100644 daten/Planer/.planung/k1-820.png create mode 100644 daten/Planer/.planung/karten-besprechen.md create mode 100644 daten/Planer/.planung/karten-pruefen.md create mode 100644 daten/Planer/.planung/komfort.png create mode 100644 daten/Planer/.planung/offen.png create mode 100644 daten/Planer/.planung/projekte.md create mode 100644 daten/Planer/.planung/vision-festhalten.md create mode 100644 daten/Planer/.planung/vision.md create mode 100644 daten/Planer/k1-1024.png create mode 100644 daten/Planer/k1-1280.png create mode 100644 daten/Planer/k1-1600.png create mode 100644 daten/Planer/k1-390.png create mode 100644 daten/Planer/k1-640.png create mode 100644 daten/Planer/k1-820.png create mode 100644 daten/Planer/karten-besprechen.md create mode 100644 daten/Planer/komfort.png create mode 100644 daten/Planer/offen.png create mode 100644 daten/RAG/.pruefung.json create mode 100644 daten/RAG/admin.md create mode 100644 daten/RAG/agenten.md create mode 100644 daten/RAG/anleitungen.md create mode 100644 daten/RAG/auftraege.md create mode 100644 daten/RAG/backup.md create mode 100644 daten/RAG/benutzer.md create mode 100644 daten/RAG/berichte.md create mode 100644 daten/RAG/chat.md create mode 100644 daten/RAG/diagnose.md create mode 100644 daten/RAG/dokumente.md create mode 100644 daten/RAG/evaluation.md create mode 100644 daten/RAG/faelle.md create mode 100644 daten/RAG/feedback.md create mode 100644 daten/RAG/knowledge-raeume.md create mode 100644 daten/RAG/konfiguration.md create mode 100644 daten/RAG/logs.md create mode 100644 daten/RAG/sonstiges.md create mode 100644 daten/RAG/system.md create mode 100644 daten/RAG/tags.md create mode 100644 daten/RAG/titel.md create mode 100644 daten/RAG/uploads.md create mode 100644 daten/RAG/verlauf.md create mode 100644 daten/RAG/versionen.md create mode 100644 daten/TFT/.pruefung.json create mode 100644 daten/TFT/analyse.md create mode 100644 daten/TFT/einheit.md create mode 100644 daten/TFT/pipeline.md create mode 100644 daten/TFT/shop.md create mode 100644 daten/TFT/spiel.md create mode 100644 frontend/k1-1024.png create mode 100644 frontend/k1-1280.png create mode 100644 frontend/k1-1600.png create mode 100644 frontend/k1-390.png create mode 100644 frontend/k1-640.png create mode 100644 frontend/k1-820.png create mode 100644 frontend/komfort.png create mode 100644 frontend/offen.png create mode 100644 frontend/src/components/ChatPanel.vue create mode 100644 frontend/src/components/k1-1024.png create mode 100644 frontend/src/components/k1-1280.png create mode 100644 frontend/src/components/k1-1600.png create mode 100644 frontend/src/components/k1-390.png create mode 100644 frontend/src/components/k1-640.png create mode 100644 frontend/src/components/k1-820.png create mode 100644 frontend/src/components/komfort.png create mode 100644 frontend/src/components/offen.png create mode 100644 frontend/src/composables/planung.js create mode 100644 k1-1024.png create mode 100644 k1-1280.png create mode 100644 k1-1600.png create mode 100644 k1-390.png create mode 100644 k1-640.png create mode 100644 k1-820.png create mode 100644 komfort.png create mode 100644 offen.png diff --git a/LEARNINGS.md b/LEARNINGS.md new file mode 100644 index 0000000..0793a3c --- /dev/null +++ b/LEARNINGS.md @@ -0,0 +1,451 @@ +# Learnings + +Was beim Bau von planer2 gemessen wurde. Nicht was plausibel klang — was sich +nachweisen ließ. Geschrieben, bevor Prüfung 3 entfernt wurde, damit ihr Wissen +bleibt. + +Stand: 29.07.2026 + + +## Der Aufbau in einem Absatz + +Markdown-Dateien sind die Wahrheit. Eine Karte ist ein Auftrag, eine Funktion +etwas, das man für sich testen kann, eine Regel eine Zusicherung. Der Code eines +fremden Projekts ist Beleg, nie Quelle der Wahrheit. Drei Prüfungen glichen ab: +Stil, „hat jede Funktion Code" und „hat jede Codestelle eine Funktion". + + +## 1. Was funktioniert hat + +### Beweislast statt Meinung + +Jede Aussage über den Code muss eine wörtlich zitierte Zeile mitbringen. +`quellcode.belegt()` schlägt sie gegen die Datei. Ein misslungenes Zitat zählt +nicht als Fund. + +Das ist der wichtigste Baustein des ganzen Systems. Ohne ihn schlug ein früher +Versuch vor, gültige Inhalte zu löschen — das Modell urteilte direkt und lag +falsch. Mit ihm ist ein Fund nachprüfbar und ein Nichtfund die einzige Aussage, +die überhaupt Stimmen braucht. + +**Die Asymmetrie ist der Hebel.** Vorhandensein lässt sich zitieren, +Nichtvorhandensein nicht. Also: ein geprüfter Fund genügt zum Freispruch, sechs +Fehlversuche sind die Anklage. + +### Das Urteilsgedächtnis + +Ein Urteil kostet sechs Anfragen und fällt bei Grenzfällen mal so, mal so. Genau +daran scheiterte die Wiederholbarkeit: derselbe Stand lieferte in Runde 1 einen +Befund, in Runde 2 keinen, in Runde 3 wieder einen. + +Gespeichert wird deshalb das Urteil, nicht nur das Ergebnis (`ledger.py`, +`.pruefung.json` im Projektordner). Ein Eintrag gilt weiter, solange seine +Voraussetzung nachweisbar dasteht: + +- ein Beleg, solange die zitierte Zeile noch in der Datei steht +- eine Fehlmeldung, solange sich am Quelltext nichts geändert hat + +Das machte gleichen Stand zu gleichem Ergebnis. Ohne dieses Gedächtnis gibt es +keine Konvergenz — der Loop würfelt jede Runde neu. + +**Der Zuschnitt des Fingerabdrucks entscheidet über die Kosten.** Anfangs ging +der Abdruck über den ganzen Funktionstext. Eine Stilkorrektur an einer Regel +tötete damit auch das Inhaltsurteil. Gemessen: R1 code 384 Anfragen, R2 code 384 +Anfragen — null Treffer im Gedächtnis. Nach der Kürzung auf Karten- und +Funktionstitel: R3 feature 30 statt 259, R3 code 21 statt 201. Rund 88 % +Trefferquote, sobald die Stiländerungen abgeklungen sind. + +Regel daraus: **ein Urteil verfällt nur, wenn sich ändert, worauf es tatsächlich +beruht.** Nicht wenn sich der Text drumherum ändert. + +### Frühabbruch statt fester Stimmenzahl + +Sechs Stimmen je Einheit waren gemessen richtig für die *Schwelle*, aber +verschwenderisch für den *Normalfall*. Ein nachgeschlagener Beleg beendet die +Frage — die anderen fünf Antworten wurden bezahlt und weggeworfen. + +Stufen (1, dann 2, dann 3) mit Abbruchprüfung nach jeder Stufe: + +- Prüfung 2: von 6 auf ~1 Anfrage im Normalfall +- Prüfung 3: von 6 auf ~3 + +Gesamter Loop auf planer2: **2719 → 1354 Anfragen** bei gleicher Rundenzahl. + +**Eine Falle dabei:** Eine ausgefallene Stimme ist keine Ja-Stimme. Der erste +Wurf brach ab, sobald die verbleibenden Stimmen die Schwelle rechnerisch nicht +mehr reißen konnten — und hielt damit einen HTTP-429 für „ist abgedeckt". Fix: +nur abbrechen, wenn alle gestellten Fragen auch beantwortet wurden. + +### Schwellen misst man, man rät sie nicht + +Alle Zahlen in `inhalt.py` stammen aus Messungen an gepflanzten Lücken: + +- `FEHLT_AB = 4` von 6 — eine echte Lücke war immer einstimmig; strittige Stellen + lagen darunter und kippten zwischen Läufen +- `TITEL_KANAL = 0.85`, `INHALT_KANAL = 0.7` — darunter explodierten die + Kandidatenpaare +- `KERN_MIN = 3` — unter drei Wörtern kennt die Überlappung nur 0, 0,5 und 1 +- `BUENDEL = 6` Stellen je Anfrage — größere Bündel verloren Stellen aus der Mitte + +Der Versuch, Grenzfälle *lexikalisch* zu filtern, ist gescheitert: „Produkt +merken" und „Konfiguration merken" sehen identisch aus, einer ist eine echte +Lücke, der andere nicht. Die Lösung war eine Entscheidung, keine Formel: +empfindlich sein (4 von 6) und Ablehnungen dauerhaft merken. + +### Der Musterkatalog als Daten + +Was eine auslösbare Stelle ist, steht in `muster/*.toml`, nicht im Code. Ein neues +Rahmenwerk ist eine Datei, keine Codeänderung. + +Auslöser dafür: Bei einem Shopware-Plugin fand das Inventar genau *eine* Stelle, +weil Twig, Symfony-Attribute und `element.addEventListener` als Regex im Programm +nicht vorkamen. Nach dem Katalog: 19 Stellen. + +Zwei Nachbesserungen, die viel ausmachten: + +- `store.reroll()` ist die Fähigkeit `reroll`, nicht `store`. Ohne diese Regel + fielen zwölf Knöpfe eines Stores auf einen einzigen Eintrag zusammen. +- Symfony schreibt Routen benannt (`path: '/x'`) **oder** positionell + (`Route('/x', ...)`). Nur die benannte Form zu kennen fand 5 von 127 Routen. + +### Erzeugen aus dem Inventar, nicht aus dem Quelltext + +Der Erzeuger geht von den Stellen aus, nicht vom Code als Ganzem. Damit ist +Vollständigkeit Bauart, nicht Hoffnung: jede Stelle bekommt eine Funktion, jede +Funktion stammt von mindestens einer Stelle. + +Was das Modell frei aufzählt, war jede Runde anders, und niemand konnte sagen, ob +etwas fehlt. + +Vier Schritte: benennen (je Stelle) → falten (gleiche Titel zusammenlegen) → +verdichten (alle Funktionen nebeneinander neu ordnen) → füllen (je Funktion Ziel, +Regeln, Testschritte aus dem Code). + +**Verdichten ist der Schritt, an dem Minimalität entsteht.** Ohne ihn kamen aus +21 Stellen 17 Karten mit je einer Funktion. Mit ihm: 5 Karten, 19 Funktionen. + +### Nachfassen statt Verlust + +Fällt eine Anfrage aus, fehlen sechs Stellen auf einmal. Bei 19 Stellen ist das +fast die Hälfte — und die Karten waren still unvollständig. Gemessen: 8 von 19 +Stellen blieben unbenannt. + +Fix: kleinere Bündel nachfragen (6 → 2 → 1), und was auch einzeln keinen Namen +bekommt, aus dem Schlüssel benennen. Ein grober Titel fällt auf; eine fehlende +Stelle fällt niemandem auf. + +Dasselbe Muster beim Verdichten: fiel eine Zuordnung aus, blieben ihre zwölf +Funktionen auf Einzelkarten stehen — aus 19 Fähigkeiten wurden wieder 16 Karten. + + +## 2. Was nicht funktioniert hat + +### Prüfung 3 — drei Konstruktionsfehler + +Die Prüfung „hat jede Codestelle eine Funktion" hat nie zuverlässig funktioniert. +Nicht wegen des Modells, sondern wegen der Grundmenge, gegen die sie zählt. +Gemessen an planer2 (64 Stellen, 45 Funktionen): + +**1. Eingabefelder fehlen ganz.** `v-model="suche"` ist kein Muster. Vier solcher +Felder im Projekt, keins im Inventar. Die Feature-Suche existiert, wird aber nie +gezählt und nie gemeldet. + +**2. Argumente fallen weg.** Der Schlüssel ist der Funktionsname. Alle vier +Prüfknöpfe rufen `startePruefung(projekt, art)` → eine Stelle statt vier. Vier +Fähigkeiten, ein Punkt. + +**3. Gleichnamige Funktionen fallen zusammen.** `alleAnnehmen` gibt es in +`FeatureKarte.vue` und in `FeatureListe.vue` — zwei verschiedene Dinge, ein +Punkt. Der neue Sammelknopf „Alle N Karten anlegen" ist dadurch unsichtbar. + +Ergebnis: Gegen das eigene Inventar meldete Prüfung 3 **62 von 64 = 97 %**. Gegen +das, was das Programm wirklich kann, waren es **rund 44 von 52 = 85 %**. + +**Dazu zwei falsche Abgedeckt-Urteile.** `DELETE /pruefung` und `GET /chat` +tragen keine Funktion. Prüfung 3 meldete null Lücken — das Modell hielt sie für +gedeckt, weil eine ähnlich klingende Funktion danebenstand. + +### Zusicherungen ohne Auslöser sind unsichtbar + +Der größte Fund, und er gilt weit über Prüfung 3 hinaus. + +Vieles, was ein Programm zusichert, hängt an keinem Auslöser: eine Beschriftung +im Markup, eine Vorbelegung beim ersten Aufruf, die Reihenfolge von Dingen, ein +Standardfall, eine Grenze. + +Gemessen an MtoVariantConfigurator: Von acht Anforderungen fehlten **fünf** auf +den erzeugten Karten, obwohl der Code sie umsetzte. Transitivität der Dropdowns, +Reihenfolge aus dem Backend, Vorbelegung aus dem Elternartikel, Schritt-Badge, +Hinweistexte. Alle vorhanden, alle unsichtbar. + +Die Vollständigkeitsprüfung meldete dabei **null Lücken** — sie zählt nur +Auslöser. + +**Der Fix, der wirkte:** Karten bekamen eigenes Ziel und eigene Regeln, gefüllt +aus den *ganzen Dateien* statt aus fünf Zeilen um die Stelle. Dazu ein +Nachtrag-Schritt je Karte: „was steht im Code und fehlt hier?". Danach 8 von 8. + +**Was nicht wirkte:** Der Prompt allein. „Nenne die Sache, nicht die Umsetzung" +stand von Anfang an drin und half nicht. + +### Dubletten: Zeichenähnlichkeit fängt Typ 4 nicht + +„Galerie vorwärts blättern" und „Galerie nächste anzeigen" sind dieselbe Sache. +Gemessene Titelähnlichkeit: **0,53**. Schwelle: **0,85**. Das Paar wurde nie +Kandidat — kein Modell hat es je gesehen. + +Die Klon-Typologie erklärt es: Typ 1 (exakt) und Typ 2 (umbenannt) fängt +String-Matching. Typ 4 (gleiche Bedeutung, andere Worte) nicht. + +**Der Fix:** ein vierter Kanal — alles auf derselben Karte wird Kandidat. +Bezahlbar, weil eine Dublette fast immer neben ihrer Zwillingsschwester steht. +Zehn Funktionen ergeben 45 Paare, nicht Tausende. Fand sofort zwei echte +Dubletten, die vier Runden lang durchgerutscht waren. + +### Streuung: gemessen, nicht behoben + +Gleicher Code, gleiche Einstellungen, andere Karten. Lange nur eine Beobachtung, +dann eine Zahl. + +Adjusted Rand Index über die Zerlegung der *Codestellen* (Titel ändern sich +zwischen Läufen, Stellen nicht): + +| | Mittel | Minimum | +|---|---|---| +| Karten | **0,34** | 0,28 | +| Funktionen | **0,53** | 0,51 | + +Kartenzahl über drei Läufe: 9, 9, 13. + +0,34 heißt: die Kartenzuordnung ist näher am Zufall als an einer Entscheidung. +Das ist der ungelöste Kern des Erzeugers. + +Was die Streuung *senkte*, aber nicht beseitigte: die Codezeile als Anker beim +Umbenennen. Ohne sie wurde aus „Konfigurator öffnen" ein „Erweiterung +aktivieren" — das Modell sah nur den Titel. + +### Der volle Stilkatalog verdirbt Struktur-Antworten + +Nach Kartentiteln gefragt, antwortete das Modell mit ganzen Karten samt +Testschritten. Die Beispiele im Katalog sind stärker als die Formatangabe. + +Fix: nur die Titelregeln mitgeben. Allgemeine Lehre — **gib einem Schritt nur +den Teil des Katalogs, den er braucht.** + +### Zu viel Parallelität + +Vier gleichzeitige Läufe → HTTP 429. Ausgefallene Stimmen sahen aus wie „nichts +gefunden". Nacheinander laufen lassen war die Lösung, nicht mehr Wiederholungen. + + +## 3. Was aus der Recherche belegt ist + +Eine Recherche zu Verfahren für vollständige und minimale Extraktion lieferte +Belege für einiges, was hier gebaut wurde, und ein paar Warnungen. + +**Bestätigt:** + +- *Adaptive Consistency* (Aggarwal et al., EMNLP 2023): Frühabbruch senkt das + Stichprobenbudget „by up to 7.9 times with an average accuracy drop of less + than 0.1%". Deckt sich mit der hier gemessenen Halbierung. +- *Early cutoff* aus der Build-System-Forschung (Mokhov et al., ICFP 2018): ein + Urteil verfällt nur, wenn sich seine echten Abhängigkeiten ändern. Genau das + Problem des zu groben Fingerabdrucks. +- *Mutanten als Ersatz für echte Fehler* (Just et al., FSE 2014): 73 % Kopplung + über 357 echte Fehler. Rechtfertigt gepflanzte Lücken als Vollständigkeitsmaß — + mit der Einschränkung, dass rund ein Viertel ungekoppelt bleibt. +- *Extraktive statt abstraktive Erzeugung* senkt Halluzination messbar. Hier: das + Zitat, das gegen die Datei geschlagen wird. + +**Gewarnt:** + +- Chao1 und Capture-Recapture schätzen Vollständigkeit systematisch zu niedrig, + besonders bei kleinen Stichproben. Für 19 Einheiten wertlos. +- Testsuite-Minimierung erkauft Größenreduktion mit Erkennungsverlust: „over 70 %" + Reduktion, „around 12.5 %" weniger gefundene Fehler. Aggressive Minimalität hat + einen Preis. +- Self-Consistency hilft bei konvergenter richtiger Antwort und *schadet* bei + systematischem Bias. Mehr Stimmen ersetzen keine bessere Verankerung. + +**Nicht anwendbar hier:** Dynamische Invariantenerkennung (Daikon) und +Coverage-Kriterien brauchen einen *laufenden* Zielprozess mit Tests. Das System +liest nur Dateien fremder Projekte. + + +## 4. Synchronisation zwischen Planung und Code + +Zweite Recherche, gezielt auf die Frage: wie hält man eine fachliche Beschreibung +und den Code dauerhaft synchron, in beide Richtungen? 25 Behauptungen gegengeprüft, +13 überlebt, 12 verworfen. + +### Beide Richtungen enden bei etwa der Hälfte + +**Planung → Code: 53,5 %.** E2EDevBench (50 reale PyPI-Projekte, Anforderungsdokument +als einziger Eingang) misst 53,50 % umgesetzte Anforderungen in der besten +Konfiguration. Ein unabhängig gebauter Benchmark mit anderen Autoren und anderen +Agenten-Rahmenwerken kommt auf 53,75 %. „The other half of the requirements +remained unfulfilled." + +Die Abnahme durch einen Menschen ist damit kein Sicherheitsgurt, sondern die +gemessene Notwendigkeit. + +**Code → Planung: 59 %.** Polikarpova, Ciupa, Meyer (ISSTA 2009, 25 Klassen, 831 +menschliche Klauseln, über 19.500 abgeleitete): Automatische Inferenz findet 59 % +aller von Programmierern geschriebenen Zusicherungen wieder — mit kleiner +Testsuite nur 50 %. Autorenfazit: „contract inference cannot completely replace +the manual work of writing assertions." + +Und die Ausbeute ist verrauscht: 90 % der abgeleiteten Klauseln sind korrekt, aber +nur **64 % relevant**. Rund ein Drittel muss aussortiert werden. + +### Der brauchbarste Einzelbefund + +Der Engpass ist **nicht das Denkvermögen, sondern der Ausdrucksvorrat**. + +Von der Abdeckungslücke gehen 31 Prozentpunkte auf „nicht ausdrückbar" und nur +etwa 10 auf „ausdrückbar, aber nicht gefunden" — Verhältnis rund 3:1. Und von den +nicht ausdrückbaren Klauseln scheiterten **54 % allein daran, dass sie eine +Funktion mit einem Argument aufrufen**, weitere 19 % an fehlenden +Implikations-Schablonen. + +Die Autoren widersprechen ausdrücklich der naheliegenden Deutung: „It is tempting +to draw the conclusion that at present the tool cannot compete with humans on +higher levels of abstraction. However … 'abstract' assertions are mostly not +expressible by the tool." + +Übertragen auf uns, als Hypothese ohne Messung: dem Extraktor das Fachvokabular +mitzugeben — Funktionsnamen, Domänenbegriffe — schlägt vermutlich ein besseres +Modell. + +### Die Beleglücke ist der eigentliche Befund + +Für drei Dinge liefert der ganze Korpus **keinen einzigen belegten Mechanismus**: + +- **Inkrementelle Synchronisation** aus Commits, Diffs, Pull Requests. Alles + Gemessene ist Greenfield-Vollerzeugung. +- **Drift-Erkennung ohne Vollvergleich.** Die einzige geprüfte Behauptung dazu — + Invarianten als Verhaltens-Fingerabdruck — wurde 1:2 verworfen. +- **Zwei-Wege-Konflikte.** In dem untersuchten Spec-Driven-Rahmenwerk kommen die + Begriffe *traceability*, *drift*, *bidirectional* und *round-trip* **null mal** + vor. Diese Verfahren sind einbahnig. + +Das heißt nicht, dass es nicht geht. Es heißt, dass niemand es gemessen hat. + +### Was gemessen wurde und fast nichts brachte + +Prozess- und Strukturarbeit auf der Spezifikationsseite: + +- Kontext-Hooks in einem Vier-Phasen-Ablauf (Specify → Plan → Tasks → Implement): + **+3,0 %** der Skala +- Spezifikation nach Epics gliedern: **+1,4 Prozentpunkte** Abdeckung, gleichzeitig + **−4,0 Prozentpunkte** auf der lexikalischen Messgröße + +Der einzige stabile Gewinn kommt aus der Erdung im echten Code und aus +ausführbaren Testsuiten. Das deckt sich mit unserem eigenen Fund: der Prompt allein +half nie, das Zeigen ganzer Dateien half sofort. + +### Verworfen — und nicht durch die Hintertür zurückholen + +Sechs Mechanismen, die für unsere Architektur naheliegend gewesen wären, haben die +Gegenprüfung nicht überstanden: + +| Behauptung | Abstimmung | +|---|---| +| Invarianten-Vergleich als Drift-Fingerabdruck | 1:2 | +| LLM-Richter je Anforderung als referenzfreie Abdeckungsmessung | 0:3 | +| Spurious Scenario Rate als Überspezifikations-Melder | 0:3 | +| Einbettungs- statt Wortabdeckung als Messgröße | 0:3 | +| Daikon-Präzision über 95 % gegen ESC/Java | 0:3 | +| Ein Zwischenartefakt Plan/Design schade der Treue | 0:3 | + +Besonders bitter: der Fingerabdruck-Gedanke. Er hätte genau unsere Drift-Frage +gelöst. + +### Ein Widerspruch, der offen bleibt + +Die Behauptung, Inferenz decke systematisch Zusicherungen auf, wo kein Mensch +etwas notiert hatte — im Mittel 4,9-fach so viele relevante Klauseln, 13,3-fach bei +Schleifeninvarianten — wurde als eigenständige Behauptung **0:3 verworfen**. +Dieselben Zahlen tauchen aber in der bestätigten Belegkette einer anderen +Behauptung wieder auf. Der Widerspruch ist ungelöst. + +Die Zahlen gelten damit nicht als belegt. Die Richtung — Extraktion ergänzt den +Menschen, ersetzt ihn nicht — ist mehrfach gestützt. + +### Grenzen dieser Recherche + +- **Alter.** Die härtesten Zahlen (59 %, 64 %, 54 %) sind von 2009 und hängen am + damaligen Schablonensatz. Sie sind **keine Obergrenze für LLM-Extraktion** — dazu + existiert keine Messung. +- **Quellenlage.** Vier der sechs tragenden Quellen sind unbegutachtete Preprints. + Begutachtet sind zwei plus eine Industriefallstudie. +- **Transfergrenze.** Alle harten Zahlen messen maschinenprüfbare Artefakte — + ausführbare Vor- und Nachbedingungen, Eiffel-Kontrakte, Gherkin. Unsere Planung + ist Prosa für Projektmanager. Der Schluss von „59 % der formalen Zusicherungen" + auf „x % der fachlichen Beschreibung" ist Plausibilität, keine Messung. +- **Zirkularität.** Die 53,5 % beruhen auf einem Modell als Richter, das teilweise + eigene Ausgaben bewertet. + +### Was das für planer2 heißt + +- Prüfung 2 sitzt auf dem belegten Teil. Beleg gegen die Datei geschlagen, ein Fund + genügt, ein Nichtfund braucht Mehrheit. +- Prüfung 3 hätte auf dem unbelegten gesessen. Das Streichen war richtig — und + jetzt auch von außen gestützt. +- Der inkrementelle Normalfall ist Neuland. Kein Beleg dagegen, aber auch keiner + dafür. Wer ihn baut, misst selbst oder weiß nichts. +- Die Kostenlage stützt ihn trotzdem: Vollsynchronisation kostete im Benchmark + ~7 $ und 5,24 Mio. gesendete Token je Projekt — für 53,5 %. + + +## 5. Handkarten gegen erzeugte Karten + +Ein direkter Vergleich auf MtoVariantConfigurator. + +| | Handkarten | Erzeuger | +|---|---|---| +| Runden bis still | 2 | 3 | +| Anfragen | 361 | 1044 | +| Karten | 7 | 4 | +| Funktionen | 26 | 17 | +| Anforderungen erfüllt | 8 von 8 | 5 von 8 | + +Die Handkarten entstanden aus Issue, Wiki **und allen 47 Kommentaren** plus dem +Code. Die Prüfungen änderten daran nur drei Stilkleinigkeiten. + +Der Unterschied liegt nicht bei den Funktionen — die findet der Erzeuger. Er +liegt bei den Kartenregeln, also bei den Zusicherungen ohne Auslöser. + +**Ein Fehler dabei, der eine eigene Lehre ist:** Beim ersten Anlauf habe ich nur +Beschreibung und Wiki gelesen und „8 von 8 erfüllt" gemeldet. Die 47 Kommentare +standen in derselben Datei. Die Zahl war falsch, weil die Grundmenge falsch war. +Wer Vollständigkeit misst, muss zuerst prüfen, ob er die Quelle ganz gelesen hat. + + +## 6. Zahlen zum Nachschlagen + +Vier Projekte, Loop aus Erzeugen und drei Prüfungen bis zur Ruhe. + +| Projekt | Dateien | Stellen | Karten | Funktionen | Runden | Anfragen | +|---|---|---|---|---|---|---| +| MtoVariantConfigurator | 19 | 19 | 4–7 | 17–26 | 2–3 | 361–1044 | +| tft | 44 | 21 | 5 | 20 | 3 | 616 | +| planer2 | 34 | 64 | 8–13 | 46–51 | 4–5 | 1354–2719 | +| MtoRagSystem | 475 | 183 | 23–33 | 150–168 | 5+ | ~4000 | + +MtoRagSystem: 6,6 Mio. Zeichen Quelltext. Prüfung 2 schickte anfangs alles je +Funktion und fiel für das ganze Projekt aus. Mit Vorauswahl (erst fragen, welche +Dateien, dann nur die zeigen): 149 von 150 Funktionen belegt, 0 Fehler. + + +## 7. Offene Fragen + +- **Streuung.** ARI 0,34 bei den Karten. Verankerung half, löste es nicht. + Deterministische Gruppierung wäre reproduzierbar, aber nicht zwingend richtig. +- **Grundmenge für Zusicherungen.** Karten-Regeln plus Nachtrag-Schritt haben den + konkreten Fall gelöst. Ein *zählbares* Maß dafür gibt es nicht. +- **Belege je Funktion.** Prüfung 2 merkt sich nur einen Beleg — den ersten, der + sich nachschlagen ließ. Für eine spätere, deterministische Abdeckungsrechnung + bräuchte sie alle. +- **Körnung.** Wann sind zwei Dinge eine Funktion, wann zwei? Es gibt kein + belegtes absolutes Maß dafür ohne Referenzmodell. diff --git a/backend/agents.py b/backend/agents.py index 86a3696..86a5004 100644 --- a/backend/agents.py +++ b/backend/agents.py @@ -14,8 +14,10 @@ API_VERSION = "2023-06-01" # Der Provider drosselt bei vielen gleichzeitigen Anfragen WIEDERHOLBAR = (429, 500, 502, 503, 504) -WIEDERHOLUNGEN = 4 +WIEDERHOLUNGEN = 6 PAUSE = 2.0 +# Länger als das zu warten hilft nicht mehr; dann ist die Drossel zu weit offen +HOECHSTPAUSE = 60.0 class NichtKonfiguriert(ValueError): @@ -37,6 +39,15 @@ def pruefe_konfiguration(): raise NichtKonfiguriert(f"Nicht konfiguriert: {', '.join(fehlend)} in .env fehlt") +def _pause(res, versuch: int) -> float: + """Wie lange bis zum nächsten Versuch — der Provider darf es selbst sagen.""" + gesagt = res.headers.get("retry-after") + try: + return min(float(gesagt), HOECHSTPAUSE) + except (TypeError, ValueError): + return min(PAUSE * (2 ** versuch), HOECHSTPAUSE) + + async def frage(system: str, inhalt: str, temperatur: float = 0.0) -> str: """Eine Anfrage, eine Antwort — der Text der Modellantwort. Kalt geroutet: Temperatur 0, kein Thinking; die Prüfung soll nicht raten. @@ -63,7 +74,7 @@ async def frage(system: str, inhalt: str, temperatur: float = 0.0) -> str: # Zu viele Anfragen oder Serverfehler: warten und noch einmal. # Ohne das fielen bei großen Läufen ganze Stimmen aus — und ein # fehlendes Urteil sah aus wie „nichts gefunden". - await asyncio.sleep(PAUSE * (2 ** versuch)) + await asyncio.sleep(_pause(res, versuch)) if res.status_code != 200: raise RuntimeError(f"Provider antwortet mit HTTP {res.status_code}") antwort = res.json() diff --git a/backend/chat.py b/backend/chat.py new file mode 100644 index 0000000..b20ded9 --- /dev/null +++ b/backend/chat.py @@ -0,0 +1,292 @@ +"""Karten im Gespräch entwickeln. + +Man schreibt, was man vorhat. Die KI antwortet und legt daneben, wie die Karten +danach aussähen. Übernommen wird einzeln — dasselbe ✓ und ✕ wie bei der Prüfung. + +Warum kein eigener Anzeigeweg: Ein Vorschlag ist ein Vorschlag, egal ob ihn die +Prüfung oder das Gespräch gemacht hat. Der Chat liefert deshalb genau die Form, die +`pruefung._stellen` erzeugt — Karten zeigen ihn an derselben Stelle an, der Vergleich +funktioniert, Annehmen schreibt die Datei. + +Das Modell schreibt nie selbst in eine Datei. Es beschreibt den Sollzustand einer +Karte; was sich dadurch ändert, rechnet der Code aus. Das ist dieselbe Beweislast wie +bei der Prüfung und der Grund, warum ein Missverständnis hier nichts kaputt macht. +""" + +import json + +import agents +import features +import parser +import projekte +import pruefung + +DATEI = ".chat.json" +# So viele Wortmeldungen bleiben stehen. Mehr wäre teuer je Anfrage und hilft wenig: +# was vor zwanzig Schritten besprochen wurde, steht längst auf den Karten. +TIEFE = 30 +# Antworten in einem Rutsch. Ein Gespräch verträgt keine sechs Stimmen — es soll +# schnell sein, und was falsch ist, sieht man am Vorschlag. +TEMPERATUR = 0.3 + +SYSTEM = """Du entwickelst mit einer Person zusammen die Feature-Karten eines Projekts. + +Eine Karte ist ein Auftrag: die Person will ein Problem gelöst haben. Die Lösung +besteht aus Regeln und Funktionen. Eine Funktion ist etwas, das man für sich testen +kann. Was nur die Umsetzung betrifft, gehört auf keine Karte. + +{stil} + +Der aktuelle Stand: + +{karten} + +Antworte ausschließlich mit JSON: +{{"antwort": "...", "karten": [ + {{"titel": "...", "art": "kern", "ziel": "...", "regeln": ["..."], + "funktionen": [{{"titel": "...", "ziel": "...", "regeln": ["..."], + "testen": ["..."]}}]}} +]}} + +- antwort: was du der Person sagst, auf Deutsch, höchstens vier Sätze +- karten: nur die Karten, die sich ändern oder dazukommen sollen — jeweils + VOLLSTÄNDIG, so wie sie danach aussehen sollen. Der Stand oben hat dieselbe Form: + kopiere die Karte von dort und ändere nur, was sich ändern soll. Jede Zeile, die + du nicht wörtlich mit abschreibst, gilt als gestrichen. +- art: „kern", wenn die Anwendung ohne die Karte keinen Sinn hätte, sonst „optional" +- ziel, regeln und testen dürfen leer sein oder fehlen + +Ist nichts zu ändern, ist karten leer. Ändere nur, wonach gefragt wurde; Karten, +die niemand erwähnt hat, lässt du weg. + +Frag nach, was du nicht weißt — aber leg trotzdem einen Entwurf daneben. Eine Frage +ohne Vorschlag hilft niemandem: an einem Entwurf sieht die Person sofort, was du +falsch verstanden hast. Erfinde dabei nichts, was nicht gesagt wurde; lass eine +Funktion lieber knapp als ausgedacht.""" + +# Die Formatregel steht auch hier, nicht nur im System-Prompt. Bei langen Antworten +# vergaß das Modell sie sonst und schrieb reinen Fließtext — die ganze Wortmeldung +# war verloren. +NACHRICHT = """{verlauf} + +Neue Nachricht der Person: +{text} + +Antworte ausschließlich mit dem JSON-Objekt, ohne Text davor oder danach.""" + +NACHBESSERN = """Deine Antwort war kein JSON. + +Schreibe sie noch einmal, ausschließlich als das JSON-Objekt aus der Vorgabe — +keine Einleitung, kein Nachsatz, keine Code-Zäune.""" + + +def _pfad(projekt: str): + return projekte.wurzel(projekt) / DATEI + + +def verlauf(projekt: str) -> list: + try: + eintraege = json.loads(_pfad(projekt).read_text()) + except (OSError, ValueError): + return [] + return eintraege if isinstance(eintraege, list) else [] + + +def _sichere(projekt: str, eintraege: list): + ziel = _pfad(projekt) + neben = ziel.with_suffix(".json.neu") + neben.write_text(json.dumps(eintraege[-TIEFE:], indent=1, ensure_ascii=False) + "\n") + neben.replace(ziel) + + +def leeren(projekt: str): + _pfad(projekt).unlink(missing_ok=True) + + +def _punkte(text: str) -> list: + return [z.strip("- ").strip() for z in (text or "").splitlines() if z.strip()] + + +def _als_spec(f: dict) -> dict: + """Eine Karte in genau der Form, in der das Modell antworten soll.""" + s = f["sektionen"] + return {"titel": s["titel"], "art": s["art"], "ziel": s["ziel"], + "regeln": _punkte(s["regeln"]), + "funktionen": [{"titel": x["text"], "ziel": x["ziel"], + "regeln": _punkte(x["regeln"]), + "testen": _punkte(x["testen"])} + for x in s["funktionen"]]} + + +def _kartenstand(projekt: str) -> str: + """Der Stand als JSON — dieselbe Form wie die Antwort. + + Vorher stand er als Fließtext da. Das Modell musste ihn beim Zurückschreiben + übersetzen und schob dabei Regeln zwischen Karten- und Funktionsebene hin und + her: aus „eine Funktion ergänzen" wurden vier Änderungen. Gleiche Form heißt, + dass Abschreiben nichts kostet. + """ + vision, karten = "", [] + for f in features.liste(projekt): + if f["sektionen"]["art"] == parser.VISION: + vision = f["sektionen"]["ziel"] + else: + karten.append(_als_spec(f)) + text = json.dumps(karten, indent=1, ensure_ascii=False) if karten \ + else "Noch keine Karten." + if vision: + text = f"So ist das Projekt gedacht:\n\n{vision}\n\nDie Karten:\n\n{text}" + return text + + +def _zeilen(wert) -> str: + """regeln und testen kommen als Liste oder als Block — hier wird eins daraus.""" + if isinstance(wert, list): + eintraege = [str(z).strip("- ").strip() for z in wert] + else: + eintraege = [z.strip("- ").strip() for z in str(wert or "").splitlines()] + return "\n".join(f"- {z}" for z in eintraege if z) + + +TRENNER = "-" * 40 + + +def roh(karte: dict) -> str: + """Aus dem Sollzustand die Markdown-Datei — dieselbe Form wie im Frontend.""" + art = str(karte.get("art") or "kern").strip().lower() + teile = [f'\n{str(karte.get("titel") or "").strip()}', + f'\n{art if art in parser.ARTEN else "kern"}'] + if str(karte.get("ziel") or "").strip(): + teile.append(f'\n{str(karte["ziel"]).strip()}') + if _zeilen(karte.get("regeln")): + teile.append(f'\n{_zeilen(karte.get("regeln"))}') + for f in karte.get("funktionen") or []: + block = [f'\n{str(f.get("titel") or "").strip()}'] + if f.get("stand") == parser.OFFEN: + block.append(f'\n{parser.OFFEN}') + if str(f.get("ziel") or "").strip(): + block.append(f'\n{str(f["ziel"]).strip()}') + for feld in ("regeln", "testen"): + if _zeilen(f.get(feld)): + block.append(f'\n{_zeilen(f.get(feld))}') + teile.append("\n".join(block)) + return f"\n{TRENNER}\n".join(teile) + "\n" + + +def _felder(sektionen: dict) -> dict: + return {"titel": sektionen["titel"], "badge": sektionen["art"], + "ziel": sektionen["ziel"], "regeln": sektionen["regeln"], + "funktionen": "\n".join(f["text"] for f in sektionen["funktionen"])} + + +def _vergleiche(alt: dict, neu: dict, feature_id: str, grund: str) -> list: + """Was sich an einer bestehenden Karte ändert, Feld für Feld. + + Auf Funktionsebene wird nur die Liste der Titel verglichen. Wer den Inhalt einer + Funktion ändern will, bekommt dafür eigene Stellen — sonst wäre ein Vorschlag ein + Klotz, den man nur ganz oder gar nicht nehmen kann. + """ + raus = [] + for feld in ("titel", "badge", "ziel", "regeln", "funktionen"): + for p in pruefung._stellen(feld, alt.get(feld, ""), neu.get(feld, ""), + grund, "Aus dem Gespräch"): + p["feature"] = feature_id + p["funktion"] = "" + # Was das Gespräch an Funktionen erfindet, ist bestellt, nicht gebaut. + # Dieselbe Stelle aus Prüfung 3 hätte belegten Code — dort wäre „offen" falsch. + if feld == "funktionen": + p["neu_offen"] = True + raus.append(p) + return raus + + +def _funktionsstellen(alt: dict, neu: dict, feature_id: str, grund: str) -> list: + """Änderungen innerhalb einer Funktion, je Feld eine eigene Stelle.""" + vorher = {f["text"]: f for f in alt["funktionen"]} + raus = [] + for f in neu["funktionen"]: + bestand = vorher.get(f["text"]) + if not bestand: + continue # neue Funktion: steckt schon im Listenvergleich + for feld in ("ziel", "regeln", "testen"): + for p in pruefung._stellen(feld, bestand[feld], f[feld], grund, + "Aus dem Gespräch"): + p["feature"] = feature_id + p["funktion"] = f["text"] + raus.append(p) + return raus + + +def vorschlaege(projekt: str, karten: list) -> list: + """Aus den Sollzuständen die einzelnen Stellen — bestehende Karten wie neue.""" + nach_titel = {f["sektionen"]["titel"].lower(): f for f in features.liste(projekt)} + raus = [] + for karte in karten: + if not isinstance(karte, dict) or not str(karte.get("titel") or "").strip(): + continue + titel = str(karte["titel"]).strip() + # Den Stand entscheidet der Code, nicht das Modell: was schon gebaut war, + # bleibt gebaut; was das Gespräch neu erfindet, ist bestellt und noch offen. + # Das Modell sieht das Feld gar nicht — ein Feld weniger, das es vergessen kann. + bestand = nach_titel.get(titel.lower()) + gebaut = {x["text"] for x in bestand["sektionen"]["funktionen"] + if x["stand"] == parser.GEBAUT} if bestand else set() + for f in karte.get("funktionen") or []: + f["stand"] = parser.GEBAUT if str(f.get("titel") or "").strip() in gebaut \ + else parser.OFFEN + text = roh(karte) + neu = parser.zerlege(text) + if bestand is None: + # Neue Karte: es gibt keine Stelle, an der man ansetzen könnte — + # deshalb ein eigener Vorschlag, der die ganze Datei mitbringt. + raus.append({"feld": "neue_karte", "original": "", "vorschlag": titel, + "roh": text, "ganzes_feld": True, "feature": "", + "funktion": "", "regel": "Aus dem Gespräch", + "problem": "Neue Karte"}) + continue + grund = f"Aus dem Gespräch: {titel}" + raus += _vergleiche(_felder(bestand["sektionen"]), _felder(neu), + bestand["id"], grund) + raus += _funktionsstellen(bestand["sektionen"], neu, bestand["id"], grund) + return raus + + +async def frage(projekt: str, text: str) -> dict: + """Eine Runde: Frage rein, Antwort und Vorschläge raus.""" + text = (text or "").strip() + if not text: + raise ValueError("Nachricht ist leer") + agents.pruefe_konfiguration() + + bisher = verlauf(projekt) + gespraech = "\n\n".join(f'{"Person" if e["rolle"] == "person" else "Du"}: {e["text"]}' + for e in bisher) or "Noch nichts besprochen." + # Beide Kataloge: der Chat schreibt Karten UND Funktionen. Vorher kannte er nur + # die Kartenregeln und erfand Funktionstitel wie „Galerie im Modal" — ein + # Bereich statt einer Handlung, und die Prüfung merkte es erst hinterher. + system = SYSTEM.format( + stil="\n\n".join(pruefung._stil_lesen(b) for b in pruefung.BEREICHE), + karten=_kartenstand(projekt)) + nachricht = NACHRICHT.format(verlauf=gespraech, text=text) + + # Ein Ausrutscher beim JSON kostet sonst die ganze Wortmeldung. Zweiter Versuch + # mit etwas mehr Streuung; danach fliegt der Fehler nach oben und ist sichtbar. + daten = None + for versuch in range(3): + antwort = await agents.frage(system, nachricht, TEMPERATUR + 0.1 * versuch) + try: + daten = pruefung._json_lesen(antwort) + break + except ValueError: + if versuch == 2: + raise ValueError("Antwort war nicht lesbar — bitte noch einmal senden") + # Nachbessern statt blind wiederholen: das Modell sieht seinen eigenen + # Fehlversuch und weiß, was daran fehlte. + nachricht = (f"{nachricht}\n\nDein letzter Versuch war:\n" + f"{antwort[:2000]}\n\n{NACHBESSERN}") + satz = str(daten.get("antwort") or "").strip() or "Verstanden." + probleme = vorschlaege(projekt, daten.get("karten") or []) + + bisher += [{"rolle": "person", "text": text}, {"rolle": "ki", "text": satz}] + _sichere(projekt, bisher) + return {"antwort": satz, "probleme": probleme, "verlauf": verlauf(projekt)} diff --git a/backend/config.py b/backend/config.py index 4df1df9..b1e8110 100644 --- a/backend/config.py +++ b/backend/config.py @@ -27,6 +27,13 @@ MINIMAX_API_KEY = os.environ.get("MINIMAX_API_KEY", "") MINIMAX_MODELL = os.environ.get("MINIMAX_MODELL", "") MINIMAX_URL = os.environ.get("MINIMAX_URL", "") +# Das Gespräch darf woanders laufen als die Prüfungen. Es ist ein einzelner Aufruf +# und lebt von Sprachgefühl; die Prüfungen sind hundert Stimmen und leben von der +# Temperaturstreuung. Nicht gesetzt heißt: alles über MiniMax. +CHAT_API_KEY = os.environ.get("CHAT_API_KEY", "") +CHAT_MODELL = os.environ.get("CHAT_MODELL", "") +CHAT_URL = os.environ.get("CHAT_URL", "https://api.anthropic.com/v1/messages") + def _zahl(name: str, standard: int) -> int: try: diff --git a/backend/features.py b/backend/features.py index c6f38a9..fe639e6 100644 --- a/backend/features.py +++ b/backend/features.py @@ -6,12 +6,15 @@ import parser import projekte _UMLAUTE = str.maketrans({"ä": "ae", "ö": "oe", "ü": "ue", "ß": "ss"}) +# Dateisysteme lassen 255 Zeichen je Name zu. Der Titel darf länger sein — er steht +# in der Datei, nicht im Namen. Ohne Deckel warf ein langer Titel einen Serverfehler. +NAMENSLAENGE = 80 def _slug(titel: str) -> str: s = titel.lower().translate(_UMLAUTE) s = re.sub(r"[^a-z0-9]+", "-", s).strip("-") - return s or "feature" + return s[:NAMENSLAENGE].strip("-") or "feature" def _eintrag(datei) -> dict: @@ -26,8 +29,14 @@ def _datei(projekt: str, id: str): return datei -def liste(projekt: str) -> list[dict]: - dateien = projekte.wurzel(projekt).glob("*.md") +def liste(projekt: str, nur_stand: bool = False) -> list[dict]: + """Die Karten. Standardmäßig die, an denen gerade gearbeitet wird. + + `nur_stand` liest stattdessen den Projektordner — die Übersicht soll sagen, + was das Projekt heute kann, nicht was jemand gerade plant. + """ + ordner = projekte.stand(projekt) if nur_stand else projekte.wurzel(projekt) + dateien = ordner.glob("*.md") eintraege = [_eintrag(d) for d in sorted(dateien)] return sorted(eintraege, key=lambda e: e["sektionen"]["titel"].lower()) @@ -38,17 +47,21 @@ def pruefbar(projekt: str) -> list[dict]: return [f for f in liste(projekt) if f["sektionen"]["art"] != parser.VISION] -def anlegen(projekt: str, roh: str) -> dict: - ordner = projekte.wurzel(projekt) - titel = parser.zerlege(roh)["titel"] - if not titel: - raise ValueError("Titel fehlt") - slug = _slug(titel) +def _frei(ordner, slug: str): + """Der erste freie Dateiname zum Slug; gleiche Namen bekommen eine Nummer.""" datei = ordner / f"{slug}.md" n = 2 while datei.exists(): datei = ordner / f"{slug}-{n}.md" n += 1 + return datei + + +def anlegen(projekt: str, roh: str) -> dict: + titel = parser.zerlege(roh)["titel"] + if not titel: + raise ValueError("Titel fehlt") + datei = _frei(projekte.wurzel(projekt), _slug(titel)) datei.write_text(roh) return _eintrag(datei) @@ -58,11 +71,7 @@ def _folge_titel(datei, titel: str): slug = _slug(titel) if re.fullmatch(re.escape(slug) + r"(-\d+)?", datei.stem): return datei # passt schon (inkl. Kollisions-Suffix) - ziel = datei.parent / f"{slug}.md" - n = 2 - while ziel.exists(): - ziel = datei.parent / f"{slug}-{n}.md" - n += 1 + ziel = _frei(datei.parent, slug) datei.rename(ziel) return ziel @@ -72,9 +81,35 @@ def speichern(projekt: str, id: str, roh: str) -> dict: titel = parser.zerlege(roh)["titel"] if not titel: raise ValueError("Titel fehlt") + vorher = datei.read_text() datei.write_text(roh) - return _eintrag(_folge_titel(datei, titel)) + neu = _folge_titel(datei, titel) + # Ein neuer Titel benennt die Datei um. Der Rückschritt muss beides kennen: + # die neue Datei fällt weg, die alte kommt mit ihrem alten Inhalt zurück. + schritt = {datei.stem: vorher} + if neu.stem != datei.stem: + schritt[neu.stem] = None + return _eintrag(neu) def loeschen(projekt: str, id: str): - _datei(projekt, id).unlink() + datei = _datei(projekt, id) + titel = parser.zerlege(datei.read_text())["titel"] or id + datei.unlink() + + +def verschieben(projekt: str, id: str, ziel: str) -> dict: + """Ein Feature in ein anderes Projekt umhängen. + + Kein Kopieren: die Datei wandert, damit es sie nur einmal gibt. Der Verlauf + hält beide Seiten fest — sonst ließe sich der Schritt nicht zurücknehmen. + """ + if ziel == projekt: + raise ValueError("Feature liegt schon in diesem Projekt") + datei = _datei(projekt, id) + roh = datei.read_text() + titel = parser.zerlege(roh)["titel"] or id + # Erst das Ziel auflösen: gibt es das Projekt nicht, ist noch nichts passiert + neu = _frei(projekte.wurzel(ziel), _slug(titel)) + datei.rename(neu) + return _eintrag(neu) diff --git a/backend/inhalt.py b/backend/inhalt.py deleted file mode 100644 index 88777ec..0000000 --- a/backend/inhalt.py +++ /dev/null @@ -1,748 +0,0 @@ -"""Zwei Abgleiche zwischen Karten und Quelltext, in beide Richtungen. - -**Feature im Code** — steht hinter jeder Funktion einer Karte auch Code? Dazu: -beschreiben zwei Funktionen dieselbe Fähigkeit? -**Code im Feature** — hat jede Stelle im Code auch eine Funktion auf einer Karte? - -Beide arbeiten mit derselben Beweislast, nur andersherum. - -Ein Vorhandensein lässt sich zitieren, ein Nichtvorhandensein nicht. Darum fragt -„Feature im Code" sechsmal unabhängig nach dem Beleg und meldet erst, wenn keine -einzige Stimme eine Codezeile findet, die auch wirklich dasteht. Ein geprüfter Fund -genügt zum Freispruch — sechs Fehlversuche sind die Anklage. Ein früherer Versuch -ließ das Modell direkt urteilen und schlug dabei vor, gültige Inhalte zu löschen. - -„Code im Feature" fragt umgekehrt je Stelle, ob eine bestehende Funktion sie -abdeckt, und meldet ab fünf von sechs Nein-Stimmen. Einstimmigkeit war zu scharf: -dieselbe Frage kippt auch bei Temperatur 0 gelegentlich. - -Was der Code selbst weiß, entscheidet der Code: die Liste der Bedienstellen kommt -aus `quellcode.interaktionen()`, jeder Beleg wird gegen die Datei geschlagen. - -Jedes Urteil wandert in `ledger`. Der nächste Lauf fragt nur noch, was er nicht -schon weiß — dadurch liefert derselbe Stand dasselbe Ergebnis. Auch das unentschiedene -Urteil wird gemerkt: es galt als abgedeckt, und ein Münzwurf, der jede Runde neu -fällt, ist schlimmer als einer, der einmal fällt. Ändert sich die Stelle im Code, -wird sie ohnehin neu beurteilt. -""" - -import asyncio -import difflib -import re -from collections import Counter - -import agents -import config -import ledger -import quellcode - -# Ohne Drossel liefen alle Anfragen gleichzeitig los und der Provider antwortete -# mit 429. Die ausgefallenen Stimmen sahen dann aus wie „nichts gefunden". -_schranke = None - - -def _drossel(): - global _schranke - if _schranke is None: - _schranke = asyncio.Semaphore(config.PRUEFUNG_PARALLEL) - return _schranke - - -async def _frage(system: str, nachricht: str, temperatur: float) -> str: - async with _drossel(): - return await agents.frage(system, nachricht, temperatur) - - -async def _urteil(system: str, nachricht: str, temperatur: float): - """Eine Stimme als JSON. Unlesbares wird einmal neu gefragt, dann aufgegeben — - bei hunderten Anfragen je Lauf ist ein Ausrutscher normal, ein Abbruch nicht.""" - for versuch in range(3): - try: - return _json(await _frage(system, nachricht, temperatur + 0.1 * versuch)) - except ValueError: - continue - return None - - -# Achtung: diese Texte gehen unformatiert als System-Prompt raus. Doppelte Klammern -# wären hier keine Escapes, sondern landeten wörtlich in der Antwort. -SUCHE_SYSTEM = """Du suchst im Quelltext den Code zu einer beschriebenen Funktion. - -Antworte ausschließlich mit JSON: -{"gefunden": true, "datei": "...", "beleg": "..."} -oder -{"gefunden": false, "grund": "..."} - -- datei: der Pfad genau so, wie er über der Datei steht -- beleg: eine Zeile aus dieser Datei, Zeichen für Zeichen abgeschrieben -- grund: höchstens 8 Wörter, wenn es den Code nicht gibt - -Suche gründlich und im ganzen Quelltext. Es zählt nicht nur, was einen Knopf hat: -Hintergrundlogik, Parser, Dateiverwaltung, Prüfregeln und Anzeigeverhalten sind -genauso Code. Ein erfundener Beleg ist wertlos — er wird nachgeschlagen.""" - -SUCHE_NACHRICHT = """{quelle} - -Ende des Quelltextes. - -Eine Karte beschreibt diese Funktion: - -{funktion} - -Finde die Stelle im Quelltext, die das umsetzt. Antworte ausschließlich mit dem -JSON-Objekt.""" - -ABDECKUNG_SYSTEM = """Du entscheidest, ob eine Stelle im Programm schon von einer -beschriebenen Funktion abgedeckt ist. Antworte ausschließlich mit JSON.""" - -ABDECKUNG = """Diese Stelle im Programm lässt sich auslösen: - - {art} in {datei}, Zeile {zeile} - -``` -{umfeld} -``` -{rumpf} -Die Karten des Projekts beschreiben bisher das hier: - -{funktionen} - -Beschreibt eine dieser Funktionen, was an der Stelle oben passiert? -Wortwahl darf abweichen; entscheidend ist die Sache. Ziel, Regeln und Testschritte -einer Funktion gehören mit zu dem, was sie abdeckt, und die Regeln der Karte -ebenso: eine Zusicherung wie „alphabetisch sortiert" ist beschrieben, auch wenn -kein Knopf dazu gehört. - -Antworte ausschließlich mit JSON: -{{"abgedeckt": true, "funktion": "..."}} -oder -{{"abgedeckt": false, "karte": "...", "titel": "..."}} - -- funktion: der bestehende Funktionstitel, wörtlich, wenn abgedeckt -- karte: der Titel der Karte, in die die Fähigkeit thematisch gehört -- titel: wie die neue Funktion heißen soll — Objekt und Verb im Infinitiv, - höchstens 5 Wörter - -Rein technische Aufhänger gelten als abgedeckt: Speichern beim Verlassen eines -Feldes, Abbrechen mit Escape, Gesundheitsprüfungen, interne Weiterleitung. -Fehlerbehandlung ebenso — eine Fehlermeldung ist kein eigener Auftrag, sondern -gehört zu der Fähigkeit, bei der etwas schiefging. -Im Zweifel abgedeckt. Nur was einer Person wirklich fehlt, soll dazukommen.""" - -DUBLETTE_SYSTEM = """Du entscheidest, ob zwei Funktionsbeschreibungen dieselbe -Fähigkeit meinen. Antworte ausschließlich mit JSON.""" - -DUBLETTE = """Zwei Funktionen aus den Karten eines Projekts: - -A -{text_a} - -B -{text_b} - -Aufgefallen sind sie so: {anlass} - -Beantworte der Reihe nach, allein aus Titel und Testschritten: - -1. Woran arbeitet A? Der Gegenstand, an dem sich etwas ändert. -2. Woran arbeitet B? -3. Meinen 1 und 2 denselben Gegenstand? -4. Was ist anders, nachdem A ausgeführt wurde? -5. Was ist anders, nachdem B ausgeführt wurde? -6. Beschreiben 4 und 5 denselben Zustand? Es zählt das Ergebnis, nicht das Wort: - verschiedene Wörter für dasselbe Ergebnis sind gleich, ein Gegenstück nicht. - -Antworte ausschließlich mit JSON: -{{"gegenstand_a": "...", "gegenstand_b": "...", "gegenstand_gleich": true, - "ergebnis_a": "...", "ergebnis_b": "...", "ergebnis_gleich": true}} - -Urteile nicht selbst über die Dublette. Ob es eine ist, wird aus deinen Antworten -auf 3 und 6 errechnet.""" - -# Sechs unabhängige Versuche, den Beleg zu finden. Eine einzige Stimme, die etwas -# findet, genügt zum Freispruch — die Anklage lautet auf Löschen, da wiegt ein -# Fehlurteil schwerer als ein übersehener Rest. -SUCHE_TEMPERATUREN = (0.0, 0.2, 0.4, 0.6, 0.8, 1.0) -# So viele Stimmen müssen überhaupt geantwortet haben, bevor angeklagt wird -ANKLAGE_AB = 4 -# Sechs Stimmen, fünf müssen „fehlt" sagen. Eindeutige Stellen antworten 6:0 oder -# 0:6, Grenzfälle etwa 3:3 — die Schwelle bei fünf trennt beides. -URTEIL_TEMPERATUREN = (0.0, 0.2, 0.4, 0.6, 0.8, 1.0) -FEHLT_AB = 5 -# So viele Stimmen müssen geantwortet haben, bevor überhaupt geurteilt wird. Das -# Urteil wird gemerkt und gilt dann dauerhaft — dafür reichen zwei Überlebende nicht. -URTEIL_AB = 4 -# Ab dieser Ähnlichkeit gelten zwei Titel als dieselbe Sache -GLEICH = 0.75 -# Drei Stimmen über ein Paar, einstimmig für die Dublette. Ein Löschvorschlag darf -# nicht an einer Einzelmeinung hängen. -DUBLETTE_TEMPERATUREN = (0.0, 0.3, 0.6) -# Kandidatenkanal „ähnlicher Titel". Höher als GLEICH: hier zahlt jedes Paar drei -# Anfragen, und „Feature anlegen"/„Feature entfernen" liegen schon bei 0,75. -TITEL_KANAL = 0.85 -# Kandidatenkanal „ähnlicher Inhalt". Anteil der Wörter, die die kürzere der beiden -# Beschreibungen mit der längeren teilt. Überlappung statt Jaccard, weil eine knappe -# Dublette sonst an der Länge der ausführlicheren scheitert. -INHALT_KANAL = 0.7 -# Wörter, die in so vielen Funktionen vorkommen, tragen nichts zur Unterscheidung -# bei. „Vollmodus öffnen", „Text ändern" stehen fast überall — ohne diesen Filter -# ähnelt jede Bearbeiten-Funktion jeder anderen zu 90 %. -FLOSKEL_ANTEIL = 0.2 -# Deckel gegen Explosion bei vielen Funktionen; was darüber liegt, meldet der Lauf -DUBLETTEN_CAP = 40 - -# Ein gemerktes Urteil gehört zu der Frage, auf die es geantwortet hat. Wird die -# Frage umgeschrieben, ist das Urteil von gestern — deshalb hängt der Fingerabdruck -# am Wortlaut des Prompts. Sonst müsste man daran denken, eine Zahl hochzuzählen. -_SUCHE_STAND = ledger.abdruck(SUCHE_SYSTEM, SUCHE_NACHRICHT) -_ABDECKUNG_STAND = ledger.abdruck(ABDECKUNG_SYSTEM, ABDECKUNG) -_DUBLETTE_STAND = ledger.abdruck(DUBLETTE_SYSTEM, DUBLETTE) - - -def _normal(text: str) -> str: - return re.sub(r"[^a-zä-ü0-9 ]", "", (text or "").lower()).strip() - - -def _aehnlich(a: str, b: str) -> float: - return difflib.SequenceMatcher(None, _normal(a), _normal(b)).ratio() - - -def _json(antwort: str) -> dict: - import pruefung # zur Laufzeit, sonst Ringschluss - - return pruefung._json_lesen(antwort) - - -async def _sammle(aufgaben: list, was: str, melde=None) -> list: - """Alle Stellen beurteilen, auch wenn einzelne platzen. - - Vorher riss die erste kaputte Stelle den ganzen Lauf ab. Zwei Folgen, beide - schlecht: die schon bezahlten Urteile der anderen waren weg, und das Gedächtnis - wurde gespeichert, während die übrigen Anfragen noch liefen — es blieb leer. - - Jetzt wird gewartet, bis alle durch sind. Was ging, zählt; was nicht ging, steht - in der Meldung. Der nächste Lauf holt nur den Rest nach. - """ - ergebnisse = await asyncio.gather(*aufgaben, return_exceptions=True) - kaputt = [e for e in ergebnisse if isinstance(e, BaseException)] - if kaputt and melde: - melde(f"{len(kaputt)} von {len(ergebnisse)} {was} nicht beurteilt: " - f"{kaputt[0]}", len(kaputt)) - return [x for x in ergebnisse if x and not isinstance(x, BaseException)] - - -# ---------------------------------------------------------------- Feature im Code - -def _funktionstext(karte: str, f: dict) -> str: - """Alles, was die Funktion behauptet — danach wird im Code gesucht. - - Ohne Karte, wenn die anderswo schon dasteht: doppelt genannt zog sie beim - Dublettenurteil mehr Gewicht auf sich als Titel und Testschritte zusammen. - """ - zeilen = [f"Karte: {karte}"] if karte else [] - zeilen.append(f'Funktion: {f["text"]}') - if f["ziel"]: - zeilen.append(f'Ziel: {f["ziel"]}') - for feld in ("regeln", "testen"): - if f[feld]: - eintraege = [z.strip("- ").strip() for z in f[feld].splitlines() if z.strip()] - zeilen.append(f'{feld.capitalize()}: {"; ".join(eintraege)}') - return "\n".join(zeilen) - - -def _quellabdruck(quelle: dict) -> str: - return ledger.abdruck(_SUCHE_STAND, - *(f"{p}\n{t}" for p, t in sorted(quelle.items()))) - - -async def feature_im_code(features: list, quelle: dict, quelltext: str, stand: dict, - zaehl=None, melde=None) -> list: - """Funktionen, für die keine Stimme einen nachprüfbaren Beleg findet. - - Ein gemerkter Beleg zählt weiter, solange die zitierte Zeile noch dasteht — - dafür braucht es kein Modell, das prüft `quellcode.belegt()` nach. Eine gemerkte - Fehlanzeige gilt nur, solange sich am Quelltext nichts geändert hat: sie fordert - zum Löschen auf, und dafür muss der Befund frisch sein. - """ - quellstand = _quellabdruck(quelle) - auftraege = [(f, x) for f in features for x in f["sektionen"]["funktionen"]] - bekannt = {ledger.schluessel(f["id"], x["text"]) for f, x in auftraege} - stand["belege"] = ledger.behalte(stand["belege"], bekannt) - stand["ohne_code"] = ledger.behalte(stand["ohne_code"], bekannt) - - async def eine(paar): - feature, x = paar - schluessel = ledger.schluessel(feature["id"], x["text"]) - text = _funktionstext(feature["sektionen"]["titel"], x) - wie_gehabt = ledger.abdruck(text) - - gemerkt = stand["belege"].get(schluessel) - if gemerkt and gemerkt["abdruck"] == wie_gehabt and quellcode.belegt( - quelle, gemerkt["datei"], gemerkt["beleg"]): - if zaehl: - zaehl() - return None - gemerkt = stand["ohne_code"].get(schluessel) - if gemerkt and gemerkt["abdruck"] == wie_gehabt \ - and gemerkt["quelle"] == quellstand: - if zaehl: - zaehl() - return {"feature": feature["id"], "titel": x["text"], - "art": "ohne_code", "grund": gemerkt["grund"]} - - nachricht = SUCHE_NACHRICHT.format(quelle=quelltext, funktion=text) - proben = await asyncio.gather(*( - _urteil(SUCHE_SYSTEM, nachricht, t) for t in SUCHE_TEMPERATUREN - ), return_exceptions=True) - - if zaehl: - zaehl() - gruende = [] - brauchbar = behauptet = 0 - beleg = None - for u in proben: - if not isinstance(u, dict): - continue - brauchbar += 1 - if u.get("gefunden"): - # Auch ein misslungenes Zitat ist ein Widerspruch. Ein Modell - # verschreibt sich beim Abschreiben von Backticks — daraus eine - # Löschempfehlung zu machen, wäre grob falsch. - behauptet += 1 - datei = str(u.get("datei") or "").strip() - zitat = str(u.get("beleg") or "").strip() - if beleg is None and quellcode.belegt(quelle, datei, zitat): - beleg = {"abdruck": wie_gehabt, "datei": datei, "beleg": zitat} - elif u.get("grund"): - gruende.append(str(u["grund"]).strip()) - - stand["belege"].pop(schluessel, None) - stand["ohne_code"].pop(schluessel, None) - if beleg: - stand["belege"][schluessel] = beleg - return None # geprüfter Beleg: die Funktion steht im Code - if behauptet: - return None # widersprüchliche Stimmen: nichts behaupten und nichts merken - if brauchbar < ANKLAGE_AB: - # Zu wenige Stimmen für eine Löschempfehlung. Lieber laut scheitern - # als eine gültige Funktion wegen eines Ausfalls anzuklagen. - raise RuntimeError( - f'{x["text"]}: nur {brauchbar} von ' - f"{len(SUCHE_TEMPERATUREN)} Stimmen brauchbar") - grund = gruende[0] if gruende else "Kein Beleg im Code gefunden" - stand["ohne_code"][schluessel] = {"abdruck": wie_gehabt, "quelle": quellstand, - "grund": grund} - return {"feature": feature["id"], "titel": x["text"], - "art": "ohne_code", "grund": grund} - - return await _sammle([eine(a) for a in auftraege], "Funktionen", melde) - - -# ---------------------------------------------------------------- Dubletten - -def _funktionen(features: list) -> dict: - """schluessel -> alles, was zur Funktion gehört.""" - raus = {} - for f in features: - for x in f["sektionen"]["funktionen"]: - raus[ledger.schluessel(f["id"], x["text"])] = { - "feature": f["id"], "karte": f["sektionen"]["titel"], - "titel": x["text"], "eintrag": x, - "text": _funktionstext("", x), - # Ohne die Feldnamen: „Regeln:" steht über jedem Block, und eine - # Funktion namens „Regeln anpassen" verlöre sonst ihr eigenes Wort - "worte": " ".join((f["sektionen"]["titel"], x["text"], x["ziel"], - x["regeln"], x["testen"]))} - return raus - - -def _gewicht(f: dict) -> tuple: - """Wer mehr sagt, bleibt stehen. Bei Gleichstand entscheidet der Name — nicht - schön, aber vorhersagbar; ein Zufallssieger machte den Vorschlag unstet.""" - x = f["eintrag"] - zeilen = len([z for z in (x["regeln"] + "\n" + x["testen"]).splitlines() if z.strip()]) - return (zeilen, len(x["ziel"]), f["titel"]) - - -_WORT = re.compile(r"[a-zä-üß0-9]{4,}") -# Beugung abschneiden statt richtig stemmen: „entfernen" und „entfernt" sind -# dasselbe Wort, und ein Stemmer legte die Sprache im Code fest. -STAMM = 5 - - -def _kerne(alle: dict) -> dict: - """Je Funktion die Wörter, die sie von den anderen unterscheiden. - - Was in jeder fünften Funktion steht, fliegt raus. Sonst misst der Vergleich nur - noch die gemeinsame Schrittfolge, und „Titel anpassen" und „Ziel anpassen" - stimmen zu hundert Prozent überein. - """ - mengen = {k: set(_WORT.findall(v["worte"].lower())) for k, v in alle.items()} - haeufig = Counter(wort for m in mengen.values() for wort in m) - grenze = max(3, int(len(mengen) * FLOSKEL_ANTEIL)) - return {k: {w[:STAMM] for w in m if haeufig[w] < grenze} for k, m in mengen.items()} - - -def _ueberlappung(a: set, b: set) -> float: - return len(a & b) / min(len(a), len(b)) if a and b else 0.0 - - -def _kandidaten(alle: dict, belege: dict) -> list[tuple]: - """Paare, die überhaupt eine Dublette sein könnten, mit dem Anlass. - - Drei Kanäle, weil eine Dublette auf drei Arten auffällt: dieselbe Codezeile als - Beleg, fast derselbe Titel, fast dieselben Wörter. Der letzte fängt, was die - ersten beiden durchlassen — „Funktion löschen" und „Funktion entfernen" haben - weder denselben Titel noch zwingend denselben Beleg. - - Jedes Paar zu fragen wäre quadratisch und träfe fast nie. Erst billig - eingrenzen, dann einmal teuer urteilen. - """ - paare = {} - - def merke(a, b, anlass): - if a != b: - paare.setdefault(ledger.paarschluessel(a, b), (a, b, anlass)) - - nach_stelle = {} - for name, eintrag in belege.items(): - if name in alle: - stelle = (eintrag["datei"], re.sub(r"\s+", " ", eintrag["beleg"]).strip()) - nach_stelle.setdefault(stelle, []).append(name) - for (datei, zeile), gruppe in nach_stelle.items(): - gruppe = sorted(gruppe) - for i, a in enumerate(gruppe): - for b in gruppe[i + 1:]: - merke(a, b, f"Beide belegen dieselbe Zeile in {datei}: {zeile}") - - kern = _kerne(alle) - namen = sorted(alle) - for i, a in enumerate(namen): - for b in namen[i + 1:]: - if _aehnlich(alle[a]["titel"], alle[b]["titel"]) >= TITEL_KANAL: - merke(a, b, "Die Titel sind fast gleich.") - elif _ueberlappung(kern[a], kern[b]) >= INHALT_KANAL: - merke(a, b, "Beide Beschreibungen bestehen fast aus denselben Wörtern.") - return [(k, *paare[k]) for k in sorted(paare)] - - -async def _ist_dublette(a: dict, b: dict, anlass: str) -> bool: - """Einstimmig gleicher Gegenstand und gleiches Ergebnis — sonst keine Dublette. - - Das Gesamturteil rechnet der Code aus den Teilantworten. Gefragt nach der - Dublette an sich, widersprach eine Stimme ihrer eigenen Analyse: derselbe - Gegenstand, dasselbe Tun, und trotzdem „nein". Zwei kleine Fragen beantwortet - sie verlässlich, die große nicht. - - Gefragt wird nach dem Ergebnis, nicht nach dem Verb. „Löschen" und „entfernen" - hielten zwei von drei Stimmen für verschiedenes Tun — was danach anders ist, - beschrieben sie gleich. - """ - nachricht = DUBLETTE.format(text_a=a["text"], text_b=b["text"], anlass=anlass) - proben = await asyncio.gather(*( - _urteil(DUBLETTE_SYSTEM, nachricht, t) for t in DUBLETTE_TEMPERATUREN - ), return_exceptions=True) - stimmen = [p for p in proben if isinstance(p, dict)] - if len(stimmen) < len(DUBLETTE_TEMPERATUREN): - raise RuntimeError(f'Dublette {a["titel"]}/{b["titel"]}: ' - f"nur {len(stimmen)} von " - f"{len(DUBLETTE_TEMPERATUREN)} Stimmen brauchbar") - return all(u.get("gegenstand_gleich") is True and u.get("ergebnis_gleich") is True - for u in stimmen) - - -async def dubletten(features: list, stand: dict, melde=None) -> list: - """Funktionen, die eine andere Funktion doppelt beschreiben. - - Gemeldet wird immer die schwächere von beiden — die stärkere bleibt stehen. - Ein einmal gefälltes Urteil bleibt gemerkt, auch das ablehnende: sonst zahlt - jeder Lauf erneut für dieselbe Frage und antwortet womöglich anders. - """ - alle = _funktionen(features) - paare = _kandidaten(alle, stand["belege"]) - stand["paare"] = ledger.behalte(stand["paare"], {p[0] for p in paare}) - if len(paare) > DUBLETTEN_CAP: - if melde: - melde(f"{len(paare)} Kandidatenpaare, geprüft wurden {DUBLETTEN_CAP}") - paare = paare[:DUBLETTEN_CAP] - - async def urteile(paar): - schluessel, a, b, anlass = paar - links, rechts = alle[a], alle[b] - wie_gehabt = ledger.abdruck(_DUBLETTE_STAND, links["text"], rechts["text"]) - gemerkt = stand["paare"].get(schluessel) - if gemerkt and gemerkt["abdruck"] == wie_gehabt: - gleich = gemerkt["gleich"] - else: - gleich = await _ist_dublette(links, rechts, anlass) - stand["paare"][schluessel] = {"abdruck": wie_gehabt, "gleich": gleich} - if not gleich: - return None - schwach, stark = sorted((links, rechts), key=_gewicht) - return {"feature": schwach["feature"], "titel": schwach["titel"], - "art": "dublette", - "grund": f'Beschreibt „{stark["titel"]}“ ' - f'(Karte {stark["karte"]}) ein zweites Mal'} - - return await _sammle([urteile(p) for p in paare], "Funktionspaare", melde) - - -def _wegfall_grund(betroffen: list) -> str: - """Was die Karte verliert, in einem Halbsatz. Ohne Trennung nach Anlass stand - über einer Dublette „ohne eigenen Code" — beides heißt streichen, aber aus - verschiedenen Gründen, und der Grund entscheidet, ob man zustimmt.""" - teile = [] - for art, eins, viele in (("dublette", "Funktion doppelt", "Funktionen doppelt"), - ("ohne_code", "Funktion ohne eigenen Code", - "Funktionen ohne eigenen Code")): - n = sum(x["art"] == art for x in betroffen) - if n: - teile.append(f"{n} {eins if n == 1 else viele}") - return ", ".join(teile) - - -def probleme_feature(features: list, ohne_code: list) -> list: - """Ein Vorschlag je Karte: die betroffenen Funktionen aus der Liste nehmen.""" - import pruefung - - raus = [] - for f in features: - ist = [x["text"] for x in f["sektionen"]["funktionen"]] - betroffen, gesehen = [], set() - for x in ohne_code: - if x["feature"] == f["id"] and x["titel"] not in gesehen: - gesehen.add(x["titel"]) - betroffen.append(x) - if not betroffen: - continue - weg = [x["titel"] for x in betroffen] - neu = [t for t in ist if t not in weg] - grund = _wegfall_grund(betroffen) - beleg = " · ".join(f'{x["titel"]}: {x["grund"]}' for x in betroffen) - for p in pruefung._stellen("funktionen", "\n".join(ist), "\n".join(neu), - grund, beleg): - p["feature"] = f["id"] - p["funktion"] = "" - raus.append(p) - return raus - - -# ---------------------------------------------------------------- Code im Feature - -def _funktionsliste(features: list) -> str: - """Die Karten mit allem, was sie sagen. - - Nur die Titel reichten nicht: der Richter musste raten, ob eine Funktion eine - Stelle abdeckt, und urteilte von Runde zu Runde anders. - - Die Regeln der Karte gehören dazu. Vieles, was ein Kunde bestellt, ist keine - Bedienung, sondern eine Zusicherung — „eine Datei je Feature", „alphabetisch - sortiert". Ohne sie sah der Richter den Code dahinter als unbeschrieben an. - """ - teile = [] - for f in features: - s = f["sektionen"] - block = [f'## Karte: {s["titel"]}'] - if s["ziel"]: - block.append(f'Ziel: {s["ziel"]}') - if s["regeln"]: - zeilen = ", ".join(z.strip("- ").strip() - for z in s["regeln"].splitlines() if z.strip()) - block.append(f"Regeln der Karte: {zeilen}") - for x in s["funktionen"]: - block.append(f'\n### {x["text"]} (Karte: {s["titel"]})') - if x["ziel"]: - block.append(f'Ziel: {x["ziel"]}') - for feld in ("regeln", "testen"): - if x[feld]: - zeilen = ", ".join(z.strip("- ").strip() - for z in x[feld].splitlines() if z.strip()) - block.append(f'{feld.capitalize()}: {zeilen}') - teile.append("\n".join(block)) - return "\n\n".join(teile) or "—" - - -async def _abdeckung(punkt: dict, liste: str) -> list: - rumpf = f'\nDahinter steht:\n\n```\n{punkt["rumpf"]}\n```\n' if punkt["rumpf"] else "" - nachricht = ABDECKUNG.format(funktionen=liste, art=punkt["art"], - datei=punkt["datei"], zeile=punkt["zeile"], - umfeld=punkt["umfeld"], rumpf=rumpf) - proben = await asyncio.gather(*( - _urteil(ABDECKUNG_SYSTEM, nachricht, t) for t in URTEIL_TEMPERATUREN - ), return_exceptions=True) - return [p for p in proben if isinstance(p, dict)] - - -def _naechste_karte(name: str, karten: dict, schwelle: float = 0.6): - if not name or not karten: - return None - treffer = max(karten, key=lambda k: _aehnlich(name, k)) - return karten[treffer] if _aehnlich(name, treffer) >= schwelle else None - - -def _zielkarte(urteile: list, karten: dict): - """Auf welche Karte gehört die fehlende Funktion? - - Die Stimmen schlagen oft Karten vor, die es nicht gibt („Export", - „Datenverwaltung"). Vorher fiel der Befund dann weg — eine Stelle, die - einstimmig fehlte, wurde verschwiegen, weil man sich über die Ablage nicht - einig war. Jetzt gewinnt der erste Vorschlag, der sich auflösen lässt, und - zur Not der ähnlichste. Falsch abgelegt kann man verschieben; verschwiegen nicht. - """ - namen = Counter(str(u.get("karte") or "").strip() for u in urteile - if u.get("abgedeckt") is False and u.get("karte")) - for name, _ in namen.most_common(): - if treffer := karten.get(name) or _naechste_karte(name, karten): - return treffer - haeufigste = namen.most_common(1) - return _naechste_karte(haeufigste[0][0], karten, schwelle=0.0) if haeufigste else None - - -def _stellenabdruck(punkt: dict) -> str: - return ledger.abdruck(_ABDECKUNG_STAND, punkt["beleg"], punkt["umfeld"], - punkt["rumpf"]) - - -async def code_im_feature(features: list, punkte: list, stand: dict, - zaehl=None, melde=None) -> list: - """Bedienstellen, die von keiner Funktion abgedeckt sind. - - Ein gemerktes Urteil gilt, solange es tragen kann: „abgedeckt durch X", solange - X noch auf einer Karte steht; „fehlt als Y", solange es kein Y gibt. Beides - fällt weg, sobald sich die Codestelle selbst ändert. - """ - liste = _funktionsliste(features) - karten = {f["sektionen"]["titel"]: f for f in features} - kennungen = {f["id"] for f in features} - titel_da = [x["text"] for f in features for x in f["sektionen"]["funktionen"]] - normal_da = {_normal(t) for t in titel_da} - stand["abdeckung"] = ledger.behalte(stand["abdeckung"], - {p["schluessel"] for p in punkte}) - stand["ohne_karte"] = ledger.behalte(stand["ohne_karte"], - {p["schluessel"] for p in punkte}) - - async def eine(punkt): - schluessel = punkt["schluessel"] - wie_gehabt = _stellenabdruck(punkt) - - gemerkt = stand["abdeckung"].get(schluessel) - if gemerkt and gemerkt["abdruck"] == wie_gehabt \ - and (not gemerkt["funktion"] or _normal(gemerkt["funktion"]) in normal_da): - if zaehl: - zaehl() - return None - gemerkt = stand["ohne_karte"].get(schluessel) - if gemerkt and gemerkt["abdruck"] == wie_gehabt \ - and gemerkt["feature"] in kennungen \ - and not any(_aehnlich(gemerkt["titel"], t) > GLEICH for t in titel_da): - if zaehl: - zaehl() - return {"feature": gemerkt["feature"], "titel": gemerkt["titel"], - "beleg": gemerkt["beleg"]} - - urteile = await _abdeckung(punkt, liste) - if zaehl: - zaehl() - nein = sum(u.get("abgedeckt") is False for u in urteile) - ausgefallen = len(URTEIL_TEMPERATUREN) - len(urteile) - if len(urteile) < URTEIL_AB or nein < FEHLT_AB <= nein + ausgefallen: - # Zu dünn oder offen. Dünn: zwei überlebende Stimmen genügen rechnerisch - # für „abgedeckt", weil die Schwelle unerreichbar wird — als Dauerurteil - # wäre das zu wenig. Offen: die ausgefallenen Stimmen hätten es kippen - # können. Beides nicht verschweigen; sonst sähe der Ausfall aus wie „ist - # abgedeckt" und der Lauf meldete stillschweigend zu wenig. - raise RuntimeError( - f'{punkt["schluessel"]}: nur {len(urteile)} von ' - f"{len(URTEIL_TEMPERATUREN)} Stimmen brauchbar") - stand["abdeckung"].pop(schluessel, None) - stand["ohne_karte"].pop(schluessel, None) - - # Steht das Ergebnis schon fest, zählen die fehlenden Stimmen nicht mehr. - # Vier Stimmen „abgedeckt" bei sechs möglichen können die Schwelle nicht - # mehr reißen — daraus einen Fehlschlag zu machen, wäre Verschwendung. - if nein < FEHLT_AB: - # Abgedeckt — oder unentschieden, was dasselbe Ergebnis hat. Gemerkt - # wird beides; der Name nur, wenn die Stimmen sich auf einen einigen. - namen = Counter(str(u.get("funktion") or "").strip() - for u in urteile if u.get("abgedeckt")) - name, treffer = namen.most_common(1)[0] if namen else ("", 0) - # Nur ein Name, den es wirklich gibt, taugt als Verfallsdatum. Deckt - # eine Regel die Stelle ab, nennt die Stimme deren Wortlaut — der - # stünde auf ewig ungültig in der Datei und würde jeden Lauf neu gefragt. - gilt = treffer >= len(urteile) / 2 and _normal(name) in normal_da - stand["abdeckung"][schluessel] = {"abdruck": wie_gehabt, - "funktion": name if gilt else ""} - return None - - treffer = _zielkarte(urteile, karten) - titel = [str(u.get("titel") or "").strip() for u in urteile if u.get("titel")] - if not treffer or not titel: - return None - gefunden = {"feature": treffer["id"], - "titel": max(titel, key=lambda t: sum(_aehnlich(t, x) for x in titel)), - "beleg": f'{punkt["datei"]}:{punkt["zeile"]}'} - stand["ohne_karte"][schluessel] = {"abdruck": wie_gehabt, **gefunden} - return gefunden - - gefunden = await _sammle([eine(p) for p in punkte], "Codestellen", melde) - # Zwei Stellen können auf dieselbe fehlende Funktion zeigen - raus = [] - for x in gefunden: - gleich = next((y for y in raus if y["feature"] == x["feature"] - and _aehnlich(y["titel"], x["titel"]) > GLEICH), None) - if gleich: - gleich["beleg"] += f', {x["beleg"]}' - else: - raus.append(dict(x)) - return raus - - -def probleme_code(features: list, fehlend: list) -> list: - """Ein Vorschlag je Karte: die fehlenden Funktionen anhängen.""" - import pruefung - - raus = [] - for f in features: - ist = [x["text"] for x in f["sektionen"]["funktionen"]] - dazu = [x for x in fehlend if x["feature"] == f["id"]] - if not dazu: - continue - # Bestehende Reihenfolge behalten, Neues hinten anhängen — sortieren würde - # aus einer Ergänzung einen Umbau machen. Angezeigt wird ohnehin alphabetisch. - neu = list(dict.fromkeys(ist + [x["titel"] for x in dazu])) - grund = (f"{len(dazu)} Stelle ohne Funktion" if len(dazu) == 1 - else f"{len(dazu)} Stellen ohne Funktion") - beleg = " · ".join(x["beleg"] for x in dazu) - for p in pruefung._stellen("funktionen", "\n".join(ist), "\n".join(neu), - grund, beleg): - p["feature"] = f["id"] - p["funktion"] = "" - raus.append(p) - return raus - - -# ---------------------------------------------------------------- Einstiege - -async def pruefe_feature_im_code(projekt: str, features: list, quelle: dict, - quelltext: str, zaehl=None, melde=None) -> list: - stand = ledger.lade(projekt) - try: - ohne = await feature_im_code(features, quelle, quelltext, stand, zaehl, melde) - doppelt = await dubletten(features, stand, melde) - finally: - # Auch ein abgebrochener Lauf hat schon Urteile gefällt; die sind bezahlt - ledger.sichere(projekt, stand) - return probleme_feature(features, ohne + doppelt) - - -async def pruefe_code_im_feature(projekt: str, features: list, quelle: dict, - zaehl=None, melde=None) -> list: - punkte = quellcode.interaktionen(quelle) - if not punkte: - raise RuntimeError("Keine Bedienstellen im Quelltext gefunden") - stand = ledger.lade(projekt) - try: - fehlend = await code_im_feature(features, punkte, stand, zaehl, melde) - finally: - ledger.sichere(projekt, stand) - return probleme_code(features, fehlend) diff --git a/backend/k1-1024.png b/backend/k1-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..02545c31d9a5592cc2e9124961e872bc4c0137a3 GIT binary patch literal 31742 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 literal 0 HcmV?d00001 diff --git a/backend/k1-1280.png b/backend/k1-1280.png new file mode 100644 index 0000000000000000000000000000000000000000..a07ba4dec582726def0f85fcaf4d892ae6fff43a GIT binary patch literal 32992 zcmce;cTkhx_dggc@K%}yLAr>FfPnN4Dgx4_mrz7X=)H%gh$vO1gcgt*TIdjZ5do$5 zKSb&F;s3`A9LW|&4nM0lS5#)J>hJ;n#N~yT zS61rrlsGvbN8JFl@x{rnw>^gP3!9i2OHHa}g5l5dwAukHu*%Awx7z;sGf$znu;se{ z003^hoPet_@p9WHyd}W7LOOu8I?n}4MLch5%)$oN8{<3q;{zF>E_|5czTNBk3Z0_! zAHif}j{Y!cczF2STMhteuqXhP$gg(=PA{PpZ6~>-ALop?|LuM zE@=CE#=u&v-e+O1!KWrQBJ;L+)DBVJu<)LGjbiD(a$~Du>~Y>aeR^p#GTZF;@om|0 z#EbHhf}+Zb+B<-uP%o2$0&5u=0KmnPetcYm01PH9q}uP~J2>V8t9@u$_J%lL4)~^v z&!gJMIafa1zTJ$iEi~))^B8P!ZBgqb9>wV>I>Jt+C|*bZv%TQv;`q>dWZFsw`G1{SCqjhU&!ewo1p7y3ZjQB=S%lz~olhy&Wb+Bu1M4a4qAwa9 zHx3!tJ&~fdx8291m9h$=Kwa_EN$283->oDXc=`-D_Wtlm(ehTxM^{KUtagKLiMZZk zwG>N_Rbb!sbm8dhHY%4sL5j6=IQQS;rf!A7O>rk{O_B6PjdUR5v%+$pO~$>Yi9>P5~z}h5(l1vXG_;;&~(X34=x~rsY&C*-}41l^0 zNWxmTS6X_dqz`#O?LGPiI~$R`a4}yR`HJ6v}GitqZhp=hSeQT0aeUj3if*AE^?PB#GG5p6ZbM zKp(bSBfZ9+M~tIyb$&YEy*09g2x_F%l=M3WLroc4L7y16+CVpT5EtpgT~im|V|~9k zzJIEDx*@;UTFbhJQ~Mw)0Nop_I6Pjp7_{Iw|0));NZ1i(o3Gs;J!a7tZ#7V~zs`5A zisyp!>foUwPs*W^t;UzD)Q!2J0WdSddt4!i&p;98?K6ou$Jl|l457dPYQOh=%`il_ zCh+@_8~n{;2RY+# zC1uRaywShh7jmFl?9cQH&Ygab3n#H^OviKdVEFs29nW!Si;_k_Xo!%kOPsQohjPclV!(>stK zFEJjDZ@C{p%`DDYnBC&k-%?9EkTzP8x3{sGUg>krb~AeD{0H5|aHV|rYxy_YCI&uYYM;S(6F^PvxG~eaCfdL ziJNFwJI^*~O$0UvIN}OD(@LLCvb72|k7a>=C!1^hc^BiFtD6CDS@sRiv?<;opd;ER1SLIjgbF+old3Qic33OMI^H(wiHBb+gl-7eVBq%sC=8A*MVkNw(O@ z6z=mT<;D5l9R5W;IyU|v!IRbHj;K)e7?)h`XjoJ))^2+9tf8a`X!o-))0sIOhmZd} zFkonLU0(vvB;tk_pTALdO5|H-={J>V7TuB^aR^yycyGc|5TU zf;O);=)89C3ld*e1olT4reP_WZtaD-QbZINe_&R-sfBR!a?v*M>+`eN2+eTT&+ZTX zHtQ%9rHH7FO_>q02u|o^|(aZ-MAF_+^zbn6t$n9HZr#MC=UU!T%vA&m%(>;%gZS<`^iVElw$Uc61)^p5wLF0!@dAGhKt9EhFVc$xz zu6WUZyO!>zG;fKNC)KxntM@kF zK~hr_iE1h!U2!ujZKYJb-Wpe=l8vYP0a~r{=tj`)Z4TRKsul?T{)?2hEitC}SED%d zJ?9S-lh|Ko_toOo{(-$67xnsBv$gx;Q%u5QIK&pby#-3AklX+H5M$S#5*yOURUXq| zH6|QC4L|ehmuftXJ-7RZ6|Y)wFfaFtxu!Axjaq+Uvc$uO)>DxxcbCJn_5U2ZlWkV^ zdABl7Q#B-g_^EXftXEtB_lDeKm3GlXoTdSVlbG(|s9U_WB?@`PLQXZhrj&U#6Tetq zI#~ezzfMRpgX+B)zjx~`HPT3@qae%&ADvgsOe@I^lIKw4?#6%`A-3M0vz%9TJ~S1_Ns^Z}17tM&IizaS4_;P|doZt5rWadxeR5eC&Xz}0}gL#5; zOnww|y-^%%w|Mb-+L6WLZ>iZ(So?IV%5zkWSGgE5_-t%P5)@2}T?nTBU_Q*V`~5b` zW(!wH0S)Oh9Bdy$`UVG{*&gN4Ha+LfUCFIbEKZ87%mE?;6Kv$qQU>@s=RwajFYH!d zhGqXsu92t-pRW?Az8ex16Sm9>3YNB^1GQ$om55N%x&aS4?i(Jzn0n-*(ly@#Ygy}WBwH>o`<`=F^(O|-G?L2OWJArM&i)r_F z^2;MptuQ+K0bq0KX=x3((R>|b*g5-wliX>5;IrPqPVN)CTW?y@e5h0!cwCfmn>NGv z;OL{3Y>v`#DnB1kr+j(ZRV)*IILR3tYg-^Q?fp-rpWvI+r@Vip>iXLWdMbst;J<6^ z7Pr~Q3T@H`kb!zuUN87S)?`XM%o{?xVhA|6Ob*&Z~;QZ~|WO6jNQ(neO zBVAYU?O9kP9W8bDk9iASI+@_tg9nZN%#ou8{A%Me`*wI~Y6psgM?*_LgpiE_;=9Pd z&AbfVs}eXYGN(Dd8TypBhr4=5uzY&{nE&I==We`zrOn@${>R&K@dAjkoCbF}&J&+# z6iR6XqKChU^}q9bJR=khqj52*e1cI2wq~851))$-qO7ziy1T!-ENC}k~mmhaS(#zf@;ghFpC=?O?}8c--zGc3Hd5L?MJk-Gx`Q9M&XsFT*2b5r}Hfx zt&r*3y=`1vmAA_X)naT z#)NfWRXAn47duNh+Rk6=kSdMLwpphD^`XIs?+9zIR`NX~HC{U`Bd))j_An-MyB2wk zs5u*``^p>bsb)iM1Yhq|d0;0_UepXsOX-eau<0_W=?KtIaKyVJY0lPqj8FG8?BhrhdH%%|h(b2sqY>P-=^Kv*!Br;tvqi+R0U8fY^4j~s;cYOi1AuJsAjIVgQw zAn-Q|Wxj0ZTkBO^ZZH{Hxu2?L$H2zTgJe71apb0^Zz--W$@YOuvreOsm?6}FNzo06 zK{COWk~9(^h68XF*;bkej?2Qz$>M@*mWmU%fEvUQjDX2+Bg>M4Rx7>|=3dyugimcu zD+3%pO_OqFEf0(0*K!WnF#+E7xg=qJ6&;}T`>dJs^t_FkfkP20Rkb2JTW+68ttKQ1 zsmZeqH8F-TtR*m|HJAaFW162zolR$Im|upYZF#ptKeR6IUbI}wTTSp>qyKrW)dY4H zg`y0H=3~rOTQTyc)*{p=O|Bh=z_{_wMT3l&v)GaRz#2;nOM7GcVOL4Xa0qS3O^uxp zKNI$;TL{Z}SFYY3O?tMuM(?dbMZ?<>y&e++83$`U&H3J{v>`R`CO(eKXC}mMugoR7 z4g|OcX{KBfVV*&Uo60TYhN6Brq6-hz9kkM9gnf`$+jC`{tk0O zxX!ltuS(~OesWI3UTpJ}Dk&QKr+7PCi!t%?^lXmQX{Q$5BF!ZL!}! z0RJVaHUKFeu)9KiIn)0~!Tk%)XMB7`MRl+4haTt|7#N!vU53-W4@u#4d2O|bp59G> z-3uu`BjD}O%K)0h52eYcC0Y>1>j04lPQ6GMK9I@{VfE$oNk3XhN8^lF}=x^e2sgvom32 zZdGqW_NneAf_kXO$MZ)&l3oZ=S^Q6%{`k0()%Cv&$h1S|Cqdm0XP@!%(cRoilURv9 zv_#Cj%{o=H;9%7dZ9NHPQGq>hg`@aF6)U5$ZW=}Rlv23iTGDL4nE84A^i__!1kT;ZGv=pN^57a9%$6&9Gi0k)$O(T1lzv8;qr9rB;?|lEYuXE5=&9_{r&|pjjo00ZrS@A_Pg?@>MvO|` zcUIYMtqye+=T#y0HET%Yx)E9=oEmtkg%%-j3HkodZ%Dsy|ZuDUrnuXjNHXt@-KUSr$$Y6 zEt*Ym9y~-xN$GF};3ljxFF%KwGHmev$N!;KN8{<8wX|G;{= z<#8bF2B2T_TU`GKo6Q?L5F;ZaFMRo(wGN7apY9>{p12TM-PHU0`v#fqgYm&+KTp05 z{DpqjWIY?9w-1;%6xPiAbI%a%<$qLlA$vX#Vz~zRSx?wCj@Wn%>!n^}N&PT*_=2;j zxY(yt&fNal4sK`*KJCo_2whXgOyq3s8uC)xG|KzyNV!{#Hw*?@JDiZbo&M<&m7;Yy zp1W&SrB8-F&+f>v646scVVo>i)47Ly48TR7D>gS>s{y{&{(+sk0r>Iqhlm)ducQlF9HZPEX|;1hyckX{-X* zVF1}ogXRi0k%*CakeW0I7)nL-XDCh542NMHWC|;K+{#lvB%l-kdF!A8} zLdn^hE{V~~Hn5wyA#mp%IuiN%4OX9S4oqu!y)uNm|GXgrm|@BluJxLuxBWH6e!0>f zP+og?*@iy5MN)R8Pvy`Uz{%d8BQ)*9|19}oQirqi*?V^KM|ZxOb$ITP7a=W1}{+;|93Q7 zk8wq__x~!N^Nl*#{KbM<4XPT zUa+eH0d8np@Qp^{&z*bk+R{~hUO(!3Vlbt6wtS@TvRNg}8^=d*nTrZB@N&!iv68`- znsBBzyVTQ2tO0Gj)#61@*IBt2S~R(D?+Pd_zS}|_WN79{)5MIWf1MUt9$r2Iy&2#5 zhLm^MdMoUFwj9U0bJoPCl4jVbYO&tNB^CZj>ggu!YB%e_D^JZgy7*eKP`&FQ*a38* z@A)Ya!w{|kUYhwu@*#$7_}Cct*0LHJ#c=%CjNtZ;?l{&Fvm82r+hd)hnv_Rc=;zO# zsqQymB%_?^p8B8r$+{wi=EF$CNkhy_vd-@ z>5B7%V3F>G;Kz?w{nO&GlV=bwSf?y}V9o5V;&g`Zgp$Fs>lE*+cmqEEzG92Vg6mP1 z^L)gO+`XkR0%pUvxEgc~(AGzlcM^dsy;vBxvGbRSHhlAKw^x+Cn9b3&Bz~`fT$1X}EO@s$l%&o2uyU8ZCa5_Aqbw>$M2Jmd@r z-+@_bDNS5k*pHun0?Q@7=XpR8I0mlMJCZG(J?M%RSn3VQXyDB1{kdx{#=v4Qw{(vF zetukC9|%eRW+@~d1~e>JNppHXM)J_KhO(0sp;_)d-P`93PkoIgX&&C zzq4wD^*KUd&olpBH-ZEv`c*IBTvTB0i}z7U#A!E$Q20w2G80-ndx8FCv-h{q{yKT0C*-9Stm)3`PQlpvW4<7JC8zxA z7cT=}BmFqGDfqs`QTy`$ohj!Lv()YR5dBf7S;KK>?p#?}D|#DVdk^5kOY&hLyogOI zfj(X>7n>@AKTu0MrS9x-TY;W7)_#u=l$d{F;~gbAT@o}`YnGA~yat6oyLu%tUV%2|hPeLsB~p8T&49+4tCH2f3{0x_5_tkdi6YYp?xe_ z=w1QzP>)*3QtS`+VI>?boU3msi)!{lXG+Cxr64Or(4h-)0~u0Js=SntB| z0U?pMdv4|LJ$`y`5#mBd)a7}#v=bAIa6Pq=pFuGexD5oW>!yBqTEIK%^Z}LN)|UkR zNhm&XHl<^JfQT1w6+sexuf1#QD;W!d<`n=dT6h2Ksk#@ftjp@K)i_D3d;TqJcLIj@ zIU!9_C4vJx%0Iyx16%!lr}7XM{%dvZhf~8716ej5W&2Kgd>VY2yqZwC(FXv-1mLW2 zL;OYa$a?kiJRc#)Qj9!w>z7fvXz-%10i^1O38m$FHsJyObHRPbA3<%me z?QS{i*KQ7i>`~6$$MEGD2l*^j>PO@*xx^t`QSKYNb1T=w%yPry4V?S5$zQi#82Cw# z_6&5)69Sx9F0;y+gqcs{=b}Xg{ zQ(qIwL7lvo6YCB7)s<`qT8#`u8@$oC!cwq{?HKC?qwDBj6PEr`8SRVNY^dIc!ZSBd z#R|J0kv+xFzLQb}E~|*vi98F9g-^7Q0b`kg;>Crct|s=RF7Z)aS+e`j5%d|Q(1tf3 z4y*~-O5xUfY;w4Ial|r33P2qEZ0+ z`j<1aJ{x*9hbITWi_WEK40-JIDHf!J&RW)UMCFlr7QhRbZAj(ec%dwYnP0aKbD-su zNr#9TDSd*sLzbdfW>OzUb8xy(ok>y}<|Rzb^!E3)dMO$f;%?yZ1@`x`8*Cd^ zgf_<^$3nnWL|RYL6FL*`d+fx_JqE|#zZY6l&5B{Rf4O)Kg7tAb0=*N~1{uCS&kZij z-=2WO%Mpm`veSa8{G5Jy*3KP!LhjiUZ^;(a&E3Kh==A=l?4bFtaRi542R9XTq3}Ie zu)M3AJlg0c;-Y*Vzc#tBE=JQvh@ONIVompSh1u=2Ey_jLQl4L62V9_yF~;}AIUN>0 z)j1J2XHh1#n`3wybhMY#0lTC;aj((b$k+R*X#}9hCo{{Y$+Cx1#$W}2jI^3N1& z>mxygsq52`@ketbSNGUMYFCyAlS1k_TW$T(S!zxy_)%0cw^cS_BJhqImXXy$w=(OD z@{gYVxYmgAYfDR4-(c8GWl=6`*I;~1CQKhHokn**+nk5m!pwNH#Lx0gSWkJ)YU^hs zL}`J^NswaJNtw8l%n`Vq(GivvM@6$SQwW7h92~34(_j&uLT>4%y}L7k2jV128#1Fw_+Vgd4R22p8Ec6FI$u(-zfO>#5U@?oxjgv;%v zw=*V21P-t{(s#5}*P&vTcoAojyJ@vKSGfel^c{JFPY-nZ6Io?|g&G|7kIuV2*|}p{ z?MLy+EvveCr&YJT7Lz&Q!_G!bu0rI6KZWcEGE?!c%3oGe!>EgjFB!yOywsOS3uMc| zajtI?d#QZZ6ovf7X2j^}9C&SG_y@3sw;bLx#Z?!APt}GV2zh#|GAqZRISVS0#oWde zlpb5I)AZ)=L+#L3ZE6C+^cTw?ScYv5tLu4*!jFHO1HK73_6`js`6lTH*R>nX?6RPp zstEH%%@^8_V|CJ{RVIzeeXFZ)XG0^h!CRgmrruf(H{|pugFC;9oI{kuW1b6yckw>> zJ=me_3|b!IZ`)dmgT@k@u?F|Oe+9L12KT#VofYkGGGO!6%ppnh?`(q|UPZQZ1^&^GVL{)Q3R*1TC=HQT->ejS%qDm7 z#hb)Ep5x52CmS-Hu-5Y_t_n3!%;qv?Er9xiKE$Fx_vk(=cBep3sz8rzv5H=k)`L#` zHK*1s+ohrQn)BvYXZy+oEKgQbv2NIK5x=cWpqu-~#Lf@R)JTq18~?@&p&&zFJd}_B zd&<3xQdzKyd~s~w%$|LE?Xh0oUYvYwzq*<{f4`phO~>)cw}S@GzZ%GW1ThbGLbv(x zA63n3 z)+q@3D4Q3@Lpc2ON!{#RNLts!k$HY{A~qnezh5lKyOehreRNVUYI6m)7d02c8}Ryz z_#Q)@v#9;g)kb*tnf!FOL*-Uajv?XCL{Gr01k4J!Q$V`s?!lmI*UT>-uP@m#1w;qs z&ab>qil&%bL%wwsv0r!pe7Oji7IeH&W@AOQEPm~skUm?a80$tj^KIf@Xsz4&r-~~B z3{c=}c>Ivd*IpTh{2tHR->U@_*Bi&5OzijR=P0!_!;d%iBd+HCvY%%x%x}GhI(HXl zE91^1r(!u-TFON+RgTE|)nyW2n5w=!pV-&AW-S#If0Uo(-)=+r_cIXB`1HafL*2XHq8 zR8oZ9+M?XQ@@7+9tM=WR5q!FtH-4(o2{PL}`)&nc;n4s~|1vAGqBZ-T#qjtqWhT&X za%cQFSHM;ymT5#_QvQM0@0E?)HRnG3dtSLG%-LbTEYxP6ho~oeO%9lmEA|^1>h|!@ zF&+3FM@d(A0=thA*5u>ASu}Ze{fwoBOOYl8NqdWEZ=vl!vpZ5pzZFjB0SZTctU_JO@@EZASO7Lmmc643l0Pf`v^S*+X zyA$ULO%6Q@92nV-HQ3#Bft?J4VA(uGV50pCxj}HC>=sHM0@+S!vfo=8%}2A3&PTnG zJ&q6=H9E7JgLJg`qj00{e655X543pqgl{Dn2z0l_w|80=MrgP~_Q!_P*4%SaUBR^1gBnmIT@2Ob5uJVv~IVAM!6z0c^GeZb?f0plgO9Sro0C>*lnw6I<55 zQdg*Ql*f)K8pQhACNvegsanb&oj0<;ZokB&9_T+TEAYAX44-j(d2Y^u&^6cP>F38l zk#+b_8ZpoUY$>t3CQpH9y){uBWuKxgIPFMG=P_$)tW%Sx23rLGjHm)G6pYuaGKk06 zgTrrl+G?iUx+mj>t<@o0sI|74s$Q`H9hF%|f)$S-ThtL-jgezVWJGJQBKm|fLWR;$ zFDThgBEYRrxYqoWy>d36mc<@EyWf$XISWqFn?^W|HecN84|2;}4ey;iBP6Kz!Suxrfe} z*eWuu%tmhvna$2(&`jQrhBJ$Zc?Ya1vl`^M)bs#@N*RQgI<^-J%+~C7LM9?#>e2_| zEWOzK{k!doD}A?RH{oT7{E&-wzy1%%%-E>{xbzt(vjs3|95k_+AiD)os+nUH_Ehnx zcze>i-$}7NJ$@0;|henY}sm2x%x@hfNg>yc$bU5 zj?Wk#vK<{+sl`zq2i6-?_k!M@6gFST*|tg6^u#UQVdn>e?hnQ)8pos zeG56O+0wJNMSj&R*;|>Wo8piEh=wfZO*~c6`qJwaX)0+`SB92hf9^xzMK2C^y8OMt zx}M{Ky^AeNPc0V()kPpGWk9C{^)$JiYxNV`e>p`)a(wPuERbe#@pn;HnNrY zq3l_J)$Wx1vvqv$__4CmxMrcU)>l(`4>OY%mvSZjs`Q{YhY8AI8nS*Y-I{%GSkk`f zyk!g2hG+!2`)C&SoNr6S818vF(7Vyb1WPs*D_|^PPU*?PFN$|I-BR*LPYQ30INp~H z3M|mW)5mI$TD(zVg*;4sGJ8yz?G7#nZ~IqWAuTS~fDT4>b|zlH zOt6E;TAuQI?Wr^AeBw2G(G9`VmvK<2%k$RQrKWHNwyOE*$zM3k_QctGPyYp-K}hS9 z0A=R57w9K0k8N+Zy+SWBPiY;!H`Q7ES>b|8sDnP-h0nn|QEGf;$hCC`eV1VVBm0rL z4x~oz_TVTbx1bb(W(Ss9D<|n&jR0zTy!u>panK@KuVzv1iHTe-_T84!GXf^-9SMyo znxXF#PU}TlT7UFW7bkUg=CSpqq_$a`wQyAYbTRn&}3b3-E{-Z_lAD3v}m5$6&X&a?J-zJXYus^dB$IMqm5_1?PW`@1>nV9ZkFb=SIuW6)HuHwu6L~kfLyN(wz0}lsO|J>kX}uz5pTlbhG}TF& z-*4ZHHttCM?jFlEMtBZPYJ1Yu#Rf^c55|5hf%CFC!JX<7)u@#8GwzDJuT<+3h*gHA zgMCuT2N=56gRbPaJc%0jJ5_I1@T)oxe2|$PmuI!)44-psA{2Q=Lu6D7*TC(S>lwp| z=G6xi4%ROI=kazUy_eAP&)cfu^+j>ER>kFagsi%@0L6j7BET!I#x*|rfw8);>kM=J z%jDDwXJ+*pW~$E!BF3rE3|YCMxVzD*pajIt=aMP#yoT6EGxx#&q zp4XW3_xB2ni!a`M-H<-!)V#jI{r$WN%9`*B*3aia@QxbjGy}B`@%L~tCvmNsdwHkw z%0Y{5i`_l-?}0${6BxBjh_O+tH@7Bbko$T3(CRw9nL}SRZ;Rc!SdkC%X-!H!icnEg z9U<(6W1HJ_jK*Gq*trhHa1G&`=_BoDF}KTIyltu4eof?E*v;SFbM0RDr`=f(w%o50 z&1+wR79*@T4p#%3!+dkA-Dc9m-O<+{qh_ELf(P-5VcDFGNYRJ2-aGPrjeh6dz?!)Z z3Z#ohAj1w#9{nl3Ldy1U3vaB0ZMFw`spwgM!HxLU6JXMBr$4Se0jgZ=4Bw$F z2tH*l*7E97$Bl$_aAIkQpu^bMJ$IF9-~3#x`c#XkWbvCXm#_V#IXO$yzCuuEj(>!H z+w>gg_%+=7uiom$R({WXg=n+UhW8Y=ds*kB6^ngiQ-WgS!VR8T@;FSHs`0VOHqHrN z`qZ?pValXSMS-%~&WLHj}9@R2L)HizjgxH14IW3jrH0lO2 zM*N2oHf{y|syn?Jq};W-;TYj#+IZ+bnEg9^P?nK(Z+G%b1gtqNp;-QO$R=|@U-u}D zn2CR-I5TG1BFky6TFuTno)c{Ch#WHB(bz+Yd4H=ie78G#qi3ihEIkoYFltVs$i@w+ z&n*pv4)<7Y%AAi^z;UL@`HYCA4sAIqrOOOR^4A0zjFXE8&`vtfTlnvyc!r|4_rYdF zjM@;WTkc+q`uT(}CAs4@rbOSS*O+%1l(Su0LaRh&!vspeiz+-?VieMLTP-yphEN*s z-TDkIyq;0ZUgsBlbE^8PZ_<$Zdk<@*UMGT@P;_0qW(q zml+v^1oy|yHCMG4;V?$spEU&uGf=0qV<6}9554&_7v|oKDO=O9bf_t@`*kA z{9i0UZZxT%ZENQN=@tMWgo5;3oq$iR-|rJiSCBr*VaCcIF3Va;`9e~D{_@~|qg=oD z0qIplR7jfvNcns6QeWvWX_1#T{zH$%&pnv|3rxe;E(P%aCi(RO@b6%Mu8_)i0DsgR z6T@qBRY}?M>m!UnDOXBiQgsLb;J@clE0ti#L88{j=y@Kg29q2Aa{|5a-hbmh>0TG= z5yK>Ne%oI7wRa0X20w&gu8;yP&%<9-hl~|kN38WrT+qw%S>V|>+=;l1Kdv0E!+2erRHnp8nS>Hp763x0+rV0r;p#|MqkMWmsIAk;o!QcmY0888 zwVS&!CB|ezKRx!g@3M>uIQ`BU9tA0b(K=%J_IXWA40DgIRdw8FbsFHh6yAY$`n84j zRdSq9iguFqnXN3S4t87um}!F6a#lX>M~TB{iKwAa^SetzI5?B&KE}CI86wZ}wAu4? z;0>Q-NV^Ays0EUF>zT1EbZk`|E=qa=TIgo> z=Wcyq@2Iao4!z4_Zix5esTd_Z)|9zBuK-dRrJ18h>2R67;IAaXFkEIx3Ox3r46m8` z97=ENaD{KYB){a?dJ1&m@2yh@bHU71=pt8B@_ISkdV3^)obKk_mGauWN8B~CH#u`w zO?&bzckse}@r z36KhLrl6A3qL&YD{WaLp=bY3(N>MkQI(~BK|F<|lnrh2Hm+od-`FqFUAPuxfXYr3d z?*p!6Rdv>|?Cf`u`?fQDl05g06zVh0<5`WXJDQzw$*)skqRR8l_rdV zERx;zw{AAKJmvDXa_Uo~q%8=bMK6zh(sycz&Xg<4M4*Oe<%I&OGl{#U>7IOohYclK znZZ8wa_`aE?s7%EPK7d_W`VH>$HuzkU}@=wW7;&K0WE}hRs~OK9yxsh)0lEFx(+UO%Ctfxs6!C{uFOmlHRi5u(crik<&S-t1AFE-H$AGw8ER{D(H>1eNB5OHDFgj6zKdzj_i3n^ z4;xJyU|M<_KEeynACmyv4XmjHN!V4P!0sK z$Pe*n5C?;H*E9!%bweB0zzCU5pzx}Y_5S21=U$o>^g~$(`B)@<*-W0+Uxz}!8gBb= zy(T7XcAsYKbRJ8S7vT$*XVfG<8{w4R;O?lI8v*VoCj1-Wxame(wNbB6Ew+TogC;Z) zjR@y>WHIA4-iCN8P+JVqZ#_YWVpbuM=P+(N;f^Xc|U3>;{9}Ec6{+HrB;_;y{QW$73H!dx?9|CfJuE`NtVzc^E$O(^E{>9I z0x}`fMd2V~5p*%E+;GEFyZ*>sutaqxgF)(5PA{tV+1hLn`7nk@?A;dY$wbN6E~D`L z5z)`59A&V)mi=t5K0xg={+4eZUHM>h8cQH&_o+)@(11Fv;Nwa}yxc`w>53_2cbH6L z+wNy?Brt9D&WwDUnSN?rT2;}ycr zPy-)gu%Q=OR8_&1&N+Oq;^fP`oyP$#DqUu1mNIR9*jHQy9xOPKG><2)`X|cHCzdW& z*+wuLXh7q?*fE)BiEDh{g~KvUo_^Q};j)aV!C|u_nBmZ+859a zY!+dxlJbPk0cB>HwOeOh*edD$fcLAlT$cgO&~`HHN}ytC*4=I}sQE0k@F|@X7q4}X zTPv?wl;Zm>p`~VlBn^+hW-^w^zR32hxaMZL2#0_7E-vhp7nItTgv>nIkA)PlZhw;e zttAwsaIg`{YaaX$!0jMNYG90l_r1zpf*~1T1w*d?pQ4_+`u|V%JkAWL>Z~1N?i|_2 zn$Nr@e5|`+X(?O_AyrcX7HmoGTK{J`$GxF}0hbyCwwe63Vs}aJ(ATY3nWyMa1xTIJ z(TPD=weQ~1{+_qNTPC?`LC`qM|zu)2m7>6kx*$d1XPMclx>v+L; zS65!ShO@;Ng{T={C5N!Czl80{0-VcHxE-3FI2@~?`|-*zD^Ev+@edhTS@lGEm182P z^yZGxMxOO(MWS_Snmk7l1hgLeQhV4_ES=9{i&Bo2amaBq>EWfLJ)=(Y3>*IZzwBLP zwG(B!O67il-=( zW8|bIT_7I2y`#!rz9grBCWVf*pl_y5G~yb`sSjQIDA(5JU2*YF>D)`n)*v1!yi)QN zXRa$fi`r?oR|8SI(`BEj7ITXZu%%Y9hC3(XRP$P1g9^aqexuPFW|A&tA+mxmI8zH` zgt0Z@#=)cVv0mcN6P@CJ^bsz=*a5A2S&c3F+hRtL7E4{#MLWona|(G}g_&qJ$pV$) z{>*(T-J=#8)hy<^3=V$QleQHj!$A?JG{kgc=~?Vtt%iA-?X8jxwo-lDQ>z}9;Sa|xU23}DZH?r_^+r}7b}%-u zDq=gXHqELA6dOLq{J~AwY|N0KNKHlR*bC|-?7vz>KWJgY_iZ*2^Q%@Ty z2H~Z#cEcTI)7yqH@gT*~2S&|}g!If{=R`48-QJD=8n7gTM4Z`^e(+JV;xHRG$$&Ms zE_V6}R9v4WC7Ae!$@?=zS4>R|>cfvoXb`GgE^ktFY+kW&|DPknRac`LALWdEHFgGj zNw6VFn5MobY5l$2n$u55cE66FK+G95yukkzkl)cf_DB@rEB)RBkBj2qa|dUbCpcD# zb@loCW-b=}kGW#=rv$YCg-xsAUHyv2O`bSG?It04*oY zC5xs=EJ9q-NA5+LvzA)iUK^ik292Gul&M_oJ9&i6nW!RnjjKASit`6l{tQ!UEKrU{ zJdHP}#-KQ#t-T1Vbla=7*|YDAfXGjjVTIm=nX3xMz*aX{H*!Qa%m@@?hd1eY246Oh z2ZS|SlpA6mjMVaT&YixWdIXv2y!+YTmz9MuIlaY5c3C9Z|CJQv*VNGyN;+v3oBRuK zu`z03f!3ife}_5MIr~%DA|nri)Hz@n!QS6E_PB>QI5C-aB z1cYFu&sn!@lh%L7FxU534R200>#y%rB#j;qE`#v&(xBI`OSns*c{+##^lZpkf_vDk zBYE?<&Ewy{pJ_^cGj@7gD68;`t3@a;By8XtAv=M(*J@cjAGAuxoUrK=+(Hb??uw!D zslC_mISsxl&L<~_QuFOp=#2Rf6v5TU5&Q$)x-)#wkR|Zuf6UOK4A`yzDG$*k?27ZVzawd^%?wB?ckuwr!*#0V(oWi+584<7{mqt zGJ3svck!7#Lt0b9;9UCN`vmNH&A~_YcKyt>=gXatJ5fQeBBC>ddO8&0ba^L|olFeg zLC?yjoN~LT-Z(BVxTtP7JYnS_aR>0z`1#<|p?pj5N5|eKg)0dW9rP~hqp@zyPFMT) z(_`GxJuin9Jd)s1YH@Z(0{W78=Ivk!4qNntdE;{t$W+cnXShvXPa$~cXDTn0hH;Hg zNa@L=Tn0R)KKPS>5o@pyV|V$+x^8W>+SGR#rH39mIMRQu{`KlHEwbg#%!A+L7EQ(% zQ35|v2@02gvH%dFK*DItN7hu;Hby2&dxs9=sF>yY&VP4}gQJ*a@)>%*p+_U4Vh$Kw z1nwY9zDKp(uQq8O=^WJ#c;o9AG@`As@q4d51op{s?LW^m6@s~FqB(p`PTsNZO|-F&@Oz9Rm84^K^I+`I z=+somngOP>@r_x{a}MQI`N`8?*1&|y_x_RR3l%T(<=PrPIzgM2T@h8CX0tfR$4xQm z!{+FQf!7TR62cwHTt9w$| zHKEx^n_juJrM-?&Px4_E-a~)d-^FLTR<9Iq3fXIKKR2^i+D;c|{6qs4dUC6WF1oNXX94p2vA#%?*2PbFy{sO8x8V{@!QFpn21Y5XG_Z z={jrn1ynANhhhI$QbC;WxQG+LS+&&)=HmXvq}(fDXzEL;USp9eB7c2zF!nXv&AoO$2kyPciO3fw%SPbrLElo_aXcBJ&!I-U6~9GyC)dZ55L zJBYxIUj)N)NwdqJu~RHV$|Q(~xB-7@F}V|BZ`hE;ujANXO9kW2hwTww=OZ4AKCnGl z#(8~V=DAUd{NgdZT7v0l|9Y_@yn{v9ZhaXy@9pO`GR!5y;bz#K_-LBy_71JrJC}@X zh;vxH&_vcFoc&;>Gk$G3O=Iu#L-Bj_W9W{ji)!>Vvv8de*UM8;dK1N(rN-cWO-0+z znyx!u2i80{4OcXRPt`oEufRP(Le?BMclJ=p+*Se73*p7wSi)(F*p zXAaGXdQDu)4l9GO@8}Z02Ncsuq7F4Sjp6NM3K?4r*H=xLUhR-En)tmkKaTesnw`sN zc>3weDGRxuOBWzsQp{AoKh4elG>DAxf6dKmG8MjML60O{1l>7@ULj)K$bJyX?e@PA>$BB-Goz$V+JllHM*6lr95)a$@Wd?eFIn{ur%lbgIQKF zPJB(%W_EFXioI8bhD6y&C=)dwlD4_G(aD>+4bX*V6oJ0Z0exNDMO0LN^OXgH>DqI6nnldialHTIGAB>b(&w!*pUGsN7tX4f!t%Kb(sTjkA!Y1>2 zrr2d)oMubPZ3{Mkc@8~qE%thKeHS338M2(^gD{~5PZQGBs0Y8$l1B5N5SAfvqx$s4 z%7OX>t_WI{n!6;j^3auzXL~?qGKsuAOImsah zfzaLhaRK4k>tCzdy*YN;yhO-_+Inv#@Q&~>e9splQ z$phz>K>=;km;1TjH75+U6dQzu4c4>OPl*?x?k=t~y19m8hv&&f;_e5Z2P!o`cR9B_ z-(pYnGPnNvTZR1aF0f-Cg#=?**EU*Q*wV~>9ZXFp>&>=O^ zQwW)6ISas=459K@MqaiRi9griZ(_^QMPO&=G#Ft!V+Bl(uu5iUDc2W2Sz^tF-M{)% zlC~kc*@C@uN^WKpBRnBum@~Q_cOVWi_gy`i*r^I?FH^X6sfA#&8ayc!WBak2DII>5 zcUmxVKRfMidGmZhs79UHN!a;@{0gN>HXT`ZXU51ITaizph&+>OKAxI8zZv3|(sgX9 ztbVMVt5?w*)0smVF(X}G-HJ9irN4j{EZd(HAKm&rM-l2dTv`>oXDl=ZX2FwTbk_Ub z!aN-b?`vav$r4^Hv=>dqQ495oS2wA3V+vkWT}~GM8VzZ--u*Zj_Sq}C=?BvT(dFBhDmcKdKGjK;UovzHY%m+zYJ-fQmOo1_)mjlKT$ z(S3YvHU8~bLvWLrMOSWBPB_X!{My=j`bX(vRfBk-hjDTzTpZUqv^5JL(3@u5)iETvN?xr=<8Bo;)Y?!Zf zhc-80THED)NVD^=tgL@yWB5B4kZ7m^=ItRI<`&vO6;K<9G9BpCWN5%z$E*ny{F|wY2ROc20nY?e$ zX1o9FB&ftF^I$SVXEDaanIBxi=Z|@<~rAq79+C>|JpDJ2va$I zwYDL2wUlQL*E?CE+iAHKlIaP$(td~Po1sTTv^+-9KDs&B2i{Y!!LL!2F&Z3hdFv5g z9BUmJ`p_JSw2b7G+w`gG@wW%oB14b4?jA^ur%5LjdtgV+_eb9WK(m|Y{SDN#-F7UH zMOmM%ZXcvdpC2zefL%JI4nosK!!#{-#<#hpRihNPVF-iOsb<=gBS|~;GACU3NUsjn z6e6*IQeUs?!*pQVo4Iw*hS2MF1yp_q=s8iYWY|fBydeYAp5Ei%u+3ZuZ!PP|#(gz9 zzgU;-FI;~RSCW6MUx@I1kZ!IN2<+h(>PA3fhoPgtHe4mV-f>xg42OAhK7Ph>9H5== zDTIz0=B{!G4F0Ra~5@XrX>m}aMwX%IrT$yvUZp(rX!g!F!sDeu| zI1D80sjs;mJiIGuF$X`o3wLw;UGCKA84Y^=Y6xxU>hi_JAAUbNS6&~P@t&xgK50>M_Yr}J-@LE+Qc&x=V_u<>bemn z42U?6DYrieymszJJFXIHmx%hL}Jij** zq#4xg!RcNQ}$+ zhoHlK0y#bgVl=6(n56`6nu)J#gjA5RWoh7i-Omga)j>t6*2l3@OmxsJy)~Y^1F$rOw7EsrL^4Y%_OG=`xaLW-ue@ z0ATFMw{^8%U%sI7R_(}E7jH4v)WkI%13Qrm({4J_--*2*q)oeHQv>CdWwrZIKeq7+ zt{}LW9h2S1AzHiB(S7Or^&1iozN+gVYB^)E{8>4QVU#f?G0DhYM~{97~vRWU*d%5AP%qQ*1oDPwa&xcO*mi!Vi7(2+Zy%C|^XuPZZb)|EVf&`f(xZ-!I~ntZhV z%j7$JD8|6p;cziDIvX&eR1_YKUky?pnXndFGNj2B6zQ4RO!IMaGE(-A4N?s~n$T zWlO6$*67qa#1mcDMicr(o#c9z>B-iKjBd`=^%XS#ofYFhQ2t5rKC?$;`cSgU3jUYc zkAfv`j0WKW++Z5qk$MS;&^>kr*vOnjIiD5S5V;;ls30HfzBh2`3V}5w2z0%Vsg{9u za^T)2y(167r;9DFlKn2Y241^i0_Pka!Jpqv*g6^XnhV<7)xat=HFFoTpX08=T5lf_ zHFry>>x6E&Csj*#{Q%ZRy%Gurqc8_ z-1aU+cm6KeNiP?fyGiBhFgf!Cpy8Nbm3MVj`ST?yd1tap4pwmZ^;%hdptvrw zE7EB&6arAfW23X?EqLB&sd-iP{5TAkWYOUwG^QUCMGc-5Vb2+=^Is}gX>~4+^5DEb z;W!#?ZCEa|IUPVrTrzOIQgU(9C|S#UzVB>I40uwxHVb`hJ{&9rV{GbcSTslUHf8)+ zO2%OiLj&a;SOE<0$cWw3-^pX2oCQsIUVcp$r(#S963{$xxOH`PWJa-`BhnP+Va9+F zxtmp7zp0Ip6&vis3|}6Yg3gT6Ot+~*kQOC^C!Z{3_s1yI>xECcZr$@-BdE0#E`q8! z>IIo9pGbCWUtOaQSmN~#ILMRbk42U>`)u1mrY#D)C>8uREEEm8&9 z<*>?1f@liuDSnjt!SkZ7(UaC%oSr_p74gpWd%ttHy?%Tle+|SJ{t2z=wS@d2_xkg` zYx2w)F?CHJ_Em|5Qf>8FelvbWR^Q_<8EbUtdc0)MMW*PR_%ZZQoy(cu;z)=gKt7Z& z_!K||4qZX~=4H8Le(|7Xd)^VOwwoOZx?=|rT4B-jvfJj4R_11FX{Fup*8SPz(1T|{ ztaz4RFhHkPd~>IlwKrw)#%{`_S*&5&Vc}O9z!^)lura$!6M)!?mq90Koj9Ce0fB@2 z06P`%p8_=oR@)bfwRM4r3_?fB3dB?7joaD{g`LfD<%5}@2lNi&x#a>bK<)?62)i#f z-UX#bgjWDgT|XmdTTix@t^zp_q*sTNSp3$;nLli7%+xJ&uL?&d4eFc8@;?AvvLFBg zB~_LINSu^vMKN-4(QI0J>9p#>D=#8OZyl`X zE$(WgC#t;7Vp>0433|s*Bs3QK(brKTCcg7Y0vff5 z`mzjZ(p}XLerfg}(>|#_!J}EZP9Eg9or|^UHncxlr-La}m@KMRQhAh~R$M_Oohm;5 z$?v5e9}DcoaK;z440%QX{#vXd`?0G;#y%?v2M4M?0UFdxdf>A!>lIUhq9B&LH2G{> z4(;m-1d#A@kefVj&c~^v(j0OmJE@J&t$U6p36lyy{q-be0y!e|pq?`Nf>|2-0575C zPLFz}PS|C2TSboDq}-U<%@gM6+R7NKjxYHu=L#D;7QSCi07Mu#n)He2G}`Rs*2%N_ zV*N4KNkTtylt6zOkKcuy9YXmQ5UVtaP2+k+1>U>mQ^YnC&TZxGCgLih4 zjFksTg2BE?Ach)LNVDOLd>VXwlA=|nv=p|wjUkJUinWw)4-{CV7LnP`l_DW!YSp-e5#M!=R4LX2 zR&G}LI`z)-cG_}noh?&1UWVps!<`vhp}84R2zIe`WyO_{`1^s2&}h(=-RBn#Q18b= zgWj&F% zS0A$3w%3M*at3l#tt|?r_bQFUcapYrT*1Mi`pYr@s%ZbxuyIMZZm(j+m{DYDb!ySR zvv=Y-w5kE-i7&;;5^7nFW!mA~Y<-4;wm&eKkVqcbqvsst#Lu0@!^YoeuHfap@^+oM?aTI!gt|T&qjxxz}K>y#3e2+Vm*x0U4Qbbp69YqW(Y) zom5IJz|8wr45{dIZ3(HRlTW!ujq+%zP05sJx@5C%lmAS3e?HI4wL3q&gjbR1(F+;8 zCgJi$3BXG@B>=er;Wuj=Tl6W|mZ@jsWr8+SrXTRTN?p4qwa{W7X7}E@&&G)EP<%~w zYFyLztc#B8gHO4R&Flu#)g!O~Qm+s>Vq&unz$9Dj*W@CVmW7} zIq@*2$5;5Ee#v4*oKVJ_y+0-zPV|v~vi5~(@jz6-M>mCW4_~&vP_3e0BQakmd@p(> znQ{AtbmPV^CdIqqw;6V3XrNbUf2_{S+ zf3NJMU=ET)Xv7E{ zGV7Aq(HH-46f-u^1{;lX_N#5U$lgZBox6L{omvE1R*`+ak-ee3Z!Y5qpI7%P^Soi= zhr}%Wl|l#3wQCIY^!j^9d?l}9Uw&uzg@&o?cma;Q35M(RsOgN7_BO@6FT795ysQ&_ zTjav2D#5jvVGRq>o4-WdV9FmEY5X>RZd0L6Vqi!PJ>$sUewoRA zT82Q-fv!Q)RUEUT*0C-U7NEFqptLlzFLxw6&ZD~mw0Q* znDRu=Cj##338lS*x-7v3Q{g5~t{i?UcUuyA`2^yE=>#jR? z33!I#Y`xR)WTI%eZliYxTqdwWL>bj}2d_cnz27yE*QY{B6@im{%<;-IuE~!1oqC@0 z=3wq}%G+?oxdqQPukodwY`Pjl=%cxB@5(>7PFN)yXl4zd8jlpAIc0NxMn|@6xMS&K zqj(ALC^#SY_EWzvWsTDUae2EBaSD&9k|lgGGJTCT?S7-LQQ^K7&Szx&RPzSK`_)|B z6%4`?g5_Qgoy~n&ZCCYU` zodb6+)^G2NQ!K@ziPQ8*mON7|jSUtcD~X0o1e1H#MdNi4isK(}MP2@?X$^Es;&3!OvhrJD+t&xvp z9yWX-bd|iE&vO9K`xEd!?@X${4L>4hB zBE+L%qz{Fgxzq>=tAXn>;cVhywBJVN(uo9*tw9*3t|3?$ zzjd@#dxMZw!9&mD;I$1e15sY4Q~WBMM|VmI-`$4Pr{MP=>en(xxxE%5S_RWeJQtU_ z=^y(Z9N-FWk$}AnBYmH19WzoganP|wuSprsp4@9FkFg2*7eFfE zyr|`wDM_j5Ith00JfrpUP=OY-x?tzva9g=x<)Kao*O*782*j&5C^EAFjsL{cDe^w8 zV!(P80l#6OHe~KoZE&(If@p*EjVy<}+I2K+xW{w+_@!Ky%d=rqm4%Slg~CI26L5OZ zF@Awsc7nl-NcL3Qf2w~8ONiEdVb9D^!dzQ_3 z!Svhy#ort!v^icidO?TH&HDgRt?tV0D$9QpXS?|LE7RZNy_&r~7-M&qf=iTIS3TOo zaFc??d*=p-a7LlAFCG(|>b*8D@(121OaX`OWagW~9_K`HMksHLn_kCeCh-;jweQ$4D1d9FGRg zU$Dn^wnJBdJr`4&3y0G-JKSCOd^i3@HBJWIS!)tgKn9wj9We9RJZbaUI|t-Bfa(?L zqxYW)cmAte_@WQuOR1k@0aPt14cFaCb$TWs0#DqZAjPNx20vp}&`)mH-z9(jr!IJ1 z0WuZR4sPV4Z%iv)gSW|Ou7zNK+bw!b^Vv}R71GG%v4V++HfpNK>zhVYlv?5ede5R| z#Sdl0?4TvRQWlx-Ky6%8mXW(}>)feCKbv;(iYAR!5buNQ!V_gk z%T9rL;uPoc?9-mf5u`R^Y|r-Y?{v^{>{vv4O^ubvGS^kq$Zz(k>L_CA-Ac6tkF5c((BJYMu-zreq60j-m$aC!6u|3) zk^o5ny$X)fSYbRSc?6k1u!R_wG zEAIt6n|v{wn~Gm?a1v4#U1&_TtXdPL2%dkf$ESVV;&?$b&LeDVG=Hk@`@)t!1gbauG3 zFY+w~hQ`2v5@%^)qElks@B~T|FeE+JB0U~;qO3i6yFjT=i{3U~9R1TYG`*S2$^FDPxIG>)v9x|?FnL5p{B*LB*qxT(A#%?jNt(gqZUPm$mBqp+qXG&) zgpH?tAqQV{Ah&?~B4W6O5MZWgrM}Z9l(G97SD`K@Lg> zKfy}up161RD-+|Mthiz1g8&_At2lwf;jhG)uy~_~#J5-BNLXc)DLQ6yt%@=K*DMP< zNC}*3!z6`h=u9I|0s#vsk+=Yw`3}?Gn-Rg|q0GVIbxK^sYo=8%H9{eD9!uJ~(~`gx77mxZTg7*Cps6fJdV1-e)#cC^U3<^&Ru;}qmsq(cyehRoz{YqlR+gf*{Zecv zwu7zL&Fkt1j6_Gp#J`R&q>t_R`h&BrDGidlnl2+o*v zMA6kZ_7?`Wpj}1N;_);^eZzPfPm7H|G<6w_LUg|e?hoA!9x@(N=_;I0! zCbzC0e_1OblVoY*HrXGpdl2C0TXJVG>FQk3vz|_3CJ*3?lV)=BK_Qtxqgu-0z&A6*dYvi! zIF)R(4OE?qg_SL+LSmZaavY@)RVHWDQ-dI9VBV1X1$F46u z7J1a#=FvhnJX4R|o>zS+D9wTrUKf?{XIwa6zIXWsiC^7GHZQ0YmD!EOuqrASE7+kim_AThOUPm^DCM1$Zbtw3x=oIfN=J+7w!eLqmJ#Z}`zDT!B^avX1!i@JeUfs^v-8AGv_j7XloS@HZ=FUUrAf*=50g z=xMzm%eOSkpf`0ekDhnsc|hZYfi$m48jKc#GIh zoK3$kS9={|WT#JZ7Mrtxxlnzj_xf=ytJ`AoOV;Tb`Fp^uGxvBmkEbtK>{auC`pth` z%dhp~KwNc92=CMzcRDQ3G}K;KZ-uT1x7#ZWUGUCy>>G0R9W&BShW#~HfQeDe7*e8n zNm>c1&Vbz~ z-RcJ{RVJ_CgV1t$2dzrSTbsS(foXJC;3(v^%Jn#-zh;K$4$m5Y+; z0HZZc@_n(pQc&s29mk3yrPwc1gz}0_=g%#yqeJSy09l97QUPX`*y_{W=oSsotCB`n z>ZREt7fYT#4@M@3l%(W%BVqKHtkB3%4aIt2L&a&MIvMI(K#RCX=a3AFU9ca`THUI3 zROtkh;y_I9s0gA)IpyYvY*v?w(pbTE#9O@fPXh&D+2C(zBldP~@+}0M5yu#(?;&=j zq+g{qmOFLw4=6Eo@A@5;ebqB^h*tIWF<9A)-o3aoYaL%Sj9**7>z-Ld?&gu_z*Te_ zC{2L5OvHulA!(}mEg~E9ve$mj5Yjm~{{oJkw(@e4w+jV?2BAxQjh@68`d@(ZqQ68l z>81V83S<6}(^DhNpLgcgt*dJ9c@?*s_F zLnxtz00DBN@As{{?z(5)d)8g|ocU|=WS%{HW_EV@?LGPaL0OLUF6~_a06_Zw-CH#P zfanzfaHHlnA^r(4eLx)mxDR;$_O-^BwB7kT`WonK+#zrOi;sLsLmw)VZr}Pw$Hw#O zTS6VB6^0NcCTKBg=fqdl-{OW1M!JfxRt8u@39kylN8`VO8G0AQp_=MR(k z_Nwc4*}uIf);D$j?fn!Y6%tR|e=qOo=qM~qo*3deRT><{@xtEgH}Lb%@!!;GWl87Z)78U^j$yt5>Afm?SGHEs_pKILnNZ7f)9NZe%#|}#tE^_e%*!(%@1paA z`s$U6#A&lY>c30RIv3Z$rOi{>1|8GJk`uMRZ>Cio-3_Xa2l$KG6qoe%)o1=$q63MJ zhL-SF<=OU)qI~b4g++RHqX6|EH(M87vPitcBsGlJrGAE6*d7gCRz4O*BS5n;A zT3|R;N&5Z{<$XS`1K$wmrtd%R9Lsvl8H;6{>|+(krxg3j+?a4f9rvrZ-(6zWo2Q5+ zFo=JElLa>x8_$2MG@OzTd#Isjc6s@SQ(GOUmI|N}+oe$GL&r(Q=UKnLYb&zW@|>$& zGQqhS^hE11kA;iJHM>>Jk6J*qU_`b_DAvd;Dok9jj@);8xIV~2BJa|mx25_HndR*5 z=%0sCRqG1P({Uj98`s2@0V5exxU%FkLz>APJ~EvauXE~TUloa&US+|s>{S}w8M(U( zlvbPACJBUSn$JajclZQZL}hqe_Jb)H!%aXMlw#5R&oKzjO-8h;&5iSA+RjAZ&`nJ! zu^Tn}6bCaH^yI|}=P~Q*-eKxap?@y9%~HbK8;Tporrr%qS5IWbq*Uo*Yf8^cKJcN= z86(jl+@}j)(-GBWkH|1J;y^yWM~phvm-!}c`zCU?YOM`M{B*!>L7gpo^0<<5otX|j`QzlCv;`$uuI?GFAn|8&7atNv8>1wM|!7<=Kv&P4Uq{W`wiusXw z-Mm+3`)Y@tF0179Ft@x_P@*3rRMQo0t@$%yaSZy!XbeH<3ciy=I4fkvfBVm-06woF z35yd9f2%|`U?vi9iszS@#VSt|CI88>o!|L#^Io2y-8fU-7E2Y{rZn5T#4xP-yX>H8`S4J5pb3Q93?&Q86qMxbK+BrUZC~4Jgo7|_^R*rj^uFUi@?*n!w zw8)%8G^R#eI&O|a&@5*05Y;RWuZ~^8PR<4}6QWwKt2$krFvx1J*|SAVcb7_SH7%11 zrkdVZNn2dY51Wczg{I;hfqv_-0CU8dq!cn*m3NkAF#>1P-vkXbl-rEhQoMFo&_dZ_ zd(vhY^im>=#}cY`uofQ!ucva)R1z0IZ%Lqx2D2KS@5vZ{OELt#OlI#iM7!x}mAURAhPC`EtrSiRoDCA! z?Zb^S40lJEKWPjTeP%U6hd~ptIb88Qt_gZ^(=wrx|x>Cy|%3K;!ez1gK0oz+0E}ez8hL%TF&7wQKipGzi z)hY$GC32cq(kRJl;nN&JY-l2D1WNY-4mDZuJjyt0sN0RY=w9& zJOhFIQ}Ri2%JJ{W=a)wc-K;;U?lJ2G8l#K$jp>W-x@O# z=H8{%`p~$bOxxztP_`CXQ!>Ov4MEbJp#LF7u~tq-Ctg z0`ZOLG{t{ac=r_P#nFuRRizIZ$?|q?7@JiFfH>(VWqYVpfpi8`LHfK z56NHIyCn#%fE-C=Dp!HU=H{YPFWJ+!e=VJbQz=g?|5bAQMSh98ml1A+IHVq|@SYO$ z#nsmFA9Pu|`>^t)Pzx3JF6D*-B7P!rUev^}rg>GZ+J4Y<3S9r?6daIm4{JN|nQfk@ zoUlv6#^;3^WXBSzzLNvtUNOfOtcmeVv6<@J2xtk%Eo7NY72B^W-3Y!l(^T7#DWi35 z37iz7EN#dsF`78`r3fNkP3%^|YPXUM6N^*t8(yNARIrl#tQWML9h{VI!q2ZPjW;J` z4-NEA3zU7sa)>dHs_&|T!h!ONcg2J5S$(7lSI)3nUejky6-Yj5u_Uj#%(*c9{)X~j z3qL|>V8D}8&}_FPvok1E_C_VFw)tHoj;~`!75r!=QrHkP3&}Hs;PfVX_4E2Penx9O z3G{&pbEJmnGa1H|sBAGuk?`5RzCcu4UJny5lv%CZRhsqcbUznUhmp7&b4X=VDQ6Y# zuo0TNNezcgpp*b!zwnlm&cRVd;8)Sv3xEA zJ6S_h-hska?yS)Xh1_&Nu4kWnEAFhW24!pZO!E;SV+N{QQW5v+GDs*gu2(~qRVCrY zxl3D)u?_P=r)C_&?7KUGd3RY|XYx?ZgDB1-u@MN|L0pN#E%T#jdqEwEHijb z?dmjjVj@Cj-{0w9deS|iw2c~;Sm-Q@-?q@&0GqZ|s~^y&sH+^(9wFiC;d#-Te zT5IZ)cLz204;9_G8H$zs=z-{v(*dU67?_dVlY9%Rv$GfTG1Xp^H->;4MVlW>U4=xX zd}A-ZhZtqhsJVHs0`%*L zux&;Ev<(;b!R%?Zn7^5wK7T85{B8SKrS`hn9>ce7tkg{mW)#YF8;Dj7`)6pjG0!`` z+6$JkX|56myAdK;$G!t&u=d+sWN+JaDxZLe*B>nxdA^l!GDC}?81^WH25Qp--cYXF z%b<=KQ1d^K(>|mCze_N0C!roh)@eVU{hl2$PV`=&^hlqf4UZin-Z%eaSrK zdoDv91qhiJukr*dqbJD3Axc*zGTl-u&-v3Os@M;)J_z772Nm4iDs3OVJK5sr&dSgB zcRy&;WlT*Wbu)@`%^*SBLDXIwYs=vQnv}uHo2A9>T-bM(;#lS$RUtNjNMfOOUPz;` z!ScWE-a7$K70cRgsM1w+&*d7Z2F>t@Vrg}R%^>mfKej#YOplSi28WS{7DsYLB;UHp zb{u_^1x$<)M=S*?-QX>^eAT^?mv_{RRlo1dCvxihISn5LIqG#A`oL=4D{3FI+(MX~ z&STx1g1Mq8bXxcR!F*9QX&U~+wMAVj!$+E^>lb?wDBr{c4TkQPi?{FSXyS;wZQEUt ztz9xj<3m+wy1A*v{F3=?V1;_DFT!O40bDukzS3i`Z+zI#Nu(2Uy(r!v<>q0wvP7cB zs{R{yUFpzo5X~#=S_Rcp_1?m9>qAIV&IWF5IP_~=Vl%iwenTUSR|<2J%{!TXfv!zE zNusSzNR)bm`EVBS`jLChq4!4zouB4K$i;}5MT`yNqNOS1nyuP)bq4*lGN&^zi>}3*|^>h2)>8h>fxnyF!?vusC~<<{M6)&)g5=02TPzNfcv!UTaK7EIF}&m3O&Hfi(O6~2Y} zZdcg)SvH)|K3K8il~*h&>>o>vN1ob_qjBBSelK;Ycjr&g7r4YPQytx~8nqAtxSB*9`fr$} zG(1RF7AOt-8R|w@XLeUpyk#jLl3Eu}50jI%OIPcq4L3TbuN+aMLtw6FeFbWYcq{ zm#8sWj79v2<4#Q&UPRIeb5vkVt?N>i8O3!y%|T48SQ4i4nwqJXh;#-qNSW4jSj^Z1 z=Q7t_ht~!BTYd}g3dYY$S7IuVCHpQm)<%`m*5cNxTKf8CrAE*HPGzBokD7KqPW3fm zKe~hWy_yYA(MPT&&##TJ;VDUdil)`>#X+t<=P}jQ>9$ub;c&Puv66Qlbo>@5Ic%^6 z28Rb~{vqVQ(W(ZhQ+9K&w)IPNeP8Y|5$C}c$5s?ktk~JmB40#Jb*fxatPo`xu0*;w z1y?oUy-Rj=tsPMNmy1mHXRU;#omn^^9A5MauPV&P8%pF#=3zC})OW>|W?}Mvi|)T# zKR2%}Euf9;MfDz@r#3tI<%J`P*=_A zXgW(0RCB53K;@|Q-EF>Y2F0~#vXFN+GKCuSwx8r>g)ocP2i<33{x23_el9Km)X(Rp z_{&)jlltwi)<;vL+}}YsVP4(E0!Jql`mFLb1Bg9$WP71mHQIDXm^*Bo{?pa}Ozs1I>ZSz zCWDSiHcoc#^3upg#k`7&m=wXmf4JlS1qbYiAH~PV6IwiQilQ!HDE-3SO2p2^;n+0$ z8qj)9d+0-iXY^G&U(o%(3v=sNx9$NH$(*SykCzVs>JLT$zmUgoLgN zCjx-$J9`qi)?ZMfmHUEy5#@N|8EpNjnL83(n{mtp#pqZ zhps$$%3(_d{}aNuD!ETGb@cah=7MgazdE$*Bq@B*)zeM3UxC-RYdJPdxKwQYNH1yY zLLlLc_xwRJ7retdTE2M`I=Ys=pnsVPD!N_9!NIAN#~;HvXECOd6c;To((gnP)OPVG zK`}vDOCiGaqJ`9SY*gbYmRwM74D_=)9-?MkpuvCo2W6=(%KJm9TrxE*RsB zjOzo5uKk90A>guq)&TGa{mQD$?xXqo4fOh=AlCQv=HJH_U9_|x(^U0G(WE= zf=9IP;zw0$>3$If&7(eTkHafkpb>Z^M@)pLRSlDNcC>cthw(0(FHHnXB(eCSg>h7)$*G<5ZR^3)yc6LkVn2ApmlHHz=T0c z$Ac-WsjQ0k;51zcRjQG%6n6nBWbC0+FQ-qoEqu*q6O8XA7a9pR%V4l}pJ^TeT3HS@ zNc3Zb&tt3VdK2Kn^UpRs$&)@C|NcM-Pzt2%SlpYDYnW#`a_PDtKYc!M?J?<`JvVXv zwR{D+cU^rM{&{>sCJ+lqsd&PadZjS2D#cMzR<^Za%mM(2P_wSRy1Is2VtfP)^d6re z9)Z8|MjH}X#N>+9Mh38wd%IRvHDY!w^HtVDi(DG2j)HJ$*TctTgn*Q4xEC4X>|N zhA0~#b4EwvHF_nVg%IH2ECi=~vsy}?L4v!qnIXY4u5L8JwVC~AC%?C|=SS|_x>+aaE(&jlS~jgC1oXj^X?0|dpTFnYX;pD6+UsiEZQuOyW>F1fBe5-X$r zytABv1nh9gel%TAbaz;V*1WA{{tf zi?ELBY~~MW2*^zSGsx7k_toP$?=kWWmxq7pWzxXHEM6Jga{H$$WPLoN`ulKjUh}gW zUOT(h2(PbGjVYko`%2K;75)Y&27z+2PVlbj|l<( z3LkGi8c7PPk^86Xxz@Cd#KFd05%f&_x*WAPa5KK8Z{Hmpx0b<}5_f5>I&9NUI}Q=Uv4zo3?R^pOEUTH5P4Mg@ z&eS@Fr`9u8YUrzq`@K7^A0`<4RAx5=tyJDAU~0Uc*Q-Q%6>8%QTm#qlr~{QeF7!J=(}=<-u<~8KX@_c71lv5n(|G7XG4vx<>o?XO-*&Rd65_Wz;?XbZ*u31k(6=H z_o|lrdCapSSKRZKjw(f!9`VW9wo&3m%&g<6nf^DiT3iwdAlUot)BdN6yq71r+baPV zS3MX`7xSBdp2YH(sHF^7rs2o@-q&OXHxLTvQ%lN2uPfcRZu#%1Y8k3p#f{dnZhy>` zegFXI2U6&~GO19*I9L@)_@24X^S01l?UzSuB}eXzVHB7;Y$V$S$!grba<=W#KcMF3 zrb-uAe1GI_&)&g44_6_91Qxlz#f;j+3RJeoR-@S4(gu4qnQ-jDnW3F%-|5VQD~a9Y zo&=?VCZdACnmyfH(E$4&RI!{w;^CCG$wa6W_lH%<(a^u6EY4L?!u1>Xh;^qr%!QLa@CYSD2 z9<-7B2eE&)Te+YYg@G4Mhu~qHA;^8C{ylEW9_Dvx;eLd%(mhmxABl_t@e~ZwqSVq@A^EgmE6n*SjBNWZ zq*5FbU=MbdDW=3&czY%Jfl1uKTpW^9(-#?D7eJrHs)NmZtQ%7{KZgS>dZ_!6@)t=r z^l9;8;TWf?m(=MgXk3d)!t{ZXbhNM#k6R_YacgbUQ0P*=b}vGe*$~t;pJq67+vocF ztX4KeX+i(Vy?TW7Epq`LI?QQ?uYtIiM*QHIwMfTRl@W+d@KiXsjTzLEB4ReT0!}u$ zt*@u+VH$u)?t8c@-y&&AL2F6piJ8&w?HWZg{SNE?Miu2=Q3kbSEAh^aolIx#Pvqs* zJp;{K6!Tj)9exNPp%px7Mbdw|PB?4W)+B*7ERH8$)ojO#Kro7UI~IYDiz5c)=eu>o z3j0nO#JwB!(>N|nYvWjTYZ$T}>n0x6l)TBSwdUrg2R8e@YjaNbo31Ka8@oybi`of- zD-a0Ls$y}L5!uNx3ForiiERN_!r}_GA}?9DlNN0;Nr~&LZ@?Wh5MZrTH!W)22m1{Q zVnv0>ww&%!1o&*0qnaegK=L{FX1*(E(NnfHV^fXnfnO|Cj=XLdBkflzh1Px zYN$R*56D&`Usp&kvFaAAX&&CF_d_&Ys=)j_!B~lBCEn-Tk4UbKUGslQIOJxVy@b?_ z8$Ldc0MlD+Xl6`2lc-THh{8Y9rcB<}L=HnCDv%Eb=4T#bDDc%zw^5osg@IhZmr3bwnHD99y% ziQ(D}n#MoNN387E1h5uC#upxPp4tL6O3SDKcEp2+-o-Di`%~)DJ;p@sjb)vbCkvo_ z%#OWtGsoJwl-l$Cy#oUJPR{Y#uXt+TPlk2^U-V&LR~5=Qng%b9oABs6>wPrQ(Sfmwk)_~L}>irA{G{t znvty>q801;1N_UBkENtKMlWp*jSsg4I`hMjWNPtJcc@TjcHK~YI1#`Or1Y|t|8s}b ztoa##{V>CeHT&-#QUfiim7x669IXzea3qk2Csk#(wl<+e?6h9`;?m7!9E<>8U$#Ff zhShl*7WjLTsMK~p2x&UBgn11F5S`2}4om6bEZB=4xzB3GJMprM*)IjD`pvOjna&?Y zKBAV@(6VK2IH@y2);Nq~&t(W(_cH6#qUt4%R6U0X_L@oG<020p$?lb&$$S@u5Se^! z<|yY_V8SiNhhM{-wzX%E3lR$BlZ(+(=F$Tvqfx==-MRM{ypvcaPJvtgvIp+I=cqT+ zY+Sn~!<_P_Tx>Y8nG=}`zQeQnf^U8{yxZ8L?Oqrs3au_RRWM`@hEc70>V*=Hn_E)J zI#zdXI`!kv4ry6zBFo;b6+!`pmaiZoRzUd~;ugWx*aDw@N$0h9s_My} zq=3O;S7M#u!W|u$D@oK~{gMsr$##5(U3ywTo_#?xW6jgeV@Fl{Tzz(xF%;-!9Z1D_ z&TjYKf3bk*@P@l064YbH2O%`t(X#A9Ja)bd%8^rsjgtq*G5OgEpVM)T_ik-lZ$^eA z)zRm5)*rr1I5XMx;`1W~Y(6t|aXY~#mYU}%06EEf5kDy;-_C!1orior?6 zdOO5pDthlbYk#1{L$|1g*Q*&eh{$_sbt4jbg}ay*9-;Z+-<9zQdM7Ff&ShU9Y1`f4 z!tQue&NWJlj2cz6E*W4{KdUU3duCLleut!vL9p_e4-{Xi;?QEJsZBL7I55g-OE0uh zZq}C}pjJV)wmGp-GX%vE1_kd5jd%N{l{um)0(4_<4#{$}YODL6JKb86an z@eW+gcQ|q`SB&%Mt^AEkiq6FRNE5SPH!lx2kKEeZ+wf%g8Y_iLGMx1JT-TDLwwv=%joR}o{Rb7?ZBww+nPaluBb<17ThKSkp!`;;O^`_8Ya_t3@uY}j8A-`@e<>G(wo8h zP>a<(Ng}&TY7VmRl~+B!q`sAHU1NK{)<4hyg*z_ ziJTk>Uy#`C|4H$1Vfl9wl09(jkjuN&b6TS|BdYnxL*CeRScbh43p|t8U#Zw4zJb8= zaGw&5EcDsyL!=rff$KaExisrw^$~UcG?Cf-`S8PNK;*&HFayxG`8R-><={!Q~g-Ks!D%5fT8xsFu^EpR?>(XN;bZZl_X5 zlAt`@KI{AN>iMXA@MLg~O_0&9-n~yL<*7F}+<^3X$7`kmcC_|WHssqL{dt;U>^y#_ znFp1jsW&1$KNX!F z?ykDL04hMh^q|G>`?j{7$p*xaf+39jxQ4jA$hot_uvpFYS)r%)t~RJASFp?K)$eF^ zlrGu^mdm?32w5>;y&&KB_--!*vbs=lt9}TudpNl6UEB}~^NI@PJFZD;X{b1)r(KwN z%_iBF*F4c}_!!f29QD2GY_>~$`ZvK?DmdQ6Vr19?gcB8|J57d!p5r}ukloPo(gb~b)~enz<8 zK9U_@89-4rw2vsJOM~!XeKRd{EC1slg_hf>74D+bi2>}mdGUKT2PUzR^<50OW`SAT zSG0F{!E%>+_Sl*1Qm}jRb&LIS-Kc#otf|pkdShR+@{P=#vr1E47yZR_1F`Js154`~ zFsa2oQ4oAr`;-u|f7;(#b-f zO178vkhm-;zR3hif%2_nxeAHuwmNM&*H_#l2DLAf+H>_HC7m_<_Fcns^iZM6&204_ zeq9>jj#kU}_O9|etewf${D56@x=9IjqQj<3feuj5(&z5m`ReGcEXcSPvV9?eOx$wl zRkR>#k_8(U*npbAm3r`g$YHFr!F;{E!Z9M%L_B&D$BL+9->zYI#@wNvB6IhtV}H(+ zP4xV%J&$l?%Bz3djMd$R87tSIn=SBaGCK98FL?;uv%6>{w`^8zm8w$;wM5) z&xe_Sww2P;6Q=!(bUQvmCd(-h@!1f|!trdcHwLq5bPAd==y9WJ@azfjDjB3vT30*2 zREzL%s}V9XR4lNVZ{NCU0v z<{fZ}{@kJ=ppMJBh-l;OqYTOTsFz`j?lcdq$IDd8mn~IX>it|fIDpL;R=8HvqTkIr1fTUb zv=t$r2E3*@yZBa1oN*=Lb*(K$i|hG?WI^}5kKPG}D)o<(Py8xG%!IsE@q9L||E1mW zu}BeYsSJNZ!t~MIq4iD64c5EpJ{fwu6)!KO~XrlGo-Ph z)wdH`SrrC4T2D&p}{X6lSbw&UcYEiP>RcHJPFrwuT0}Es-g2#N){69 zkwB>lY(bK{$AY0c(Gt&}3^W&l)>}nUgLkz^1Ovs6vVx+iORAeTzh9|HI4&c!Bn`L6 zSK~d!X%4{eRCzm_hMuCtLqZjtwjREO3LacGS-1IlKGVlXT^i|89+aOMreWMWI??Z+ z;y;PjSg-C*$WHdie756{pXxx7D>i!5L1tUGFhsIbEk3oQOek6d_lS#a6=5j@cbS98 zEW*}xjrF&Q#SxaM`DcfVLhc%2Q~8{RK(G9v3%yMdUyp{Bb>up1N4Um<+NnG8zN5_D zBJ1k}gXOJtYUDZ|98^+fzNPbKdxdUB8!fLtR!)#J@51gV{&or0q!%ufXk|aLzP_bl z=gU)V`Lihmn)+@g(fYpH%IcPQ71XM)VJ$6s!49z&cu%t>(Ywg$q4ag6P=7)xqWO5K z9QpNiVMbTVFL|+GU*ANw8NIlA-_Dr2y0|Mu8}dCy*;j}lacrTt8*-|k2T^0cckyZa zclZuD&Am4sN-A=QkRoX1(HxJ>y^A*mB97aDB8|jY>ksb7ZWSftS%t;~31bVktus5J z+D!ANhE)wJ&wv8MnRlGWC+Oo#y2hn7)1vXkoKznR(ryr+;fpX^2fNQ7;{nOBwl+jx zc5$Ox&v(iqUBS~JJd~^SDu>b$nte$Bpm6A&eri_#OvT1e>8%gI!FBmmPTuH+v_Vb5 z^pL=sA!Ws$o>}nEF9R$tKchV4Gkv>vN14q~?hKN6-|O_Un7g0RvZQ#npCzmy(Q37e z99+>hVh=xZP1Yr@T2wj`x7YfrR$%jr%8fnHNflXzbw+FBTmmB~^@O%KToPwmj>bF^ ze_PaL?$w*SK&bZ`OOU!CJ?uZUC;a#_*`=B+4M8|&CZbF04@_V8ZWVuY>kp+SnC*|l zgg95Kl_{1D(Hlb5x}kmZN|53A{Y6RvVU^>~fn9^^HnQ1ABuvlIHG*!P!4mm}o~2`5 z-TeF{LRqV1zhfB;)OaY0sd9)+~%NN~|=JR^vg4_(+Hr3Mz>@%BJIF&+Cc!ZY9g>6AJd%0r2@gSOReK5O&}j55-c za2V>YY(su#kMY0@3p0=!4%7#nhS8u~?O)c3On2EobM5Il705Hkhuy^+>L z7ywrI5FE+4RNUC{vOuB5f?D!*_Xtgq6wPW9Kahj1Z0g|LGKH^Sie|YTO@tTt6hU^; zipu&<=R13GaQ@y=0O07esxCXUFrx0JwA*gwvcd$)7q{>#;#Je%l=JRelTh%-p}h

oMSwO+N9r1McGJJfR^aX=|2=O_Kq&xT(f{Bfe@h7|#9KG@nyL!wu zzBaz+4ne{X8YkhQ44m@h`YoZMjHZ09WFf@jYy3cb6Xd*E{{Kv6ew}QI=A(veyeb|1aRSfR(#7Z4l-~N|^E{=|iItPT=kV%lP_b*Y zf~-`37#~-2{JAIK5V7xGF7YJ}K=P_G_S`Euk;GgL;Glk3Ln3JUCvI)a*X{kkk_N;OcfWK9iuQ0K5e~szmTL3{i5QeVWFAlSleILL0E!m+t zcu5o^y-897hwz*(z~Vlg68I1md8&aVaXvn^|KVd@rB$r^VxYQQAV+PlCSu!@+|iX@ zI)8{9UqUbyqB0w#IEgaKegqhiP}Ip?Jm>YoL#*}qR3UtjUVu>W1_$-yhWncWzD}Q<#{{m;XVbuP6 z*e@l`$kTDE!PfpB*_J2|j|nP_qJ7hrTcYBm{MEKd?QqpZ_Ay-o^3+FaPq(1N(>?Kqz8=_%iWCAgCF(HU2ygg|{vH0nH>%-`Xb z$AL=hlzPMD-J zmeP-ZuO&rzY>JGcKxcDtHz$*(G0Z*p zK3^kw+#O{|hT2_j(~f)faOz5GC;EyqJ(~oFA#uJ#AgGHM1fL9cZ{*V;F!2=AO@C0P zqt(YrakDk=;JG!b*x(S?652QlVY``xMg$*2BAtXrq;M{&u(EBnpuadWr4+~$L$sv?Be<9oLd6Qt#Q(4j>r zQs`H$!VTf_Z3#DIX!C-VoI9>(E7~_$TD*Ew_6_ZcE*OYuQV~}-1lpys!A0;Xc zCtvC{((@kGw6?dMPvKv@EB;dzmKL2nxwQ8KF*&+WRFnw9mn)kd4!n+3`{e=|jH5Lt zADl_+(XxbU(1x8cp1SbWj_BTWUI z9#AkYVaPh zR>Xsk1|9?N>{d>GZDPJiVBL1H>GKA=uGWUP!wZfNAjDC>8kFB(I^}lXBBu*0Vq6V; zd^EZFbzw|N@KHR-o_aN`!?r%FUGSo~MB$Uvv^AvxH2Ve!)#GlS7p#(c{T1V9eyhk< z$d0G4jiE@`{0q60wmiX1{o-@t#h&tJx`i~!d1=M4-Sy8svv|SpX7T>~>IN$kS-ArL zTz?Zo;-DRmtZ=i6;Bc>wG1B_Oa;vLFbWN=XIH}yc@Hy7u$fbdT;0(FjbN-#z zT|#w}FJ!6KJ$*iUYP`Qziu=#j0W1U~1PFJ+^rgF_&_kYk#>bgIMrL%M#s*&$ls3kf z^p}yh==1+(F<-8Gx?n&QEG256o-q2KtBQl+GNvqvb+Qkmy&B)`ePpGTzP#z&cF|Fx zhWAu@H%$gQ0nZ)@ear^p=W%#ApG)zd_gbr;{_nWE=$}{2X6gnWQUzO+t~}yj>y98H zNv$b)_jlb6-1xhaGcP`K)6ezJlw80|HUm^g`K$#_R)Sxwc}wviBjV^Lu;+27Jk5qu z%|r5kJ;ql2Ei}OA4%u<@OIVI%{6*Vb;}xCBB5etk^`m>vw!6Fe8ZcXvh6U+4`a=IL z4B@|(gj1muI{uBn^d-EAiP5BVr*BUtbVm&@;z%vU*zLneQ1txl1!Z~hzWr+i42%ZR zwi&b*J)z%`0#=>D)7ov9u;dUsQs3+Gwac+^7~Iy&#NpMjqa%&i{|%e39$J%sDa*h6YAAP68HHHMv^}iZ?60jgnZJ{Cr$aWm=jp&Qq9gp8sFl zD`keayQea|apSru| z(@+@6AEO3oK8_JF*Irj|7}%RB9D2H763HmB_3RO@j>Yo#?e3G>>@H0?o4?1Y zPff_R6#T`bZvcEa+`^xa(UZ z`|2E+-{+He!1k8HbQd{P{vFYswIK3w04r=@akl>FYq-RD(a z6_A?>eikO4j;MUuGa9ubH`S!*G{_0r$>`&X*i|B3O?6QYzS5kx_SEZh-%4@-eGpsIn3;S;Wypq278eN8 zq-M!BMrX~)HTRO+GatS;Xx~L_@%Bc%SyvMuu-_i($2>nc-*84$kDRibL|(@HH6Dj+AH;rGAukCWocFx*>fTK_kM9J8lQ2uyFH9Wi61DK zp`Bn}v%+6sh0pd!=M44>& z$LFPM2Q4USn=6d^4TpHyCz@Jrhwz`wlFWq=eSuM-)u8VX8G9weBQVkf*9xjmH37{j z_U}fKCm#&I-27KP?zB?A!5^DXUv7qE!@Q$h_`a`!`Ct;_fOJr1&dc>s6xdYp$G{1Y zSntz?IUk47y{vj~x#-cBM#IDtdipLI^J%wP42|ey@f^W5B1>c%GIa%r(-mMEc2Ap2 zDr4bL1$Gxww7Y7d#G5Nkj~(senT(?Cxmg)2a}=`V5n|8M<6iw=Rs{L~2+-E?D-;yB zXx?&N!MR*SHC9ol%u&0*(^ZAHXhf=o{fPSl*np<4B4jIE{AfOT-g#36mx*-xT0<*B zZMqz(nJRD+Ja$a%OaL-U1INo_not$$Q`uSFET=_-{ zaVk_hngl}+bjqx>cqh-jiZ=vL!_Rb^IwCD8D2k#qp=t%Q=O;)Jx3Q$J`cZ*bkQTnG>!QbN03MQ)}x#pH65%R9$KqDN1s);O-`0QPudAp)> zrSDNur(;Hk9~}P#>-c;4-@EPue_sw`Ix09HsSx`=Uq9yC!2M)?wEf2edcqo^))CKD zj@S7A{$D^-;qHlr3Z(gkh&`@rx>nY@Gv!vhK5t9(e^S{!I+eO~QeB(+37-wee5sCK zTWq>ZPbSWrm`~1>>>4yd>V98Zg0>|N29u>F<2pS&bj9HvQB1C%W<=~UlX$g}(77F8 zc>OsK9Ij;7*XN$s^ZYM+U4bJt*{jd+pI1b1G*wj zSGsLS;g||X2N71g3nB)NKL>DG&=I|*%Ajn^3RA#Pxj57m`ubvH8_G(Fw&J8b2F^c8@hPma%c`7A+O|oHpyII70-6)bC=8MC2N{DlRY8-{&9kTxS*lG=?h8=b&-y)MlrvZ z!l}#!o6yp622Yv_ zbJ=S=XPR)iri(vb`k8^Nc9ITl5IPSl#DOEuD2xk4GTd51#Nuawh2?BZWLE!}rz zeQ0?7e{us2^>T67rWSFhj^Cq7rE_`!x0#{}pJGH_>+SUk-LX_PB-o@%R=cH`!sj+Y zg5uh)|D%4ycUD>x0aLMlHI%-7CgwRa2kv_G84tfWX)+biT)h{-T{ z>BaIkz6jb@ zxMwxUn$I&ont42SR@Hb?zU3qNoi^T?stshHd>VZ*`Ck2%#agjwbV}U0eQ__lBsTP^ z2%p(Wl?FH&XCPV$wze&W9MX>Tv-4W&>R+G@_%D%o*ywK~9et_&wDF$LLRNZjU#0U^ zU_?=^b5|i+43otqi{8-^&+OGsPk&tPGFdaXWK12W?|#6*XMIvL%IDbjan-TcZqJ~p zNq?A$(KG{29WVCW%qHnPHD)#q@~r{J`(%L zu%T2zy!&2K%<-d|ud>Wel_%hOdYHXH#@yX_b!mS+r@rjvC4}rhTu!b2AMJf-SX0}& zF6vTLL{yr9G#echDMBa;QUvLpP(;Ackq)5*L_k3V=`Hjc2)(xmN-^|a0|HV*kq)8c z&fr>S?|trCXP5ijbI-odntym6GRGWcj`@vmyx;qNLz-Ay8l$w?atQcp+cRq-PMlI( ziL`DLjv^UD-90`WnN7CcmuaC!WO7N_vE*T?24kkMMH_gt*H!V{p|f;xS=+(SXpTCU zBQaFJ*yw~M^Iu$nL6#3~tceO;TZbIpTOTwjR`I&}M z0_nWpZCzJlNz1^v6T^6oRQR`dMjeDk%bnu8aFW%*IraV*rF$%SN}L>&MBNDHpP%D; zRy#%=i?}%^0XW&r_ciwn@iqGu0OceiiUoEIOFg|AXf0RXZ zONsQC6au z^bner=^3wh=EU|tAT%S7qP(uzgPZGc`-gGTzO%T90kWP72VS6rlZ?QN|nWck^V~ z2fF*ur=`(%@iuMMeOL*EOSX~Vq2%m^5nz8sUB187W7A32Igx@gbMWl+ztfj?j%?xi zgh=xIx2(HOdZj`@_kb(zzGcsOD?ZO=6lhee4M)FuW0X}!bV!1VC5Sxedp%`y)6J_<3eN*WbGRh z@#b_gk*VVFA*p$_Q9kzo8P%#@na(`@{l{fSiwNtg28b`Rx3-MuLtGNZQhNHeESagb z(y`~y^^E9MCuxC?1_DDBt-4GtX7$_^@{s}c*fLw!x>a6r*!;&0khvLr>*rcURH=N6 zSX(Og0zME^u(dLum1AJkeYa_i!slayO@7@?VvFMG!DSwVu3<74pPBGMrFx5&|FVWs znK)RMgGsnZ`Df#aG-&U9;Ht*onV&|Fk4r?9J@8g)9K_*-omZ5;uWSI=(LI$3Q|Q!n`?K#h2youYm6`ljYMf^@X-{%XUK$BQ}STMQ6c zW70xDf4uW|b!a@kNx*z$atS7XKA`Lr6t}Lru|Sr|g*}=L5_6-|OdosGPD4(!tk?Hx z@^hi*X9vrf-diuXX>p_J9k=EbXpmh{;qghSJAT^d^l{}@zCB7ry!L>|s!6GHuT-tH zxWdcA+lg4qGWato3U`WVT=|c*X+Rsag6W<=y&5&t8ruU7=z=-bPf~mywTgahn1YOW0uk(f7j(or>4D>R^yvdz92e6W405lH^ zEUGZ&W(My09-u1r=*Zx(U&KL~=ut_L>+7W^C3(V5pGllx_kfoow#%OFel}UhEjg{@ zs8dsXmH*`7FA3R}ZnSfuu!mj{#EL%4qYJVClZ5Ze>O`Age@r}Bd41I$!lS0sj{{Xd)|H^Av2E| zAE0#gzN`3O38hE~_VJrAA;1^M8y<0o2K@!eB=xelqq8~g1QGk>G<}PoDETXI4BA!$ zs*(Fe`!2mdp*^qYf#IV|dG)!H2vVWgi^NuLpLJsV3Kp*}DXjUb56I| z+{AN=-FhS8qy^$ZHKcf+#%K_%gxR@#!A}==mrMIxdvv$EBPUTS;Ts+cn_x#L&D_(? zq(__KlmR@enV2^PT6L>!S+Dp={Xpcqvf}&P4Oeev%ocpexRWvG52_g)DrI$pE`(oj zTao#~^Ft{fy@G8`K4!PVTt#9P|j>q!L< zx3j6l#&M}{%U0t=hU9KaT8q;8UHdDKN;Fk;++wE`n_?jh_{wL$j3ST4{f;io#FNOO zxQd`N8C1+Ha_QT!e!d#P!X^kF!iAvKDzI9y+HRFZ+hOt|`QeAmoD4MXE%ERSZN$bW zEtq&2W;!E!)pb1M7<*YR;5L2CtcGEvGD`4xbAQsZt6#^o7r#BW$|ybxKlH@+6g+V> z%OPl!AN4ucof^#JF%G&UaeZT`!^_h5<(HbC$Lxy^b*d|AS9>jt`fR=@e5N}Xc zSR$sT3XZB@u24v-HK*O3%f8G-SSh~QV8?cxVJeDCm)loMn5+VLm^tLn99CZV;dC*g@Jf4|fa9QP?&T&H*y z=6-o?GVT}^aiZdO^_Nzf<;e$n)VjdUAd7vPloXDJ>*mU)bIAZU~o>E z?LPm|t5{?L?gInuxBQ*+bPtL`_WSvGMESw6RioX)`v9F<4|5RwenT*z&VTx*q?3!B z)?~7chH;IRzQ{p!e8m7ZxRJ?wF0XbPeXB4q(mUXWRR`%j7FFjJy*R`SaTt5rAA2z=4af&kwPj`n zDnw>)H8oR^=;CFZ}#HZ+{fO*vB4lE zJ)@U~*aIsAIwLwOt^F0@&s~sCORGuUb(7?bhdRe2K7ky^=L}}=oTuy*W%Mkb|N3U& zE6v@I>>@H3bN%_pmRSvH=O(lwj_U@^wUui?ghj490`m<}ww8odpoG2b*C-urij#Z4 z7HENrcHfGb9(C5H>M1W4zQ+2FXn3fx0jAnkQ&3$3fxiw76| zq^(&lFAt9nT57+Mk(V|Eyn^H$!gphco_@n!1?OoV0D-D!3CnmQG}1s zM?Z+t?5z*eyZZiL;=)$uXtlp)@`NemlBrV}_U|Qqn2u(=G|3gELYq6Pz$AGsSsHy3|oXRO+?)K3;T56eED-Zbh9WbxQsCtsxw z5xRdU0`hob-;K7-bhiBDCft4HH*ml)HXHAhqdV>@^|enj=~*jzVu5FcMXI2Kl~1#Z ziq5{vyQi%ob?{&*<7lX@<8BDoctt2a9vChro?t#d<;9&XK~SO?3~oG(a`Dr*_qBOI zP6k*>+N2CWAn~S@j+?QEWS?sul5;l6fZ%#u|Ix<#> z;4|up1E|L%auz9BAo=JlWhCI3%~D=dQE^Lak3^k2V&+leG_@{Hw#+4Cu%U&8q-I`$QK-8cI1g4y7KI4V9rzg;e15KVTN7v?t zhhDfz@reHNA}}6DznZ!nw5wQW*N?+g&>yFi6Fe`VGv@$xxLJfnJPYwV-@E2TsxHHO zM^kd!qJtKG8V6G@AB0tEMTVwRuDXZ~4ysaUl$Dpzj!UMfoZl9m6Zd<1@(gb%FoeM^ z4Reh6()&CVG?|_J=Rr;1VeI_9`ejZ-gH&w}Ts5T?ssjR=9Emhu5MsZRVnoq0-e>u$ zHB zlb9Vbjr0s?+qUNF8ni3O@yV!fnJc;yU&7IbMj7nxHc-u>b@b2Zii}555H?^$L;$e0 zeqAwQHd+>@b!;0j1sllK)!JGxs#|MAMbF0#;R`p`ct$}YGs@e_3Z$G<7VFB-6}<1T zyR6+?&es+82;urQaq+ePgeU%LGKd~+I^c&JJxNYB9HHdRE+^Ig!BqaovBi_8{5{g< z??0}R?b5#8Ok-oFHOIB!WY*cwKZui#0On*gW@i5L8K@$lHqVc=+06C*eD}^=(95)6 zi3Kld-yANgO}gG=vU;kSQz=Y}n>zU_32-H?T8;oWx&%PK;PH44u%iU)ioQpkhX*{8 zbQJ;YjFc)iYr<^Enh*1+<$|L_DzX9)Q*eFqjPMEK?V@J!joGK7zHDB!*_cL0WX@o%Q_^oVfv=KB~y2mMp)K$wS}(lc1b?%cUK z>>N{PQg;@Zk)GmMdKy=i)+k)*WWOrHWHCDWK1gOMd%PNseFBd!RhS1YViveBQ+GIW zp!Gm5dg@ADiuA8jQy~Rim50emOLYZ02hBfDL3YL59h~QIOEo}BwzOy~j(h#3TVynK zcTs!}O>d_*%c&T2aN5a$Tw1J8l_%!B4q|L~zZCNMu%>KHgz2!#l&-z6@6w2+!3CI? zyuq>meNkbdnzPRW4MA+IOdeDm5QcEcOI{DFpcmCXVuYuTjn9K3)hnpNCOd>Cj=EFO9{7PGnXQEcRSA%lv zu{75NgjOM#s%G$uEE&=3-4hRz@jn)m?#>Uv-)70{i0DFFI}V}s)fR@2SFk(J_r||_ zUMNXg>8ny3vcqEAJJhS7T6p=hxXNJ;jZU$;*N9bU6=G}TDPtVjSP8hRp{rhH0G#7& zT?%_NTs6-?J>ZxvIe|S}e>p|< zierI{3tq0uxZ~Wr%JtOYTwuCe0r!Z@;)XWv{qP8*3A9d(rFVY%l&BllkY3O>>+Xy7 z5O5gP`&Z9k92Vn&R-Yqx7{Zg^<5=Bxt4&oDY4D!Rj(gKLHyf<9g}!nbe+4t%PNIen zLqq;|=4v$=o&9v8`_via*qd3bYCR03TD8-pQgHkGg^(Y+gS8m_U$t)u^qaR151?Zv zENgul;%VvqB8$V}f?D%`p^~s2J9N8}!nZzdp>KCy=tagJPqRD3varp%IqkeO?XUgf zITnsexH^&>WGNc{?V?L_=j0MYoyC}cI*hDLA(8R^L#SWxA^J9qS2g^G+U89xED_%r zROH93W~^3@jH5&tu8)`44vLsct{+ocD!ysgi7a-*US#qhJo&eT?837+2iz1r zU|)-4eLhU1FNV#BB-ZNCh#7a32N#8ll+4S7yc>bMV%);De|pVdA}-5Dfy<*TnTNP4 z#ZeB7%)i#kbG~92*}G+GEZrgRKtqm4t*}i#Bki%Bh%waLOjgZMJ@8Y~-=2wz;9;q< zq((jDN|}Rv3XK+l9hP=nHd2e`g4yQno)v%e2VCM4#P~Z9H!-vFC&wnPfx+i1U7v_#?R%(Q40k;qpuS4^d-Jn}^l0TW4Lz$Pca|9wS zAG5G>Y?V>lth^&fMqNnkmATn$JGzI^_D7JE3tsC$-W081hevxcveDB?eFZPBE1J)Z zx*|7+W5dq@7(n$NSu9_(5{iX6<43B$MbdM@6ihhs0gD-3Uy!>ve`8l@wHn7AZ9kf? zI&y2Dma3u{Qa*l6;V*c`bMSgA57FLcb}z=4Hdt>rs>Ok2Cb~&R+k>-BO*gv##p~R>C20;naeP z(H@LAFEl-AN_hZ9a8`+0N%#xBo1MK#IWw9S)C}o{9L{1Q-DQvtia9J zGmLCe40BfCu1<5xCnNin?h)jl&2VV>Z3k9N*4b#b&)g@djebyLfajRpGO`yGDp zK361n{o{OG8Mq88K3mQQ2R|8pw@JhL~4;thIS6du(`nDh( zC^VGP?wtp(r4&eI)jt#xd00N#n%$aWbez9^TTCuEC|X+M;E9zwtze5oS6}n^!=w%2)QM1?g1h)d>8n^8Cbaw+# zP-l@)VJ6&+e%dBXF%T?_A0c~jdh%$at~JOZX>*Q}-LF@=pN@2-;)5%!_s>;TpFu$2 zsFLLSlGKTr7zNcD~CY*>Y{s=>9|U@GaY6t#*i~wa+7U-6dgPUXy+oDXxN0Lrq8Jf z?^m*J_U`s?h8VYo#M77bd7{y~hb6{k$zI)}4D0uWNF^akpC? zJldA^4`^G#^bid{F+Y%|b!Ru7Tvt-k!Z$jh!J$faGDVyt#6G2_7tM40G~Lu`sU=A$4g3^B?>a$@w@>`fIdJ z_u4+1OLM&ZjyC(N-pQ(N zUiqVVsRC`TNSWb#WSF_C`*Zmhc?Egkbyg6&?VvOQt$8uTbUwC*RrVbW((y6=D&%Bi zOOP$`2>^~1Z99;obW zH>PSm_>wkr<1R<%C4Cdlyc$SkM=Bc{@2Pz_`wmfqjO3UoTpN)%uQrnD1c}Ou-#OOF zv9ca0OIvY}w5k!-ev6Er3fZlBwPEdYs(3>MGzl#CMRPD_tw zbHhqc25auw{~|mTC_1b+E}2P+mcgX#vxoA$z~fn zmzZJlM@D`4Fr_sviVNf`dK6{)T3!|T-=B7YK&9D`3V~hLXQ3!v=pQ3}{ zK)|hZq|(Pt-bWf+SE|{~axHT{d1u}L?K_heiN-MuF$zDJ$MUA-uH?Z+&C(C7t&(nV zKQa2+fHB1h2y~I!+6jc(Yn0kDpVijX*GIOykdU@j$S+22=M8CuJT+4LXf!uI&GSGG zC4xv;_S*TetdaU~sE`TcZ1-H$JfgYJdE-^a5_`zW@k-v!O+**J4LYo5-|z})o%Ecm zN!!lQm&!cLAy<-zG+^jSg^-Z+JjaPExXZt(%i8c+N>RNW2-^yMjoi==Xd{KhYj0gD zU3sCu{}~siFSWgu3{uA(N5i`IH?}f`iJkq@PQK>kA_Cl$zY)LBvc?E@#g}B&bLUxg zQ(eTi_z!2dp~ZD+ugwCb}lG?n(DamX18DTkCJZJQPFv0 zW;yoY>C|@tTzQNKS;ckPd(*iOh`aPGWFo8e`ivHP9?ZHsv~_Uwqg8w~C2SM!Vf**+ z6u~hXe7l8L^3kwT)bpVzea2$CylYK&sCTs0&S2Mgyx3|2e|^;|z^fKaP_;f-QX-NtJ-!3!L%UTLVepT*Hk1Qga$Vci6?7ybPRPoj>)>>B?eH=zIUAM zEw=G=RNkX|hn@d$5&LcMYt^QAwmCpm8yKT4CO1xHr0*U;svQ8CPm>N_$tONOsj-^^ zc*h%=;-!wGa-PFuPirb}chIng&DB+#7=FBx5o=e_Ig$51F1pgzeIxq8O?M|djr)ry zjp^ni7=pFZoq&D$dW>i3_lql+SO!HW3GDoBgMX~T5HLz*HP(g zj0N0FH)%HbufWNRmdgY7s zMWhv0r{MD2W7naD!=&)(s7~09Z_Fnblm|~Q{L0DUHQm1edFda|6rqjG01OAG&l|q2oMf#%LB!;ti=XLLYTgislOKLYfMd`7UI^ zijUSE{IhrDfG;^t#C2m0yZ$XZfN{BJaMix!QWFRdx-*U9cNsXN<%Ktx^dEd7n9dcu zF}JleJ6M+#C&bZyqMjh?rU1T&zb0L#v^_a0kRJd@ok<5RRIA`tQw5+RCZ6Betp7NE zEFivT_Zt@Q-+WSETtsRF*=I(N9S7vE(@|X;$h(llJl{7ZIWg|upnGs?t*ONy6ogIg zcind-A&UggLjIx|w^-&i^vL&ggtTgjjrY8mt-K*EH$EHDwy z1BW4iB^DPjcao!F+Z~eWchfm;&9~oJy2%^$#OZuoy_D7fI&^dYhfOCuDYz{+@tSs} z>4tayXDt)?-Anub8S;$QEMt|6#bi13XT<`^2MAU0(E~>YBBLtYR!d25dNf<6Sg;M- zFAiX&P_~dn186!QkCSnx3dP!FsH&MwPS;4B!7}agT53OD1n);}Od^@toM{E-=TJvY zS3xG9asRXhd{O|nYz9O)`z_4Yg^{buUQN<#e0c=Se|1gqqJ6gR)VI}11&5nlN7^}8 zs<%2u;!?;N%;E4-)Tacl5ELNM&&MU#ML19)|8v4$j$o#DwV{CqUF*A&p%#wCe-t& zPZF5?4^3NoVIJZ~VfQsvaA?6f$adoXr0iOCRrn~&u)Gk=-CxtHwRBOSr43UzEYm(2 z8rCN$B(o^mn9JilBP2~v$0|^%&KQQ<{02if(}TdbI3mn=WYp^v$=0gT>V)8n^hxp{jb0KoofRHjtAsnAvA#@Tu?En3VdKf z3HdBxq)BtJf2^X+$kuMHu=B&*fSf{s7sCtpIClVjTl(scuu&5?Sgf~NL{v0R2xms? zJ|wO$XObXv;~%gNuM~mX2;kYt{Y3xM&*}Ux_g#OmZ(8cnHBI3_0G!fxSzFIux@1CE ze=_F(D(}deDZL(&@YOP%aOD4zcI1}nt^v1)0Pu_V@(*Up?0|~gSwq+ZKY*;aIW##d zW=-QmaDYb$4F0Q25QlpeR$zY>0{_$rrQ)7fYe?+}{7huhoLXG0N~9q1tKV|_PBS_* zr|BR%o4{ig>!MgajIL{pJK>{;(gU%k?UIrrZNB=ZK1Rw50BfDZG~vH?#L$ORQH~*8@K#(exjifRGnxFek8JDagzyGUsVnoQuRc#%tW5cJrKr@1`MJyg z$Bz#A=Nb5bqX9JZk2nJVXO7y*ga3d098Nm+k9z_C%`5+(ts{)UpY!g2(Am)c%9``% zH2!lM10(Qn16lup>-4wN_y>NZ2skkZSnD4j5B3eKTt8)bny@kU=0EX(KE-_^pj6Kl zPFCf@yC*KCHu(t-lXu|+#2@_S1d{x-7%)!%Rzq?vX8=k>bneyDCy&+te1}9te@^Q^ zzw|$?*uR?<`_pp$n^`UZhrr`Q)acxSnRbq__M9Q&LPXSsvOYP%LZ3=0KFODO{`!9b DzyLPQ literal 0 HcmV?d00001 diff --git a/backend/k1-390.png b/backend/k1-390.png new file mode 100644 index 0000000000000000000000000000000000000000..f512aebdd37c8356b353eb4cf622ecd1afe5e02f GIT binary patch literal 28532 zcmb@tXE>bE_cl5tk|2l(l4#M17QK^%VASZ*qxa6}B+-dBdKn^m8KQR*ozc6|dpC?S z24jxjhyS_Gb-nNZI`4bl^X2)l_H#XDuf5m0*S+o?`B_z-h~PB=001BYD#&U8061X) zzyswcxc8P>Vh9ibcm@E}^rQ`qv}#}sNfAtMPD z8*pa06qdG@q^jI6zIRhos1=vJP&&h3@jvP24W!vO{Z8)H6)4vEntYYTEYbJ$+}O>~ zOb5hmJ6;HFO9n>!W|T)E?;`8$e;j+JwR!xkp)K*Mb7bCo*(}zM71`1`oL^}mkUeW# z-bs=~OyzD(CUu`Y_-@8`mWjgx{%%6Gl4=5;n_5?6YRd9olb zT4#kDZ9UnHY=}n&+KgqNgiFk_w`V(k*^~6W>_}y8CnrVo@Orq^Q|_jHITfjdJekTs zs>_az)Ih`iMgQhoNY;4zL}fjm@BTO0Gf*$YmC#!5*F6B+KZP3bisCVF%v!1U#l?TW znAOpc`YIGx{KG1iA{%d(#wW#(lWbEE+$Qc4+-+T&OU9 z5nglT^0dmuE|D@(;n4j!4r8sv&&`W}ps-A21Br9k=>hkOs2`QD&-aw4pd{hotE>D*lD!`H}d zPw7wcbZs+}?f&J8wbHx1E{5bs8LdGdRh=>7Cc8p*S$TGuHnZkm#le)6Nq=R*(AmGP z1(~79WU}vYzh|D;OnW099D~w=1$-T!!g1R0*s*Nr2j_NGqZ~QQO45E@MkOy|AcB8B zO{Ks45Ki(t7BO;kU~o%1J3g882TJdw%6(Y#!8!!zf#bnR@}0ox`3#{&|IdN!W_-W) zg=fBMeKYpEOqIMQ)eV)zVoo>7l>rZGDeXSE@|aE5M^HQ{3_#3*7m1WQp7D(xaR_CKeyywBlMrlz7b~JQD{E~Xvm0=xpd}f_fn6={j z=F|M3C)im<$A0>LA~dZ&8H4BjJl_@nLC!lo@bi*ypgl@f$JbN*E!AFw7+cnvX@BsP zL2Yrp@%;2nB=$*pNMs*s1q>D&Q0l0)zQ}ecs>*xhjaGF_Jw~sL#LJfam?GBnQP9fp z6WL>Nz^tVA#pbm`rggpTNB0>~q1*vSz>hYHG^zF3Y&EKnLaW*oJ8E(!$$eC*H`4tA z<);`mOgK5u+L76`S|lyI z#GzTrC~*7FQh+5}C8n?>XMW5Q8hJo%AT;UM@#z>+4*%4V-SZ7cM@mx2poBU=zf#^ry8If}R!+}CF?MY1Y` z5>>MEor~WR-Q~-71oFc}i&etujai~v^wj3Lq-|7aR}!a%4)-S~lOkT$pFQg<71KOS zQ9WijEilmYgi|H$&30nxS+ZjvJ=#{SfYKSY$DgE4)xbfE$ZE#CNMjCn60bP=WAbYg zWv+p&?puhX&DK|r&yMZXLUF^lIX5esRz@$JM+XOS89!>{U%Jy|JE9U#+?Ws!a6DvuvHF4;*LN&p}5wdcG8Gj}?M1i~Lvni5KXOc=KD1pb%C! z$n7uLOO-j2wZZJXB;WD5A6-+n&l{w`#qiOx^9x zstZ{zHwLrg=JeWu78=i-NqF5W1GGTue44F@8`S@;kF37#z6_gt%^i?ag~*aP8j{I8 z!u(qw#p{j;F&?y=G5y(QH%sBu+#u=4B(ZM%xN_!V-ly!SRDfGl?sDR+R3BV7jGe(V z5(%6M*pC--_|01FJRGH>65E<-UG^5WSs>5Me*~#_l(qA;52f*qJ!{5#%zvL_v^Ep_ z=}Pg;MyvS|-R}LSWA!9!eR)3g57O7X9p=ea=<+buJit>mTfxCTyTQ{@Hkw$HwaGes zB{^ZHt|EIs?fhk3<8YIwUu@1WeJ(qT=7H9+X>3-lzyFc*={G6!07SWQ%kC5U;i1QY zLW4g7csMmW8-y!mwv^Cpn2PFJ!UT6Ls3I0f6?jxwxDR@_r+3%Ft=2svRwZ3_Xqo=S zRy}oQaijYLhNalNrP>WbqZ6%pEPbvsrrJ()D{v+tdyUu4*+!nH{dZ4_UJZR1MlC%O z$ugw#ahu)`qE^=5%Be| z$JPaIHBn8gKD3J-eF5%7<;2YGf5 z_+r?`E`?Dc&-uSed#r);L2_kskc3A_qzT8!> z8_(^((K~`I44uvp;x|FFSgysAASLmX?iSc_`?XVJmWwY-&ha%3ndzu=&+Vsqa<_Nm9E|5Y1hl(hpH>U%a+;j)0=8qr>; zW{8pfm6B2C3fb(DYVp}gFo=ula7dRqG(8XsPoS0Y%be{}cVS5md#HSOc`%T}7hX1h zNTE0%+)SJCmCC~f>E5at+bQiU#!oOBV&xe6d^;|NhCQPQ|VpPtCtD!I~~aNB6O0zRc1k z?pCnh)L+$t3gidb%8;_D7BV9)HpA7et>)@*89>or!!bR(IhGZC#Il;JU6uYv|W_ z2kY~CiMcR|_|1YwOzd<$hEL)WY%)c}n)U0-`;agHws4~Yhw4shD1VzXm6M2x_+GjM z1cRzrjvH|RS|QPi0KlhbK)`!a+2?@I4-*~&UVLD}`QJ9>Up72oRt!d_zw#Z1}vurga{2G*4L zR@OK6b~E~dvc|6COu^iXbHxWDY=ucqJBhDbz67Pr6o%cxd1^A;vG$=WwW~vgbEvJ7 z$5K_AP?_mCNcilSEey5%oH2Cw^Nn8}4YDR+*uPXFdS0M(aU1?ws$Ft{yn}N2qsc4Ls*DWAM~t!=$y{4rcWw&S+8%CA zx4CB>tTA%W-H~#Itu(f87q__?x79#91I+X3RkxGGRmF(>3u*BQo& z*Jld8951s^nQDD}Y|D)=nRL~P$D~FinN+&6u$0dvvx)E58)tNr$`sJ|MQz()-2T*4 z+g+Z!i9%qsvM4;pQ#USmvYnWK=dO7>!|SX*bw%uDf{|3+P{gXe8!WCl-6dTZIh!qN z9_DG<{`IKUzYwDj|CnHnNEbLs{B}qjJ1XHY;;3czkRRXNSD%_CpWK`mV9yE2iym_4=XNt1**}E#*uz z%pwu+(&Pw#Su|)cLTahS6STJ_X$khS{T$^?V|Zw?=!-m|_0duaRUO-R)9~euokPJL9=&<->uraj(43-}Lk+lZvMj>rbl@|O)v?e>S7EtC zqJ{*j=BzhH8l3HETTmof!-pZUB6nup3B;6pD}-k=7I8{FGn#So@u|+25~BHTRCK&# z=tpvawm7|gwWKgqLd7FAUy5EWH7R4ZXSy*P6V7>;QxbSog#9lrfaXlk|LnkI9{I?h z(m7Wyf~i7X4I65rY~W=B`{{I@A2_fjyNOOnK3rcuux#VfyG{67mG0$CT4bTQsvk%2 zG{b7tUXq(lKy*#6e|^N?D%?=iXRto}@~l3@h>$o74s3Owx#}ssdp$eknZ_R}N^RT> z8<^y#ZSV2C1o3JLGF?do+~n5as%7I7WjLiYTaK)+R{yh@6&k@_KiLy>?5U(;X?bGu z1xKP?dv?IyE5u0RL^Eh)zUK_9I}@5z6w0~cyI^U2s>JwkHt@?W%;b4zt>KTEIDSVb zY)^J$2-QHibk!Q4W7L?kdJek`SD8&2FJ^e}4rZ=m<$xdC+-Pp9=4LaqDH;yb0D}Db z)+HzIqJw#|Me7?$L_4g;XACqLcBSlL$K*zMxRt|{&P?*bv(exGT5 z#IAWlWOP?a7AX-3%^zlH_uS=4$Bb3{);+JOcA}QZapbp}`DvW;vHfrBY;owM7;qFD z$eW!0BNrC0y4bzC-d9Sy5-D2&i?5JluBk@w+ZC6^D15a*2>K{L2K#c9dE}_GHA31A zTQ(DOB@N4oO#CwqyN+c7d>1kaLJOBzV-C2$OiT)jc|QdZQnuH{PCYy^r&tB1CJNWe zsEn{%Q^ky*&NBn$rNYcHL{dp#MI4sTzh8#==a#_c^h_?9D80f8la5BMBw2$*Yl9O$ zf1M0kOv-K@nwyX_ z&DdhPc(W3S_dF^Vn&GbfZI`$3a$_RMhz#!TBv966BJCn5;QI(N%kT%%6C_>&`zKB%SwxN0(+UK{pma zw}HpL{+Eg1(?jxtPlDW|WAJ$0JGn;XozE=hg=pl=pupp%X%#6Bqaooc%4D^0Yb)!I z3|K1$xSU|zHbcvd<%V0DProI}miEX7`o(0;=Jn<1Y@FSXRs{_*!)zcAYvRrT`)E7J zyRR}R#6+o8cjE7==)eHXJ#|H?U*pM5W)h;v@O!~4wUqdi&&wvCdn^uA?@qco5oFA9 z>5*y%O)kak4UKi@{_*?Ljr%jDhTx?5%Xe0haYx{t$u<1!q}Gk=AWG-FhBx3ev+AvH z+1EHlv3)4IG#8P`759R+_(WvXTGMbDd=FMHZyNr+?O~tVqdpW$!i#UAc$V{EJ@(~2 zl9fJap6~9-)CIkxJnas*M&Eum^)ME+1{jXd|mQg4)u17ek)SR zi_E?K_OMmmM0W{iQ>!V$?RT+V^+j%Dt7KkIq=JQ+mSymkAf4fbeR2_YJW6r}^}JO? za$5QV!@Vr$+~)(7$jn{d*30dnLt{RduF1ALYeROHk+W`rQVzy!A5`16!* z*Ws-N@gLZ+rJ|kx;wk#+(<497YGLT1NY153YBWrke@$u9ym}Djsb}XPrrsv6A#Ru( z8G-%Nd97~2Y?aERh0*p(uqwJ zZCb<62rPrwqa@_vKw^x`yGeLU%e+z#^>i5W1in1xU1E4qz6wkFneq;ga@X|zI@h0`gn#~wNkzIMA<=B z7M#YNOi9&CafYe1r2)FdP>WmY^gY#~vd^I3eBIMl|G`k1^U zVamW7b?5u8&?@}VuP+a3!7oV2o;&v?-O9cQ`W^EPmQ*15DQjj4rZ}Gb#K_uztw*xM zJ3hK>lw>G@G#f^F@SrFo-vP3Mi^7!!e5%uXU z8J{QYE8`-P8(LIoY(~re{Wul>nFSB0&R$9ug&*-@-ULlKpk^wu+tw6c_cxD`tKV?4 zje2RdXl6GI0;^3&n|V{#6REaUbB={U)hly8Sn(Wgo&Z}I-%fbARgA}>)P9Y$MH^+M z$(N!BVy(v}<>+itH{q2cdsKo+&SuPQhw2vQSzh*8dk*}#(r20CGCRNu&)qNfz_Pz& zn+D&IMFm8PI5}D#=!DyEGbaw1!&3zn8---7RO(wAdRG?e7g{&;+)OLc->G`>8E4`U zTYJ2qfS+F%M-SxZ1x%L;Ky=h=qC@(0jg4iuQv^B3*+!3l-Z&f()uv7TzB~dTkq21+ zKFVDi_t!qLCyL0VUweTI=czRM^9BkwI<7Duci~LRdaM`GT`!TbQp(^9dGBjn>iV!S zln%9PurG_6Xwy#lVs(p=IOBJQwG;UC4qZmvsX*VFy^VJSQ*o38W^s_nJ_=Ti+XYhI zb6iUsQDCxpSj_xy;Xz$~1HkS-HDVnjP_xDq@$43PPURbW0{XwJCOi4((FLDgPrxRf zcSSoF)*5-dIsQ{qM(z7|eI?Sy>S-z|UC6w)ynk`=T8a$X zO7rXpOQU{s->ND0dSdlIv}x+3cOy1T_J5zvF)%BIK2ZDoTS$H}DqB+XEn)npy26r@ ze^xaDf~6t}mH4w<%t{wgJ>R@OIJPGw5p1eM-r2|Lg=@D@g&d@S3w(Rb{5@jZ*4)sto=7v!e_vtmpLS+c+egb^V_YjYDYO4}_u8&D+Df$zdo%N>L>|?M+cc|a zqga!y@q&arTz}kTJdi$T>)30RxcHlt%Tbvgb1P_5uY~?Gk)Ly4J4^>DtuiS&ZHcD* z!J3U815+jvYg(;C6%{Ezt-wnUc+xsC4V-O zQ?lHy&IE_wHPhx`WdDsf)E}%)1TAio(u7Qp#US!ljm=zgy=A+|PyCl@~DH zbA6G~g^2!cy@pB%{B%D5JO{A8Hk8V=a7kn%*vZvsZs2mp=C2NxGia0-9X3;F1sa{hsSrY z-Y;%jB>a<3kfkPuH_?a22SyZy)6lNjjy!#;rpwgh(uK7_4N!$4?Sko=@Q~fwyER6$ z_K<4WOh<%f{W-2=)8x0(FjfHhlsl6vI_z?!qGx6K9&09qRQ>BSXI}Dat4@B?=DF+A ztd1R+A?=_R%aIx@|Css1neVR=7EWi6I$z}L$=1bCi+3zut-Gafzh_Ndhq(W0i4*|M z^qk$N3-L4(BlN-8glPzdbu{7$YMv+J$VfZ}k#*A%$0q3bYR?7DeDs=+MSx_L zfHIu9Uw*GfafX&!CUs}EG6)^QVg$)5lib}iQwdQsASIqQSIMS1A0$9~|3 zaF#0thCyQ!w0WZ)JE&7%HlGXl(9`sgii2cNeB<^?_wS0uWchNnS!*Viblv&W9Mk! z<3@5sm3S1Ln=Hr}rlaiTvqf1eaWRCbGED8MDE<8I?6%*o4|~@Lo*!;8YfI0q`eZg#$sJzszEmeMPV@D;Nr_cAj@@>BEuI+ufT(-HD6^=u!fqanS2$Xt7C53;1; zlJyY0rH;8jem|9OXL(Gpr`Pk-7Wca?;kwVGZ-RLoA>`U~3@p$_+s&E|FRROxXepUR zIfZ#bPrF)j=?53O%7>MQh93&R2>t}POOXTny{@#kU3i_ z-aLse>J>g%HIwTG2m3SlVGiy76nkoFEFb?(4kyKGQJJbZ8QN*$xXaFm2TfIkf85_d%yee9`2%FU)vkO6Y`w-mB49Cr_ zmXPRl2G61OE&I_gm4}*(=0erH(s+kkZq5)IO3$gT2bzLsSwP2komZVB{M$ZpITtX!Cd0X!<^evM5Rg#k zpq~lQ+HM9u%_{CMt!3ix)^p{P+eupUIEuDcR)X`D(%0$ld(p2haxS;f1MaEHcbvmP zX)X9B+F!v1x5?Zo2W7l1`;>LrC)9V&cRxFBu?-gCO7YUz+p-x`#Oqc@K&gN+6MMA` zg$fBfcG~xRqFvbe)Q|hvsKjx!2HTOq9X?Cfnsj7_T7PjhvO)0_AGH9AGr?FWjT)6J zPp7}WMkUedP&Z_AF8fMof6(yaZm+Moz1V&*Lwj4&@y$gg9J)lm*aW(mNyh1^L_UPZ zJd_B}HiG&LeSB*t(y~ucw|v4SKb-0BdU*Xw`t^mP_q5od)cG{x$u}{(72-EMCLexf z-$RkNcZvhe1r{a7U!Ho)uR1UO&-D^^^58<2R;PVN=FK2Rkcs1 z!c%9Ni2jpEJFPB9G{nKR0)nSRI$lF|7J%c8;(t>ZqH#mTvBN>IIrwq^_P`cmJRXU{fULq;<%T_|&SqLU^OXIVu#T2}pYT4trc&Utw{ zapqJwT=sdQyhDA8vAZKK;C=rFs}CODCuOS8sdP9Ibz#Rns)>}q{pQA%abRO((@&0< zKQa}|6k7dRw`KV{25Kc1k4s`JbF+y6 zJYUUncl9J?pLgQ@Pqi=~-I>@CS+}m^`{rKACxBMQ*Q@#RTY334|5(j6k1?rgUxq`& z9JyM~kC)~@hXVkuav1rEyt!5BkD5=L&tE!O^-t3KkZ4rvab_J80R+{tdi1ITBb1=M z*-H5ZFess*Am9``_&5ktz1Hd1C5^Hlqw8BBli8v1ZB{Q3NEJ;6XU;sKm968NbZ#v%~j}4`%u630s+We1ZQZAPi z4a|ld>Yd{pCo2;VC+6o`)Cg)rkHk<^Q#i~Rg>EW=Fi+al9A;X3< zR(S_ocmxS2LHrK5NVVh;K9mA6?|o2-nyk)O;zfBwZdtA`5R1zb)olSc$O$soSX)j@ z0ezhH*X4qS7Sj(Put<(AA%@b6{Zn7y*sqaoE+4K1IO^DRWUxJ(Nhc+ixfU_I&<@=% z7%5GqWwL}l0gP4RL`fW`9NnlntZb+&E>06#2hW7+`^M2MUnEaEZsi@yqlXvfUL%eD zLwnZoi3YiedaSDIfX0E@Z@sED={BPgcgW#sf(IR}Fpef6+_I(*RK`Aqdw99R zg_^?G2+i3oOHtis^nrk7St5U9@Q9z|(6af~fEE{(wtMJ{r0{qRmOGw~P5MmhIdF0g zgh6x0qZ$6_Bdt%o$4&{Lu+)TmjnT0`wfoZNj!-FP|g zF#mv(`xf&)=G&l>Xuav);ID&HR|{ac4v&7@4MKhhEZIz3>oy+Or{NOF@?O*CTkJxR z7th0RDfVn{_uO2cRCUe8g|gU%nuW^~Dr1+!!!W!XB>q7g2-4!AVN99&GtYe4c`yVu zV%+%0aVwh@FW*NT5ou0j;>l$Mf{o-A+L$!E>^Y3Ro_;CY;#m}T7$HWGR{f%ksXJ-# z$B))(e=WYa{WV_*;4|TUynYW(w7zYp#Q_v^ZUn}@udE0v{4U*s_unhr{u8kuv2$|% zCpx^V`c;zqVPE+^IM~|0CD>mRY5|-GnVNksn0}GaZE3%?&G7{A9#8Eoi8_{|g#Usu zvddRTmKJs*{1xzdUt0T(#H7`17hQ1)<}ovK_BKa)U|y_HX4k~T#K#!wRio~yxU{?1 zla9WZKLsW$atLv!`M@vHQTNiE;$MG?BlM^N-l%s+&kGxeEbaLqtQu-|bobK03*rFo z|E-9uK@yY>rtw=Jhfu}wn`2=S!>Lkl04Lnz+f=Qyy?2s~Eh&!T4aakFQ!0?V-lGzx z3&qtd?6E8<0Pyi##i;q`O5s8^R|ym@ud#2kU`9N`qqR*qY&2wqIoCI+dp7TqNq8Rz zl{VFw;%e6EtXcC7?^M7P1M9nRbOoO~jgnnKN-(?pd8d=v(5O~>aTcaxXowyF;Mv=iL`ZHBE9*!oM>E-JNP{OT__6w^r|&UO0Hxg_!Ip6YvgDL8 z&wzWRLmjs|DGvd^Ui(6|Nl)J$y;e_z7bz;>OnbbcBO{s`5d0uG+QYwvYuQpCM3>mva-bG? zvlWDQG-Mr?Chr#-vcyf5b+h~@;ts=A_e6bhiL%KHy_CP8_`AsQaIq9)b8y!c+H^C* z`O>}PmxIfl&1jFo!Y;YA&fN`SOE4%rEP`KAZjak7b82}~DbA>!jglwmAo+Lm?+*rv z1Exz5gJcOzzBfMM@QmMR`nmsCfQ@X-tfHNhkV5~%ug0>yOF^(~SP=L%xT~9BrKeGa zkj7p72$`#w!ey{mf@HJAG&%R>7b7DQ5_4RIFvxk z+eNOeNa^7z%O52jX&Q`{#eDx!HEbou&bWWf8Zvl>{6gKV-D#21?!0pfQ^AYt8NaES zUuMvz@bt=XSHJPw+0_zVFfBrDuJt4&Vc9(3)BOvjaw!Kh+`;K7;{mSSNSGgL2P=7l z9FGm~Hx%LF)aebI+g+1fgxisR^Lp zd|5~S>uezk$(_Ab^?R6|Rylh5V_9uvQc@tAA<;F%3bxeyl#)Q-<(%_Vb{P%LGOO&J ziN{HvBGGRUqRy=PDDZLsYQy$V{5|@O9X2%wir%yE@RxI?wS_&&=4bWRBkQh~88(<)EbzP7z-QH*0IE?)z4KUmM2wttLX)uy;u0czo9EBY9Qu z7Y6GL1z+N&9LnH1XbAC0DT+PPJ1G(C|5c|+UVQU(9U*8K`n zjpQ(pZ&@#E02&DJPI`ev%_$x~e01Hji0XU~Go-=-6y<>+l=4N73RFs63|CD;akWY6FoV*L^%a0U11_GK> zdXL2UNKe?V^^K1qhxtq&&qGEmllMw(@E>`aP%l7r5$g&akha-_p^^C3*F&XlW#Im_Z*hdHYyX_}2U7W&Gf)qPEPaR?v>ao1t! zeCmk&q9&MSx_^hc&St({T=SFWvgD2PU{4TY03S9ohx9D4G*X&O_$SjoZ#NMIq-Z)v zW^A@-H`vsAtjw}=yX|ag4f=+jxBo!LP5(|mj?T@S?wuWJqT$yYm>1OZI4{82&qSWK zl^dp*V$}nT#A}7e>6?PEcjzfJp_)}{Uz{mow7#4cLGS&-uYqOdim13sEqSx{)l}48 z1hBHeggCHUfYHFO;rUdtW2Y@Y+!6jrJGyXnBxu^R`kd2%K&vX5EP%Jj-;x6nk;j;p zAxtXLFy-fC%%y*UMFtc$b1z|0mRd=x&~6I-CSNiAIRXz6UzQ3T9t7SaRc=I0vWD5R zdlF-gK#82RpFt(0>Xl}D6UODYGi=4V z!ayaeiYo@9{rDnEgVK1pNsZITu=p0WG8U>nKIAId>5N#?XoyOv)%ROy^3)oBBjYKD z`*)!zy=mc#NpvG7Tn15{B^R^j+*@|?yFO;LALqwSE+y?8i3^3`1+X*5%UB~_hl>U> zpWu~*HRzeW0PG*u!hI_im9QWah+h3I(hEF4bq((bo> zhT(?%b6clvuBrK);X^FcaNnl)zqo+bp9a#-h)rhW+e(QS`IOkoT|f)TTlrx6}a55?C*{nLE~HGD^Ckr<-!d3-@+>YKOH{kZ=nK;>ZXDayAAxG+A=XZ zGPIN;1ve2#!c#4ktbo>CqDUs6^{_h{*+OP%h@tN_Ub)!w+4nac5{^Y3E5f?d8DhFN z7W+2lHh-A`pD8(!y{k`Jg07dml`6Er2|j1atJSCMn}4tAdoLikX!g_*StYIr->0qH z6=w{9&+^V1eKF1!^V3~z;i!0C9QV|RUx1a_vCsMOt4E9Sc7~n-=RZ#n*4%s{SxPS7 zk0033L3`4*9C)mzE~`SchRg2w>%%O!IwWjQ3!JZ8ny(Pi(eoFl5eOOPy#={uUasn6 zLI(G@BxyXcOHE%1_yue3b5o(Sv=JO(ZnbH?UL{T(-2s(C|k)%1nWQEYbE zJcyI(=cX(j+NwNm-$!Y5nUTV&?JYgv^9M3n4MjV6KkwZUyyfaA^{50(UGLV^*Ec@f zJ)RsD`T?XKEZ2*pnvN5JX>I$;R$CwPtEdV`MF(@9HCi=7F}o|5BOaTtRBthEI&f(8 zirAiZ#us?|UJfSSOiXZhZaNVb?jGkabqUK$=h4k$(hW5BOuBJhMHA|h47(;DW9|N_ zYs)H{3v*vdE!uosEr6Zw1Z8YZj(0}L1AhHriOAP;r!cxb7@RC>(yfpS6te%Wzwx~3 z_JiW)-d}AKXv+X%qOwe#NN&v|O9Zt+D}?*Ny=V<5k7f&~tC2k$xjE4dnUr2&K`qq= z{@}t2Y7WLpS4)2qa2+3N7h-t8SoDFPRYb9p4q95!RY!Z(x!5ZCcGUqPRi1I=EB_Lak{2v6k3`2EFpR$5zH){_sGLo zZ*9IpLr;pdRYZ-EW25@p1`@68%pDG7lp>1_-k|W`CY|y5vvM*nMF%G!1p<-lB8oHEC$!0Ss+y?eHfzK!(C6>iJqQ2?AM@~z7IU4V@IW3)Bd|&a2d;&RF7)?V54{qb$wyNdg>mA;+Xj>Z#ZKJh+OjC|PU>xbDC{po z4|1hJi+4Bh@!*!UzWms$LZg@$>i<&H0>n+SynUx9=*(W&sk~pXy7Gz^vo1Hdl1Y1O zUmIE|X9&DHmfpxm-VPFRONOtJ(Y)wO;a+?OzIy+5IHIH0`K-dlHD-rNWs%aGskIT@ z!?~aQ0`H#N{eAH0^S{iXOQ98~_3O&Vum(Q^&v#yz1_@?@o@rYL2OpDNVge|*PIV45 z+RoYBYmIk>?46{Y`e%(nkT%_=a*yYLS-YW>zbebE9A&*;Rqh9TZ@xOF`EnIz{qbyX z(<-7&6MvjVp?c*s9{%VdAbYZZShI5HPf%&8gSgd=J!}wgqPigZLEG$fsdza@Z*|lO z=l|f~Rb!n+qVY$S?7GpF1;2j<)VP4Rjdh!_v(g?Yvwbv--|bJe=d(32CjhgH{Q%|k z@eH`G$BXF8ks{#N3nwnUa=C_-B-Y2*>FFuLGih`=(A3c(53dV+WsYi;Ta#6zx;?ttLy^+eohF_&Kzpx_Zv{n)nck&0pPQS9?#^&<0OX7M)!PjzoBBUj zAQ_-&A1RL0xwxf^Q10M+bb>JL0uo1awF4RixS7D|Agj5Yfu2al*p93r#I7yloAjb~ zB=#<9%xe-&NPi$L6k)u*WAZ!$@EPBUtE3mo43k%s`eWzVI!(Dk+^|LHAgK%-ys%(N z%m-TkwltDP&#BYuNe}`Jzc9@94(qU~5ifX!E_f|3(nGX_GY^FY|He=SU4JCt!(aV$ zKWD?vTzYS%16PC(p405yi7grm>M=g{GT%!Wdr`uO(ny+{nr*2RxSmQco6n13$~`5B zJ_UVbAZ*KEQEfZ6Z|LZ>Q0{hj_HS8G*=9}E#s%jJCGZBH9_>6t&^Z1JaK(QD(E4VeG;=!x ze!3U41QUu{O6A-~NpxHlW)oiz&=Ek7dX*S1T>>H|< zcH@n9=`gs^d+qzF0@yrjtYZSSp8lV!uw{=FCbm09Z!=TRc<#9#IiPG(cc}hUY(9k? zO?nXBQp`OLnfCTz4MU?OH)3T~>LT(lhdQv9i%kEqd$VRF)qS1Pfaz#x?AHIry{Kp= z0U#niep;3e!YFFFn#xb*gP2}{sQ>c63%Wj09U3oq2v}w2l~0if@NQ@tEB6d0pAF^*=N^B%FSsTRhD7hc_XG(3i*w;kc6O?{ zrzMt|(R{9|pw5lMkR(_KuOur)L;BL6WGkl)1?ZF%_+=B;(vT?YAe>f%ZqZNpuki4_2x%qRm0Jz2@;YLP<%6em zju`j!HU158HDwl_8bJ>-qVIYB#ur6b9>E?PMa>ZDVoQ?pl!O#47N@3|a4 zY>r#+`KCwp7{h*<3KK7;&X~}GmkRHG=q(K{6Q%BH?KI-wbm93KT1Pu5=APp*pVYeB zF*u93zF$xAY@v<@Li_T76M`kUJ3O*>q>n8!<9^`kC&TvDYaD=g0m@td^i}BndI*Od z4KZwcOWzxrGlj}Sp4K^sLP3p8R^<9rj9|d3V48yBkXB1_KB!S5NvaDS4>-|R{yeol zD*BB3f8|($3$4(5M>fK!q|i^FK8;3Y3r_Vw1O){I1O?~xGaP2br##*>;S_%#plhoB ztp4kA1vrIE2Kp2_NAg$6TUz9`>Qa`N~9soS(jeq>7cKHhZr@<;w#1Nl2e-W9dY!LDlF*8 zV(RtFUruQh1k8G4HcP#Q6T1mXuYAr+%Qthc_DeX@AAWOF7GyQ~pic0Pu#5A#kCGsW zYwyE(35PNRz8HvExKg2lt}R1wPF{BZVd`RNSOMEFC#*F^WP$d=rR@KMY%w98B%5A) zRbO>-zCXX9KJ`Wz93 zDf;le9XcWA90*bLV4pKw1-L|Z4% z4-$~2)6;nV`IY~eK6>W)X+;B0bW_v+`mgxTgmb>eSS zxe5P8i+cn6oXl%sFdw5@nXlt@tg)(58|0@}K*OXipNY?G;na#0?aBOL4KSU6VYs<{ z99siDogm+I#}3-Wvu z4Jgk0^~cJuy_$_(AjlHe_MlJ_syUB=c?h&E&M`{PO)h@9c0k?&<++qJUOdkdmahG^ zJ`*JVk=D1P@Pp}*dd{cXe6D9jV`zz?ljB+q@g$>?cJ)V}nJtIy2Gqb?NuXU?do>n&n1 z3f434Ag;%p#yzZ<42&~Fkz{l}E2R`?M`$?l0LwBgq^ zNmG5V>As9tH0k%UV2fi()7tQoDs*@rCQA#Ik_dC#WKP_8E#BzGx6T(=8^h_BR@R%W zNS>d9q6+uYGF2yf%{cLcD~QdxMxY2o*O2HGI{Au@{2|Stf!{l4HGk8BBUSXFvCdi> zZs&$Aa*!dnPH>0ufg6t^Em$vaLOX_{{6}BpTJEb5#~I8dFY(Zs#G&1PaRGNI0r^Xj zhSk%yr~u+lPNmC&Gg8!4`=q+0T{jZ6J-lvAm0)Z*(_^QHo}Ad7)a}OnjIPOhE5R5z zpd^t?O2)y*;_=qMnfigd`d->%l&2FqxJ+L7QFc_6S`-XSANtF5Aj;_-cHid2<86*H zME8Z8UNR5#?8~x{egTzTN+*H??@U_0+jzY4<3VJBXgM7RXYrd|!w;Q_L5I;bG!_^ zKgtERP*hS1G;=+Dz+GwP>st1c&vi3u9##)&qh;RqiOp!*OSNQP68rY(-^BU;ulcM! z5JW@qZT&mhtR;K&EVhs2E)65$>meXnE|@+%-u+_r}y(&^uQO)LghQX^2rJLRjlMbKemy%@6^$PWOf4Nrr*<$@ndRDAwI+TH z3%swFU#?ocHW;dn$ZTE%$VX?B3W{unq^S%ucRX4G5rG&RK z@4NR4)tdwB`e3Q(-HuUOovKb~-j-xUfJ>X3(w|OGhS^QDmcT>*n(lKv5)ukeI5>-F~_a{X6Pidbik?nr0TI-SAY2+EMqsJa9RP%R5(jf zpvV-UOEO8|obJ4~W}&LpHy&#|Tv3RyS{E-3k0~XG)$BNCV&)jBRwsI za0V_gk9o-AEc-w|E3wC-tq;EF3of1sdb3am$rJU^^n?{xo7I=5ys*|{>TA2PCSSO*afeH{_QCFT-ruMv3P>}T}9_=0fH@RdUff%DV zj#bH)e;TtWaS_!4n#^x#z*p#k;T!A<9^0@~WqFyQ{;&4FGODd@Q5P)*Hc%+iqQxEB z;uczp7AsKPT>`<11u0Nyp)|z_6e}*l-Dz?60L6j^g1gI2_c-soH{Lk+-aXF#asS-E zYpjf{%r&#tH$R(#G<=wL1aiY^QoX=F<~Q&ql*>k|j#6WI%rw!ab}pI{3)D4#Ei44$ z5TefwKdv#6z>mh+r#2GyfKrUx0HbTknefrrfHGY8Q|5g$%3R9o9TD7S-S~+ky#QV( zG0g86pK`R_!VSkJ>Ku7(%zI`DsTy$eN!bV!FICerIr(`C+O5m07Y@^ie!teIc~p5- zJzFxrf6vd@eXU8CPj<^D@p@Ex&naoSwWMjSThOn5;G$pz0Am?w{;<~Y7Ex9Me zAsYCyWPvk@fo7V)7wIqj+e!bD5d`8@Xw~IE2c%q7wZ0BuHg>HzU@910Aj4>?A92P0 z&vn=T)>9%l7LT#YsqUwXWY_WQ)4SU6OPw&Ke^0OFW(z3Rk2q%A;sh9+4Jmpu7>|WT z$HAs6M5Lp0gtnOJj&!~H-o`t>o5NU;gLsm?(2&^}r+eH{=v5hw6g@)gkCS@rm~;Ji zr*AWY?e4p;Zk=%@+SXlelcpJ&tGyg(w^cFg%%yxiYnPx?*YBVdtdkO*mNLdpNI*j8 z8}l7j_~KXNCb8WIBW!O%AsrSeo*vCqr{nEXmkU!?brhADM5V~ET zV21jypxpm#fkD8e^iQ5clfFAQ z-NXLuYk=Vjyb&Zj9wi?zJ`VSFw*Y9ULxkz=%pg=s7o1nuJQ86l+}EQ1J}*`7Lv2^h zthb&NUI^8=w^24E>ZFk$jl08%IF|^D9i4c1&x!ngf=V(Vkkn#Q^%K3cnsLNlGEB3Y z?ZtETLE47>s>G(X>~d~!%dt{HK$EVlR&5ux{YsFo!<*Mr*jh%=wG@_Ga4sQnkAT&D#N8j>bW zX0JI>89eqWK5J>>+(MY5&bEBGI&R&S-$Or#PCaKJva!mNp%qtQ+2mGuE!h(cAbly{ z!&=@xu!psMY_e&(+QFc|w6|{Y>*vfozZt5aPWSyY=)ld7XlMCj&eW?h>DU$Z_-hB` z>cg^&F>Ie-QEF)`BvxzPdzaoFXBjcaPR#R({C8;n+H@lT8DZ(gm$B4%9^@d4Pij#!XyO>+gD0ymZrlRK(!UbvlY z*RnW6UnUAA<%=LXI11v&;XB?!IoP0Pd^_5T&Gji7rI%sJT>|_`g_G;Ljg|~?rL}1Q z?ly}^zSOa1OFZ8@EeddlpJj54dLP98t=k3DEZ=TttHI-=oL)xhLdw~SSmirT1i3n| z^qOK|EbQ#)tYvt(7tX(LGe-#Ikv(ivI9uE-3A|0S=>&efn4p(5#XS5{W-OrKJqvBp zy4$hlR-mu#D{Z`srWt^}k{aaEF0LV0v4VUqD3Sx6qgFc5)gcswEGWHhZDl&1e|Ia>a~VmL z3B9=3d!5h<+J${}y9pqO5UrUXe!4p~+$8VVr@=dbLfCxkaxyu6rI(ZXa@OY9+1FP5 z@DKLe05R^J$xi3gW3Cn+^;wadN(N08v{>5+cDr!djUMg}@DYsFJ1+v1HC4VD@$&5` zE~?u1Xi<}L6zw%HUyku2Crj$(@tsa*{U_zuF32kemVx~gcyBSOvR}Kqj7=zwDCUAb zz1q=LzFWQYXQ1^JbKIM1Z=8OtJ9-jjgl|OUKwow>hKjl)nj|({pOrSF(yg{>tNB9t zv6#!ScZ_BWa3%R>SxjVqGiP48DZ4ROUEk<5VXY#$ky!Hh+Vcz^W|@3_+^)+zr`IB! zZGUAm{EMw7rN-vyR1S1+^@Kj8m`3_ay<~U_k1rKJ#XhNt&#bLbuimHiB4Uo7R`0T1 z8$X(D*PwxK$OcK)`n86?=vnFODWSp01%UbXnTGts(>srg&87OZG3jBe-aeDn!wW2h z^!mnO)4B$)T%W$&VJceQ*?X%==34;c{k*iZxt*6V_L-(K%w7Th5<^$`X2f@a(e;2d zhuG8hZEf4<_<~hk5SEK}O95~k6?suNeQ&-4hkI$D55TiaCaCx*J>{QBP7?q zTYZC@NhWf5{YvaHpS%(rn9jpt)^W=FnbfO`|0~WGXnlEL2U$ z))Cp^I&Z^EJv1=$W6uA0Ad*fjs;~mkZfb)CAeY2_>u%fDq2Q{Erc( z3RK)5pzCcYQPWdhYuZ6eF-risBdH!-(@Y;UNq zz2ZSmJmKlOFMs+T?^ub2O~oqAetBZ6#q)|=(w-@ywIQiPpoTM9LcpDG_(xCFou7G_ z5tn7x6q^tuRX01UGDx0iqp6~;(m1EW@35`2zh0hrw`+_!gHuysH;1FVpw!FM{QvGp3_axSCwVSO)_84A;JYZ2w-J29VVdx<1WkL;y-t*j#rwbe5ieedJs z;)7-?3tJpbzW1m^yAICN zhUUC-AXMcIVJUG`>t$4^#ocXukeXJ&kreUWk8m+!?o#xvFQX5-??D5g$`{!mzphAu zL#_84RAna|Z#Lq)BucHGTs28<9gkV()qfBfyxFIi$7#7qS!~WSz5W*8uLxNm(%v&b z^7FAm*K1I#!yh0fez&2BYKXX(&Ssw*f3NVEXn{Qg-YX|2 zB2)3(73`)_M1VA+eImG2RBCn|Hn!&&1pF~P)nz+>|5vTkJlbns?_cY6vJX95ecdd^ zx8$Z6FCn3h@EQ!F0?U6{2BmUkE5RL33$#1drv1pg&7xBm`uU$N=}8V6&_i^2tx#?@ zIQ+-SuJaashd+eq1|i4mlxLmJRVIsPs;P8 zt4m?ro{qN<=&4*;W|b*b&%2z~&o_{$_@bhpbB{rHqW9`(@Y8$x!PXXTmSWFPyHA8);dTR}1S|{E%J$2ayBMUtF>Q`_ z#@T~5lHPChsY_7Cba}aG!9Uhv5xNIS3JAXvY7hjS6+)inq=sF`X&ENfQ%%jfX@a`K z#bg-Oo9`)$nXiWfa+4aN0S~=7^?CfG$b7+Pr~acvWmN8RX#xJB2eYjP;8potL4_1b z`X(Uosa7$xn@+DrcqWeXkCXi*2?Vq6O7M=z=k>cWYVPjZeR>PVTlY>bcs6~77~mvJihMr9OOvfCTBXhBaeFZ|WFLeSdkJ zns`)d_P7;yIpWW)4mMUe_)$sJ@?m35CeUS$xhFnFsFPQ3TjIfDu&+A;3(Vaq+_FfF zl`oC_`T@o`Zn(pv?S*wf<_+oxBigj0iXP-m3NI2-6YAm#6ymEI$m5r7?(&5C4?*J+EW zm@f6rtO$(EX?=*7j}bpHQ_~c6TdHFWegj93SyPpiU9Q}t0+&Hk*Bo`l3# z_;>rntiY1q+e6@i@;4UtyYW!Ve)=Jx3yJ zjr@79PG`pP>}R*^qm~~NndJ3YP`WupXcHS0;?7=qd*^puUw~I;>=K#{`q09cv*4$@ z%^cjoZ}!{GodXH8#X^;{K+)Pl6h}DpXvn7w;9#u!K}|pI!KIbPoPYqyf}<_v9esBz z)J6yNGkhNlKV4`dh}E(4`S|*D;4;_{p4M~`(RB*X);N!(;qTVq@W}eQG7Axw=?uIvNuj!%@cgeME!emioQcdK&f@i4K zzC_8kN~>>W9+Bv^byf1=dDN;tq|2;Qo_P5_0YPm_j4h`rSli$cqxHwp#Vs-q z$=G#(W#*^SJnhMW(FYqqxBJmb+<(A7OQhN}+;Ahvey&bL_~f1I)}I*#jMQJZ-%-Nf zp@-3fx-q_EBBtwf?3AH{mv@Bxtgw%oZI~f0mRksC$K!f1jOF>>+1o=4=dc_&!XyH! zTXvf$QzVaL=i(uhsMPBo(T6-&NifXj*e!}Tf3Do#lCH*2cQ{o)muS>hAc-H1w|6Q0 zbI0j2IYnQ{*Z{*jRsL)CvcXswvhr$64|b_fEvY@bsz2Ghyc<)&p$vaF_F(fZy%JQ& z?18TA=hKf|o%|}LLcWI^$WGFzMpkV|3t210tjQBEA^v}&<<8yY$ok95j za?F3Mq^fDsKe~-9taL3bx#Tg8dMVH}zEW0PIVvUi?{B0) z)0p)J%+so|3kz&dFfdBnY5PCV|Ih`Jr;OtL4bAtTMQYI^Trp^jaNXQYWz@%r7H2aL zinHL*AQa0663xAT9uQq!j+nTkUdW$JM*yS{9Et=)fPpy)%JKA-GBhX zuO0CwIEHDoOE)&%jI&WvQkJleR%WPjH`gP`EplL7^lce2W>`Fo+`#7(a1)0HgG@4 zeYhMOEM7b612=Q~6>qwJers?F>@A29D%R}J5+2rXDqAfNm{Lc(sVGS?ydN&!o5L7+ zeQaB?HU_kzCxsFd`+M9<~hxu2A} z$E;zA26RY%Y??bs6B&O!&?9g_z|`n-Stu)%EyycqV6(ks)e*m-clK*Nh-|n%NSA-d zWSMnd$iHv-DL!VP$V*FwvGF+fEn$Ypy5zIVmuqN@&PPOX86Yy=yh;oLBh^wvNU}03 zlXN0QFNdv`77MUXVqbv(Z&)V=InXzV@8isJ^3^Mr8ccTuU;W4TRgM3#D9ex}UWxiNr#PA&ip zPuH*ziP%tnEYs+NyuKdDuABIzL5P>c?+4&*dDC}1`DXIocT=tSTEdE~;nMID;Y7F0 z_g6N?7E^Mq#I*&9ENGU2d$*zAm2>r-WZrnK4ifp?uwwTZUPW(iZGRb^Equt4VO%&xE_>y?{SP3v51MwVU?UJPd8-F{h_IVmT#qw&}VGDnJ+ zy*HICKPeM5BZlFtLh35&VD|T)1d3>ARmbSTz2;b`&_2Qhd+}$1P+GL)ds>vHp6y1S=SN?h2ziwi)li~}{1Z$kIU{O(lg=s}k&CpttHRFB{OBnV zBo9ghucQ8auIo%yQerL|kAN~+JU@Wx$gh9#{*6S^zd*nLExhgm``Ew)%9*i&O0-TIV1IYemNxpJ&h|=PNObsH;uH<#{8;bUocG z1JS;nPS1+fJ_Gt>`2L#HM`8s_v?C}s0R0xi;7_XKv+aL3Z?H;QaN?tsDs2Y2jhbhC zaX5w8_=)*~Gq<&?DiVO|^sF+AHYiZ-E;ede{)Kh`@j&!=zX4~e%%4fiNTvAV?}JF! z$)9y!C6NiZFLH}Dn$5GM&QwRfp5Tmmof4tJW<}0sL(XbN35WwQ{|?-(1NCTtzt3L* zR_EKcey2x2v%a@{PsjZmuiAn&>jW->|7);n>r}#65WDoNojI(-z#v}wy^jD9ceIWK zyi-ZgSHeYcegd`3qJEU_-@-aI8FFLduDT`61GF@1BU(&l9^!o6!=YGbxWA!fzC7Q? zaO3e#RMi!~7N~?PP`e8H*5y@Q0^~ynES5A=mdA<4AnBW)x8Gg)-_iU_i`APeHc+-_ zbjR@&m^Z4^u|qW$~-HAg8|H{80Y+jj&s*~R8!xizA0fsXOO?TGnUc6mWmRZ} z7BXWheF_Ou#LDN))sJK6f1(r3v!R98O-B@glnk~66#)m?8^J=-m6?rXW+wI^oQfkl~i52OdP9#pb6V9DtSQ_rSyI1i3Fk0krU`*v{UNQW{m@!5bjifR_|F zhfE66)%r0FhXJaAXR6wfs&@8_JVRLsNTkkhaPCw^vT?q*kdsetS20^_XxiQO z;fzhH`Woa_(2kBCyIDpao2k27qAGij*y*Zylr$7w7OqEvKg&hTk{*s+2}$)AQ2#+y39pNdEhl_}mXpQ!E!&2|Lsss0N1nOBuIgLw z_p;t?gX67`=jJWEL)(BDnWC;DeJQw!P{oMl?rtnz@EPAG%z?nw39VP|oLL^&i&%h6 z?k9~$`@BxuUr!>pBAcMG9#ne?j^QySGs=HZzV2I@hFC0P1#T;dSAIl&ao4T(Pm@MX zZNGmgwxiD?Rlje3!7KSL@t*QhLM1MlCi82LVMw2a#pEU#&%QV4mg?3_Gkw;(vrb3~2FLTRb%eFz`K#iIWW%Tsp1^A^6Zwfp%L&=cX<+`6J-d zb#cckk1_3@S7g!*w2D(pruKEFHf2Wj7y8+!b|2P^auvJUa9+1)rV_T3mg^qFM!**K z#9Q42gk1Ny~{jaP$3_q8M(7Vl~GE?^Dwj})T? zTkgs*pJ9!!syu9?AT=f&EC;E#vMTA`-+>rw>bz1=m zm&wk<(oP|=DM`FK502CW2=!S;kOTvCD!tV#J~E3>8eil>#1767^2vmCEQWj+?mNMu zc{$~_B{^9|L?>#0({&ZL>>)5Q@%GBuMeMJ{3lBkQIB#S)Ha8?}kI+di-}~CF4#^}J z2m8p*_Bq;%it`CaF~msMO!22zy-S3kyudYSVnNOwNQAgJ!38D29eE;b^_=f^d-R4g zvp^zXb|P5;W0OJ|_R+WH-f+muUVcVh*7O5yodF$qOkC?HPLZd@^lK5=>RuDxF;5U~ zm4`tBH3_!To{iK4r3rbjH(U0Q5}#4u!n1}L@WaD~mwt(gdpG$0aX=^D(O=$s6qXU4 zoM+n7A3R-#e&sB|g!5Pv4`Oju zZrIdES6#*4LpSQ+kP)!cbg?S@7kLQgZk z!v^_yG>v7IJchHG#(s#XYNo<^X-&t$cy0MOO!zOHR9-yg{CTbZy(OcG=r16^>;tv< zfx7fp7>k2ef6-Z$Pp5S0N93wT1iHn?*b`>sNUVE;22C+VvIh8%RedhZF}#^O<~hrR zb*{L)9MH9+%!46~f8wUx9SiGh&$fK2U`RRgy*k>u6*zUir+&;cl$ge}M+*783ey*1VB}4(Er$uRdj!A85@h zNiPlCVSXogIJM@ORALw*$y5#CFF3+08fB=Ez)`%tq>&QE;OIP_N<1B9Z=U{2S$!RQ zJM#{`V-fV&j`Ah(>C8m;aQgy7r_$psE zm8qbk{*kqeyt#$EhK$Y9D|<^s;v{df8NCRxg<)D#n4HuV?mtovH$49nN!5RU zf31IeW3K=G;J@zbLeKlZvEAAKj_Uu&sNRuaVBFo|*fDuvU|`()z1YP@hb(d9cG=-* R$^ipINls0+M8+)mKLB40U&{ah literal 0 HcmV?d00001 diff --git a/backend/k1-640.png b/backend/k1-640.png new file mode 100644 index 0000000000000000000000000000000000000000..cd25ede07723788ef06ba4add578f9d065bceffa GIT binary patch literal 30416 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%0A`I&VS#}@M~Xi|#=9A#)y|47<>X-h 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 literal 0 HcmV?d00001 diff --git a/backend/komfort.png b/backend/komfort.png new file mode 100644 index 0000000000000000000000000000000000000000..ea169bd304c3be03608d11048356d27cb4e2714a GIT binary patch literal 22217 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

eI7Jv;%nq8qnGl~@wX~o4W!lByoVc7! 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 literal 0 HcmV?d00001 diff --git a/backend/ledger.py b/backend/ledger.py index ccd11e6..4915504 100644 --- a/backend/ledger.py +++ b/backend/ledger.py @@ -9,8 +9,7 @@ nur noch, was er nicht schon weiß. Ein Eintrag gilt weiter, solange seine Voraussetzung nachweisbar dasteht: - ein Beleg, solange die zitierte Zeile noch in der Datei steht -- eine Abdeckung, solange die nennende Funktion noch auf einer Karte steht -- eine Fehlmeldung, solange keine passende Funktion dazugekommen ist +- eine Fehlanzeige, solange sich am Quelltext nichts geändert hat Fällt die Voraussetzung weg, fällt der Eintrag weg und wird neu gefragt. Damit bleibt gleicher Stand gleiches Ergebnis, und geänderter Stand wird wirklich neu @@ -30,11 +29,10 @@ DATEI = ".pruefung.json" # Ein Fach je Frage. Getrennt, weil sie unterschiedlich ungültig werden. FAECHER = ( + "stil", # Prüfstelle -> ihr Stilurteil (Prüfung 1) "belege", # Funktion -> Codestelle, die sie umsetzt (Prüfung 2) "ohne_code", # Funktion -> kein Code gefunden (Prüfung 2) "paare", # Funktionspaar -> Dublette oder verschieden (Prüfung 2) - "abdeckung", # Codestelle -> Funktion, die sie beschreibt (Prüfung 3) - "ohne_karte", # Codestelle -> keine Funktion beschreibt sie (Prüfung 3) ) diff --git a/backend/offen.png b/backend/offen.png new file mode 100644 index 0000000000000000000000000000000000000000..ebc8f58dcd809bdb8b26e0062edf14811a8d7934 GIT binary patch literal 26027 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 B3VHwl literal 0 HcmV?d00001 diff --git a/backend/parser.py b/backend/parser.py index e7add51..7b09331 100644 --- a/backend/parser.py +++ b/backend/parser.py @@ -19,6 +19,14 @@ TRENNER = re.compile(r"^-{3,}\s*$") VISION = "vision" ARTEN = ("kern", "optional", VISION) +# Eine Funktion ist entweder geliefert oder noch offen. „offen" heißt: die Karte +# beschreibt sie schon, den Code gibt es noch nicht — bestellt, nicht gebaut. +# Ohne diese Unterscheidung meldet die Vorwärtsprüfung jede geplante Funktion als +# Fehler und will sie streichen. +OFFEN = "offen" +GEBAUT = "gebaut" +STAENDE = (GEBAUT, OFFEN) + def _art(bloecke: list) -> str: wert = bloecke[0].strip().lower() if bloecke else "" @@ -61,7 +69,11 @@ def zerlege(roh: str) -> dict: # vor der ersten Funktion: Karten-Ziel, danach: Ziel der Funktion (funktionen[-1]["ziel"] if funktionen else ziel).append(text) elif schluessel == "funktion": - funktionen.append({"text": text, "ziel": [], "regeln": [], "testen": []}) + funktionen.append({"text": text, "ziel": [], "regeln": [], "testen": [], + "stand": GEBAUT}) + elif schluessel == "stand" and funktionen: + wert = text.strip().lower() + funktionen[-1]["stand"] = wert if wert in STAENDE else GEBAUT elif schluessel in ("regel", "regeln"): # vor der ersten Funktion: Karten-Regeln, danach: Regeln der Funktion (funktionen[-1]["regeln"] if funktionen else regeln).append(text) diff --git a/backend/planung.py b/backend/planung.py new file mode 100644 index 0000000..9cd40ac --- /dev/null +++ b/backend/planung.py @@ -0,0 +1,163 @@ +"""Eine Planung: der Kartensatz, wie er nach der nächsten Umsetzung aussehen soll. + +Die Übersicht beantwortet „was kann mein Projekt". Eine geplante Funktion gehört +dort nicht hin — sie wäre gelogen. Deshalb liegt die Planung in einer eigenen +Kopie und der Projektordner bleibt unberührt, bis sie umgesetzt wird. + +Kopiert wird der ganze Ordner, nicht nur die Karten. Gespräch und +Urteilsgedächtnis gehören zur Planung: was während des Planens besprochen und +beurteilt wurde, gilt für den geplanten Stand, nicht für den heutigen. + +Solange eine Planung läuft, arbeitet `projekte.wurzel()` in der Kopie. Keine +Schreibfunktion muss davon wissen. + +Es gibt höchstens eine Planung je Projekt. Sie endet auf zwei Arten: umgesetzt — +dann ersetzt die Kopie den Projektstand — oder abgebrochen, dann verschwindet sie +spurlos. +""" + +import shutil + +import parser +import projekte + +# Was beim Vergleich zählt: der sichtbare Inhalt einer Funktion, nicht ihre Datei. +# Wird eine Karte umbenannt, wandert ihre Datei — der Vergleich hinge sonst an +# einem Dateinamen statt an dem, was dasteht. +FELDER = ("ziel", "regeln", "testen", "stand") + + +def laeuft(projekt: str) -> bool: + return (projekte.stand(projekt) / projekte.PLANUNG).is_dir() + + +def _kopie(projekt: str): + return projekte.stand(projekt) / projekte.PLANUNG + + +def starte(projekt: str): + """Arbeitskopie anlegen. Ab hier zeigt `wurzel()` dorthin.""" + ziel = _kopie(projekt) + if ziel.is_dir(): + raise ValueError("Für dieses Projekt läuft schon eine Planung") + shutil.copytree(projekte.stand(projekt), ziel, + ignore=shutil.ignore_patterns(projekte.PLANUNG)) + + +def brich_ab(projekt: str): + """Planung verwerfen. Der Projektstand hat sie nie gesehen.""" + shutil.rmtree(_kopie(projekt), ignore_errors=True) + + +def setze_um(projekt: str): + """Die Kopie wird der neue Projektstand. + + Erst die Kopie herausheben, dann den alten Stand räumen, dann die Kopie an + seine Stelle. Ein Absturz mitten im Räumen ließe sonst ein Projekt ohne Karten + zurück — und die Planung gleich mit. + """ + kopie = _kopie(projekt) + if not kopie.is_dir(): + raise ValueError("Für dieses Projekt läuft keine Planung") + ordner = projekte.stand(projekt) + daneben = ordner.parent / f"{ordner.name}.neu" + shutil.rmtree(daneben, ignore_errors=True) + kopie.rename(daneben) + for eintrag in ordner.iterdir(): + shutil.rmtree(eintrag) if eintrag.is_dir() else eintrag.unlink() + for eintrag in daneben.iterdir(): + eintrag.rename(ordner / eintrag.name) + daneben.rmdir() + + +def _karten(ordner) -> dict: + """titel -> Sektionen. Verglichen wird über den Titel, nicht über die Datei.""" + raus = {} + for datei in sorted(ordner.glob("*.md")): + s = parser.zerlege(datei.read_text()) + raus[s["titel"]] = s + return raus + + +def _funktionstext(f: dict) -> str: + return "\n".join(str(f.get(feld) or "") for feld in FELDER) + + +def _funktionen(karte: dict) -> dict: + return {f["text"]: _funktionstext(f) for f in karte["funktionen"]} + + +def _kartentext(karte: dict) -> str: + return "\n".join((karte.get("art") or "", karte.get("ziel") or "", + karte.get("regeln") or "")) + + +def aenderungen(projekt: str) -> dict: + """Was die Planung am Projektstand ändert — je Karte und je Funktion. + + Ohne laufende Planung ist das leer. Die Übersicht zeigt dann nichts an, und + die Karten sehen aus wie immer. + """ + if not laeuft(projekt): + return {} + alt = _karten(projekte.stand(projekt)) + neu = _karten(_kopie(projekt)) + + raus = {} + for titel in set(alt) | set(neu): + a, b = alt.get(titel), neu.get(titel) + if a is None: + raus[titel] = {"art": "neu", "funktionen": { + f["text"]: "neu" for f in b["funktionen"]}} + continue + if b is None: + raus[titel] = {"art": "weg", "funktionen": { + f["text"]: "weg" for f in a["funktionen"]}} + continue + + fa, fb = _funktionen(a), _funktionen(b) + funktionen = {} + for name in set(fa) | set(fb): + if name not in fa: + funktionen[name] = "neu" + elif name not in fb: + funktionen[name] = "weg" + elif fa[name] != fb[name]: + funktionen[name] = "geaendert" + kopf = _kartentext(a) != _kartentext(b) + if funktionen or kopf: + raus[titel] = {"art": "geaendert", "funktionen": funktionen, + "kopf": kopf} + return raus + + +def _datei_zu(ordner, titel: str): + for datei in ordner.glob("*.md"): + if parser.zerlege(datei.read_text())["titel"] == titel: + return datei + return None + + +def zuruecksetzen(projekt: str, titel: str): + """Eine Karte auf den Projektstand zurückholen. + + Drei Fälle: neu dazugekommen (löschen), weggefallen (zurückholen), geändert + (überschreiben). Der Rest der Planung bleibt stehen. + """ + if not laeuft(projekt): + raise ValueError("Für dieses Projekt läuft keine Planung") + ordner, kopie = projekte.stand(projekt), _kopie(projekt) + urspruenglich = _datei_zu(ordner, titel) + geplant = _datei_zu(kopie, titel) + + if urspruenglich is None and geplant is None: + raise FileNotFoundError(f"Karte „{titel}“ nicht gefunden") + if urspruenglich is None: + geplant.unlink() + return + ziel = geplant or (kopie / urspruenglich.name) + ziel.write_text(urspruenglich.read_text()) + + +def stand(projekt: str) -> dict: + return {"laeuft": laeuft(projekt), "aenderungen": aenderungen(projekt)} diff --git a/backend/projekte.py b/backend/projekte.py index c0d6de2..93d6d1c 100644 --- a/backend/projekte.py +++ b/backend/projekte.py @@ -4,6 +4,10 @@ import shutil import config +# Die Arbeitskopie einer laufenden Planung. Liegt im Projektordner und beginnt mit +# einem Punkt — damit taucht sie im Listing nicht als eigenes Projekt auf. +PLANUNG = ".planung" + def _pruefe_name(name: str): if not name or not name.strip(): @@ -51,9 +55,24 @@ def loeschen(name: str): shutil.rmtree(ordner) -def wurzel(name: str): - """Projektordner für Feature-Zugriffe; FileNotFoundError bei unbekanntem Projekt.""" +def stand(name: str): + """Der Projektordner selbst — was das Projekt heute kann. + + Nur wer den umgesetzten Stand meint, ruft das. Alles andere nimmt `wurzel()`. + """ ordner = _ordner(name) if not ordner.is_dir(): raise FileNotFoundError(f"Projekt „{name}“ nicht gefunden") return ordner + + +def wurzel(name: str): + """Der Ordner, in dem gerade gearbeitet wird. + + Ohne offene Planung ist das der Projektordner. Läuft eine Planung, ist es ihre + Arbeitskopie — und zwar für alles: Karten, Gespräch, Gedächtnis. Ein + Schalter statt einer Fallunterscheidung in jeder Schreibfunktion. + """ + ordner = stand(name) + kopie = ordner / PLANUNG + return kopie if kopie.is_dir() else ordner diff --git a/backend/pruefung.py b/backend/pruefung.py index 09776e0..6214801 100644 --- a/backend/pruefung.py +++ b/backend/pruefung.py @@ -18,10 +18,18 @@ from collections import Counter import agents import config import features -import inhalt as inhaltspruefung -import quellcode +import ledger import struktur +class LaeuftBereits(ValueError): + """Eigener Typ, weil 409 genau eine Bedeutung haben muss. + + Vorher war jeder Fehlstart ein 409 — auch ein fehlendes Quellverzeichnis. Das + Frontend liest 409 als „läuft schon" und hängt sich an einen Lauf, den es nicht + gibt. Ergebnis: „Keine Probleme gefunden" statt der Fehlermeldung. + """ + + # projektname -> {"laeuft": bool, "fertig": int, "gesamt": int, "fehler": int, # "probleme": [...], "meldung": str} _laeufe = {} @@ -445,7 +453,17 @@ async def _neue_felder(system: str, aufgabe: dict, offen: list, erlaubt: tuple, return vorschlaege -async def _pruefe(stil: dict, aufgabe: dict) -> list[dict]: +def _stilschluessel(aufgabe: dict) -> str: + return ledger.schluessel(aufgabe["feature"], aufgabe["funktion"]) + + +def _stilabdruck(aufgabe: dict, system: str) -> str: + """Woran das Urteil hängt: der geprüfte Ausschnitt, der Katalog, die Frage. + Ändert sich eines davon, ist das gemerkte Urteil von gestern.""" + return ledger.abdruck(system, inhalt(aufgabe)) + + +async def _pruefe(stil: dict, aufgabe: dict, stand: dict = None) -> list[dict]: """Erst messen, dann umschreiben lassen, dann den Unterschied ausrechnen.""" bereich = BEREICHE[aufgabe["bereich"]] system = SYSTEM.format( @@ -455,6 +473,15 @@ async def _pruefe(stil: dict, aufgabe: dict) -> list[dict]: hinweis=bereich["hinweis"], ) offen = struktur.befunde(aufgabe["bereich"], aufgabe["felder"]) + + # Gemessene Verstöße stehen fest — die dürfen nie aus dem Gedächtnis kommen. + # Sonst bliebe eine neu hinzugekommene Messregel an alten Karten wirkungslos. + schluessel, wie_gehabt = _stilschluessel(aufgabe), _stilabdruck(aufgabe, system) + if stand is not None and not offen: + gemerkt = stand["stil"].get(schluessel) + if gemerkt and gemerkt["abdruck"] == wie_gehabt: + return [dict(p) for p in gemerkt["probleme"]] + vorschlaege = await _neue_felder(system, aufgabe, offen, bereich["felder"], katalogzeilen(stil[aufgabe["bereich"]])) @@ -466,83 +493,33 @@ async def _pruefe(stil: dict, aufgabe: dict) -> list[dict]: for p in probleme: p["feature"] = aufgabe["feature"] p["funktion"] = aufgabe["funktion"] + if stand is not None: + stand["stil"][schluessel] = {"abdruck": wie_gehabt, "probleme": probleme} return probleme async def _stil_aufgaben(projekt: str): - """Prüfstellen der Stilprüfung samt der Kataloge, die sie brauchen.""" + """Prüfstellen der Stilprüfung samt der Kataloge, die sie brauchen. + + Auch hier ein Gedächtnis: 176 Anfragen je Lauf brachten den Anbieter zum + Drosseln, und die ausgefallenen Stellen meldeten dann nichts. Unveränderter + Ausschnitt bei unverändertem Katalog heißt: das Urteil von vorhin gilt noch. + """ stil = {b: _stil_lesen(b) for b in BEREICHE} liste = [a for f in features.pruefbar(projekt) for a in aufgaben(f)] - return liste, lambda a, _zaehl: _pruefe(stil, a) - - -def _quelle(projekt: str): - alle = features.pruefbar(projekt) - quelle = quellcode.dateien() - if not quelle: - raise ValueError("Kein Quelltext gefunden") - return alle, quelle - - -async def _feature_aufgaben(projekt: str): - """Ein Lauf über alle Funktionen: steht hinter jeder auch Code? Und beschreibt - keine zwei Funktionen dieselbe Sache? - - Ein Aufruf statt vieler, weil das Ergebnis je Karte gebündelt wird — zwei - Vorschläge für dieselbe Funktionsliste wären nicht unabhängig anwendbar. - Der Zähler läuft trotzdem je Funktion mit. - """ - alle, quelle = _quelle(projekt) - text = quellcode.als_text(quelle) - anzahl = sum(len(f["sektionen"]["funktionen"]) for f in alle) - - async def abgleich(_, zaehl): - return await inhaltspruefung.pruefe_feature_im_code( - projekt, alle, quelle, text, zaehl, _melder(projekt)) - - return _platzhalter(anzahl), abgleich - - -async def _code_aufgaben(projekt: str): - """Ein Lauf über alle Bedienstellen — Vollständigkeit ist eine Eigenschaft der - Menge, nicht der einzelnen Karte.""" - alle, quelle = _quelle(projekt) - punkte = quellcode.interaktionen(quelle) - - async def abgleich(_, zaehl): - return await inhaltspruefung.pruefe_code_im_feature( - projekt, alle, quelle, zaehl, _melder(projekt)) - - return _platzhalter(len(punkte)), abgleich - - -def _melder(projekt: str): - """Sagt dem Lauf, was schiefging, ohne ihn abzubrechen. - - Ein Sammellauf ist eine einzige Aufgabe. Flöge er wegen einer Stelle, wären - alle anderen Befunde weg — und der Balken stünde trotzdem auf 100 %. So bleibt - das Ergebnis erhalten und der Fehlstand steht daneben. - """ - def melde(text: str, fehler: int = 0): - if lauf := _laeufe.get(projekt): - lauf["meldung"] = text - lauf["fehler"] += fehler - return melde - - -def _platzhalter(anzahl: int) -> list: - """Eine echte Aufgabe, der Rest nur für den Fortschrittsbalken.""" - return [True] + [None] * max(0, anzahl - 1) + stand = ledger.lade(projekt) + stand["stil"] = ledger.behalte(stand["stil"], {_stilschluessel(a) for a in liste}) + return (liste, + lambda a, _zaehl: _pruefe(stil, a, stand), + lambda: ledger.sichere(projekt, stand)) ARTEN = { "stil": _stil_aufgaben, - "feature": _feature_aufgaben, # Feature im Code: was steht ohne Code da? - "code": _code_aufgaben, # Code im Feature: was fehlt auf den Karten? } -async def _lauf(projekt: str, liste: list[dict], arbeite): +async def _lauf(projekt: str, liste: list[dict], arbeite, abschluss=None): lauf = _laeufe[projekt] schranke = asyncio.Semaphore(config.PRUEFUNG_PARALLEL) @@ -570,6 +547,9 @@ async def _lauf(projekt: str, liste: list[dict], arbeite): try: await asyncio.gather(*(eine(a) for a in liste)) finally: + # Auch ein abgebrochener Lauf hat schon Urteile gefällt; die sind bezahlt + if abschluss: + abschluss() lauf["laeuft"] = False @@ -578,10 +558,10 @@ async def starte(projekt: str, art: str = "stil") -> dict: if art not in ARTEN: raise ValueError(f"Unbekannte Prüfart „{art}“") if status(projekt)["laeuft"]: - raise ValueError("Prüfung läuft bereits") + raise LaeuftBereits("Prüfung läuft bereits") agents.pruefe_konfiguration() # früher Stopp statt halbem Lauf # Vorbereiten vor dem Task: ein Fehler darin wäre sonst unsichtbar - liste, arbeite = await ARTEN[art](projekt) + liste, arbeite, *rest = await ARTEN[art](projekt) _laeufe[projekt] = { "laeuft": True, "art": art, @@ -591,7 +571,7 @@ async def starte(projekt: str, art: str = "stil") -> dict: "probleme": [], "meldung": "", } - aufgabe = asyncio.create_task(_lauf(projekt, liste, arbeite)) + aufgabe = asyncio.create_task(_lauf(projekt, liste, arbeite, *rest)) _aufgaben.add(aufgabe) aufgabe.add_done_callback(_aufgaben.discard) return _laeufe[projekt] diff --git a/backend/quellcode.py b/backend/quellcode.py deleted file mode 100644 index 6842eb8..0000000 --- a/backend/quellcode.py +++ /dev/null @@ -1,189 +0,0 @@ -"""Der Quelltext als Prüfgrundlage. - -Die Inhaltsprüfung vergleicht Karten mit dem, was das Programm wirklich kann. -Damit das nicht auf Behauptungen hinausläuft, muss jede Aussage über den Code -eine wörtlich zitierte Zeile mitbringen — `belegt()` prüft sie nach. -""" - -import re - -import config - -# Was zum lauffähigen Programm gehört. Tests beschreiben keine Nutzerfunktionen. -MUSTER = ( - "backend/*.py", - "frontend/index.html", - "frontend/src/*.js", - "frontend/src/**/*.js", - "frontend/src/**/*.vue", -) -AUSGENOMMEN = ("tests/", "/tests/", "node_modules/", "dist/") - - -def _passt(pfad: str) -> bool: - return not any(a in pfad for a in AUSGENOMMEN) - - -def dateien() -> dict: - """Pfad relativ zur Projektwurzel -> Inhalt, in fester Reihenfolge.""" - raus = {} - for muster in MUSTER: - for datei in sorted(config.PROJECT_ROOT.glob(muster)): - pfad = str(datei.relative_to(config.PROJECT_ROOT)) - if datei.is_file() and _passt(pfad): - raus[pfad] = datei.read_text() - return dict(sorted(raus.items())) - - -def als_text(quelle: dict = None) -> str: - """Alle Dateien am Stück, jede mit Überschrift — so kann das Modell zitieren.""" - quelle = dateien() if quelle is None else quelle - return "\n\n".join(f"### {pfad}\n{text.rstrip()}" for pfad, text in quelle.items()) - - -def _normal(zeile: str) -> str: - return re.sub(r"\s+", " ", zeile).strip() - - -def belegt(quelle: dict, pfad: str, schnipsel: str) -> bool: - """Steht der Schnipsel wörtlich in der Datei? - - Verglichen wird ohne Rücksicht auf Einrückung — Modelle geben sie ungenau - wieder. Alles andere muss stimmen, sonst ist der Beleg wertlos. - """ - text = quelle.get(pfad) - if text is None or not schnipsel.strip(): - return False - gesucht = [_normal(z) for z in schnipsel.splitlines() if z.strip()] - if not gesucht: - return False - vorhanden = [_normal(z) for z in text.splitlines()] - # Zusammenhängend: eine mehrzeilige Angabe muss auch mehrzeilig dastehen - for i in range(len(vorhanden) - len(gesucht) + 1): - if vorhanden[i:i + len(gesucht)] == gesucht: - return True - return False - - -# Die Stellen, an denen ein Mensch etwas auslöst. Vorher hat ein Modell die -# Fähigkeiten frei aufgezählt — jede Runde andere, jede Runde anders benannt. -# Hier steht die Liste fest, weil sie aus dem Code fällt. -_EREIGNIS = re.compile(r'@(click|auxclick|contextmenu|keyup|keydown|blur|submit|change)' - r'[\w.]*\s*=\s*"([^"]*)"') -_MENUEPUNKT = re.compile(r"""\{\s*text:\s*['"](.+?)['"]\s*,\s*aktion:""") -_ROUTE = re.compile(r'@router\.(get|post|put|delete)\("([^"]+)"\)') -_LAUSCHER = re.compile(r'(window|document)\.addEventListener\(\s*[\'"](\w+)[\'"]') -_NAME = re.compile(r"[A-Za-zÄÖÜäöü_$][\w$]*") - -# Rein technische Aufhänger: Speichern beim Verlassen, Abbrechen mit Escape. -# Sie tragen keine eigene Fähigkeit, sondern gehören zur Bedienung eines Feldes. -_UNINTERESSANT = {"fertig", "abbrechen", "blur", "waehle"} -# emit('auswaehlen') ist eine Fähigkeit, emit('abbrechen') nicht — es zählt das -# Ereignis, nicht der Aufruf. Vorher fiel mit „emit" auch das Auswählen weg. -_EMIT = re.compile(r"""emit\(\s*['"](\w+)['"]""") -_ZUWEISUNG = re.compile(r"^\s*[\w.]+\s*=[^=]") - - -def _umfeld(zeilen: list, nr: int, rand: int = 5) -> str: - von, bis = max(0, nr - rand - 1), min(len(zeilen), nr + rand) - return "\n".join(zeilen[von:bis]).strip() - - -def _pyrumpf(zeilen: list, nr: int, hoechstens: int = 14) -> str: - """Der eingerückte Block unter einer Zeile — für Python statt geschweifter Klammern.""" - if nr > len(zeilen): - return "" # Dekorator ohne Rumpf, etwa am Dateiende - block = [zeilen[nr - 1]] - for weiter in zeilen[nr:nr + hoechstens]: - if weiter.strip() and not weiter[:1].isspace() and not weiter.startswith("@"): - break - block.append(weiter) - return "\n".join(block).rstrip() - - -def _rumpf(zeilen: list, name: str, hoechstens: int = 14) -> str: - """Die Umsetzung hinter einem Namen. - - Das Markup allein sagt nur, dass ein Knopf etwas aufruft. Was er tut, steht im - Rumpf — ohne den musste der Prüfer raten und urteilte jede Runde anders. - """ - anfang = re.compile(rf"^\s*(async\s+)?function\s+{re.escape(name)}\s*\(|" - rf"^\s*const\s+{re.escape(name)}\s*=") - for i, zeile in enumerate(zeilen): - if not anfang.match(zeile): - continue - block = [zeile] - for weiter in zeilen[i + 1:i + hoechstens]: - block.append(weiter) - if weiter.startswith("}"): - break - return "\n".join(block) - return "" - - -def interaktionen(quelle: dict = None) -> list[dict]: - """Auslösbare Stellen im Code, eine je Bedienhandlung. - - Zusammengefasst nach dem aufgerufenen Namen: `@click="starte('ziel')"` steht - zwölfmal im Markup, ist aber eine Fähigkeit. - - Dazu Fenster-Lauscher: ein Tastaturgriff ist eine Fähigkeit, auch ohne Knopf. - - Dazu die Backend-Routen. Sie standen zwischenzeitlich nicht drin, weil sie - doppelt gemeldet und dabei der falschen Karte zugeordnet wurden. Beides ist - jetzt aufgefangen: das Gedächtnis hält die Zuordnung fest, und der - Dublettenabgleich fängt zwei Funktionen für dieselbe Sache. Was hinter einem - Knopf liegt, ist der einzige Weg an Parser, Dateiverwaltung und Prüflogik — - ohne die Routen bliebe der ganze Rücken des Programms ungeprüft. - - Reine Hilfsfunktionen bleiben draußen. Ein Kunde bestellt keine Funktion namens - `_slug`; sie wird über die Route erreicht, die ihn interessiert. Jedes - öffentliche Symbol aufzunehmen ergäbe wieder ein Code-Inventar statt einer - Auftragsliste. - """ - quelle = dateien() if quelle is None else quelle - raus, gesehen = [], set() - - def merke(schluessel, art, pfad, nr, zeilen, beleg): - if schluessel in gesehen: - return None - gesehen.add(schluessel) - punkt = {"schluessel": schluessel, "art": art, "datei": pfad, "zeile": nr, - "beleg": beleg.strip(), "umfeld": _umfeld(zeilen, nr), "rumpf": ""} - raus.append(punkt) - return punkt - - for pfad, text in quelle.items(): - zeilen = text.splitlines() - for nr, zeile in enumerate(zeilen, 1): - for m in _MENUEPUNKT.finditer(zeile): - merke(f"menue:{m.group(1)}", "Menüpunkt", pfad, nr, zeilen, zeile) - for m in _LAUSCHER.finditer(zeile): - merke(f"lauscher:{m.group(1)}.{m.group(2)}", "Tastatur oder Maus", - pfad, nr, zeilen, zeile) - for m in _ROUTE.finditer(zeile): - punkt = merke(f"route:{m.group(1)} {m.group(2)}", "Schnittstelle", - pfad, nr, zeilen, zeile) - if punkt is not None: - punkt["rumpf"] = _pyrumpf(zeilen, nr + 1) - if not pfad.endswith(".vue"): - continue - for m in _EREIGNIS.finditer(zeile): - ausdruck = m.group(2) - if _ZUWEISUNG.match(ausdruck) or ausdruck.startswith("$"): - continue # Zuweisung oder Ereignis-Objekt, keine Fähigkeit - treffer = _EMIT.search(ausdruck) or _NAME.search(ausdruck) - if not treffer or treffer.group(1 if _EMIT.search(ausdruck) else 0) \ - in _UNINTERESSANT: - continue - name = treffer.group(1) if _EMIT.search(ausdruck) else treffer.group(0) - punkt = merke(f"bedienen:{name}", "Bedienung", pfad, nr, zeilen, zeile) - if punkt is not None: - punkt["rumpf"] = _rumpf(zeilen, name) - return raus - - -def uebersicht(quelle: dict = None) -> str: - """Kurze Dateiliste mit Zeilenzahl — für Prompts, die den Code nicht brauchen.""" - quelle = dateien() if quelle is None else quelle - return "\n".join(f"- {p} ({len(t.splitlines())} Zeilen)" for p, t in quelle.items()) diff --git a/backend/routes.py b/backend/routes.py index d56f20c..2b23e2c 100644 --- a/backend/routes.py +++ b/backend/routes.py @@ -4,8 +4,10 @@ hier wird auf 400/404/409 gemappt.""" from fastapi import APIRouter, HTTPException import agents +import chat import features import projekte +import planung import pruefung router = APIRouter(prefix="/api") @@ -55,9 +57,13 @@ async def projekt_loeschen(name: str): @router.get("/projekte/{name}/features") -async def features_liste(name: str): +async def features_liste(name: str, sicht: str = "planung"): + """`sicht=uebersicht` liest den Projektstand, sonst die Arbeitskopie. + + Ohne laufende Planung sind beide dasselbe Verzeichnis. + """ try: - return features.liste(name) + return features.liste(name, nur_stand=sicht == "uebersicht") except (FileNotFoundError, ValueError) as e: raise HTTPException(404, str(e)) @@ -89,10 +95,10 @@ async def pruefung_starten(name: str, body: dict | None = None): return await pruefung.starte(name, art) except FileNotFoundError as e: raise HTTPException(404, str(e)) - except agents.NichtKonfiguriert as e: - raise HTTPException(400, str(e)) # 409 heißt „läuft bereits" — hier fehlt die .env + except pruefung.LaeuftBereits as e: + raise HTTPException(409, str(e)) # 409 heißt genau das und sonst nichts except ValueError as e: - raise HTTPException(409, str(e)) + raise HTTPException(400, str(e)) @router.get("/projekte/{name}/pruefung") @@ -100,6 +106,56 @@ async def pruefung_status(name: str): return pruefung.status(name) +@router.get("/projekte/{name}/planung") +async def planung_stand(name: str): + try: + return planung.stand(name) + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + + +@router.post("/projekte/{name}/planung") +async def planung_starten(name: str): + try: + planung.starte(name) + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + except ValueError as e: + raise HTTPException(409, str(e)) + return planung.stand(name) + + +@router.post("/projekte/{name}/planung/umsetzen") +async def planung_umsetzen(name: str): + try: + planung.setze_um(name) + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + except ValueError as e: + raise HTTPException(409, str(e)) + return {"ok": True} + + +@router.delete("/projekte/{name}/planung") +async def planung_abbrechen(name: str): + try: + planung.brich_ab(name) + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + return {"ok": True} + + +@router.post("/projekte/{name}/planung/zuruecksetzen") +async def planung_zuruecksetzen(name: str, body: dict): + try: + planung.zuruecksetzen(name, (body or {}).get("titel") or "") + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + except ValueError as e: + raise HTTPException(409, str(e)) + return planung.stand(name) + + @router.delete("/projekte/{name}/pruefung") async def pruefung_beenden(name: str): pruefung.beende(name) @@ -113,3 +169,42 @@ async def feature_loeschen(name: str, id: str): except (FileNotFoundError, ValueError) as e: raise HTTPException(404, str(e)) return {"ok": True} + + +@router.put("/projekte/{name}/features/{id}/projekt") +async def feature_verschieben(name: str, id: str, body: dict): + try: + return features.verschieben(name, id, (body.get("ziel") or "").strip()) + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + except ValueError as e: + raise HTTPException(400, str(e)) + + +@router.get("/projekte/{name}/chat") +async def chat_verlauf(name: str): + try: + return {"verlauf": chat.verlauf(name)} + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + + +@router.post("/projekte/{name}/chat") +async def chat_frage(name: str, body: dict): + try: + return await chat.frage(name, body.get("text") or "") + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + except agents.NichtKonfiguriert as e: + raise HTTPException(400, str(e)) + except ValueError as e: + raise HTTPException(400, str(e)) + + +@router.delete("/projekte/{name}/chat") +async def chat_leeren(name: str): + try: + chat.leeren(name) + except FileNotFoundError as e: + raise HTTPException(404, str(e)) + return {"ok": True} diff --git a/backend/stil/allgemein.md b/backend/stil/allgemein.md index 0016b78..fd0663f 100644 --- a/backend/stil/allgemein.md +++ b/backend/stil/allgemein.md @@ -18,6 +18,9 @@ Gilt für jedes Feld. Diese Vorgaben prüft der Code selbst, exakt und für jede Zeile. Halte dich beim Schreiben daran — aber berufe dich nie darauf. Als `regel` sind sie nicht zulässig. +- Jede Funktion hat Ziel, Regeln oder Testschritte — nie nur einen Titel +- Titel einer Funktion endet auf ein Verb im Infinitiv +- Testschritte beschreiben genau einen Ablauf - Kein Satzzeichen am Zeilenende, kein Punkt und kein Semikolon - Keine Füllwörter. Die Liste ist abschließend: auch, noch, einfach, jeweils, ggf. - Keine Klammern und keine Schrägstriche diff --git a/backend/stil/funktion-testen.md b/backend/stil/funktion-testen.md index 97fc3a9..ad9d089 100644 --- a/backend/stil/funktion-testen.md +++ b/backend/stil/funktion-testen.md @@ -3,6 +3,8 @@ Feld `testen`. Gibt es nur bei Funktionen, nie auf Kartenebene. - Eine Zeile je Schritt +- Genau ein Ablauf: handeln, handeln, Ergebnis +- Nach dem Ergebnis folgt keine Handlung mehr - Schritte in Reihenfolge der Bedienung - Kein Schritt der Bedienung fehlt - Letzte Zeile beschreibt den Endzustand, keine Handlung @@ -16,3 +18,12 @@ Richtig: - Funktion entfernt ``` Falsch: letzte Zeile `Klick zum entfernen` (Handlung statt Endzustand) + +Falsch, weil zwei Abläufe in einer Funktion stehen: +``` +- Klick auf Miniaturbild +- Großansicht öffnet und schließt +- Option aus Großansicht auswählbar +``` +Jede Zeile ist hier ein eigenes Ergebnis, kein Schritt eines Durchlaufs. Solche +Funktionen sind mehrere und gehören getrennt. diff --git a/backend/stil/funktion-titel.md b/backend/stil/funktion-titel.md index 1e76e28..a88d93f 100644 --- a/backend/stil/funktion-titel.md +++ b/backend/stil/funktion-titel.md @@ -4,6 +4,8 @@ Feld `titel`, wenn `funktion` gesetzt ist. - Kurzsatz aus Objekt und Verb im Infinitiv - Genau eine Tätigkeit +- Endet auf ein Verb im Infinitiv +- Nennt eine Handlung, keinen Bereich, keinen Zustand Richtig: `Feature erstellen` · `Anzeigemodus umschalten` · `Feature als Datei speichern` -Falsch: `Erstellung von Features` (Substantivierung) · `Feature erstellen und öffnen` (zwei Tätigkeiten) +Falsch: `Erstellung von Features` (Substantivierung) · `Feature erstellen und öffnen` (zwei Tätigkeiten) · `Galerie im Modal` (ein Bereich) · `Preis aktualisiert` (ein Zustand) · `In den Warenkorb` (kein Verb) diff --git a/backend/struktur.py b/backend/struktur.py index c6e41eb..b203686 100644 --- a/backend/struktur.py +++ b/backend/struktur.py @@ -29,8 +29,21 @@ BADGE = ("kern", "optional") # „funktionen" gehört der Inhaltsprüfung, hat aber dieselbe Gestalt. ZEILENFELDER = ("regeln", "testen", "funktionen") +# Ein Funktionstitel nennt eine Handlung. Ohne Verb am Ende steht dort ein Bereich +# („Galerie im Modal") oder ein Zustand („Preis aktualisiert") — beides beschreibt +# nichts, was man für sich testen könnte. Deutsche Infinitive enden auf -en, -ln, +# -rn; wie Füllwörter und Wortgrenzen ist auch das an die Sprache gebunden. +_INFINITIV = re.compile(r"(?:e[lr]?n|ln|rn)$", re.I) +# Eine Handlung steht als Infinitiv am Anfang oder am Ende der Zeile („Bestätigen im +# Modal", „Text ändern") oder beginnt mit einer Taste. Alles andere ist ein Ergebnis. +# Nur Anfang und Ende, nicht irgendwo: deutsche Mehrzahl endet auch auf -en. +_TASTE = re.compile(r"^(?:LMB|RMB|MMB|Klick|Doppelklick|Enter|Escape|Strg|Tab)\b", re.I) + SATZENDE = ".;" _KLAMMER = re.compile(r"[()/]") +# Eine Vorlage ist kein Inhalt. Das Modell schlug `` als Testschritt +# vor — formal richtig, gemeint war „hier fehlt noch etwas". +_LUECKE = re.compile(r"<[^<>]*>|\.\.\.|\bTODO\b|\bXXX\b", re.I) _STRICH = re.compile(r"^[-*]\s*") @@ -68,9 +81,15 @@ def _umschreiben(bereich: str, feld: str, zeile: str) -> list[str]: gruende = [] if _KLAMMER.search(zeile): gruende.append("Klammer oder Schrägstrich") + if _LUECKE.search(zeile): + gruende.append("Platzhalter statt Inhalt") grenze = WORTGRENZEN.get((bereich, feld)) if grenze and len(zeile.split()) > grenze: gruende.append(f"Mehr als {grenze} Wörter") + if bereich == "funktion" and feld == "titel": + woerter = zeile.split() + if woerter and not _INFINITIV.search(woerter[-1]): + gruende.append("Kein Verb im Infinitiv am Ende") if feld == "ziel": saetze = [s.strip() for s in re.split(r"[.!?]+", zeile) if s.strip()] if len(saetze) > ZIEL_SAETZE: @@ -80,6 +99,30 @@ def _umschreiben(bereich: str, feld: str, zeile: str) -> list[str]: return gruende +def _handlung(zeile: str) -> bool: + woerter = zeile.split() + if not woerter: + return True + return bool(_TASTE.match(zeile) or _INFINITIV.search(woerter[-1]) + or _INFINITIV.search(woerter[0])) + + +def _zweiter_ablauf(zeilen: list[str]) -> str: + """Die Zeile, ab der ein zweiter Durchlauf beginnt — sonst leer. + + Ein Ablauf ist: handeln, handeln, Ergebnis. Steht nach dem Ergebnis wieder eine + Handlung, sind es zwei Abläufe — und damit zwei Funktionen. Genau so entstand + „Bildergalerie bedienen" mit blättern, Miniatur wählen und Großansicht in einem. + """ + ergebnis = False + for zeile in zeilen: + if ergebnis and _handlung(zeile): + return zeile + if not _handlung(zeile): + ergebnis = True + return "" + + def _zeile(bereich: str, feld: str, zeile: str) -> list[dict]: """Höchstens ein Befund je Zeile. Zwei Vorschläge für dieselbe Zeile wären nicht unabhängig — der zweite fände seine Stelle nach dem ersten nicht mehr.""" @@ -94,13 +137,28 @@ def _zeile(bereich: str, feld: str, zeile: str) -> list[dict]: def befunde(bereich: str, felder: dict) -> list[dict]: """Alle messbaren Verstöße einer Prüfstelle, in Reihenfolge der Felder.""" raus = [] + # Ein bloßer Titel beschreibt nichts — und lässt sich über alles stülpen. Der + # Prüfer hielt damit einen Druckknopf für „Modal mit Tastatur steuern". + # Nur wenn die ganze Funktion vorliegt: bei einem einzelnen Feld sagt das Fehlen + # der anderen nichts. + inhaltsfelder = ("ziel", "regeln", "testen") + if bereich == "funktion" and all(f in felder for f in inhaltsfelder) \ + and not any((felder.get(f) or "").strip() for f in inhaltsfelder): + raus.append(_problem("testen", "", "Funktion ohne Ziel, Regeln und Testen")) + return raus for feld, text in felder.items(): if feld == "badge": if text and text not in BADGE: raus.append(_problem(feld, text, "Weder kern noch optional", "kern")) continue - for zeile in _zeilen(feld, text or ""): + zeilen = _zeilen(feld, text or "") + for zeile in zeilen: raus += _zeile(bereich, feld, zeile) + if feld == "testen" and not raus: + # Erst prüfen, wenn die Zeilen für sich in Ordnung sind: sonst hängen + # zwei Vorschläge am selben Feld und der zweite findet seine Stelle nicht. + if bruch := _zweiter_ablauf(zeilen): + raus.append(_problem(feld, bruch, "Zweiter Ablauf in einer Funktion")) return raus diff --git a/backend/tests/test_inhalt.py b/backend/tests/test_inhalt.py deleted file mode 100644 index decf102..0000000 --- a/backend/tests/test_inhalt.py +++ /dev/null @@ -1,60 +0,0 @@ -import inhalt -import quellcode - - -def test_unformatierte_prompts_ohne_doppelklammern(): - """Was nicht durch .format() geht, darf keine Escape-Klammern tragen — - das Modell schrieb sie sonst wörtlich in die Antwort und das JSON war kaputt.""" - for name in ("ABDECKUNG_SYSTEM",): - text = getattr(inhalt, name) - assert "{{" not in text and "}}" not in text, name - - -def test_formatierte_prompts_ueberstehen_format(): - punkt = {"art": "Bedienung", "datei": "a.vue", "zeile": 1, - "umfeld": "x", "rumpf": ""} - fertig = inhalt.ABDECKUNG.format(funktionen="—", **punkt) - assert '{"abgedeckt": true' in fertig - assert "{{" not in fertig - - -def test_beleg_muss_woertlich_dastehen(): - quelle = {"a.py": "def eins():\n return 1\n"} - assert quellcode.belegt(quelle, "a.py", "def eins():") - assert quellcode.belegt(quelle, "a.py", " def eins(): ") # Einrückung egal - assert quellcode.belegt(quelle, "a.py", "def eins():\nreturn 1") - assert not quellcode.belegt(quelle, "a.py", "def zwei():") - assert not quellcode.belegt(quelle, "b.py", "def eins():") - assert not quellcode.belegt(quelle, "a.py", "") - - -def test_interaktionen_sind_deterministisch(): - quelle = { - "frontend/src/X.vue": ( - '\n' - '\n' - '

c
\n' - '\n' - 'zu\n' - ), - "backend/routes.py": '@router.get("/projekte")\n@router.post("/projekte")\n', - "frontend/src/m.js": " { text: '+ Projekt erstellen', aktion: () => x() },\n", - } - schluessel = [p["schluessel"] for p in quellcode.interaktionen(quelle)] - # Zwölf Aufrufe von starte() sind eine Fähigkeit, nicht zwölf - assert schluessel.count("bedienen:starte") == 1 - assert "bedienen:menue" in schluessel - # Routen: der einzige Weg an Parser, Dateiverwaltung und Prüflogik - assert "route:get /projekte" in schluessel - assert "route:post /projekte" in schluessel - assert "menue:+ Projekt erstellen" in schluessel - # Technische Aufhänger und Zuweisungen sind keine Fähigkeiten - assert not any(s.startswith("bedienen:fertig") for s in schluessel) - assert not any(s.startswith("bedienen:abbrechen") for s in schluessel) - assert not any(s.startswith("bedienen:offen") for s in schluessel) - # Zweiter Aufruf liefert exakt dasselbe - assert schluessel == [p["schluessel"] for p in quellcode.interaktionen(quelle)] - - -def test_tests_sind_kein_quelltext(): - assert not any("tests/" in p for p in quellcode.dateien()) diff --git a/backend/tests/test_ledger.py b/backend/tests/test_ledger.py index cbed1a9..a86118c 100644 --- a/backend/tests/test_ledger.py +++ b/backend/tests/test_ledger.py @@ -1,8 +1,8 @@ -"""Das Gedächtnis der Inhaltsprüfungen: was gilt weiter, was wird neu gefragt. +"""Das Gedächtnis der Stilprüfung: was gilt weiter, was wird neu gefragt. -Die Prüfungen 2 und 3 fragen ein Modell. Dieselbe Frage kippt bei Grenzfällen auch -bei Temperatur 0 — vorher meldete Runde 1 einen Befund, Runde 2 keinen, Runde 3 -wieder einen. Hier steht, unter welchen Bedingungen ein Urteil stehen bleibt. +Die Prüfung fragt ein Modell. Dieselbe Frage kippt bei Grenzfällen auch bei +Temperatur 0 — vorher meldete Runde 1 einen Befund, Runde 2 keinen, Runde 3 wieder +einen. Hier steht, unter welchen Bedingungen ein Urteil stehen bleibt. """ import json @@ -11,7 +11,6 @@ import pytest import agents import features -import inhalt import ledger import projekte @@ -33,9 +32,6 @@ def karte(projekt, titel, *funktionen): return features.anlegen(projekt, text) -QUELLE = {"frontend/src/App.vue": '\n'} - - class Zaehler: """Ersetzt das Modell und zählt mit, wie oft überhaupt gefragt wurde.""" @@ -82,431 +78,6 @@ def test_gedaechtnis_ist_kein_feature(projekt): assert [f["sektionen"]["titel"] for f in features.liste(projekt)] == ["Eins"] -# ---------------------------------------------------------------- Prüfung 2 - -GEFUNDEN = json.dumps({"gefunden": True, "datei": "frontend/src/App.vue", - "beleg": ''}) - - -async def test_beleg_wird_gemerkt_und_beim_zweiten_lauf_nicht_gefragt( - projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(GEFUNDEN) - monkeypatch.setattr(agents, "frage", modell) - - alle = features.liste(projekt) - text = "### frontend/src/App.vue\n" + QUELLE["frontend/src/App.vue"] - assert await inhalt.pruefe_feature_im_code(projekt, alle, QUELLE, text) == [] - erste_runde = modell.rufe - assert erste_runde >= len(inhalt.SUCHE_TEMPERATUREN) - - assert await inhalt.pruefe_feature_im_code(projekt, alle, QUELLE, text) == [] - assert modell.rufe == erste_runde # keine einzige neue Anfrage - - -async def test_beleg_verfaellt_wenn_die_zeile_verschwindet(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(GEFUNDEN) - monkeypatch.setattr(agents, "frage", modell) - - alle = features.liste(projekt) - text = "### frontend/src/App.vue\n" + QUELLE["frontend/src/App.vue"] - await inhalt.pruefe_feature_im_code(projekt, alle, QUELLE, text) - vorher = modell.rufe - - anders = {"frontend/src/App.vue": "
nichts mehr
\n"} - await inhalt.pruefe_feature_im_code(projekt, alle, anders, "### x\n
") - assert modell.rufe > vorher # der Beleg trägt nicht mehr, also neu fragen - - -async def test_geaenderte_funktion_wird_neu_gefragt(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(GEFUNDEN) - monkeypatch.setattr(agents, "frage", modell) - - text = "### frontend/src/App.vue\n" + QUELLE["frontend/src/App.vue"] - await inhalt.pruefe_feature_im_code(projekt, features.liste(projekt), QUELLE, text) - vorher = modell.rufe - - datei = projekte.wurzel(projekt) / f"{features.liste(projekt)[0]['id']}.md" - datei.write_text(datei.read_text().replace("- Knopf", "- Ganz anderer Inhalt")) - await inhalt.pruefe_feature_im_code(projekt, features.liste(projekt), QUELLE, text) - assert modell.rufe > vorher - - -async def test_fehlanzeige_gilt_nur_bei_unveraendertem_quelltext(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(json.dumps({"gefunden": False, "grund": "gibt es nicht"})) - monkeypatch.setattr(agents, "frage", modell) - - alle = features.liste(projekt) - text = "### frontend/src/App.vue\n" + QUELLE["frontend/src/App.vue"] - erste = await inhalt.pruefe_feature_im_code(projekt, alle, QUELLE, text) - assert len(erste) == 1 - vorher = modell.rufe - - zweite = await inhalt.pruefe_feature_im_code(projekt, alle, QUELLE, text) - assert [p["vorschlag"] for p in zweite] == [p["vorschlag"] for p in erste] - assert modell.rufe == vorher - - # Neuer Quelltext: eine Löschempfehlung muss frisch belegt werden - mehr = {**QUELLE, "backend/neu.py": "def starte():\n pass\n"} - await inhalt.pruefe_feature_im_code(projekt, alle, mehr, text) - assert modell.rufe > vorher - - -# ---------------------------------------------------------------- Dubletten - -def punkt(schluessel="bedienen:starte", beleg=''): - return {"schluessel": schluessel, "art": "Bedienung", - "datei": "frontend/src/App.vue", "zeile": 1, "beleg": beleg, - "umfeld": beleg, "rumpf": ""} - - -async def test_gleicher_beleg_macht_zwei_funktionen_zu_kandidaten(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - karte(projekt, "Zwei", ("Lauf beginnen", "Knopf")) - monkeypatch.setattr(agents, "frage", Zaehler(json.dumps({"gegenstand_gleich": True, "ergebnis_gleich": True}))) - - alle = features.liste(projekt) - stand = ledger.lade(projekt) - for f in alle: - stand["belege"][ledger.schluessel(f["id"], f["sektionen"]["funktionen"][0]["text"])] = { - "abdruck": "egal", "datei": "frontend/src/App.vue", - "beleg": ''} - gefunden = await inhalt.dubletten(alle, stand) - assert len(gefunden) == 1 - # Gleich stark: der Titel entscheidet, damit der Vorschlag nicht springt - assert gefunden[0]["titel"] == "Etwas starten" - assert "Lauf beginnen" in gefunden[0]["grund"] - - -async def test_uneiniges_urteil_ist_keine_dublette_und_wird_gemerkt( - projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - karte(projekt, "Zwei", ("Lauf beginnen", "Knopf")) - - def wechselhaft(nachricht, ruf): - return json.dumps({"gegenstand_gleich": True, "ergebnis_gleich": ruf == 1}) - - modell = Zaehler(wechselhaft) - monkeypatch.setattr(agents, "frage", modell) - - alle = features.liste(projekt) - stand = ledger.lade(projekt) - for f in alle: - stand["belege"][ledger.schluessel(f["id"], f["sektionen"]["funktionen"][0]["text"])] = { - "abdruck": "egal", "datei": "a.vue", "beleg": "x"} - assert await inhalt.dubletten(alle, stand) == [] - vorher = modell.rufe - assert await inhalt.dubletten(alle, stand) == [] - assert modell.rufe == vorher # Ablehnung wird gemerkt, nicht neu bezahlt - - -def test_gegenstueck_faellt_nicht_ueber_den_titel(): - """anlegen/entfernen und öffnen/schließen dürfen den Titelkanal nicht auslösen — - sonst kostet jedes Gegensatzpaar drei Anfragen für nichts.""" - for a, b in (("Feature anlegen", "Feature entfernen"), - ("Panel öffnen", "Panel schließen")): - assert inhalt._aehnlich(a, b) < inhalt.TITEL_KANAL - - -ENTFERNEN = ["Vollmodus öffnen", "RMB auf die Funktion", - 'Klick auf "Funktion entfernen"', "Funktion entfernt"] - - -def test_umschriebene_dublette_wird_kandidat(projekt): - """Anderer Titel, andere Karte, dieselbe Sache. Weder Titel noch Beleg fangen - das — nur der Inhaltskanal.""" - karte(projekt, "Funktionen", - ("Funktion entfernen", "x-Icon", ENTFERNEN), - ("Funktion anlegen", "+-Icon", ["Vollmodus öffnen", "RMB auf die Karte", - 'Klick auf "Funktion erstellen"', - "Funktion angelegt"]), - ("Testschritte anpassen", "Ein Schritt je Zeile", - ["Vollmodus öffnen", "LMB auf Testen", "Text ändern", "Schritte angepasst"])) - karte(projekt, "Features", ("Funktion löschen", "x-Icon", ENTFERNEN)) - - alle = inhalt._funktionen(features.liste(projekt)) - paare = {frozenset((alle[a]["titel"], alle[b]["titel"])) for _, a, b, _ in - inhalt._kandidaten(alle, {})} - assert frozenset(("Funktion entfernen", "Funktion löschen")) in paare - assert frozenset(("Funktion anlegen", "Funktion entfernen")) not in paare - - -def test_floskeln_zaehlen_nicht_mit(projekt): - """Was fast überall steht, unterscheidet nichts und fliegt aus dem Vergleich.""" - schritte = ["Vollmodus öffnen", "Text ändern", "Angepasst"] - karte(projekt, "Eins", - *[(f"{feld} anpassen", "eine Regel", schritte) - for feld in ("Titel", "Ziel", "Regeln", "Testen", "Badge")]) - kerne = inhalt._kerne(inhalt._funktionen(features.liste(projekt))) - gemeinsam = set.intersection(*kerne.values()) - assert gemeinsam == set() # „vollmodus", „ändern", „angepasst" sind raus - assert all(k for k in kerne.values()) # jede Funktion behält ihr eigenes Wort - - -# ---------------------------------------------------------------- Prüfung 3 - -ABGEDECKT = json.dumps({"abgedeckt": True, "funktion": "Etwas starten"}) -FEHLT = json.dumps({"abgedeckt": False, "karte": "Eins", "titel": "Neu bedienen"}) - - -async def test_abdeckung_wird_gemerkt_solange_die_funktion_dasteht( - projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(ABGEDECKT) - monkeypatch.setattr(agents, "frage", modell) - - stand = ledger.lade(projekt) - alle = features.liste(projekt) - assert await inhalt.code_im_feature(alle, [punkt()], stand) == [] - vorher = modell.rufe - assert await inhalt.code_im_feature(alle, [punkt()], stand) == [] - assert modell.rufe == vorher - - # Funktion weg: die Abdeckung trägt nicht mehr - ohne = features.liste(projekt) - ohne[0]["sektionen"]["funktionen"] = [] - await inhalt.code_im_feature(ohne, [punkt()], stand) - assert modell.rufe > vorher - - -async def test_geaenderte_codestelle_wird_neu_beurteilt(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(ABGEDECKT) - monkeypatch.setattr(agents, "frage", modell) - - stand = ledger.lade(projekt) - alle = features.liste(projekt) - await inhalt.code_im_feature(alle, [punkt()], stand) - vorher = modell.rufe - await inhalt.code_im_feature(alle, [punkt(beleg="ganz anderer Code")], stand) - assert modell.rufe > vorher - - -async def test_fehlmeldung_bleibt_wortgleich_bis_die_funktion_da_ist( - projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(FEHLT) - monkeypatch.setattr(agents, "frage", modell) - - stand = ledger.lade(projekt) - alle = features.liste(projekt) - erste = await inhalt.code_im_feature(alle, [punkt()], stand) - assert [x["titel"] for x in erste] == ["Neu bedienen"] - vorher = modell.rufe - - zweite = await inhalt.code_im_feature(alle, [punkt()], stand) - assert zweite == erste - assert modell.rufe == vorher # kein Flackern, keine neue Anfrage - - -async def test_angenommener_vorschlag_loest_die_fehlmeldung_ab(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - modell = Zaehler(FEHLT) - monkeypatch.setattr(agents, "frage", modell) - - stand = ledger.lade(projekt) - await inhalt.code_im_feature(features.liste(projekt), [punkt()], stand) - vorher = modell.rufe - - # Der Nutzer nimmt den Vorschlag an — jetzt muss neu beurteilt werden - modell.antwort = ABGEDECKT - karte(projekt, "Zwei", ("Neu bedienen", "Knopf")) - assert await inhalt.code_im_feature(features.liste(projekt), [punkt()], stand) == [] - assert modell.rufe > vorher - - -async def test_unentschiedenes_urteil_wird_festgehalten(projekt, monkeypatch): - """Drei zu drei ist ein Münzwurf. Der darf einmal fallen, nicht jede Runde.""" - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - - def haelfte(nachricht, ruf): - return ABGEDECKT if ruf % 2 else FEHLT - - modell = Zaehler(haelfte) - monkeypatch.setattr(agents, "frage", modell) - - stand = ledger.lade(projekt) - alle = features.liste(projekt) - assert await inhalt.code_im_feature(alle, [punkt()], stand) == [] - vorher = modell.rufe - assert await inhalt.code_im_feature(alle, [punkt()], stand) == [] - assert modell.rufe == vorher - - -async def test_verschwundene_stelle_raeumt_ihren_eintrag_weg(projekt, monkeypatch): - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - monkeypatch.setattr(agents, "frage", Zaehler(ABGEDECKT)) - - stand = ledger.lade(projekt) - alle = features.liste(projekt) - await inhalt.code_im_feature(alle, [punkt()], stand) - assert stand["abdeckung"] - await inhalt.code_im_feature(alle, [punkt(schluessel="bedienen:anderes")], stand) - assert "bedienen:starte" not in stand["abdeckung"] - - -def test_fehlende_stelle_landet_auch_auf_erfundener_karte(projekt): - """Sechs Stimmen sagen „fehlt", nennen aber Karten, die es nicht gibt. Vorher - fiel der Befund lautlos weg.""" - karte(projekt, "Projekte", ("Projekt anlegen", "+-Icon")) - karten = {f["sektionen"]["titel"]: f for f in features.liste(projekt)} - urteile = [{"abgedeckt": False, "karte": "Datenverwaltung", "titel": "x"}] * 4 - assert inhalt._zielkarte(urteile, karten) is karten["Projekte"] - - -def test_erster_aufloesbarer_kartenname_gewinnt(projekt): - karte(projekt, "Projekte", ("Projekt anlegen", "+-Icon")) - karte(projekt, "Darkmode", ("Darkmode umschalten", "Icon")) - karten = {f["sektionen"]["titel"]: f for f in features.liste(projekt)} - urteile = ([{"abgedeckt": False, "karte": "Export", "titel": "x"}] * 3 - + [{"abgedeckt": False, "karte": "Darkmode", "titel": "x"}] * 2) - assert inhalt._zielkarte(urteile, karten) is karten["Darkmode"] - - -def test_ohne_karten_kein_ziel(projekt): - assert inhalt._zielkarte([{"abgedeckt": False, "karte": "X"}], {}) is None - - -def test_grund_trennt_dublette_von_fehlendem_code(): - """Beides heißt streichen — aber aus verschiedenen Gründen, und der Grund - entscheidet, ob man zustimmt.""" - assert inhalt._wegfall_grund([{"art": "dublette"}]) == "1 Funktion doppelt" - assert inhalt._wegfall_grund([{"art": "ohne_code"}] * 2) \ - == "2 Funktionen ohne eigenen Code" - assert inhalt._wegfall_grund([{"art": "dublette"}, {"art": "ohne_code"}]) \ - == "1 Funktion doppelt, 1 Funktion ohne eigenen Code" - - -def test_halbe_datei_ueberschreibt_nicht_die_ganze(projekt, monkeypatch): - """Absturz beim Schreiben: die alte Datei muss stehen bleiben.""" - stand = ledger.lade(projekt) - stand["belege"]["a"] = {"abdruck": "x", "datei": "a.py", "beleg": "z"} - ledger.sichere(projekt, stand) - - echt = ledger.json.dumps - - def platzt(*a, **k): - raise MemoryError("mittendrin") - - monkeypatch.setattr(ledger.json, "dumps", platzt) - with pytest.raises(MemoryError): - ledger.sichere(projekt, {"belege": {"b": {}}}) - monkeypatch.setattr(ledger.json, "dumps", echt) - assert ledger.lade(projekt)["belege"] == stand["belege"] - - -async def test_ausgefallene_stimmen_merken_nichts(projekt, monkeypatch): - """Fällt der Anbieter aus, darf keine Löschempfehlung im Gedächtnis landen.""" - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - - async def tot(system, nachricht, temperatur=0.0): - raise RuntimeError("429") - - monkeypatch.setattr(agents, "frage", tot) - stand = ledger.lade(projekt) - gemeldet = [] - assert await inhalt.feature_im_code(features.liste(projekt), QUELLE, "x", stand, - melde=lambda t, n=0: gemeldet.append(n)) == [] - assert gemeldet == [1] # laut gescheitert, nicht still - assert stand["ohne_code"] == {} - assert stand["belege"] == {} - - -async def test_ein_ausfall_rettet_die_anderen_urteile(projekt, monkeypatch): - """Eine kaputte Stelle darf die bezahlten Urteile der anderen nicht wegwerfen.""" - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - - async def launisch(system, nachricht, temperatur=0.0): - if "bedienen:kaputt" in nachricht: - raise RuntimeError("429") - return ABGEDECKT - - monkeypatch.setattr(agents, "frage", launisch) - stand = ledger.lade(projekt) - gemeldet = [] - await inhalt.code_im_feature( - features.liste(projekt), - [punkt(), punkt(schluessel="bedienen:kaputt", beleg="bedienen:kaputt")], - stand, melde=lambda t, n=0: gemeldet.append(n)) - assert gemeldet == [1] - assert "bedienen:starte" in stand["abdeckung"] - assert "bedienen:kaputt" not in stand["abdeckung"] - - -async def test_projekt_ohne_karten_stuerzt_nicht_ab(projekt, monkeypatch): - monkeypatch.setattr(agents, "frage", Zaehler(FEHLT)) - stand = ledger.lade(projekt) - assert await inhalt.code_im_feature([], [punkt()], stand) == [] - assert await inhalt.dubletten([], stand) == [] - assert await inhalt.feature_im_code([], QUELLE, "x", stand) == [] - - -async def test_feststehendes_urteil_braucht_keine_vollen_stimmen(projekt, monkeypatch): - """Vier von sechs sagen „abgedeckt": die zwei fehlenden könnten die Schwelle - nicht mehr reißen. Daraus einen Fehlschlag zu machen wäre Verschwendung.""" - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - ausfaelle = {"n": 0} - - async def zwei_platzen(system, nachricht, temperatur=0.0): - ausfaelle["n"] += 1 - if ausfaelle["n"] <= 2: - raise RuntimeError("429") - return ABGEDECKT - - monkeypatch.setattr(agents, "frage", zwei_platzen) - stand = ledger.lade(projekt) - gemeldet = [] - assert await inhalt.code_im_feature(features.liste(projekt), [punkt()], stand, - melde=lambda t, n=0: gemeldet.append(n)) == [] - assert gemeldet == [] # kein Fehler: das Ergebnis stand fest - assert "bedienen:starte" in stand["abdeckung"] - - -async def test_offenes_urteil_bei_ausfall_wird_gemeldet(projekt, monkeypatch): - """Vier Stimmen sagen „fehlt", zwei fehlen — mit ihnen wäre die Schwelle - erreicht. Das ist offen und muss laut scheitern, nicht still durchgehen.""" - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - ausfaelle = {"n": 0} - - async def zwei_platzen(system, nachricht, temperatur=0.0): - ausfaelle["n"] += 1 - if ausfaelle["n"] <= 2: - raise RuntimeError("429") - return FEHLT - - monkeypatch.setattr(agents, "frage", zwei_platzen) - stand = ledger.lade(projekt) - gemeldet = [] - assert await inhalt.code_im_feature(features.liste(projekt), [punkt()], stand, - melde=lambda t, n=0: gemeldet.append(n)) == [] - assert gemeldet == [1] - assert stand["abdeckung"] == {} and stand["ohne_karte"] == {} - - -async def test_zwei_ueberlebende_stimmen_urteilen_nicht(projekt, monkeypatch): - """Rechnerisch könnten zwei Stimmen die Schwelle unerreichbar machen. Als - dauerhaft gemerktes Urteil ist das zu wenig.""" - karte(projekt, "Eins", ("Etwas starten", "Knopf")) - ausfaelle = {"n": 0} - - async def vier_platzen(system, nachricht, temperatur=0.0): - ausfaelle["n"] += 1 - if ausfaelle["n"] <= 4: - raise RuntimeError("429") - return ABGEDECKT - - monkeypatch.setattr(agents, "frage", vier_platzen) - stand = ledger.lade(projekt) - gemeldet = [] - await inhalt.code_im_feature(features.liste(projekt), [punkt()], stand, - melde=lambda t, n=0: gemeldet.append(n)) - assert gemeldet == [1] - assert stand["abdeckung"] == {} - - # ---------------------------------------------------------------- Vision VISION = "\nVision\n\nvision\n\nSo soll es werden\n" @@ -530,3 +101,65 @@ def test_keine_pruefung_fasst_die_vision_an(projekt): assert len(features.liste(projekt)) == 2 titel = [f["sektionen"]["titel"] for f in features.pruefbar(projekt)] assert titel == ["Eins"] + + +# ---------------------------------------------------------------- Prüfung 1 + +async def test_stilurteil_wird_gemerkt_und_nicht_neu_gefragt(projekt, monkeypatch): + """176 Anfragen je Lauf brachten den Anbieter zum Drosseln. Unveränderter + Ausschnitt bei unverändertem Katalog heißt: das Urteil von vorhin gilt.""" + import pruefung + + karte(projekt, "Eins", ("Etwas starten", "Knopf")) + modell = Zaehler('{"felder": {}}') + monkeypatch.setattr(agents, "frage", modell) + + liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) + for a in liste: + assert await arbeite(a, None) == [] + abschluss() + erste = modell.rufe + assert erste >= len(pruefung.TEMPERATUREN) + + liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) + for a in liste: + assert await arbeite(a, None) == [] + assert modell.rufe == erste # keine einzige neue Anfrage + + +async def test_geaenderter_text_wird_neu_gefragt(projekt, monkeypatch): + import pruefung + + karte(projekt, "Eins", ("Etwas starten", "Knopf")) + modell = Zaehler('{"felder": {}}') + monkeypatch.setattr(agents, "frage", modell) + + liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) + for a in liste: + await arbeite(a, None) + abschluss() + vorher = modell.rufe + + datei = projekte.wurzel(projekt) / f"{features.liste(projekt)[0]['id']}.md" + datei.write_text(datei.read_text().replace("- Knopf", "- Ganz anderer Text")) + liste, arbeite, _ = await pruefung._stil_aufgaben(projekt) + for a in liste: + await arbeite(a, None) + assert modell.rufe > vorher + + +async def test_gemessener_verstoss_kommt_nie_aus_dem_gedaechtnis(projekt, monkeypatch): + """Sonst bliebe eine neu hinzugekommene Messregel an alten Karten wirkungslos.""" + import pruefung + + karte(projekt, "Eins", ("Etwas starten", "Auch Passwort prüfen.")) + modell = Zaehler('{"felder": {"regeln": {"neu": "- Passwort prüfen",' + ' "grund": "Füllwort", "regel": "x"}}}') + monkeypatch.setattr(agents, "frage", modell) + + for lauf in range(2): + liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) + gefunden = [p for a in liste for p in await arbeite(a, None)] + abschluss() + assert [p["vorschlag"] for p in gefunden] == ["Passwort prüfen"], lauf + assert modell.rufe > len(pruefung.TEMPERATUREN) # zweimal wirklich gefragt diff --git a/backend/tests/test_parser.py b/backend/tests/test_parser.py index 4fcacff..1f9c3d0 100644 --- a/backend/tests/test_parser.py +++ b/backend/tests/test_parser.py @@ -33,8 +33,10 @@ def test_alle_sektionen(): "ziel": "", "regeln": "- Passwort nie loggen\n- Sperre nach 5 Fehlversuchen", "testen": "- Formular öffnen\n- Daten eingeben", + "stand": "gebaut", }, - {"text": "Abmeldung", "ziel": "", "regeln": "", "testen": ""}, + {"text": "Abmeldung", "ziel": "", "regeln": "", "testen": "", + "stand": "gebaut"}, ] @@ -114,3 +116,22 @@ def test_marker_mit_leerraum(): def test_titel_erste_nicht_leere_zeile(): s = zerlege("\n\nErste\nZweite\n") assert s["titel"] == "Erste" + + +def test_stand_offen_wird_gelesen(): + """Bestellt, aber noch nicht gebaut — sonst klagt die Vorwärtsprüfung sie an.""" + s = zerlege("\nX\n\nA\n\noffen\n" + "\nB\n") + assert [(f["text"], f["stand"]) for f in s["funktionen"]] == [("A", "offen"), + ("B", "gebaut")] + assert s["sonstiges"] == "" # der Marker landet nicht im Rest + + +def test_unbekannter_stand_gilt_als_gebaut(): + s = zerlege("\nX\n\nA\n\nirgendwas\n") + assert s["funktionen"][0]["stand"] == "gebaut" + + +def test_stand_ohne_funktion_faellt_in_sonstiges(): + s = zerlege("\nX\n\noffen\n") + assert s["sonstiges"] == "offen" diff --git a/backend/tests/test_planung.py b/backend/tests/test_planung.py new file mode 100644 index 0000000..b0f5244 --- /dev/null +++ b/backend/tests/test_planung.py @@ -0,0 +1,201 @@ +"""Die Planung: eine Arbeitskopie, die den Projektstand nicht anfasst. + +Geprüft wird die eine Zusage — solange die Planung läuft, bleibt die Übersicht, +was sie war. Und dass sie einen Neustart übersteht, weil sie auf der Platte liegt. +""" + +import features +import parser +import planung +import projekte +import pytest + + +def karte(projekt: str, titel: str, *funktionen: str) -> str: + roh = f"\n{titel}\n" + "".join( + f"{'-' * 40}\n\n{f}\n\n- Etwas gilt\n" + for f in funktionen) + return features.anlegen(projekt, roh)["id"] + + +def titel(projekt: str) -> list: + return sorted(f["sektionen"]["titel"] for f in features.liste(projekt)) + + +@pytest.fixture +def projekt(datenordner): + projekte.anlegen("P") + karte("P", "Galerie", "Bild wählen") + karte("P", "Shop", "Karte kaufen") + return "P" + + +def test_ohne_planung_arbeitet_alles_im_projektordner(projekt): + assert not planung.laeuft(projekt) + assert projekte.wurzel(projekt) == projekte.stand(projekt) + assert planung.aenderungen(projekt) == {} + + +def test_planung_leitet_das_schreiben_um(projekt): + planung.starte(projekt) + assert projekte.wurzel(projekt) != projekte.stand(projekt) + + karte(projekt, "Neu", "Etwas tun") + # Die Karte steht in der Kopie … + assert "Neu" in titel(projekt) + # … und nicht im Projektstand + assert not (projekte.stand(projekt) / "neu.md").exists() + + +def test_zweite_planung_wird_abgelehnt(projekt): + planung.starte(projekt) + with pytest.raises(ValueError): + planung.starte(projekt) + + +def test_planung_ueberlebt_einen_neustart(projekt): + planung.starte(projekt) + karte(projekt, "Neu", "Etwas tun") + # Nichts im Speicher — der nächste Prozess sieht nur die Platte + assert planung.laeuft(projekt) + assert "Neu" in planung.aenderungen(projekt) + + +def test_abbruch_laesst_den_projektstand_unberuehrt(projekt): + vorher = titel(projekt) + planung.starte(projekt) + karte(projekt, "Neu", "Etwas tun") + planung.brich_ab(projekt) + assert not planung.laeuft(projekt) + assert titel(projekt) == vorher + + +def test_umsetzen_macht_die_kopie_zum_stand(projekt): + planung.starte(projekt) + karte(projekt, "Neu", "Etwas tun") + planung.setze_um(projekt) + assert not planung.laeuft(projekt) + assert "Neu" in titel(projekt) + assert not (projekte.stand(projekt) / projekte.PLANUNG).exists() + + +def test_umsetzen_ohne_planung_ist_ein_fehler(projekt): + with pytest.raises(ValueError): + planung.setze_um(projekt) + + +# ---------------------------------------------------------------- Änderungen + +def test_neue_karte_ist_neu(projekt): + planung.starte(projekt) + karte(projekt, "Neu", "Etwas tun") + a = planung.aenderungen(projekt) + assert a["Neu"]["art"] == "neu" + assert a["Neu"]["funktionen"] == {"Etwas tun": "neu"} + assert "Galerie" not in a + + +def test_entfernte_karte_ist_weg(projekt): + planung.starte(projekt) + features.loeschen(projekt, "shop") + a = planung.aenderungen(projekt) + assert a["Shop"]["art"] == "weg" + assert a["Shop"]["funktionen"] == {"Karte kaufen": "weg"} + + +def test_neue_funktion_wird_markiert(projekt): + planung.starte(projekt) + f = next(x for x in features.liste(projekt) if x["sektionen"]["titel"] == "Galerie") + features.speichern(projekt, f["id"], + f["roh"] + f"{'-' * 40}\n\nBild löschen\n") + a = planung.aenderungen(projekt) + assert a["Galerie"]["art"] == "geaendert" + assert a["Galerie"]["funktionen"] == {"Bild löschen": "neu"} + + +def test_geaenderte_regel_wird_markiert(projekt): + planung.starte(projekt) + f = next(x for x in features.liste(projekt) if x["sektionen"]["titel"] == "Galerie") + features.speichern(projekt, f["id"], f["roh"].replace("Etwas gilt", "Anderes gilt")) + assert planung.aenderungen(projekt)["Galerie"]["funktionen"] == { + "Bild wählen": "geaendert"} + + +def test_umbenannte_karte_ist_neu_und_weg(projekt): + """Verglichen wird über den Titel. Eine Umbenennung ist zwei Änderungen.""" + planung.starte(projekt) + f = next(x for x in features.liste(projekt) if x["sektionen"]["titel"] == "Shop") + features.speichern(projekt, f["id"], f["roh"].replace("Shop", "Laden", 1)) + a = planung.aenderungen(projekt) + assert a["Shop"]["art"] == "weg" and a["Laden"]["art"] == "neu" + + +def test_gleicher_inhalt_ist_keine_aenderung(projekt): + planung.starte(projekt) + f = features.liste(projekt)[0] + features.speichern(projekt, f["id"], f["roh"]) + assert planung.aenderungen(projekt) == {} + + +# ---------------------------------------------------------------- Zurücksetzen + +def test_zuruecksetzen_loescht_eine_neue_karte(projekt): + planung.starte(projekt) + karte(projekt, "Neu", "Etwas tun") + planung.zuruecksetzen(projekt, "Neu") + assert planung.aenderungen(projekt) == {} + assert "Neu" not in titel(projekt) + + +def test_zuruecksetzen_holt_eine_geloeschte_karte_zurueck(projekt): + planung.starte(projekt) + features.loeschen(projekt, "shop") + planung.zuruecksetzen(projekt, "Shop") + assert planung.aenderungen(projekt) == {} + assert "Shop" in titel(projekt) + + +def test_zuruecksetzen_stellt_den_alten_inhalt_her(projekt): + planung.starte(projekt) + f = next(x for x in features.liste(projekt) if x["sektionen"]["titel"] == "Galerie") + features.speichern(projekt, f["id"], f["roh"].replace("Etwas gilt", "Anderes gilt")) + planung.zuruecksetzen(projekt, "Galerie") + assert planung.aenderungen(projekt) == {} + + +def test_zuruecksetzen_laesst_die_uebrigen_stehen(projekt): + planung.starte(projekt) + karte(projekt, "Eins", "A tun") + karte(projekt, "Zwei", "B tun") + planung.zuruecksetzen(projekt, "Eins") + assert set(planung.aenderungen(projekt)) == {"Zwei"} + + +def test_zuruecksetzen_ohne_planung_ist_ein_fehler(projekt): + with pytest.raises(ValueError): + planung.zuruecksetzen(projekt, "Galerie") + + +def test_unbekannte_karte_zuruecksetzen_meldet_es(projekt): + planung.starte(projekt) + with pytest.raises(FileNotFoundError): + planung.zuruecksetzen(projekt, "Gibt es nicht") + + +# ---------------------------------------------------------------- Nachbarschaft + +def test_die_kopie_ist_kein_eigenes_projekt(projekt): + planung.starte(projekt) + assert [p["name"] for p in projekte.liste()] == ["P"] + + +def test_gespraech_und_gedaechtnis_wandern_mit(projekt): + """Was während des Planens beurteilt wurde, gilt für den geplanten Stand.""" + (projekte.stand(projekt) / ".pruefung.json").write_text('{"stil": {}}') + planung.starte(projekt) + assert (projekte.wurzel(projekt) / ".pruefung.json").is_file() + + +def test_die_kopie_kopiert_sich_nicht_selbst(projekt): + planung.starte(projekt) + assert not (projekte.wurzel(projekt) / projekte.PLANUNG).exists() diff --git a/backend/tests/test_pruefung.py b/backend/tests/test_pruefung.py index b15ccc9..6f4fafa 100644 --- a/backend/tests/test_pruefung.py +++ b/backend/tests/test_pruefung.py @@ -197,8 +197,9 @@ async def test_herkunft_kommt_vom_code_nicht_vom_modell(datenordner, monkeypatch async def luegt(system, inhalt, temperatur=0.0): # Das Modell behauptet eine fremde Funktion — das muss ignoriert werden + # „Anmelden" ist selbst ein gültiger Titel — sonst weist die Messung ihn ab return ('{"felder": {"titel": {"regel": "Sprache: Deutsch, Präsens, keine Anrede",' - ' "neu": "Anders", "grund": "x"},' + ' "neu": "Einloggen", "grund": "x"},' ' "funktion": {"neu": "Erfunden", "grund": "y"}}}') monkeypatch.setattr(agents, "frage", luegt) diff --git a/backend/tests/test_struktur.py b/backend/tests/test_struktur.py index 510b2ce..f509e82 100644 --- a/backend/tests/test_struktur.py +++ b/backend/tests/test_struktur.py @@ -166,3 +166,96 @@ def test_gemessene_befunde_haengen_am_ausschnitt(datenordner): text = pruefung.inhalt(karte, befunde) assert "Gemessen, bitte neu schreiben:" in text assert "Mehr als 3 Wörter" in text + + +def test_funktionstitel_braucht_ein_verb(): + """Ohne Verb steht dort ein Bereich oder ein Zustand — nichts Testbares.""" + for titel in ("Galerie im Modal", "Preis aktualisiert", "In den Warenkorb", + "Modal tastaturgesteuert"): + assert _probleme(_pruefe("funktion", "titel", titel)) \ + == ["Kein Verb im Infinitiv am Ende"], titel + + +def test_gute_funktionstitel_bleiben_unberuehrt(): + for titel in ("Feature anlegen", "Anzeigemodus umschalten", "Option wählen", + "Nächsten Rückschritt anzeigen", "Karten prüfen", "Stand umschalten", + "Projekt aufrufen", "Bildergalerie bedienen", "PDF hochladen"): + assert _pruefe("funktion", "titel", titel) == [], titel + + +def test_kartentitel_darf_ohne_verb_stehen(): + """Eine Karte ist ein Gegenstand, keine Handlung.""" + assert _pruefe("feature", "titel", "Karten prüfen") == [] + assert _pruefe("feature", "titel", "Darkmode") == [] + + +ABLAUF = "- Vollmodus öffnen\n- LMB auf Regeln\n- Text ändern\n- Regeln angepasst" + + +def test_ein_ablauf_geht_durch(): + assert _pruefe("funktion", "testen", ABLAUF) == [] + + +def test_zweiter_ablauf_wird_gemeldet(): + """So entstand „Bildergalerie bedienen": blättern, Miniatur, Großansicht in einem.""" + zwei = ("- Zurück-Button klicken\n- Vorheriges Bild erscheint\n" + "- Miniaturbild klicken\n- Zugehöriges Bild erscheint") + b = _pruefe("funktion", "testen", zwei) + assert _probleme(b) == ["Zweiter Ablauf in einer Funktion"] + assert b[0]["original"] == "Miniaturbild klicken" + + +def test_nominalstil_ist_eine_handlung(): + """„Bestätigen im Modal" hat das Verb vorn — sonst gälte es als Ergebnis.""" + text = ("- RMB auf Featurecard\n- Klick auf \"Feature entfernen\"\n" + "- Bestätigen im Modal\n- Feature entfernt") + assert _pruefe("funktion", "testen", text) == [] + + +def test_mehrzahl_auf_en_ist_kein_verb(): + """Deutsche Mehrzahl endet auch auf -en — nur Anfang und Ende zählen.""" + text = "- LMB auf Icon\n- Fehlerhafte Karten rot markiert" + assert _pruefe("funktion", "testen", text) == [] + + +def test_zeilenfehler_haben_vorrang(): + """Erst die Zeilen in Ordnung bringen; zwei Vorschläge je Feld wären nicht + unabhängig anwendbar.""" + text = "- Auch klicken.\n- Ergebnis da\n- Weiter klicken" + assert _probleme(_pruefe("funktion", "testen", text)) \ + == ["Satzzeichen am Zeilenende, Füllwort „auch“"] + + +def test_funktion_ohne_jedes_feld_ist_leer(): + """Ein bloßer Titel beschreibt nichts — der Prüfer stülpt ihn über alles.""" + b = struktur.befunde("funktion", {"titel": "Modal steuern", "ziel": "", + "regeln": "", "testen": ""}) + assert _probleme(b) == ["Funktion ohne Ziel, Regeln und Testen"] + + +def test_ein_einziges_feld_genuegt(): + for feld in ("ziel", "regeln", "testen"): + felder = {"titel": "Modal steuern", "ziel": "", "regeln": "", "testen": ""} + felder[feld] = "Etwas tun" if feld == "ziel" else "- Etwas tun" + assert struktur.befunde("funktion", felder) == [], feld + + +def test_einzelnes_feld_loest_nichts_aus(): + """Beim Prüfen eines Feldes sagt das Fehlen der anderen nichts.""" + assert struktur.befunde("funktion", {"titel": "Modal steuern"}) == [] + + +def test_kartenebene_darf_leer_sein(): + assert struktur.befunde("feature", {"titel": "Darkmode", "badge": "kern", + "ziel": "", "regeln": ""}) == [] + + +def test_platzhalter_ist_kein_inhalt(): + """`` erfüllt jede Formregel und sagt trotzdem nichts.""" + assert struktur._umschreiben("funktion", "testen", "") + assert struktur._umschreiben("funktion", "regeln", "Noch offen ...") + assert struktur._umschreiben("funktion", "regeln", "TODO klären") + + +def test_kleiner_als_ist_kein_platzhalter(): + assert not struktur._umschreiben("funktion", "regeln", "Wert 3 < 5") diff --git a/daten/MtoVariantConfigurator/.planung/.pruefung.json b/daten/MtoVariantConfigurator/.planung/.pruefung.json new file mode 100644 index 0000000..f578988 --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/.pruefung.json @@ -0,0 +1,537 @@ +{ + "abdeckung": { + "einbinden:VariantConfiguratorPlugin": { + "abdruck": "823481507a44729d", + "funktion": "Konfigurationsdaten bereitstellen", + "trug": "5fbc8363b7cffe59" + }, + "einbinden:erweitert @Storefront/storefront/component/buy-widget/configurator.html.twig": { + "abdruck": "c6d031d6bc598089", + "funktion": "Konfigurator aktivieren", + "trug": "6cf5a2b08ce2371a" + }, + "einbinden:override sw-product-detail-variants": { + "abdruck": "2fcf518e7333458a", + "funktion": "", + "trug": "" + }, + "einbinden:register mto-vc-variants-card": { + "abdruck": "c472feadaac5ac71", + "funktion": "", + "trug": "" + }, + "hoeren:[data-mto-vc-gallery-next].click": { + "abdruck": "c402ad6f114e8c3d", + "funktion": "Galerie blättern", + "trug": "bacf45ebf9dd77b8" + }, + "hoeren:[data-mto-vc-gallery-prev].click": { + "abdruck": "f50d4f7effc60a06", + "funktion": "Galerie blättern", + "trug": "bacf45ebf9dd77b8" + }, + "hoeren:[data-mto-vc-lightbox-close].click": { + "abdruck": "89a22850af7694bb", + "funktion": "Galerie blättern", + "trug": "bacf45ebf9dd77b8" + }, + "hoeren:document.keydown": { + "abdruck": "7c018ebbfa346bee", + "funktion": "Schritt öffnen", + "trug": "efe9634e3080c073" + }, + "hoeren:el.click": { + "abdruck": "6a423a062267755c", + "funktion": "Nächsten Schritt anzeigen", + "trug": "f6b276e3fedf287d" + }, + "hoeren:info.click": { + "abdruck": "7a5a70dfb792bf19", + "funktion": "Optionsdetail öffnen", + "trug": "39fed29af6734cd4" + }, + "hoeren:info.keydown": { + "abdruck": "409cecf6fb3bbb4a", + "funktion": "Optionsdetail öffnen", + "trug": "39fed29af6734cd4" + }, + "hoeren:lightboxSelect.click": { + "abdruck": "9add2d2c77b440b5", + "funktion": "Ansicht schließen", + "trug": "24d52cc6d249d4f5" + }, + "hoeren:next.click": { + "abdruck": "d5b0cdcce40afcff", + "funktion": "Konfigurator schließen", + "trug": "1cc1a6b5fc943e03" + }, + "hoeren:prev.click": { + "abdruck": "6b8db8d885c0d6f8", + "funktion": "Konfigurator schließen", + "trug": "1cc1a6b5fc943e03" + }, + "hoeren:row.click": { + "abdruck": "b4ec6f63c613c35f", + "funktion": "Option wählen", + "trug": "80df89cf0c129387" + }, + "hoeren:thumb.click": { + "abdruck": "b4aa2111971f6886", + "funktion": "Bild wählen", + "trug": "0604a0a6875489b8" + }, + "hoeren:trigger.click": { + "abdruck": "e219933925adc81a", + "funktion": "Schritt öffnen", + "trug": "efe9634e3080c073" + }, + "reaktion:ProductPageLoadedEvent": { + "abdruck": "6f808b91c1a0c4f5", + "funktion": "Konfigurationsdaten bereitstellen", + "trug": "5fbc8363b7cffe59" + }, + "route:get /mto-variant-configurator/resolve/{productId}": { + "abdruck": "b14355d6007564a1", + "funktion": "Konfigurationsdaten bereitstellen", + "trug": "5fbc8363b7cffe59" + } + }, + "belege": { + "[\"auswahl-anstossen\", \"Gewählte Option anzeigen\"]": { + "abdruck": "626af3ee300b610a", + "beleg": "\n {{ mtoVcSelected ? mtoVcSelected.translated.name : 'mto.variantConfigurator.choose'|trans }}\n ", + "datei": "src/Resources/views/storefront/component/buy-widget/configurator.html.twig" + }, + "[\"auswahl-anstossen\", \"Hinweistext anzeigen\"]": { + "abdruck": "b9baf394ca99d4e6", + "beleg": "{% if mtoVcBubble != mtoVcBubbleKey and mtoVcBubble is not empty %}\n

{{ mtoVcBubble|sw_sanitize }}

\n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/configurator.html.twig" + }, + "[\"auswahl-anstossen\", \"Schrittnummer anzeigen\"]": { + "abdruck": "b9e4deada2c3a6f1", + "beleg": "{{ 'mto.variantConfigurator.step'|trans({ '%step%': mtoVcStep })|sw_sanitize }}", + "datei": "src/Resources/views/storefront/component/buy-widget/configurator.html.twig" + }, + "[\"beratung-anbieten\", \"Beratung erreichen\"]": { + "abdruck": "fa513f8d265ad713", + "beleg": "{% if ctaPhone is not empty %}\n \n {{ ctaPhone|sw_sanitize }}\n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"beratung-anbieten\", \"Optionsübersicht öffnen\"]": { + "abdruck": "8aba7fb9bf50281b", + "beleg": "{% if pdfUrl %}\n \n {{ 'mto.variantConfigurator.allOptions'|trans|sw_sanitize }}\n \n {% else %}\n \n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"beratung-anbieten\", \"Vertrauen zeigen\"]": { + "abdruck": "5b204dff7de6f96d", + "beleg": "{% if trustLogo %}\n \"\"\n{% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"layout-zuweisen\", \"Konfigurator aktivieren\"]": { + "abdruck": "60a65511f06ae7fe", + "beleg": "", + "datei": "src/Resources/app/administration/src/component/mto-vc-variants-card/mto-vc-variants-card.html.twig" + }, + "[\"layout-zuweisen\", \"Optionsübersicht hinterlegen\"]": { + "abdruck": "97b421cf540a6cc2", + "beleg": "{% if pdfUrl %}\n \n {{ 'mto.variantConfigurator.allOptions'|trans|sw_sanitize }}\n \n {% else %}\n \n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"layout-zuweisen\", \"Trust-Logo hinterlegen\"]": { + "abdruck": "1954311a4c3a9cc1", + "beleg": "$mediaId = $this->systemConfigService->get(\n MtoVariantConfigurator::CONFIG_TRUST_LOGO,\n $salesChannelId,\n );", + "datei": "src/Core/Content/Product/VariantResolveService.php" + }, + "[\"option-ansehen\", \"Ansicht schließen\"]": { + "abdruck": "6eac493d9a481e30", + "beleg": "if (!this._nodes.lightbox.hidden) {\n this._closeLightbox();\n } else {\n this._close();\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"option-ansehen\", \"Option aus Ansicht wählen\"]": { + "abdruck": "b4223f8cf3e2456e", + "beleg": "this._nodes.lightboxSelect?.addEventListener('click', () => {\n if (this._lightboxOption) {\n this._selectOption(this.options.groups[this._currentStep], this._lightboxOption.id);\n }\n this._closeLightbox();\n });", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"option-ansehen\", \"Optionsdetail öffnen\"]": { + "abdruck": "59faab581e0fac7f", + "beleg": "info.addEventListener('click', open);\n info.addEventListener('keydown', (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n open(event);\n }\n });", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"schritt-zeigen\", \"Eigenschaft benennen\"]": { + "abdruck": "dd54064a67689e2c", + "beleg": "this._nodes.title.textContent = group.name;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"schritt-zeigen\", \"Optionen auflisten\"]": { + "abdruck": "a71af321f056608d", + "beleg": "if (option.media) {\n const visual = document.createElement('span');\n visual.className = 'mto-vc-option-media';\n const img = document.createElement('img');\n img.src = option.media;\n img.alt = '';\n img.loading = 'lazy';\n visual.appendChild(img);\n row.appendChild(visual);\n } else if (option.color) {\n const visual = document.createElement('span');\n visual.className = 'mto-vc-option-swatch';\n visual.style.backgroundColor = option.color;\n row.appendChild(visual);\n } else {\n row.classList.add('has-no-visual');\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"schritt-zeigen\", \"Schrittstand anzeigen\"]": { + "abdruck": "aa7b8888103f8bd0", + "beleg": "this._nodes.counter.textContent = (this._snippets.stepCount || '__step__ / __total__')\n .replace('__step__', String(step))\n .replace('__total__', String(total));\n this._nodes.progress.style.width = `${(step / total) * 100}%`;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Auswahl übernehmen\"]": { + "abdruck": "21ccf5bc0286c95c", + "beleg": "if (optionId && select.value !== optionId) {\n select.value = optionId;\n lastChanged = select;\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Konfigurationsdaten bereitstellen\"]": { + "abdruck": "e6e5848381fce5aa", + "beleg": "$page->assign([", + "datei": "src/Subscriber/ProductPageSubscriber.php" + }, + "[\"varianten-waehlen\", \"Konfigurator schließen\"]": { + "abdruck": "1b7d4aea18cdb896", + "beleg": "_close() {\n this._closeLightbox();\n this._modalEl.hidden = true;\n document.body.classList.remove('mto-vc-modal-open');\n document.removeEventListener('keydown', this._keydownHandler);\n this._lastFocus?.focus();\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Nächsten Schritt anzeigen\"]": { + "abdruck": "3deee97595984a3e", + "beleg": "const isLast = this._nextUsableStep(this._currentStep + 1, 1) === null;\n this._nodes.next.textContent = isLast\n ? this._nodes.next.dataset.finishLabel\n : this._nodes.next.dataset.nextLabel;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Option wählen\"]": { + "abdruck": "4b9f7dc844cf7aac", + "beleg": "this._selected[group.id] = optionId;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Schritt öffnen\"]": { + "abdruck": "94b3aa8d50c53fc8", + "beleg": "this._triggers.forEach((trigger) => {\n trigger.addEventListener('click', (event) => {\n event.preventDefault();\n this._open(parseInt(trigger.dataset.mtoVcStepIndex, 10));\n });\n });", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Vorherigen Schritt anzeigen\"]": { + "abdruck": "df5e60fe148da5e6", + "beleg": "this._nodes.prev.disabled = this._nextUsableStep(this._currentStep - 1, -1) === null;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"vorschau-zeigen\", \"Bild wählen\"]": { + "abdruck": "ab1e74251036541a", + "beleg": "thumb.className = `mto-vc-thumb${index === this._galleryIndex ? ' is-active' : ''}`;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"vorschau-zeigen\", \"Galerie blättern\"]": { + "abdruck": "6b28a5866629b878", + "beleg": "_stepGallery(delta) {\n if (this._gallery.length < 2) {\n return;\n }\n const count = this._gallery.length;\n this._galleryIndex = (this._galleryIndex + delta + count) % count;\n this._renderGallery();\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"vorschau-zeigen\", \"Vorschau laden\"]": { + "abdruck": "413024bc244f7770", + "beleg": "return new JsonResponse($this->variantResolveService->resolveVariant($variantId, $context));", + "datei": "src/Storefront/Controller/VariantConfiguratorController.php" + } + }, + "ohne_code": {}, + "ohne_karte": {}, + "paare": { + "[\"[\\\"auswahl-anstossen\\\", \\\"Gewählte Option anzeigen\\\"]\", \"[\\\"auswahl-anstossen\\\", \\\"Hinweistext anzeigen\\\"]\"]": { + "abdruck": "450345e8a27f5695", + "gleich": false + }, + "[\"[\\\"auswahl-anstossen\\\", \\\"Gewählte Option anzeigen\\\"]\", \"[\\\"auswahl-anstossen\\\", \\\"Schrittnummer anzeigen\\\"]\"]": { + "abdruck": "60008fdb6d69349b", + "gleich": false + }, + "[\"[\\\"auswahl-anstossen\\\", \\\"Hinweistext anzeigen\\\"]\", \"[\\\"auswahl-anstossen\\\", \\\"Schrittnummer anzeigen\\\"]\"]": { + "abdruck": "3eaf19062d6d53a3", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Beratung erreichen\\\"]\", \"[\\\"beratung-anbieten\\\", \\\"Optionsübersicht öffnen\\\"]\"]": { + "abdruck": "9d3da3bf8c127ae1", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Beratung erreichen\\\"]\", \"[\\\"beratung-anbieten\\\", \\\"Vertrauen zeigen\\\"]\"]": { + "abdruck": "2c3c62cb4b935c56", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Optionsübersicht öffnen\\\"]\", \"[\\\"beratung-anbieten\\\", \\\"Vertrauen zeigen\\\"]\"]": { + "abdruck": "bf601d5dc7c6c507", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Optionsübersicht öffnen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\"]": { + "abdruck": "bc9dc09e54b78a75", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Konfigurator aktivieren\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsbild am Datensatz pflegen\\\"]\"]": { + "abdruck": "5a4d802d668ddd55", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Konfigurator aktivieren\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\"]": { + "abdruck": "eeed78a6284711f1", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Konfigurator aktivieren\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Trust-Logo hinterlegen\\\"]\"]": { + "abdruck": "b4944e5aa4df871a", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Optionsbild am Datensatz pflegen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\"]": { + "abdruck": "b91bdff82a120a8d", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Optionsbild am Datensatz pflegen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Trust-Logo hinterlegen\\\"]\"]": { + "abdruck": "97268714e2b5d989", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Trust-Logo hinterlegen\\\"]\"]": { + "abdruck": "b52cedd4106ee837", + "gleich": false + }, + "[\"[\\\"option-ansehen\\\", \\\"Ansicht schließen\\\"]\", \"[\\\"option-ansehen\\\", \\\"Option aus Ansicht wählen\\\"]\"]": { + "abdruck": "caa5ce4c5ff31774", + "gleich": false + }, + "[\"[\\\"option-ansehen\\\", \\\"Ansicht schließen\\\"]\", \"[\\\"option-ansehen\\\", \\\"Optionsdetail öffnen\\\"]\"]": { + "abdruck": "462a46d7a2030874", + "gleich": false + }, + "[\"[\\\"option-ansehen\\\", \\\"Option aus Ansicht wählen\\\"]\", \"[\\\"option-ansehen\\\", \\\"Optionsdetail öffnen\\\"]\"]": { + "abdruck": "8f695dfd90060204", + "gleich": false + }, + "[\"[\\\"schritt-zeigen\\\", \\\"Eigenschaft benennen\\\"]\", \"[\\\"schritt-zeigen\\\", \\\"Optionen auflisten\\\"]\"]": { + "abdruck": "5372df6b482e9a5c", + "gleich": false + }, + "[\"[\\\"schritt-zeigen\\\", \\\"Eigenschaft benennen\\\"]\", \"[\\\"schritt-zeigen\\\", \\\"Schrittstand anzeigen\\\"]\"]": { + "abdruck": "732d371c2135b53f", + "gleich": false + }, + "[\"[\\\"schritt-zeigen\\\", \\\"Optionen auflisten\\\"]\", \"[\\\"schritt-zeigen\\\", \\\"Schrittstand anzeigen\\\"]\"]": { + "abdruck": "590d6974e948c69c", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\"]": { + "abdruck": "34e23fca918e5dc0", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\"]": { + "abdruck": "eb521941a5dc979a", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\"]": { + "abdruck": "271109c8b42cf5d5", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "618d3c213492555a", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "b45252ce7cc39ed9", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "d7ade9bdd7d0c66e", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\"]": { + "abdruck": "97ceded85ca2035c", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\"]": { + "abdruck": "ba83ab596b72af22", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "6f23248b5fbd7be4", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "7350e93a2a368ac1", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "50753ef9f3d5c8b5", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\"]": { + "abdruck": "b49e65e1c60b5307", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "b165f28b36fc3637", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "0bf509fed71f1c25", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "de5acdbf92511e14", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "7c9a06867c701267", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "f45378da83876bae", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "9fc4c9cf8ae1d7fb", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "a71f8b8b92d1025c", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "e3270a7176c63620", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "44e775b8e8b106d1", + "gleich": false + }, + "[\"[\\\"vorschau-zeigen\\\", \\\"Bild wählen\\\"]\", \"[\\\"vorschau-zeigen\\\", \\\"Galerie blättern\\\"]\"]": { + "abdruck": "19851d2901c309a1", + "gleich": false + }, + "[\"[\\\"vorschau-zeigen\\\", \\\"Bild wählen\\\"]\", \"[\\\"vorschau-zeigen\\\", \\\"Vorschau laden\\\"]\"]": { + "abdruck": "508415e6500f9fca", + "gleich": false + }, + "[\"[\\\"vorschau-zeigen\\\", \\\"Galerie blättern\\\"]\", \"[\\\"vorschau-zeigen\\\", \\\"Vorschau laden\\\"]\"]": { + "abdruck": "86aa1f412d5a5dcd", + "gleich": false + } + }, + "stil": { + "[\"auswahl-anstossen\", \"\"]": { + "abdruck": "aeec25973dafe92f", + "probleme": [] + }, + "[\"auswahl-anstossen\", \"Gewählte Option anzeigen\"]": { + "abdruck": "59058982f7989af8", + "probleme": [] + }, + "[\"auswahl-anstossen\", \"Hinweistext anzeigen\"]": { + "abdruck": "b3568e0a2585d71c", + "probleme": [] + }, + "[\"auswahl-anstossen\", \"Schrittnummer anzeigen\"]": { + "abdruck": "117d58f0d4b21973", + "probleme": [] + }, + "[\"beratung-anbieten\", \"\"]": { + "abdruck": "4b0267b165360857", + "probleme": [] + }, + "[\"beratung-anbieten\", \"Beratung erreichen\"]": { + "abdruck": "cfdb65d682c3e068", + "probleme": [] + }, + "[\"beratung-anbieten\", \"Optionsübersicht öffnen\"]": { + "abdruck": "28d5587c78199c54", + "probleme": [] + }, + "[\"beratung-anbieten\", \"Vertrauen zeigen\"]": { + "abdruck": "8c00dec8d3ebf751", + "probleme": [] + }, + "[\"layout-zuweisen\", \"\"]": { + "abdruck": "1e0d2ca5296aabea", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Konfigurator aktivieren\"]": { + "abdruck": "dca9bbf7361f5520", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Optionsbild am Datensatz pflegen\"]": { + "abdruck": "cc0701aafd02ac3a", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Optionsübersicht hinterlegen\"]": { + "abdruck": "de6c0e3e80d47496", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Trust-Logo hinterlegen\"]": { + "abdruck": "ebd1a72ece157e69", + "probleme": [] + }, + "[\"option-ansehen\", \"\"]": { + "abdruck": "ace46c77101e26b3", + "probleme": [] + }, + "[\"option-ansehen\", \"Ansicht schließen\"]": { + "abdruck": "6bdaf5e60fb3baa9", + "probleme": [] + }, + "[\"option-ansehen\", \"Option aus Ansicht wählen\"]": { + "abdruck": "cc10af5dda4a7857", + "probleme": [] + }, + "[\"option-ansehen\", \"Optionsdetail öffnen\"]": { + "abdruck": "e00d07ce7b75d8fc", + "probleme": [] + }, + "[\"schritt-zeigen\", \"\"]": { + "abdruck": "f0d53ef421968759", + "probleme": [] + }, + "[\"schritt-zeigen\", \"Eigenschaft benennen\"]": { + "abdruck": "ec4828e2e9197083", + "probleme": [] + }, + "[\"schritt-zeigen\", \"Optionen auflisten\"]": { + "abdruck": "d8e6daed0f36098f", + "probleme": [] + }, + "[\"schritt-zeigen\", \"Schrittstand anzeigen\"]": { + "abdruck": "42a1c7f94c30f72d", + "probleme": [] + }, + "[\"varianten-waehlen\", \"\"]": { + "abdruck": "0835908894fa892c", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Auswahl übernehmen\"]": { + "abdruck": "6683956c63370244", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Konfigurationsdaten bereitstellen\"]": { + "abdruck": "498f3141e86f8db0", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Konfigurator schließen\"]": { + "abdruck": "866918b327061449", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Nächsten Schritt anzeigen\"]": { + "abdruck": "8d810a760dfec037", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Option wählen\"]": { + "abdruck": "ac4eae399ac3a15e", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Schritt öffnen\"]": { + "abdruck": "40f795456747214e", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Vorherigen Schritt anzeigen\"]": { + "abdruck": "a63a26a8baea9c07", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"\"]": { + "abdruck": "52976631fd09993a", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"Bild wählen\"]": { + "abdruck": "a3e980ef7678a446", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"Galerie blättern\"]": { + "abdruck": "47ccb441120c1470", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"Vorschau laden\"]": { + "abdruck": "29e5951f170dba26", + "probleme": [] + } + }, + "verworfen": {} +} diff --git a/daten/MtoVariantConfigurator/.planung/.verlauf.json b/daten/MtoVariantConfigurator/.planung/.verlauf.json new file mode 100644 index 0000000..1135079 --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/.verlauf.json @@ -0,0 +1,122 @@ +[ + { + "titel": "„Lightbox“ geändert", + "dateien": { + "lightbox": "\nLightbox\n----------------------------------------\n\nkern\n----------------------------------------\n\nZeigt eine vergrößerte Ansicht der Optionsabbildung mit ihrem Namen\n----------------------------------------\n\n- lightboxSelect bestätigt Auswahl und schließt\n- Escape und x-Icon schließen\n- Tab und Shift-Tab zirkulieren im Fokusring\n- Geschlossen kehrt Fokus zum Auslöser zurück\n- hidden-Attribut entfernt aus dem Barrierefreiheitsbaum\n----------------------------------------\n\nAuswahl bestätigen\n\nWählt eine Option im aktuellen Schritt und berechnet die gültigen Folgeschritte neu\n\n- Bleibt im aktuellen Schritt\n- Invalidiert Folgeschritte mit ungültigen Kombinationen\n- Setzt Fokus auf die gewählte Option\n- Aktualisiert Galerie und Preis\n\n- Lightbox mit Option öffnen\n- LMB auf Auswahl bestätigen\n- Option ist markiert\n- Lightbox geschlossen\n----------------------------------------\n\nKonfigurator schließen\n\n- Schließt die Lightbox, ohne den Konfigurator zu schließen\n- x-Icon oder Escape beenden die Lightbox\n- Fokus kehrt zum Auslöser in der Optionsliste zurück\n\n- Option mit Bildauswahl öffnet die Lightbox\n- Escape drücken\n- Lightbox geschlossen, Modal offen\n----------------------------------------\n\nLightbox schließen\n\nEntfernt die vergrößerte Produktansicht wieder\n\n- x-Icon oder Escape schließt\n- Zurück zum Dialog gibt Focus\n\n- Modal öffnen\n- Option mit Bild wählen\n- Leinwand-Icon klicken\n- Lightbox sichtbar\n- Escape drücken\n- Lightbox geschlossen, Dialog fokussiert\n----------------------------------------\n\nLightbox öffnen\n\nZeigt das Produktfoto einer Variante option in Originalgröße\n\n- lightboxImage zeigt option.media\n- lightboxCaption zeigt option.name\n- lightboxSelect erhält Fokus\n\n- Modal öffnen\n- Auf Option mit Bild klicken\n- Info-Button der Option klicken\n- Lightbox zeigt das Foto in Originalgröße\n----------------------------------------\n\nTastatur verwenden\n\nBedient Modal und Lightbox per Tastatur\n\n- Escape schließt Lightbox oder Modal\n- Tab zirkuliert im Fokusring vorwärts\n- Shift-Tab zirkuliert im Fokusring rückwärts\n\n- Modal öffnen\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen\n- Escape drücken\n- Modal geschlossen\n" + } + }, + { + "titel": "„Konfigurator“ geändert", + "dateien": { + "konfigurator": "\nKonfigurator\n----------------------------------------\n\nkern\n----------------------------------------\n\nFührt durch Variantenkonfiguration in Einzelschritten mit Live-Vorschau\n----------------------------------------\n\n- Aktiv nur wenn Produkt mto_variant_configurator_active gesetzt hat\n- Optionen-Bilder nur bis zwei Schritte\n- Galerie und Preis aktualisieren live ohne Seitenreload\n- Body erhält CSS-Klasse mto-vc-modal-open solange Modal offen\n- Escape schließt Modal\n- Schließen stellt Fokus auf vorheriges Element\n- Registriert als mto-vc-variants-card in swProductDetail\n- Einstellungen in customFields des Produkts gespeichert\n- Falls inaktiv: Fallback auf Standard-Konfigurator von Shopware\n- Natives Select pro Gruppe im DOM\n- Schritte ohne gültige Optionen werden beim Navigieren übersprungen\n- Ungültige Kombinationen für Folgeschritte werden beim Wählen verworfen\n- Unbesuchte Schritte werden beim Bestätigen mit erster gültiger Option aufgefüllt\n- Deaktivierte Optionen sind nicht auswählbar\n- Gallery-Container erhält CSS-Klasse has-no-gallery wenn keine Bilder vorhanden\n- Schließen bei Lightbox: fokus auf Lightbox-Auswahl-Button\n----------------------------------------\n\nGeführte Konfiguration aktivieren\n\nFührt Kunden schrittweise durch die Variantenauswahl mit Hinweisen und Modal\n\n- Aktiviert bei Produkten mit aktivem Konfigurator-Layout\n- Zeigt jeden Konfigurationsschritt mit Beschriftung\n- Blendentext je Gruppe über Modal aus\n- Inkrementelle Variantenauflösung über resolveUrl\n\n- Produktseite mit aktivem Konfigurator öffnen\n- LMB auf ersten Konfigurationsschritt\n- Option im Modal wählen\n- Modal schließt und nächster Schritt markiert\n----------------------------------------\n\nKonfigurationsdaten abrufen\n\nLiefert Variantendaten für eine Live-Aktualisierung im Konfigurator.\n\n- GET /mto-variant-configurator/resolve/{productId}\n- Query-Parameter switched enthält die aktuell gewechselte Gruppe\n- Query-Parameter options enthält ein JSON-Array gewählter Optionen\n- Ungültiges JSON führt zu leerem options-Array\n- VariantNotFoundException hält productId als Fallback\n- Rückgabe enthält variantId, gallery media und Preis\n- Kein HTTP-Cache wegen kundenspezifischer Preise\n\n- GET /mto-variant-configurator/resolve/STRG-PRODUKT-ID?options=[{\"optionId\":\"farbe\",\"option\":\"rot\"}]\n- Antwort enthält variantId\n- Antwort enthält gallery media\n- Antwort enthält Preis\n----------------------------------------\n\nKonfigurator öffnen\n\nÖffnet den Konfigurator ab einem gewählten Schritt\n\n- Erster Aufruf zeigt das Modal\n- Weiterer Aufruf wechselt den Schritt\n- Fokus vorheriges Element wird gespeichert\n- Body erhält CSS-Klasse mto-vc-modal-open\n- Escape-Schließen wird registriert\n- Galerie und Preis werden aktualisiert\n- Fokus springt auf den Next-Button\n\n- LMB auf Konfigurator-Trigger klicken\n- Modal erscheint im gewählten Schritt\n----------------------------------------\n\nKonfigurator-Karte registrieren\n\nMacht die Einstellungen des Varianten-Konfigurators auf der Produktdetail-Seite verfügbar\n\n- Registriert als mto-vc-variants-card\n- Nutzt Produkt aus swProductDetail\n- Speichert Einstellungen in customFields des Produkts\n\n- Produktdetail-Seite eines Produkts öffnen\n- Tab Variants aufrufen\n- Registrierte mto-vc-variants-card wird angezeigt\n----------------------------------------\n\nPlugin registrieren\n\nMacht das Plugin für Elemente mit dem Selektor verfügbar\n\n- Registriert unter VariantConfiguratorPlugin\n- Nutzt window.PluginManager\n- Bindet an [data-mto-variant-configurator]\n\n- PluginManager.register aufrufen\n- Element mit data-mto-variant-configurator erstellen\n- Plugin auf Element angewendet\n" + } + }, + { + "titel": "„Konfigurator“ geändert", + "dateien": { + "konfigurator": "\nKonfigurator\n----------------------------------------\n\nkern\n----------------------------------------\n\nFührt durch Variantenkonfiguration in Einzelschritten mit Live-Vorschau\n----------------------------------------\n\n- Aktiv nur wenn Produkt mto_variant_configurator_active gesetzt hat\n- Optionen-Bilder nur bis zwei Schritte\n- Galerie und Preis aktualisieren live ohne Seitenreload\n- Body erhält CSS-Klasse mto-vc-modal-open solange Modal offen\n- Escape schließt Modal\n- Schließen stellt Fokus auf vorheriges Element\n- Registriert als mto-vc-variants-card in swProductDetail\n- Einstellungen in customFields des Produkts gespeichert\n- Falls inaktiv: Fallback auf Standard-Konfigurator von Shopware\n- Natives Select pro Gruppe im DOM\n- Schritte ohne gültige Optionen werden beim Navigieren übersprungen\n- Ungültige Kombinationen für Folgeschritte werden beim Wählen verworfen\n- Unbesuchte Schritte werden beim Bestätigen mit erster gültiger Option aufgefüllt\n- Deaktivierte Optionen sind nicht auswählbar\n- Gallery-Container erhält CSS-Klasse has-no-gallery wenn keine Bilder vorhanden\n- Schließen bei Lightbox: fokus auf Lightbox-Auswahl-Button\n----------------------------------------\n\nGeführte Konfiguration aktivieren\n\nFührt Kunden schrittweise durch die Variantenauswahl mit Hinweisen und Modal\n\n- Aktiviert bei Produkten mit aktivem Konfigurator-Layout\n- Zeigt jeden Konfigurationsschritt mit Beschriftung\n- Blendentext je Gruppe über Modal aus\n- Inkrementelle Variantenauflösung über resolveUrl\n\n- Produktseite mit aktivem Konfigurator öffnen\n- LMB auf ersten Konfigurationsschritt\n- Option im Modal wählen\n- Modal schließt und nächster Schritt markiert\n----------------------------------------\n\nKonfigurationsdaten abrufen\n\nLiefert Variantendaten für eine Live-Aktualisierung im Konfigurator\n\n- GET /mto-variant-configurator/resolve/{productId}\n- Query-Parameter switched enthält die aktuell gewechselte Gruppe\n- Query-Parameter options enthält ein JSON-Array gewählter Optionen\n- Ungültiges JSON führt zu leerem options-Array\n- VariantNotFoundException hält productId als Fallback\n- Rückgabe enthält variantId, gallery media und Preis\n- Kein HTTP-Cache wegen kundenspezifischer Preise\n\n- GET /mto-variant-configurator/resolve/STRG-PRODUKT-ID?options=[{\"optionId\":\"farbe\",\"option\":\"rot\"}]\n- Antwort enthält variantId\n- Antwort enthält gallery media\n- Antwort enthält Preis\n----------------------------------------\n\nKonfigurator öffnen\n\nÖffnet den Konfigurator ab einem gewählten Schritt\n\n- Erster Aufruf zeigt das Modal\n- Weiterer Aufruf wechselt den Schritt\n- Fokus vorheriges Element wird gespeichert\n- Body erhält CSS-Klasse mto-vc-modal-open\n- Escape-Schließen wird registriert\n- Galerie und Preis werden aktualisiert\n- Fokus springt auf den Next-Button\n\n- LMB auf Konfigurator-Trigger klicken\n- Modal erscheint im gewählten Schritt\n----------------------------------------\n\nKonfigurator-Karte registrieren\n\nMacht die Einstellungen des Varianten-Konfigurators auf der Produktdetail-Seite verfügbar\n\n- Registriert als mto-vc-variants-card\n- Nutzt Produkt aus swProductDetail\n- Speichert Einstellungen in customFields des Produkts\n\n- Produktdetail-Seite eines Produkts öffnen\n- Tab Variants aufrufen\n- Registrierte mto-vc-variants-card wird angezeigt\n----------------------------------------\n\nPlugin registrieren\n\nMacht das Plugin für Elemente mit dem Selektor verfügbar\n\n- Registriert unter VariantConfiguratorPlugin\n- Nutzt window.PluginManager\n- Bindet an [data-mto-variant-configurator]\n\n- PluginManager.register aufrufen\n- Element mit data-mto-variant-configurator erstellen\n- Plugin auf Element angewendet\n" + } + }, + { + "titel": "„Konfigurator“ geändert", + "dateien": { + "konfigurator": "\nKonfigurator\n----------------------------------------\n\nkern\n----------------------------------------\n\nFührt durch Variantenkonfiguration in Einzelschritten mit Live-Vorschau\n----------------------------------------\n\n- Aktiv nur wenn Produkt mto_variant_configurator_active gesetzt hat\n- Optionen-Bilder nur bis zwei Schritte\n- Galerie und Preis aktualisieren live ohne Seitenreload\n- Body erhält CSS-Klasse mto-vc-modal-open solange Modal offen\n- Escape schließt Modal\n- Schließen stellt Fokus auf vorheriges Element\n- Registriert als mto-vc-variants-card in swProductDetail\n- Einstellungen in customFields des Produkts gespeichert\n- Falls inaktiv: Fallback auf Standard-Konfigurator von Shopware\n- Natives Select pro Gruppe im DOM\n- Schritte ohne gültige Optionen werden beim Navigieren übersprungen\n- Ungültige Kombinationen für Folgeschritte werden beim Wählen verworfen\n- Unbesuchte Schritte werden beim Bestätigen mit erster gültiger Option aufgefüllt\n- Deaktivierte Optionen sind nicht auswählbar\n- Gallery-Container erhält CSS-Klasse has-no-gallery wenn keine Bilder vorhanden\n- Schließen bei Lightbox: fokus auf Lightbox-Auswahl-Button\n----------------------------------------\n\nGeführte Konfiguration aktivieren\n\nFührt Kunden schrittweise durch die Variantenauswahl mit Hinweisen und Modal\n\n- Aktiviert bei Produkten mit aktivem Konfigurator-Layout\n- Zeigt jeden Konfigurationsschritt mit Beschriftung\n- Blendentext je Gruppe über Modal aus\n- Inkrementelle Variantenauflösung über resolveUrl\n\n- Produktseite mit aktivem Konfigurator öffnen\n- LMB auf ersten Konfigurationsschritt\n- Option im Modal wählen\n- Modal schließt und nächster Schritt markiert\n----------------------------------------\n\nKonfigurationsdaten abrufen\n\nLiefert Variantendaten für eine Live-Aktualisierung im Konfigurator\n\n- Endpoint mto-variant-configurator resolve\n- Query-Parameter switched enthält die aktuell gewechselte Gruppe\n- Query-Parameter options enthält ein JSON-Array gewählter Optionen\n- Ungültiges JSON führt zu leerem options-Array\n- VariantNotFoundException hält productId als Fallback\n- Rückgabe enthält variantId, gallery media und Preis\n- Kein HTTP-Cache wegen kundenspezifischer Preise\n\n- GET /mto-variant-configurator/resolve/STRG-PRODUKT-ID?options=[{\"optionId\":\"farbe\",\"option\":\"rot\"}]\n- Antwort enthält variantId\n- Antwort enthält gallery media\n- Antwort enthält Preis\n----------------------------------------\n\nKonfigurator öffnen\n\nÖffnet den Konfigurator ab einem gewählten Schritt\n\n- Erster Aufruf zeigt das Modal\n- Weiterer Aufruf wechselt den Schritt\n- Fokus vorheriges Element wird gespeichert\n- Body erhält CSS-Klasse mto-vc-modal-open\n- Escape-Schließen wird registriert\n- Galerie und Preis werden aktualisiert\n- Fokus springt auf den Next-Button\n\n- LMB auf Konfigurator-Trigger klicken\n- Modal erscheint im gewählten Schritt\n----------------------------------------\n\nKonfigurator-Karte registrieren\n\nMacht die Einstellungen des Varianten-Konfigurators auf der Produktdetail-Seite verfügbar\n\n- Registriert als mto-vc-variants-card\n- Nutzt Produkt aus swProductDetail\n- Speichert Einstellungen in customFields des Produkts\n\n- Produktdetail-Seite eines Produkts öffnen\n- Tab Variants aufrufen\n- Registrierte mto-vc-variants-card wird angezeigt\n----------------------------------------\n\nPlugin registrieren\n\nMacht das Plugin für Elemente mit dem Selektor verfügbar\n\n- Registriert unter VariantConfiguratorPlugin\n- Nutzt window.PluginManager\n- Bindet an [data-mto-variant-configurator]\n\n- PluginManager.register aufrufen\n- Element mit data-mto-variant-configurator erstellen\n- Plugin auf Element angewendet\n" + } + }, + { + "titel": "„Galerie“ geändert", + "dateien": { + "galerie": "\nGalerie\n----------------------------------------\n\nkern\n----------------------------------------\n\nErmöglicht das Anzeigen und Durchblättern von Produktbildern im Konfigurator-Modal\n----------------------------------------\n\n- Einzelne Galerie pro Modal\n- Navigiert zyklisch\n- Ein Bild deaktiviert Navigation\n- Hauptbild über thumbnails aktualisierbar\n----------------------------------------\n\nGalerie nächste anzeigen\n\nZeigt das nächste Bild der Galerie\n\n- Mindestens 2 Bilder vorhanden\n- Zyklisch von letztem zu erstem Bild\n\n- Auf next-Button klicken\n- Nächstes Bild wird angezeigt\n----------------------------------------\n\nGalerie rückwärts blättern\n\nVorheriges Bild der Galerie anzeigen\n\n- Nur mit mindestens zwei Bildern\n- Springt von erstem zum letzten Bild\n- Aktualisiert Miniaturansicht\n\n- Vollmodus öffnen\n- Klick auf Vorheriges-Bild-Icon\n- Erstes Bild zeigt\n----------------------------------------\n\nGalerie vorherige anzeigen\n\nBlendet das vorherige Bild der Galerie ein\n\n- mto-vc-gallery-prev-Icon\n- Bei nur einem Bild keine Wirkung\n\n- Galerie mit mindestens zwei Bildern öffnen\n- LMB auf mto-vc-gallery-prev-Icon\n- Vorheriges Bild im Stage-Image angezeigt\n----------------------------------------\n\nGalerie vorwärts blättern\n\nZeigt das nächste Bild der Galerie\n\n- Geht bei weniger als zwei Bildern nicht\n- Springt vom letzten zum ersten Bild\n\n- Modal öffnen\n- Klick auf gallery-next\n- Nächstes Bild wird angezeigt\n- Klick erneut bei letztem Bild\n- Erstes Bild wird angezeigt\n----------------------------------------\n\nThumbnail auswählen\n\nGreift direkt auf ein Produktbild zu, ohne durch die Galerie zu blättern\n\n- Aktives Thumbnail zeigt x-Icon\n- Klick aktualisiert Hauptbild und Aktivzustand\n\n- Galerie mit mehreren Thumbnails öffnen\n- Klick auf Thumbnail\n- Hauptbild entspricht geklicktem Thumbnail\n" + } + }, + { + "titel": "„Lightbox“ geändert", + "dateien": { + "lightbox": "\nLightbox\n----------------------------------------\n\nkern\n----------------------------------------\n\nZeigt eine vergrößerte Ansicht der Optionsabbildung mit ihrem Namen\n----------------------------------------\n\n- lightboxSelect bestätigt Auswahl und schließt\n- Escape und x-Icon schließen\n- Tab und Shift-Tab zirkulieren im Fokusring\n- Geschlossen kehrt Fokus zum Auslöser zurück\n- hidden-Attribut entfernt aus dem Barrierefreiheitsbaum\n----------------------------------------\n\nAuswahl bestätigen\n\nWählt eine Option im aktuellen Schritt und berechnet die gültigen Folgeschritte neu\n\n- Bleibt im aktuellen Schritt\n- Invalidiert Folgeschritte mit ungültigen Kombinationen\n- Setzt Fokus auf die gewählte Option\n- Aktualisiert Galerie und Preis\n\n- Lightbox mit Option öffnen\n- LMB auf Auswahl bestätigen\n- Option markiert\n----------------------------------------\n\nKonfigurator schließen\n\n- Schließt die Lightbox, ohne den Konfigurator zu schließen\n- x-Icon oder Escape beenden die Lightbox\n- Fokus kehrt zum Auslöser in der Optionsliste zurück\n\n- Option mit Bildauswahl öffnet die Lightbox\n- Escape drücken\n- Lightbox geschlossen, Modal offen\n----------------------------------------\n\nLightbox schließen\n\nEntfernt die vergrößerte Produktansicht wieder\n\n- x-Icon oder Escape schließt\n- Zurück zum Dialog gibt Focus\n\n- Modal öffnen\n- Option mit Bild wählen\n- Leinwand-Icon klicken\n- Lightbox sichtbar\n- Escape drücken\n- Lightbox geschlossen, Dialog fokussiert\n----------------------------------------\n\nLightbox öffnen\n\nZeigt das Produktfoto einer Variante option in Originalgröße\n\n- lightboxImage zeigt option.media\n- lightboxCaption zeigt option.name\n- lightboxSelect erhält Fokus\n\n- Modal öffnen\n- Auf Option mit Bild klicken\n- Info-Button der Option klicken\n- Lightbox zeigt das Foto in Originalgröße\n----------------------------------------\n\nTastatur verwenden\n\nBedient Modal und Lightbox per Tastatur\n\n- Escape schließt Lightbox oder Modal\n- Tab zirkuliert im Fokusring vorwärts\n- Shift-Tab zirkuliert im Fokusring rückwärts\n\n- Modal öffnen\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen\n- Escape drücken\n- Modal geschlossen\n" + } + }, + { + "titel": "„Produkt“ geändert", + "dateien": { + "produkt": "\nProdukt\n----------------------------------------\n\nkern\n----------------------------------------\n\nStellt dem Produkttemplate Daten des Variantenkonfigurators bereit\n----------------------------------------\n\n- Inaktiver Konfigurator setzt mtoVariantConfiguratorActive auf false\n- Aktiver Konfigurator weist alle Konfigurator-Variablen zu\n- sw-product-detail-variants wird mit eigener Template-Datei überschrieben\n- mtoVariantConfiguratorTrustLogo fehlt in Regeln und Funktion\n- Produktseite laden: Testschritte beschreiben Ergebnis statt Handlung\n- Variantenansicht erweitern: Funktion hat keine Testschritte, nur Regeln\n----------------------------------------\n\nProduktseite laden\n\nBereitet Variant-Konfigurationsdaten für die Produktseite vor\n\n- mtoVariantConfiguratorActive false bei inaktivem Konfigurator\n- Alle Variablen bei aktivem Konfigurator zugewiesen\n- Initial-Variante für vorausgefülltes Modal geladen\n\n- Produkt mit aktivem Konfigurator öffnen\n- Seite vollständig laden\n- Template-Variablen prüfen\n- Seite ohne Konfigurator öffnen\n- mtoVariantConfiguratorActive ist false\n----------------------------------------\n\nVariantenansicht erweitern\n\nFügt der Produktdetail-Variantenansicht zusätzliche Felder oder Funktionen hinzu\n\n- Überschreibt sw-product-detail-variants\n- Eigene Template-Datei wird geladen\n\n- Produktdetailseite öffnen\n- Varianten-Bereich aufrufen\n- Erweiterte Felder oder Funktionen sichtbar\n" + } + }, + { + "titel": "„Lightbox“ geändert", + "dateien": { + "lightbox": "\nLightbox\n----------------------------------------\n\nkern\n----------------------------------------\n\nZeigt eine vergrößerte Ansicht der Optionsabbildung mit ihrem Namen\n----------------------------------------\n\n- lightboxSelect bestätigt Auswahl und schließt\n- Escape und x-Icon schließen\n- Tab und Shift-Tab zirkulieren im Fokusring\n- Geschlossen kehrt Fokus zum Auslöser zurück\n- hidden-Attribut entfernt aus dem Barrierefreiheitsbaum\n----------------------------------------\n\nAuswahl bestätigen\n\nWählt eine Option im aktuellen Schritt und berechnet die gültigen Folgeschritte neu\n\n- Bleibt im aktuellen Schritt\n- Invalidiert Folgeschritte mit ungültigen Kombinationen\n- Setzt Fokus auf die gewählte Option\n- Aktualisiert Galerie und Preis\n\n- Lightbox mit Option öffnen\n- LMB auf Auswahl bestätigen\n- Option markiert\n----------------------------------------\n\nKonfigurator schließen\n\n- Schließt die Lightbox, ohne den Konfigurator zu schließen\n- x-Icon oder Escape beenden die Lightbox\n- Fokus kehrt zum Auslöser in der Optionsliste zurück\n\n- Option mit Bildauswahl öffnet die Lightbox\n- Escape drücken\n- Lightbox geschlossen, Modal offen\n----------------------------------------\n\nLightbox schließen\n\nEntfernt die vergrößerte Produktansicht wieder\n\n- x-Icon oder Escape schließt\n- Zurück zum Dialog gibt Focus\n\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen, Dialog fokussiert\n----------------------------------------\n\nLightbox öffnen\n\nZeigt das Produktfoto einer Variante option in Originalgröße\n\n- lightboxImage zeigt option.media\n- lightboxCaption zeigt option.name\n- lightboxSelect erhält Fokus\n\n- Modal öffnen\n- Auf Option mit Bild klicken\n- Info-Button der Option klicken\n- Lightbox zeigt das Foto in Originalgröße\n----------------------------------------\n\nTastatur verwenden\n\nBedient Modal und Lightbox per Tastatur\n\n- Escape schließt Lightbox oder Modal\n- Tab zirkuliert im Fokusring vorwärts\n- Shift-Tab zirkuliert im Fokusring rückwärts\n\n- Modal öffnen\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen\n- Escape drücken\n- Modal geschlossen\n" + } + }, + { + "titel": "„Galerie“ geändert", + "dateien": { + "galerie": "\nGalerie\n----------------------------------------\n\nkern\n----------------------------------------\n\nErmöglicht das Anzeigen und Durchblättern von Produktbildern im Konfigurator-Modal\n----------------------------------------\n\n- Einzelne Galerie pro Modal\n- Navigiert zyklisch\n- Ein Bild deaktiviert Navigation\n- Hauptbild über thumbnails aktualisierbar\n----------------------------------------\n\nGalerie nächste anzeigen\n\nZeigt das nächste Bild der Galerie\n\n- Mindestens 2 Bilder vorhanden\n- Zyklisch von letztem zu erstem Bild\n\n- Auf next-Button klicken\n- Nächstes Bild wird angezeigt\n----------------------------------------\n\nGalerie rückwärts blättern\n\nVorheriges Bild der Galerie anzeigen\n\n- Nur mit mindestens zwei Bildern\n- Springt von erstem zum letzten Bild\n- Aktualisiert Miniaturansicht\n\n- Vollmodus öffnen\n- Klick auf Vorheriges-Bild-Icon\n- Erstes Bild zeigt\n----------------------------------------\n\nGalerie vorherige anzeigen\n\nBlendet das vorherige Bild der Galerie ein\n\n- mto-vc-gallery-prev-Icon\n- Bei nur einem Bild keine Wirkung\n\n- Galerie mit mindestens zwei Bildern öffnen\n- LMB auf mto-vc-gallery-prev-Icon\n- Vorheriges Bild im Stage-Image angezeigt\n----------------------------------------\n\nGalerie vorwärts blättern\n\nZeigt das nächste Bild der Galerie\n\n- Geht bei weniger als zwei Bildern nicht\n- Springt vom letzten zum ersten Bild\n\n- Modal öffnen\n- Klick auf gallery-next\n- Nächstes Bild wird angezeigt\n----------------------------------------\n\nThumbnail auswählen\n\nGreift direkt auf ein Produktbild zu, ohne durch die Galerie zu blättern\n\n- Aktives Thumbnail zeigt x-Icon\n- Klick aktualisiert Hauptbild und Aktivzustand\n\n- Galerie mit mehreren Thumbnails öffnen\n- Klick auf Thumbnail\n- Hauptbild entspricht geklicktem Thumbnail\n" + } + }, + { + "titel": "„Lightbox“ geändert", + "dateien": { + "lightbox": "\nLightbox\n----------------------------------------\n\nkern\n----------------------------------------\n\nZeigt eine vergrößerte Ansicht der Optionsabbildung mit ihrem Namen\n----------------------------------------\n\n- lightboxSelect bestätigt Auswahl und schließt\n- Escape und x-Icon schließen\n- Tab und Shift-Tab zirkulieren im Fokusring\n- Geschlossen kehrt Fokus zum Auslöser zurück\n- hidden-Attribut entfernt aus dem Barrierefreiheitsbaum\n----------------------------------------\n\nAuswahl bestätigen\n\nWählt eine Option im aktuellen Schritt und berechnet die gültigen Folgeschritte neu\n\n- Bleibt im aktuellen Schritt\n- Invalidiert Folgeschritte mit ungültigen Kombinationen\n- Setzt Fokus auf die gewählte Option\n- Aktualisiert Galerie und Preis\n\n- Lightbox mit Option öffnen\n- LMB auf Auswahl bestätigen\n- Option markiert\n----------------------------------------\n\nKonfigurator schließen\n\n- Schließt die Lightbox, ohne den Konfigurator zu schließen\n- x-Icon oder Escape beenden die Lightbox\n- Fokus kehrt zum Auslöser in der Optionsliste zurück\n\n- LMB auf Option mit Bildauswahl\n- Escape drücken\n- Lightbox geschlossen, Modal offen\n----------------------------------------\n\nLightbox schließen\n\nEntfernt die vergrößerte Produktansicht wieder\n\n- x-Icon oder Escape schließt\n- Zurück zum Dialog gibt Focus\n\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen, Dialog fokussiert\n----------------------------------------\n\nLightbox öffnen\n\nZeigt das Produktfoto einer Variante option in Originalgröße\n\n- lightboxImage zeigt option.media\n- lightboxCaption zeigt option.name\n- lightboxSelect erhält Fokus\n\n- Modal öffnen\n- Auf Option mit Bild klicken\n- Info-Button der Option klicken\n- Lightbox zeigt das Foto in Originalgröße\n----------------------------------------\n\nTastatur verwenden\n\nBedient Modal und Lightbox per Tastatur\n\n- Escape schließt Lightbox oder Modal\n- Tab zirkuliert im Fokusring vorwärts\n- Shift-Tab zirkuliert im Fokusring rückwärts\n\n- Modal öffnen\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen\n- Escape drücken\n- Modal geschlossen\n" + } + }, + { + "titel": "„Lightbox“ geändert", + "dateien": { + "lightbox": "\nLightbox\n----------------------------------------\n\nkern\n----------------------------------------\n\nZeigt eine vergrößerte Ansicht der Optionsabbildung mit ihrem Namen\n----------------------------------------\n\n- lightboxSelect bestätigt Auswahl\n- lightboxSelect schließt\n- Escape schließt\n- x-Icon schließt\n- Geschlossen kehrt Fokus zum Auslöser zurück\n- hidden-Attribut entfernt aus dem Barrierefreiheitsbaum\n----------------------------------------\n\nAuswahl bestätigen\n\nWählt eine Option im aktuellen Schritt und berechnet die gültigen Folgeschritte neu\n\n- Bleibt im aktuellen Schritt\n- Invalidiert Folgeschritte mit ungültigen Kombinationen\n- Setzt Fokus auf die gewählte Option\n- Aktualisiert Galerie und Preis\n\n- Lightbox mit Option öffnen\n- LMB auf Auswahl bestätigen\n- Option markiert\n----------------------------------------\n\nKonfigurator schließen\n\n- Schließt die Lightbox, ohne den Konfigurator zu schließen\n- x-Icon oder Escape beenden die Lightbox\n- Fokus kehrt zum Auslöser in der Optionsliste zurück\n\n- LMB auf Option mit Bildauswahl\n- Escape drücken\n- Lightbox geschlossen, Modal offen\n----------------------------------------\n\nLightbox schließen\n\nEntfernt die vergrößerte Produktansicht wieder\n\n- x-Icon oder Escape schließt\n- Zurück zum Dialog gibt Focus\n\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen, Dialog fokussiert\n----------------------------------------\n\nLightbox öffnen\n\nZeigt das Produktfoto einer Variante option in Originalgröße\n\n- lightboxImage zeigt option.media\n- lightboxCaption zeigt option.name\n- lightboxSelect erhält Fokus\n\n- Modal öffnen\n- Auf Option mit Bild klicken\n- Info-Button der Option klicken\n- Lightbox zeigt das Foto in Originalgröße\n----------------------------------------\n\nTastatur verwenden\n\nBedient Modal und Lightbox per Tastatur\n\n- Escape schließt Lightbox oder Modal\n- Tab zirkuliert im Fokusring vorwärts\n- Shift-Tab zirkuliert im Fokusring rückwärts\n\n- Modal öffnen\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen\n- Escape drücken\n- Modal geschlossen\n" + } + }, + { + "titel": "„Konfigurator“ geändert", + "dateien": { + "konfigurator": "\nKonfigurator\n----------------------------------------\n\nkern\n----------------------------------------\n\nFührt durch Variantenkonfiguration in Einzelschritten mit Live-Vorschau\n----------------------------------------\n\n- Aktiv nur wenn Produkt mto_variant_configurator_active gesetzt hat\n- Optionen-Bilder nur bis zwei Schritte\n- Galerie und Preis aktualisieren live ohne Seitenreload\n- Body erhält CSS-Klasse mto-vc-modal-open solange Modal offen\n- Escape schließt Modal\n- Schließen stellt Fokus auf vorheriges Element\n- Registriert als mto-vc-variants-card in swProductDetail\n- Einstellungen in customFields des Produkts gespeichert\n- Falls inaktiv: Fallback auf Standard-Konfigurator von Shopware\n- Natives Select pro Gruppe im DOM\n- Schritte ohne gültige Optionen werden beim Navigieren übersprungen\n- Ungültige Kombinationen für Folgeschritte werden beim Wählen verworfen\n- Unbesuchte Schritte werden beim Bestätigen mit erster gültiger Option aufgefüllt\n- Deaktivierte Optionen sind nicht auswählbar\n- Gallery-Container erhält CSS-Klasse has-no-gallery wenn keine Bilder vorhanden\n- Schließen bei Lightbox: fokus auf Lightbox-Auswahl-Button\n----------------------------------------\n\nGeführte Konfiguration aktivieren\n\nFührt Kunden schrittweise durch die Variantenauswahl mit Hinweisen und Modal\n\n- Aktiviert bei Produkten mit aktivem Konfigurator-Layout\n- Zeigt jeden Konfigurationsschritt mit Beschriftung\n- Blendentext je Gruppe über Modal aus\n- Inkrementelle Variantenauflösung über resolveUrl\n\n- Produktseite mit aktivem Konfigurator öffnen\n- LMB auf ersten Konfigurationsschritt\n- Option im Modal wählen\n- Modal schließt und nächster Schritt markiert\n----------------------------------------\n\nKonfigurationsdaten abrufen\n\nLiefert Variantendaten für eine Live-Aktualisierung im Konfigurator\n\n- Endpoint mto-variant-configurator resolve\n- Query-Parameter switched enthält die aktuell gewechselte Gruppe\n- Query-Parameter options enthält ein JSON-Array gewählter Optionen\n- Ungültiges JSON führt zu leerem options-Array\n- VariantNotFoundException hält productId als Fallback\n- Rückgabe enthält variantId, gallery media und Preis\n- Kein HTTP-Cache wegen kundenspezifischer Preise\n\n- Resolve-Endpunkt mit Produkt-ID und Option aufrufen\n- Antwort enthält variantId\n- Antwort enthält gallery media\n- Antwort enthält Preis\n----------------------------------------\n\nKonfigurator öffnen\n\nÖffnet den Konfigurator ab einem gewählten Schritt\n\n- Erster Aufruf zeigt das Modal\n- Weiterer Aufruf wechselt den Schritt\n- Fokus vorheriges Element wird gespeichert\n- Body erhält CSS-Klasse mto-vc-modal-open\n- Escape-Schließen wird registriert\n- Galerie und Preis werden aktualisiert\n- Fokus springt auf den Next-Button\n\n- LMB auf Konfigurator-Trigger klicken\n- Modal erscheint im gewählten Schritt\n----------------------------------------\n\nKonfigurator-Karte registrieren\n\nMacht die Einstellungen des Varianten-Konfigurators auf der Produktdetail-Seite verfügbar\n\n- Registriert als mto-vc-variants-card\n- Nutzt Produkt aus swProductDetail\n- Speichert Einstellungen in customFields des Produkts\n\n- Produktdetail-Seite eines Produkts öffnen\n- Tab Variants aufrufen\n- Registrierte mto-vc-variants-card wird angezeigt\n----------------------------------------\n\nPlugin registrieren\n\nMacht das Plugin für Elemente mit dem Selektor verfügbar\n\n- Registriert unter VariantConfiguratorPlugin\n- Nutzt window.PluginManager\n- Bindet an [data-mto-variant-configurator]\n\n- PluginManager.register aufrufen\n- Element mit data-mto-variant-configurator erstellen\n- Plugin auf Element angewendet\n" + } + }, + { + "titel": "„Lightbox“ geändert", + "dateien": { + "lightbox": "\nLightbox\n----------------------------------------\n\nkern\n----------------------------------------\n\nZeigt eine vergrößerte Ansicht der Optionsabbildung mit ihrem Namen\n----------------------------------------\n\n- lightboxSelect bestätigt Auswahl\n- lightboxSelect schließt\n- Escape schließt\n- x-Icon schließt\n- Geschlossen kehrt Fokus zum Auslöser zurück\n- hidden-Attribut entfernt aus dem Barrierefreiheitsbaum\n----------------------------------------\n\nAuswahl bestätigen\n\nWählt eine Option im aktuellen Schritt und berechnet die gültigen Folgeschritte neu\n\n- Bleibt im aktuellen Schritt\n- Invalidiert Folgeschritte mit ungültigen Kombinationen\n- Setzt Fokus auf die gewählte Option\n- Aktualisiert Galerie und Preis\n\n- Lightbox mit Option öffnen\n- LMB auf Auswahl bestätigen\n- Option markiert\n----------------------------------------\n\nKonfigurator schließen\n\n- Schließt die Lightbox, ohne den Konfigurator zu schließen\n- x-Icon oder Escape beenden die Lightbox\n- Fokus kehrt zum Auslöser in der Optionsliste zurück\n\n- LMB auf Option mit Bildauswahl\n- Escape drücken\n- Lightbox geschlossen, Modal offen\n----------------------------------------\n\nLightbox schließen\n\nEntfernt die vergrößerte Produktansicht wieder\n\n- x-Icon schließt\n- Escape schließt\n- Zurück zum Dialog gibt Focus\n\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen, Dialog fokussiert\n----------------------------------------\n\nLightbox öffnen\n\nZeigt das Produktfoto einer Variante option in Originalgröße\n\n- lightboxImage zeigt option.media\n- lightboxCaption zeigt option.name\n- lightboxSelect erhält Fokus\n\n- Modal öffnen\n- Auf Option mit Bild klicken\n- Info-Button der Option klicken\n- Lightbox zeigt das Foto in Originalgröße\n----------------------------------------\n\nTastatur verwenden\n\nBedient Modal und Lightbox per Tastatur\n\n- Escape schließt Lightbox oder Modal\n- Tab zirkuliert im Fokusring vorwärts\n- Shift-Tab zirkuliert im Fokusring rückwärts\n\n- Modal öffnen\n- Lightbox öffnen\n- Escape drücken\n- Lightbox geschlossen\n- Escape drücken\n- Modal geschlossen\n" + } + }, + { + "titel": "„Option ansehen“ geändert", + "dateien": { + "option-ansehen": "\nOption ansehen\n----------------------------------------\n\nkern\n----------------------------------------\n\nDer Kunde prüft eine Option groß, bevor er sie nimmt\n----------------------------------------\n\n- Nur Optionen mit Bild tragen den Hinweis\n- Optionsbilder erscheinen bis zwei Schritte\n- Ansicht liegt über dem Konfigurator\n----------------------------------------\n\nOptionsdetail öffnen\n\nZeigt Bild und Namen einer Option in voller Größe\n\n- i-Icon öffnet die Ansicht\n- Enter öffnet die Ansicht\n- Leertaste öffnet die Ansicht\n\n- Konfigurator öffnen\n- LMB auf i-Icon einer Option\n- Große Ansicht erscheint\n----------------------------------------\n\nOption aus Ansicht wählen\n\nÜbernimmt die betrachtete Option in die Auswahl\n\n- Knopf übernimmt und schließt die Ansicht\n- Schritt bleibt derselbe\n\n- Optionsdetail öffnen\n- LMB auf Wählen-Knopf\n- Option ist gewählt\n----------------------------------------\n\nAnsicht schließen\n\nKehrt zur Optionsliste zurück ohne Auswahl\n\n- x-Icon schließt die Ansicht\n- Escape schließt die Ansicht\n- Konfigurator bleibt offen\n\n- Optionsdetail öffnen\n- Escape drücken\n- Optionsliste erscheint wieder\n" + } + }, + { + "titel": "„Varianten wählen“ geändert", + "dateien": { + "varianten-waehlen": "\nVarianten wählen\n----------------------------------------\n\nkern\n----------------------------------------\n\nDer Kunde findet Schritt für Schritt eine bestellbare Kombination\n----------------------------------------\n\n- Erster Schritt zeigt alle Optionen seiner Eigenschaft\n- Folgeschritte zeigen nur kombinierbare Optionen\n- Reihenfolge der Schritte kommt aus dem Backend\n- Ohne Auswahl greifen die Standardvarianten des Elternartikels\n- Schritte ohne gültige Option werden übersprungen\n- Eine Auswahl wechselt den Schritt nicht\n- Ungültige Folgeauswahl fällt beim Wechsel weg\n- Escape schließt den Konfigurator\n- Tabulator bleibt im Dialog\n----------------------------------------\n\nSchritt öffnen\n\nÖffnet den Konfigurator beim angeklickten Schritt\n\n- LMB auf einen Schritt öffnet das Modal\n- Offener Konfigurator wechselt nur den Schritt\n- Modal hängt am Seitenkörper\n\n- Produktseite öffnen\n- LMB auf zweiten Schritt\n- Modal öffnet bei Schritt 2\n----------------------------------------\n\nOption wählen\n\nÜbernimmt eine Option in die laufende Auswahl\n\n- Gewählte Option ist hervorgehoben\n- Nicht kombinierbare Optionen sind gesperrt\n- Auswahl verwirft ungültige Folgeschritte\n\n- Konfigurator öffnen\n- LMB auf eine Option\n- Option ist hervorgehoben\n----------------------------------------\n\nNächsten Schritt anzeigen\n\nFührt zum nächsten Schritt mit gültigen Optionen\n\n- Weiter-Knopf heißt am letzten Schritt Fertig\n- Leere Schritte werden übersprungen\n\n- Konfigurator öffnen\n- LMB auf Weiter-Knopf\n- Nächster Schritt erscheint\n----------------------------------------\n\nVorherigen Schritt anzeigen\n\nFührt zurück zum letzten Schritt mit Optionen\n\n- Zurück-Knopf ist am ersten Schritt gesperrt\n- Leere Schritte werden übersprungen\n\n- Zum zweiten Schritt gehen\n- LMB auf Zurück-Knopf\n- Erster Schritt erscheint\n----------------------------------------\n\nAuswahl übernehmen\n\nWechselt das Produkt auf die gewählte Variante\n\n- Fertig schreibt die Auswahl in die Auswahlfelder\n- Unbesuchte Schritte bekommen die erste gültige Option\n- Der Variantenwechsel von Shopware führt den Wechsel aus\n\n- Alle Schritte durchgehen\n- LMB auf Fertig-Knopf\n- Seite zeigt die gewählte Variante\n----------------------------------------\n\nKonfigurator schließen\n\nBeendet die Auswahl ohne Wechsel der Variante\n\n- x-Icon schließt das Modal\n- Escape schließt das Modal\n- Fokus kehrt zum Auslöser zurück\n\n- Konfigurator öffnen\n- Escape drücken\n- Modal ist geschlossen\n" + } + }, + { + "titel": "„Vorschau zeigen“ geändert", + "dateien": { + "vorschau-zeigen": "\nVorschau zeigen\n----------------------------------------\n\nkern\n----------------------------------------\n\nDer Kunde sieht Bild und Preis der gewählten Kombination\n----------------------------------------\n\n- Preis stimmt mit dem Preis der Produktseite überein\n- Antwort wird nicht zwischengespeichert\n- Späte Antworten überholter Anfragen werden verworfen\n- Ohne eigene Bilder greifen die Bilder des Elternartikels\n----------------------------------------\n\nVorschau laden\n\nHolt Bilder und Preis zur laufenden Auswahl\n\n- Jede Auswahl löst eine neue Anfrage aus\n- Ohne Treffer bleibt die Produkt-ID als Rückfall\n- Erstes Bild ist das Titelbild der Variante\n\n- Konfigurator öffnen\n- Andere Option wählen\n- Bild und Preis ändern sich\n----------------------------------------\n\nGalerie blättern\n\nZeigt weitere Bilder der gewählten Variante\n\n- Pfeil-Icons blättern vor und zurück\n- Nach dem letzten Bild folgt das erste\n- Bei einem Bild bleibt die Navigation aus\n\n- Konfigurator öffnen\n- LMB auf Vor-Icon\n- Nächstes Bild erscheint\n----------------------------------------\n\nBild wählen\n\nWechselt das große Bild über die Vorschaubilder\n\n- Aktives Vorschaubild ist hervorgehoben\n- Großes Bild folgt der Wahl\n\n- Konfigurator öffnen\n- LMB auf drittes Vorschaubild\n- Großes Bild zeigt dieses Motiv\n" + } + }, + { + "titel": "„Varianten wählen“ geändert", + "dateien": { + "varianten-waehlen": "\nVarianten wählen\n----------------------------------------\n\nkern\n----------------------------------------\n\nDer Kunde findet Schritt für Schritt eine bestellbare Kombination\n----------------------------------------\n\n- Erster Schritt zeigt alle Optionen seiner Eigenschaft\n- Folgeschritte zeigen nur kombinierbare Optionen\n- Der Ablauf trägt beliebig viele Eigenschaften\n- Reihenfolge der Schritte kommt aus dem Backend\n- Ohne Auswahl greifen die Standardvarianten des Elternartikels\n- Schritte ohne gültige Option werden übersprungen\n- Eine Auswahl wechselt den Schritt nicht\n- Ungültige Folgeauswahl fällt beim Wechsel weg\n- Auf kleinen Bildschirmen bleibt der Ablauf derselbe\n- Escape schließt den Konfigurator\n- Tabulator bleibt im Dialog\n----------------------------------------\n\nSchritt öffnen\n\nÖffnet den Konfigurator beim angeklickten Schritt\n\n- LMB auf einen Schritt öffnet das Modal\n- Offener Konfigurator wechselt nur den Schritt\n- Modal hängt am Seitenkörper\n\n- Produktseite öffnen\n- LMB auf zweiten Schritt\n- Modal öffnet bei Schritt 2\n----------------------------------------\n\nOption wählen\n\nÜbernimmt eine Option in die laufende Auswahl\n\n- Gewählte Option ist hervorgehoben\n- Nicht kombinierbare Optionen sind gesperrt\n- Auswahl verwirft ungültige Folgeschritte\n- Schritt bleibt nach der Wahl derselbe\n\n- Konfigurator öffnen\n- LMB auf eine Option\n- Option ist hervorgehoben\n----------------------------------------\n\nNächsten Schritt anzeigen\n\nFührt zum nächsten Schritt mit gültigen Optionen\n\n- Weiter-Knopf heißt am letzten Schritt Fertig\n- Leere Schritte werden übersprungen\n\n- Konfigurator öffnen\n- LMB auf Weiter-Knopf\n- Nächster Schritt erscheint\n----------------------------------------\n\nVorherigen Schritt anzeigen\n\nFührt zurück zum letzten Schritt mit Optionen\n\n- Zurück-Knopf ist am ersten Schritt gesperrt\n- Leere Schritte werden übersprungen\n\n- Zum zweiten Schritt gehen\n- LMB auf Zurück-Knopf\n- Erster Schritt erscheint\n----------------------------------------\n\nAuswahl übernehmen\n\nWechselt das Produkt auf die gewählte Variante\n\n- Fertig schreibt die Auswahl in die Auswahlfelder\n- Unbesuchte Schritte bekommen die erste gültige Option\n- Der Variantenwechsel von Shopware führt den Wechsel aus\n- Die Seite zeigt danach die Adresse der Variante\n\n- Alle Schritte durchgehen\n- LMB auf Fertig-Knopf\n- Produktseite zeigt die gewählte Variante\n----------------------------------------\n\nKonfigurator schließen\n\nBeendet die Auswahl ohne Wechsel der Variante\n\n- x-Icon schließt das Modal\n- Escape schließt das Modal\n- Fokus kehrt zum Auslöser zurück\n\n- Konfigurator öffnen\n- Escape drücken\n- Modal ist geschlossen\n" + } + }, + { + "titel": "„Layout zuweisen“ geändert", + "dateien": { + "layout-zuweisen": "\nLayout zuweisen\n----------------------------------------\n\nkern\n----------------------------------------\n\nEin Händler entscheidet je Produkt, ob die geführte Auswahl erscheint\n----------------------------------------\n\n- Einstellungen liegen auf dem Varianten-Tab des Produkts\n- Werte stehen in den customFields des Produkts\n- Bearbeiten erfordert das Recht product.editor\n- Ohne Zuweisung bleibt das Standardlayout aktiv\n----------------------------------------\n\nKonfigurator aktivieren\n\nSchaltet die geführte Variantenauswahl für ein Produkt frei\n\n- Schalter steht auf dem Varianten-Tab\n- Aktiv ersetzt die Buybox des Produkts\n- Inaktiv zeigt das Standardlayout von Shopware\n\n- Produkt im Admin öffnen\n- Varianten-Tab öffnen\n- Schalter aktivieren und speichern\n- Buybox zeigt die geführte Auswahl\n----------------------------------------\n\nOptionsübersicht hinterlegen\n\nHinterlegt ein PDF mit allen Varianten und Kombinationen\n\n- Medienfeld steht auf dem Varianten-Tab\n- Feld hängt am Hauptartikel\n- Ohne PDF bleibt der Knopf unsichtbar\n\n- Varianten-Tab öffnen\n- PDF im Medienfeld wählen\n- Produkt speichern\n- Modal zeigt den Knopf für Optionen\n----------------------------------------\n\nTrust-Logo hinterlegen\n\nZeigt ein Vertrauenssiegel neben dem Gesamtpreis\n\n- Logo steht in der Plugin-Konfiguration\n- Gilt für den ganzen Verkaufskanal\n- Ohne Logo erscheint nur der Text\n\n- Plugin-Konfiguration öffnen\n- Logo im Medienfeld wählen\n- Modal zeigt das Logo am Preis\n----------------------------------------\n\nOptionsbild zuordnen\n\noffen\n\nHinterlegt je Variante ein Farbbild oder Materialbild\n\n- Zuordnung erfolgt auf Variantenebene\n- Bild erscheint neben der Option im Modal\n\n- Variante im Admin öffnen\n- Bild der Variante zuordnen\n- Modal zeigt das Bild an der Option\n" + } + }, + { + "titel": "„Varianten wählen“ geändert", + "dateien": { + "varianten-waehlen": "\nVarianten wählen\n----------------------------------------\n\nkern\n----------------------------------------\n\nDer Kunde findet Schritt für Schritt eine bestellbare Kombination\n----------------------------------------\n\n- Erster Schritt zeigt alle Optionen seiner Eigenschaft\n- Folgeschritte zeigen nur kombinierbare Optionen\n- Der Ablauf trägt beliebig viele Eigenschaften\n- Reihenfolge der Schritte kommt aus dem Backend\n- Ohne Auswahl greifen die Standardvarianten des Elternartikels\n- Schritte ohne gültige Option werden übersprungen\n- Eine Auswahl wechselt den Schritt nicht\n- Ungültige Folgeauswahl fällt beim Wechsel weg\n- Auf kleinen Bildschirmen bleibt der Ablauf derselbe\n- Escape schließt den Konfigurator\n- Tabulator bleibt im Dialog\n----------------------------------------\n\nSchritt öffnen\n\nÖffnet den Konfigurator beim angeklickten Schritt\n\n- LMB auf einen Schritt öffnet das Modal\n- Offener Konfigurator wechselt nur den Schritt\n- Modal hängt am Seitenkörper\n\n- Produktseite öffnen\n- LMB auf zweiten Schritt\n- Modal öffnet bei Schritt 2\n----------------------------------------\n\nOption wählen\n\nÜbernimmt eine Option in die laufende Auswahl\n\n- Gewählte Option ist hervorgehoben\n- Nicht kombinierbare Optionen sind gesperrt\n- Auswahl verwirft ungültige Folgeschritte\n- Schritt bleibt nach der Wahl derselbe\n\n- Konfigurator öffnen\n- LMB auf eine Option\n- Option ist hervorgehoben\n----------------------------------------\n\nNächsten Schritt anzeigen\n\nFührt zum nächsten Schritt mit gültigen Optionen\n\n- Weiter-Knopf heißt am letzten Schritt Fertig\n- Leere Schritte werden übersprungen\n\n- Konfigurator öffnen\n- LMB auf Weiter-Knopf\n- Nächster Schritt erscheint\n----------------------------------------\n\nVorherigen Schritt anzeigen\n\nFührt zurück zum letzten Schritt mit Optionen\n\n- Zurück-Knopf ist am ersten Schritt gesperrt\n- Leere Schritte werden übersprungen\n\n- Zum zweiten Schritt gehen\n- LMB auf Zurück-Knopf\n- Erster Schritt erscheint\n----------------------------------------\n\nAuswahl übernehmen\n\nWechselt das Produkt auf die gewählte Variante\n\n- Fertig überträgt die Auswahl in die Auswahlfelder\n- Unbesuchte Schritte bekommen die erste gültige Option\n- Shopware führt den Variantenwechsel aus\n\n- Alle Schritte durchgehen\n- LMB auf Fertig-Knopf\n- Produktseite zeigt die gewählte Variante\n----------------------------------------\n\nKonfigurator schließen\n\nBeendet die Auswahl ohne Wechsel der Variante\n\n- x-Icon schließt das Modal\n- Escape schließt das Modal\n- Fokus kehrt zum Auslöser zurück\n\n- Konfigurator öffnen\n- Escape drücken\n- Modal ist geschlossen\n" + } + }, + { + "titel": "„Schritt zeigen“ geändert", + "dateien": { + "schritt-zeigen": "\nSchritt zeigen\n----------------------------------------\n\nkern\n----------------------------------------\n\nDer Kunde weiß im Modal, wo er steht und was er wählt\n----------------------------------------\n\n- Optionen stehen rechts, die Bilder links\n- Lange Optionslisten lassen sich scrollen\n----------------------------------------\n\nEigenschaft benennen\n\nZeigt den Namen der Eigenschaft des aktuellen Schritts\n\n- Name steht als Überschrift über der Liste\n- Name kommt aus der Eigenschaftsgruppe\n\n- Konfigurator öffnen\n- Überschrift nennt die erste Eigenschaft\n----------------------------------------\n\nSchrittstand anzeigen\n\nZeigt den aktuellen Schritt und die Gesamtzahl\n\n- Zähler nennt Schritt und Gesamtzahl\n- Balken wächst mit dem Fortschritt\n- Text kommt aus einem Textbaustein\n\n- Konfigurator öffnen\n- Zähler zeigt 1 von 3\n----------------------------------------\n\nOptionen auflisten\n\nZeigt alle Optionen der Eigenschaft mit Namen und Bild\n\n- Jede Option nennt ihren Namen\n- Bild erscheint nur bis zwei Schritte\n- Ohne Bild erscheint der Farbwert\n- Ohne Farbwert bleibt die Zeile ohne Zeichen\n\n- Konfigurator öffnen\n- Jede Option zeigt ihren Namen\n" + } + } +] diff --git a/daten/MtoVariantConfigurator/.planung/auswahl-anstossen.md b/daten/MtoVariantConfigurator/.planung/auswahl-anstossen.md new file mode 100644 index 0000000..665f2fa --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/auswahl-anstossen.md @@ -0,0 +1,49 @@ + +Auswahl anstoßen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde erkennt in der Buybox die Reihenfolge der Schritte +---------------------------------------- + +- Jede Eigenschaft bildet einen eigenen Schritt +- Natives Auswahlfeld bleibt für den Variantenwechsel erhalten +- Eigene Darstellung gilt unabhängig vom Anzeigetyp der Eigenschaft +- Ohne aktives Layout erscheint die Standard-Buybox +---------------------------------------- + +Schrittnummer anzeigen + +Zeigt neben jeder Eigenschaft ihre Position im Ablauf + +- Beschriftung nennt das Wort Schritt und die Nummer +- Nummer folgt der Reihenfolge aus dem Backend + +- Produktseite öffnen +- Erste Eigenschaft zeigt Schritt 1 +---------------------------------------- + +Hinweistext anzeigen + +Erklärt dem Kunden, worauf er im Schritt achtet + +- Text kommt aus einem Textbaustein je Schritt +- Leerer Textbaustein blendet den Hinweis aus +- Hinweis hängt an der Nummer statt an der Eigenschaft + +- Textbaustein für Schritt 1 füllen +- Produktseite öffnen +- Hinweis steht unter der Überschrift +---------------------------------------- + +Gewählte Option anzeigen + +Zeigt am Schritt, welche Option gerade gilt + +- Ohne Auswahl steht dort Bitte wählen +- Vorbelegung erscheint ohne Zutun des Kunden + +- Hauptartikel ohne Variante öffnen +- Jeder Schritt nennt eine Option diff --git a/daten/MtoVariantConfigurator/.planung/beratung-anbieten.md b/daten/MtoVariantConfigurator/.planung/beratung-anbieten.md new file mode 100644 index 0000000..c0beeb5 --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/beratung-anbieten.md @@ -0,0 +1,47 @@ + +Beratung anbieten +---------------------------------------- + +optional +---------------------------------------- + +Der Kunde findet im Konfigurator Vertrauen und einen Kontakt +---------------------------------------- + +- Alle Texte kommen aus Textbausteinen +- Leerer Textbaustein blendet den Bereich aus +---------------------------------------- + +Vertrauen zeigen + +Zeigt Siegel und Zusage neben dem Gesamtpreis + +- Logo stammt aus der Plugin-Konfiguration +- Ohne Logo bleibt der Text stehen + +- Konfigurator öffnen +- Siegel steht neben dem Preis +---------------------------------------- + +Beratung erreichen + +Bietet eine Telefonnummer für Fragen zur Konfiguration + +- Nummer ist als Telefonlink klickbar +- Leere Nummer blendet den Bereich aus + +- Konfigurator öffnen +- LMB auf die Nummer +- Telefon-App öffnet sich +---------------------------------------- + +Optionsübersicht öffnen + +Öffnet das hinterlegte PDF mit allen Optionen + +- Knopf erscheint nur mit hinterlegtem PDF +- PDF öffnet in einem neuen Tab + +- Konfigurator öffnen +- LMB auf Optionen-Knopf +- PDF öffnet in neuem Tab diff --git a/daten/MtoVariantConfigurator/.planung/layout-zuweisen.md b/daten/MtoVariantConfigurator/.planung/layout-zuweisen.md new file mode 100644 index 0000000..1e06c7a --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/layout-zuweisen.md @@ -0,0 +1,69 @@ + +Layout zuweisen +---------------------------------------- + +kern +---------------------------------------- + +Ein Händler entscheidet je Produkt, ob die geführte Auswahl erscheint +---------------------------------------- + +- Einstellungen liegen auf dem Varianten-Tab des Produkts +- Werte stehen in den customFields des Produkts +- Bearbeiten erfordert das Recht product.editor +- Ohne Zuweisung bleibt das Standardlayout aktiv +---------------------------------------- + +Konfigurator aktivieren + +Schaltet die geführte Variantenauswahl für ein Produkt frei + +- Schalter steht auf dem Varianten-Tab +- Aktiv ersetzt die Buybox des Produkts +- Inaktiv zeigt das Standardlayout von Shopware + +- Produkt im Admin öffnen +- Varianten-Tab öffnen +- Schalter aktivieren und speichern +- Buybox zeigt die geführte Auswahl +---------------------------------------- + +Optionsübersicht hinterlegen + +Hinterlegt ein PDF mit allen Varianten und Kombinationen + +- Medienfeld steht auf dem Varianten-Tab +- Feld hängt am Hauptartikel +- Ohne PDF bleibt der Knopf unsichtbar + +- Varianten-Tab öffnen +- PDF im Medienfeld wählen +- Produkt speichern +- Modal zeigt den Knopf für Optionen +---------------------------------------- + +Trust-Logo hinterlegen + +Zeigt ein Vertrauenssiegel neben dem Gesamtpreis + +- Logo steht in der Plugin-Konfiguration +- Gilt für den ganzen Verkaufskanal +- Ohne Logo erscheint nur der Text + +- Plugin-Konfiguration öffnen +- Logo im Medienfeld wählen +- Modal zeigt das Logo am Preis +---------------------------------------- + +Optionsbild am Datensatz pflegen + +offen + +Hinterlegt das Bild einer Option am Datensatz der Variante + +- Feld liegt im Formular der einzelnen Variante +- Heute stammt das Bild aus der Eigenschaftsgruppe + +- Variante im Admin öffnen +- Bildfeld der Variante füllen +- Variante speichern diff --git a/daten/MtoVariantConfigurator/.planung/option-ansehen.md b/daten/MtoVariantConfigurator/.planung/option-ansehen.md new file mode 100644 index 0000000..bda54d3 --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/option-ansehen.md @@ -0,0 +1,51 @@ + +Option ansehen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde prüft eine Option groß, bevor er sie nimmt +---------------------------------------- + +- Nur Optionen mit Bild tragen den Hinweis +- Ansicht liegt über dem Konfigurator +---------------------------------------- + +Optionsdetail öffnen + +Zeigt Bild und Namen einer Option in voller Größe + +- i-Icon öffnet die Ansicht +- Enter öffnet die Ansicht +- Leertaste öffnet die Ansicht + +- Konfigurator öffnen +- LMB auf i-Icon einer Option +- Große Ansicht erscheint +---------------------------------------- + +Option aus Ansicht wählen + +Übernimmt die betrachtete Option in die Auswahl + +- Knopf übernimmt die Option +- Knopf schließt die Ansicht +- Schritt bleibt derselbe + +- Optionsdetail öffnen +- LMB auf Wählen-Knopf +- Option ist gewählt +---------------------------------------- + +Ansicht schließen + +Kehrt zur Optionsliste zurück ohne Auswahl + +- x-Icon schließt die Ansicht +- Escape schließt die Ansicht +- Konfigurator bleibt offen + +- Optionsdetail öffnen +- Escape drücken +- Optionsliste erscheint wieder diff --git a/daten/MtoVariantConfigurator/.planung/schritt-zeigen.md b/daten/MtoVariantConfigurator/.planung/schritt-zeigen.md new file mode 100644 index 0000000..3ceb620 --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/schritt-zeigen.md @@ -0,0 +1,49 @@ + +Schritt zeigen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde weiß im Modal, wo er steht und was er wählt +---------------------------------------- + +- Optionen stehen rechts +- Bilder links +- Lange Optionslisten lassen sich scrollen +---------------------------------------- + +Eigenschaft benennen + +Zeigt den Namen der Eigenschaft des aktuellen Schritts + +- Name steht als Überschrift über der Liste +- Name kommt aus der Eigenschaftsgruppe + +- Konfigurator öffnen +- Überschrift nennt die erste Eigenschaft +---------------------------------------- + +Schrittstand anzeigen + +Zeigt den aktuellen Schritt und die Gesamtzahl + +- Zähler nennt Schritt und Gesamtzahl +- Balken wächst mit dem Fortschritt +- Text kommt aus einem Textbaustein + +- Konfigurator öffnen +- Zähler zeigt 1 von 3 +---------------------------------------- + +Optionen auflisten + +Zeigt alle Optionen der Eigenschaft mit Namen und Bild + +- Jede Option nennt ihren Namen +- Bild erscheint nur bis zwei Schritte +- Ohne Bild erscheint der Farbwert +- Ohne Farbwert bleibt die Zeile ohne Zeichen + +- Konfigurator öffnen +- Jede Option zeigt ihren Namen diff --git a/daten/MtoVariantConfigurator/.planung/varianten-waehlen.md b/daten/MtoVariantConfigurator/.planung/varianten-waehlen.md new file mode 100644 index 0000000..c732ab7 --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/varianten-waehlen.md @@ -0,0 +1,109 @@ + +Varianten wählen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde findet Schritt für Schritt eine bestellbare Kombination +---------------------------------------- + +- Erster Schritt zeigt alle Optionen seiner Eigenschaft +- Folgeschritte zeigen nur kombinierbare Optionen +- Der Ablauf trägt beliebig viele Eigenschaften +- Reihenfolge der Schritte kommt aus dem Backend +- Ohne Auswahl greifen die Standardvarianten des Elternartikels +- Schritte ohne gültige Option werden übersprungen +- Eine Auswahl wechselt den Schritt nicht +- Ungültige Folgeauswahl fällt beim Wechsel weg +- Auf kleinen Bildschirmen bleibt der Ablauf derselbe +- Escape schließt den Konfigurator +- Tabulator bleibt im Dialog +---------------------------------------- + +Schritt öffnen + +Öffnet den Konfigurator beim angeklickten Schritt + +- LMB auf einen Schritt öffnet das Modal +- Offener Konfigurator wechselt nur den Schritt +- Modal hängt am Seitenkörper + +- Produktseite öffnen +- LMB auf zweiten Schritt +- Modal öffnet bei Schritt 2 +---------------------------------------- + +Option wählen + +Übernimmt eine Option in die laufende Auswahl + +- Gewählte Option ist hervorgehoben +- Nicht kombinierbare Optionen sind gesperrt +- Auswahl verwirft ungültige Folgeschritte +- Schritt bleibt nach der Wahl derselbe + +- Konfigurator öffnen +- LMB auf eine Option +- Option ist hervorgehoben +---------------------------------------- + +Nächsten Schritt anzeigen + +Führt zum nächsten Schritt mit gültigen Optionen + +- Weiter-Knopf heißt am letzten Schritt Fertig +- Leere Schritte werden übersprungen + +- Konfigurator öffnen +- LMB auf Weiter-Knopf +- Nächster Schritt erscheint +---------------------------------------- + +Vorherigen Schritt anzeigen + +Führt zurück zum letzten Schritt mit Optionen + +- Zurück-Knopf ist am ersten Schritt gesperrt +- Leere Schritte werden übersprungen + +- Zum zweiten Schritt gehen +- LMB auf Zurück-Knopf +- Erster Schritt erscheint +---------------------------------------- + +Auswahl übernehmen + +Wechselt das Produkt auf die gewählte Variante + +- Fertig überträgt die Auswahl in die Auswahlfelder +- Unbesuchte Schritte bekommen die erste gültige Option +- Shopware führt den Variantenwechsel aus + +- Alle Schritte durchgehen +- LMB auf Fertig-Knopf +- Produktseite zeigt die gewählte Variante +---------------------------------------- + +Konfigurator schließen + +Beendet die Auswahl ohne Wechsel der Variante + +- x-Icon schließt das Modal +- Escape schließt das Modal +- Fokus kehrt zum Auslöser zurück + +- Konfigurator öffnen +- Escape drücken +- Modal ist geschlossen +---------------------------------------- + +Konfigurationsdaten bereitstellen + +Legt der Produktseite alles bei, was der Konfigurator braucht + +- Kombinationen stammen vom Hauptartikel +- Ohne aktives Layout bleibt die Beilage aus + +- Produktseite mit aktivem Layout öffnen +- Seite trägt Kombinationen und Vorbelegung diff --git a/daten/MtoVariantConfigurator/.planung/vorschau-zeigen.md b/daten/MtoVariantConfigurator/.planung/vorschau-zeigen.md new file mode 100644 index 0000000..d4704fd --- /dev/null +++ b/daten/MtoVariantConfigurator/.planung/vorschau-zeigen.md @@ -0,0 +1,53 @@ + +Vorschau zeigen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde sieht Bild und Preis der gewählten Kombination +---------------------------------------- + +- Preis stimmt mit dem Preis der Produktseite überein +- Antwort wird nicht zwischengespeichert +- Späte Antworten überholter Anfragen werden verworfen +- Ohne eigene Bilder greifen die Bilder des Elternartikels +---------------------------------------- + +Vorschau laden + +Holt Bilder und Preis zur laufenden Auswahl + +- Jede Auswahl löst eine neue Anfrage aus +- Titelbild der Variante steht an erster Stelle +- Ohne Treffer bleibt die Produkt-ID als Rückfall + +- Konfigurator öffnen +- Andere Option wählen +- Bild und Preis ändern sich +---------------------------------------- + +Galerie blättern + +Zeigt weitere Bilder der gewählten Variante + +- Pfeil-Icons blättern vor +- Pfeil-Icons blättern zurück +- Nach dem letzten Bild folgt das erste +- Bei einem Bild bleibt die Navigation aus + +- Konfigurator öffnen +- LMB auf Vor-Icon +- Nächstes Bild erscheint +---------------------------------------- + +Bild wählen + +Wechselt das große Bild über die Vorschaubilder + +- Aktives Vorschaubild ist hervorgehoben +- Großes Bild folgt der Wahl + +- Konfigurator öffnen +- LMB auf drittes Vorschaubild +- Großes Bild zeigt dieses Motiv diff --git a/daten/MtoVariantConfigurator/.pruefung.json b/daten/MtoVariantConfigurator/.pruefung.json new file mode 100644 index 0000000..f578988 --- /dev/null +++ b/daten/MtoVariantConfigurator/.pruefung.json @@ -0,0 +1,537 @@ +{ + "abdeckung": { + "einbinden:VariantConfiguratorPlugin": { + "abdruck": "823481507a44729d", + "funktion": "Konfigurationsdaten bereitstellen", + "trug": "5fbc8363b7cffe59" + }, + "einbinden:erweitert @Storefront/storefront/component/buy-widget/configurator.html.twig": { + "abdruck": "c6d031d6bc598089", + "funktion": "Konfigurator aktivieren", + "trug": "6cf5a2b08ce2371a" + }, + "einbinden:override sw-product-detail-variants": { + "abdruck": "2fcf518e7333458a", + "funktion": "", + "trug": "" + }, + "einbinden:register mto-vc-variants-card": { + "abdruck": "c472feadaac5ac71", + "funktion": "", + "trug": "" + }, + "hoeren:[data-mto-vc-gallery-next].click": { + "abdruck": "c402ad6f114e8c3d", + "funktion": "Galerie blättern", + "trug": "bacf45ebf9dd77b8" + }, + "hoeren:[data-mto-vc-gallery-prev].click": { + "abdruck": "f50d4f7effc60a06", + "funktion": "Galerie blättern", + "trug": "bacf45ebf9dd77b8" + }, + "hoeren:[data-mto-vc-lightbox-close].click": { + "abdruck": "89a22850af7694bb", + "funktion": "Galerie blättern", + "trug": "bacf45ebf9dd77b8" + }, + "hoeren:document.keydown": { + "abdruck": "7c018ebbfa346bee", + "funktion": "Schritt öffnen", + "trug": "efe9634e3080c073" + }, + "hoeren:el.click": { + "abdruck": "6a423a062267755c", + "funktion": "Nächsten Schritt anzeigen", + "trug": "f6b276e3fedf287d" + }, + "hoeren:info.click": { + "abdruck": "7a5a70dfb792bf19", + "funktion": "Optionsdetail öffnen", + "trug": "39fed29af6734cd4" + }, + "hoeren:info.keydown": { + "abdruck": "409cecf6fb3bbb4a", + "funktion": "Optionsdetail öffnen", + "trug": "39fed29af6734cd4" + }, + "hoeren:lightboxSelect.click": { + "abdruck": "9add2d2c77b440b5", + "funktion": "Ansicht schließen", + "trug": "24d52cc6d249d4f5" + }, + "hoeren:next.click": { + "abdruck": "d5b0cdcce40afcff", + "funktion": "Konfigurator schließen", + "trug": "1cc1a6b5fc943e03" + }, + "hoeren:prev.click": { + "abdruck": "6b8db8d885c0d6f8", + "funktion": "Konfigurator schließen", + "trug": "1cc1a6b5fc943e03" + }, + "hoeren:row.click": { + "abdruck": "b4ec6f63c613c35f", + "funktion": "Option wählen", + "trug": "80df89cf0c129387" + }, + "hoeren:thumb.click": { + "abdruck": "b4aa2111971f6886", + "funktion": "Bild wählen", + "trug": "0604a0a6875489b8" + }, + "hoeren:trigger.click": { + "abdruck": "e219933925adc81a", + "funktion": "Schritt öffnen", + "trug": "efe9634e3080c073" + }, + "reaktion:ProductPageLoadedEvent": { + "abdruck": "6f808b91c1a0c4f5", + "funktion": "Konfigurationsdaten bereitstellen", + "trug": "5fbc8363b7cffe59" + }, + "route:get /mto-variant-configurator/resolve/{productId}": { + "abdruck": "b14355d6007564a1", + "funktion": "Konfigurationsdaten bereitstellen", + "trug": "5fbc8363b7cffe59" + } + }, + "belege": { + "[\"auswahl-anstossen\", \"Gewählte Option anzeigen\"]": { + "abdruck": "626af3ee300b610a", + "beleg": "\n {{ mtoVcSelected ? mtoVcSelected.translated.name : 'mto.variantConfigurator.choose'|trans }}\n ", + "datei": "src/Resources/views/storefront/component/buy-widget/configurator.html.twig" + }, + "[\"auswahl-anstossen\", \"Hinweistext anzeigen\"]": { + "abdruck": "b9baf394ca99d4e6", + "beleg": "{% if mtoVcBubble != mtoVcBubbleKey and mtoVcBubble is not empty %}\n

{{ mtoVcBubble|sw_sanitize }}

\n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/configurator.html.twig" + }, + "[\"auswahl-anstossen\", \"Schrittnummer anzeigen\"]": { + "abdruck": "b9e4deada2c3a6f1", + "beleg": "{{ 'mto.variantConfigurator.step'|trans({ '%step%': mtoVcStep })|sw_sanitize }}", + "datei": "src/Resources/views/storefront/component/buy-widget/configurator.html.twig" + }, + "[\"beratung-anbieten\", \"Beratung erreichen\"]": { + "abdruck": "fa513f8d265ad713", + "beleg": "{% if ctaPhone is not empty %}\n \n {{ ctaPhone|sw_sanitize }}\n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"beratung-anbieten\", \"Optionsübersicht öffnen\"]": { + "abdruck": "8aba7fb9bf50281b", + "beleg": "{% if pdfUrl %}\n \n {{ 'mto.variantConfigurator.allOptions'|trans|sw_sanitize }}\n \n {% else %}\n \n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"beratung-anbieten\", \"Vertrauen zeigen\"]": { + "abdruck": "5b204dff7de6f96d", + "beleg": "{% if trustLogo %}\n \"\"\n{% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"layout-zuweisen\", \"Konfigurator aktivieren\"]": { + "abdruck": "60a65511f06ae7fe", + "beleg": "", + "datei": "src/Resources/app/administration/src/component/mto-vc-variants-card/mto-vc-variants-card.html.twig" + }, + "[\"layout-zuweisen\", \"Optionsübersicht hinterlegen\"]": { + "abdruck": "97b421cf540a6cc2", + "beleg": "{% if pdfUrl %}\n \n {{ 'mto.variantConfigurator.allOptions'|trans|sw_sanitize }}\n \n {% else %}\n \n {% endif %}", + "datei": "src/Resources/views/storefront/component/buy-widget/mto-variant-configurator-modal.html.twig" + }, + "[\"layout-zuweisen\", \"Trust-Logo hinterlegen\"]": { + "abdruck": "1954311a4c3a9cc1", + "beleg": "$mediaId = $this->systemConfigService->get(\n MtoVariantConfigurator::CONFIG_TRUST_LOGO,\n $salesChannelId,\n );", + "datei": "src/Core/Content/Product/VariantResolveService.php" + }, + "[\"option-ansehen\", \"Ansicht schließen\"]": { + "abdruck": "6eac493d9a481e30", + "beleg": "if (!this._nodes.lightbox.hidden) {\n this._closeLightbox();\n } else {\n this._close();\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"option-ansehen\", \"Option aus Ansicht wählen\"]": { + "abdruck": "b4223f8cf3e2456e", + "beleg": "this._nodes.lightboxSelect?.addEventListener('click', () => {\n if (this._lightboxOption) {\n this._selectOption(this.options.groups[this._currentStep], this._lightboxOption.id);\n }\n this._closeLightbox();\n });", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"option-ansehen\", \"Optionsdetail öffnen\"]": { + "abdruck": "59faab581e0fac7f", + "beleg": "info.addEventListener('click', open);\n info.addEventListener('keydown', (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n open(event);\n }\n });", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"schritt-zeigen\", \"Eigenschaft benennen\"]": { + "abdruck": "dd54064a67689e2c", + "beleg": "this._nodes.title.textContent = group.name;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"schritt-zeigen\", \"Optionen auflisten\"]": { + "abdruck": "a71af321f056608d", + "beleg": "if (option.media) {\n const visual = document.createElement('span');\n visual.className = 'mto-vc-option-media';\n const img = document.createElement('img');\n img.src = option.media;\n img.alt = '';\n img.loading = 'lazy';\n visual.appendChild(img);\n row.appendChild(visual);\n } else if (option.color) {\n const visual = document.createElement('span');\n visual.className = 'mto-vc-option-swatch';\n visual.style.backgroundColor = option.color;\n row.appendChild(visual);\n } else {\n row.classList.add('has-no-visual');\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"schritt-zeigen\", \"Schrittstand anzeigen\"]": { + "abdruck": "aa7b8888103f8bd0", + "beleg": "this._nodes.counter.textContent = (this._snippets.stepCount || '__step__ / __total__')\n .replace('__step__', String(step))\n .replace('__total__', String(total));\n this._nodes.progress.style.width = `${(step / total) * 100}%`;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Auswahl übernehmen\"]": { + "abdruck": "21ccf5bc0286c95c", + "beleg": "if (optionId && select.value !== optionId) {\n select.value = optionId;\n lastChanged = select;\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Konfigurationsdaten bereitstellen\"]": { + "abdruck": "e6e5848381fce5aa", + "beleg": "$page->assign([", + "datei": "src/Subscriber/ProductPageSubscriber.php" + }, + "[\"varianten-waehlen\", \"Konfigurator schließen\"]": { + "abdruck": "1b7d4aea18cdb896", + "beleg": "_close() {\n this._closeLightbox();\n this._modalEl.hidden = true;\n document.body.classList.remove('mto-vc-modal-open');\n document.removeEventListener('keydown', this._keydownHandler);\n this._lastFocus?.focus();\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Nächsten Schritt anzeigen\"]": { + "abdruck": "3deee97595984a3e", + "beleg": "const isLast = this._nextUsableStep(this._currentStep + 1, 1) === null;\n this._nodes.next.textContent = isLast\n ? this._nodes.next.dataset.finishLabel\n : this._nodes.next.dataset.nextLabel;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Option wählen\"]": { + "abdruck": "4b9f7dc844cf7aac", + "beleg": "this._selected[group.id] = optionId;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Schritt öffnen\"]": { + "abdruck": "94b3aa8d50c53fc8", + "beleg": "this._triggers.forEach((trigger) => {\n trigger.addEventListener('click', (event) => {\n event.preventDefault();\n this._open(parseInt(trigger.dataset.mtoVcStepIndex, 10));\n });\n });", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"varianten-waehlen\", \"Vorherigen Schritt anzeigen\"]": { + "abdruck": "df5e60fe148da5e6", + "beleg": "this._nodes.prev.disabled = this._nextUsableStep(this._currentStep - 1, -1) === null;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"vorschau-zeigen\", \"Bild wählen\"]": { + "abdruck": "ab1e74251036541a", + "beleg": "thumb.className = `mto-vc-thumb${index === this._galleryIndex ? ' is-active' : ''}`;", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"vorschau-zeigen\", \"Galerie blättern\"]": { + "abdruck": "6b28a5866629b878", + "beleg": "_stepGallery(delta) {\n if (this._gallery.length < 2) {\n return;\n }\n const count = this._gallery.length;\n this._galleryIndex = (this._galleryIndex + delta + count) % count;\n this._renderGallery();\n }", + "datei": "src/Resources/app/storefront/src/js/variant-configurator.plugin.js" + }, + "[\"vorschau-zeigen\", \"Vorschau laden\"]": { + "abdruck": "413024bc244f7770", + "beleg": "return new JsonResponse($this->variantResolveService->resolveVariant($variantId, $context));", + "datei": "src/Storefront/Controller/VariantConfiguratorController.php" + } + }, + "ohne_code": {}, + "ohne_karte": {}, + "paare": { + "[\"[\\\"auswahl-anstossen\\\", \\\"Gewählte Option anzeigen\\\"]\", \"[\\\"auswahl-anstossen\\\", \\\"Hinweistext anzeigen\\\"]\"]": { + "abdruck": "450345e8a27f5695", + "gleich": false + }, + "[\"[\\\"auswahl-anstossen\\\", \\\"Gewählte Option anzeigen\\\"]\", \"[\\\"auswahl-anstossen\\\", \\\"Schrittnummer anzeigen\\\"]\"]": { + "abdruck": "60008fdb6d69349b", + "gleich": false + }, + "[\"[\\\"auswahl-anstossen\\\", \\\"Hinweistext anzeigen\\\"]\", \"[\\\"auswahl-anstossen\\\", \\\"Schrittnummer anzeigen\\\"]\"]": { + "abdruck": "3eaf19062d6d53a3", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Beratung erreichen\\\"]\", \"[\\\"beratung-anbieten\\\", \\\"Optionsübersicht öffnen\\\"]\"]": { + "abdruck": "9d3da3bf8c127ae1", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Beratung erreichen\\\"]\", \"[\\\"beratung-anbieten\\\", \\\"Vertrauen zeigen\\\"]\"]": { + "abdruck": "2c3c62cb4b935c56", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Optionsübersicht öffnen\\\"]\", \"[\\\"beratung-anbieten\\\", \\\"Vertrauen zeigen\\\"]\"]": { + "abdruck": "bf601d5dc7c6c507", + "gleich": false + }, + "[\"[\\\"beratung-anbieten\\\", \\\"Optionsübersicht öffnen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\"]": { + "abdruck": "bc9dc09e54b78a75", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Konfigurator aktivieren\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsbild am Datensatz pflegen\\\"]\"]": { + "abdruck": "5a4d802d668ddd55", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Konfigurator aktivieren\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\"]": { + "abdruck": "eeed78a6284711f1", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Konfigurator aktivieren\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Trust-Logo hinterlegen\\\"]\"]": { + "abdruck": "b4944e5aa4df871a", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Optionsbild am Datensatz pflegen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\"]": { + "abdruck": "b91bdff82a120a8d", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Optionsbild am Datensatz pflegen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Trust-Logo hinterlegen\\\"]\"]": { + "abdruck": "97268714e2b5d989", + "gleich": false + }, + "[\"[\\\"layout-zuweisen\\\", \\\"Optionsübersicht hinterlegen\\\"]\", \"[\\\"layout-zuweisen\\\", \\\"Trust-Logo hinterlegen\\\"]\"]": { + "abdruck": "b52cedd4106ee837", + "gleich": false + }, + "[\"[\\\"option-ansehen\\\", \\\"Ansicht schließen\\\"]\", \"[\\\"option-ansehen\\\", \\\"Option aus Ansicht wählen\\\"]\"]": { + "abdruck": "caa5ce4c5ff31774", + "gleich": false + }, + "[\"[\\\"option-ansehen\\\", \\\"Ansicht schließen\\\"]\", \"[\\\"option-ansehen\\\", \\\"Optionsdetail öffnen\\\"]\"]": { + "abdruck": "462a46d7a2030874", + "gleich": false + }, + "[\"[\\\"option-ansehen\\\", \\\"Option aus Ansicht wählen\\\"]\", \"[\\\"option-ansehen\\\", \\\"Optionsdetail öffnen\\\"]\"]": { + "abdruck": "8f695dfd90060204", + "gleich": false + }, + "[\"[\\\"schritt-zeigen\\\", \\\"Eigenschaft benennen\\\"]\", \"[\\\"schritt-zeigen\\\", \\\"Optionen auflisten\\\"]\"]": { + "abdruck": "5372df6b482e9a5c", + "gleich": false + }, + "[\"[\\\"schritt-zeigen\\\", \\\"Eigenschaft benennen\\\"]\", \"[\\\"schritt-zeigen\\\", \\\"Schrittstand anzeigen\\\"]\"]": { + "abdruck": "732d371c2135b53f", + "gleich": false + }, + "[\"[\\\"schritt-zeigen\\\", \\\"Optionen auflisten\\\"]\", \"[\\\"schritt-zeigen\\\", \\\"Schrittstand anzeigen\\\"]\"]": { + "abdruck": "590d6974e948c69c", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\"]": { + "abdruck": "34e23fca918e5dc0", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\"]": { + "abdruck": "eb521941a5dc979a", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\"]": { + "abdruck": "271109c8b42cf5d5", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "618d3c213492555a", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "b45252ce7cc39ed9", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Auswahl übernehmen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "d7ade9bdd7d0c66e", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\"]": { + "abdruck": "97ceded85ca2035c", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\"]": { + "abdruck": "ba83ab596b72af22", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "6f23248b5fbd7be4", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "7350e93a2a368ac1", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurationsdaten bereitstellen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "50753ef9f3d5c8b5", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\"]": { + "abdruck": "b49e65e1c60b5307", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "b165f28b36fc3637", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "0bf509fed71f1c25", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Konfigurator schließen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "de5acdbf92511e14", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\"]": { + "abdruck": "7c9a06867c701267", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "f45378da83876bae", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Nächsten Schritt anzeigen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "9fc4c9cf8ae1d7fb", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\"]": { + "abdruck": "a71f8b8b92d1025c", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Option wählen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "e3270a7176c63620", + "gleich": false + }, + "[\"[\\\"varianten-waehlen\\\", \\\"Schritt öffnen\\\"]\", \"[\\\"varianten-waehlen\\\", \\\"Vorherigen Schritt anzeigen\\\"]\"]": { + "abdruck": "44e775b8e8b106d1", + "gleich": false + }, + "[\"[\\\"vorschau-zeigen\\\", \\\"Bild wählen\\\"]\", \"[\\\"vorschau-zeigen\\\", \\\"Galerie blättern\\\"]\"]": { + "abdruck": "19851d2901c309a1", + "gleich": false + }, + "[\"[\\\"vorschau-zeigen\\\", \\\"Bild wählen\\\"]\", \"[\\\"vorschau-zeigen\\\", \\\"Vorschau laden\\\"]\"]": { + "abdruck": "508415e6500f9fca", + "gleich": false + }, + "[\"[\\\"vorschau-zeigen\\\", \\\"Galerie blättern\\\"]\", \"[\\\"vorschau-zeigen\\\", \\\"Vorschau laden\\\"]\"]": { + "abdruck": "86aa1f412d5a5dcd", + "gleich": false + } + }, + "stil": { + "[\"auswahl-anstossen\", \"\"]": { + "abdruck": "aeec25973dafe92f", + "probleme": [] + }, + "[\"auswahl-anstossen\", \"Gewählte Option anzeigen\"]": { + "abdruck": "59058982f7989af8", + "probleme": [] + }, + "[\"auswahl-anstossen\", \"Hinweistext anzeigen\"]": { + "abdruck": "b3568e0a2585d71c", + "probleme": [] + }, + "[\"auswahl-anstossen\", \"Schrittnummer anzeigen\"]": { + "abdruck": "117d58f0d4b21973", + "probleme": [] + }, + "[\"beratung-anbieten\", \"\"]": { + "abdruck": "4b0267b165360857", + "probleme": [] + }, + "[\"beratung-anbieten\", \"Beratung erreichen\"]": { + "abdruck": "cfdb65d682c3e068", + "probleme": [] + }, + "[\"beratung-anbieten\", \"Optionsübersicht öffnen\"]": { + "abdruck": "28d5587c78199c54", + "probleme": [] + }, + "[\"beratung-anbieten\", \"Vertrauen zeigen\"]": { + "abdruck": "8c00dec8d3ebf751", + "probleme": [] + }, + "[\"layout-zuweisen\", \"\"]": { + "abdruck": "1e0d2ca5296aabea", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Konfigurator aktivieren\"]": { + "abdruck": "dca9bbf7361f5520", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Optionsbild am Datensatz pflegen\"]": { + "abdruck": "cc0701aafd02ac3a", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Optionsübersicht hinterlegen\"]": { + "abdruck": "de6c0e3e80d47496", + "probleme": [] + }, + "[\"layout-zuweisen\", \"Trust-Logo hinterlegen\"]": { + "abdruck": "ebd1a72ece157e69", + "probleme": [] + }, + "[\"option-ansehen\", \"\"]": { + "abdruck": "ace46c77101e26b3", + "probleme": [] + }, + "[\"option-ansehen\", \"Ansicht schließen\"]": { + "abdruck": "6bdaf5e60fb3baa9", + "probleme": [] + }, + "[\"option-ansehen\", \"Option aus Ansicht wählen\"]": { + "abdruck": "cc10af5dda4a7857", + "probleme": [] + }, + "[\"option-ansehen\", \"Optionsdetail öffnen\"]": { + "abdruck": "e00d07ce7b75d8fc", + "probleme": [] + }, + "[\"schritt-zeigen\", \"\"]": { + "abdruck": "f0d53ef421968759", + "probleme": [] + }, + "[\"schritt-zeigen\", \"Eigenschaft benennen\"]": { + "abdruck": "ec4828e2e9197083", + "probleme": [] + }, + "[\"schritt-zeigen\", \"Optionen auflisten\"]": { + "abdruck": "d8e6daed0f36098f", + "probleme": [] + }, + "[\"schritt-zeigen\", \"Schrittstand anzeigen\"]": { + "abdruck": "42a1c7f94c30f72d", + "probleme": [] + }, + "[\"varianten-waehlen\", \"\"]": { + "abdruck": "0835908894fa892c", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Auswahl übernehmen\"]": { + "abdruck": "6683956c63370244", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Konfigurationsdaten bereitstellen\"]": { + "abdruck": "498f3141e86f8db0", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Konfigurator schließen\"]": { + "abdruck": "866918b327061449", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Nächsten Schritt anzeigen\"]": { + "abdruck": "8d810a760dfec037", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Option wählen\"]": { + "abdruck": "ac4eae399ac3a15e", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Schritt öffnen\"]": { + "abdruck": "40f795456747214e", + "probleme": [] + }, + "[\"varianten-waehlen\", \"Vorherigen Schritt anzeigen\"]": { + "abdruck": "a63a26a8baea9c07", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"\"]": { + "abdruck": "52976631fd09993a", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"Bild wählen\"]": { + "abdruck": "a3e980ef7678a446", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"Galerie blättern\"]": { + "abdruck": "47ccb441120c1470", + "probleme": [] + }, + "[\"vorschau-zeigen\", \"Vorschau laden\"]": { + "abdruck": "29e5951f170dba26", + "probleme": [] + } + }, + "verworfen": {} +} diff --git a/daten/MtoVariantConfigurator/auswahl-anstossen.md b/daten/MtoVariantConfigurator/auswahl-anstossen.md new file mode 100644 index 0000000..665f2fa --- /dev/null +++ b/daten/MtoVariantConfigurator/auswahl-anstossen.md @@ -0,0 +1,49 @@ + +Auswahl anstoßen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde erkennt in der Buybox die Reihenfolge der Schritte +---------------------------------------- + +- Jede Eigenschaft bildet einen eigenen Schritt +- Natives Auswahlfeld bleibt für den Variantenwechsel erhalten +- Eigene Darstellung gilt unabhängig vom Anzeigetyp der Eigenschaft +- Ohne aktives Layout erscheint die Standard-Buybox +---------------------------------------- + +Schrittnummer anzeigen + +Zeigt neben jeder Eigenschaft ihre Position im Ablauf + +- Beschriftung nennt das Wort Schritt und die Nummer +- Nummer folgt der Reihenfolge aus dem Backend + +- Produktseite öffnen +- Erste Eigenschaft zeigt Schritt 1 +---------------------------------------- + +Hinweistext anzeigen + +Erklärt dem Kunden, worauf er im Schritt achtet + +- Text kommt aus einem Textbaustein je Schritt +- Leerer Textbaustein blendet den Hinweis aus +- Hinweis hängt an der Nummer statt an der Eigenschaft + +- Textbaustein für Schritt 1 füllen +- Produktseite öffnen +- Hinweis steht unter der Überschrift +---------------------------------------- + +Gewählte Option anzeigen + +Zeigt am Schritt, welche Option gerade gilt + +- Ohne Auswahl steht dort Bitte wählen +- Vorbelegung erscheint ohne Zutun des Kunden + +- Hauptartikel ohne Variante öffnen +- Jeder Schritt nennt eine Option diff --git a/daten/MtoVariantConfigurator/beratung-anbieten.md b/daten/MtoVariantConfigurator/beratung-anbieten.md new file mode 100644 index 0000000..c0beeb5 --- /dev/null +++ b/daten/MtoVariantConfigurator/beratung-anbieten.md @@ -0,0 +1,47 @@ + +Beratung anbieten +---------------------------------------- + +optional +---------------------------------------- + +Der Kunde findet im Konfigurator Vertrauen und einen Kontakt +---------------------------------------- + +- Alle Texte kommen aus Textbausteinen +- Leerer Textbaustein blendet den Bereich aus +---------------------------------------- + +Vertrauen zeigen + +Zeigt Siegel und Zusage neben dem Gesamtpreis + +- Logo stammt aus der Plugin-Konfiguration +- Ohne Logo bleibt der Text stehen + +- Konfigurator öffnen +- Siegel steht neben dem Preis +---------------------------------------- + +Beratung erreichen + +Bietet eine Telefonnummer für Fragen zur Konfiguration + +- Nummer ist als Telefonlink klickbar +- Leere Nummer blendet den Bereich aus + +- Konfigurator öffnen +- LMB auf die Nummer +- Telefon-App öffnet sich +---------------------------------------- + +Optionsübersicht öffnen + +Öffnet das hinterlegte PDF mit allen Optionen + +- Knopf erscheint nur mit hinterlegtem PDF +- PDF öffnet in einem neuen Tab + +- Konfigurator öffnen +- LMB auf Optionen-Knopf +- PDF öffnet in neuem Tab diff --git a/daten/MtoVariantConfigurator/layout-zuweisen.md b/daten/MtoVariantConfigurator/layout-zuweisen.md new file mode 100644 index 0000000..1e06c7a --- /dev/null +++ b/daten/MtoVariantConfigurator/layout-zuweisen.md @@ -0,0 +1,69 @@ + +Layout zuweisen +---------------------------------------- + +kern +---------------------------------------- + +Ein Händler entscheidet je Produkt, ob die geführte Auswahl erscheint +---------------------------------------- + +- Einstellungen liegen auf dem Varianten-Tab des Produkts +- Werte stehen in den customFields des Produkts +- Bearbeiten erfordert das Recht product.editor +- Ohne Zuweisung bleibt das Standardlayout aktiv +---------------------------------------- + +Konfigurator aktivieren + +Schaltet die geführte Variantenauswahl für ein Produkt frei + +- Schalter steht auf dem Varianten-Tab +- Aktiv ersetzt die Buybox des Produkts +- Inaktiv zeigt das Standardlayout von Shopware + +- Produkt im Admin öffnen +- Varianten-Tab öffnen +- Schalter aktivieren und speichern +- Buybox zeigt die geführte Auswahl +---------------------------------------- + +Optionsübersicht hinterlegen + +Hinterlegt ein PDF mit allen Varianten und Kombinationen + +- Medienfeld steht auf dem Varianten-Tab +- Feld hängt am Hauptartikel +- Ohne PDF bleibt der Knopf unsichtbar + +- Varianten-Tab öffnen +- PDF im Medienfeld wählen +- Produkt speichern +- Modal zeigt den Knopf für Optionen +---------------------------------------- + +Trust-Logo hinterlegen + +Zeigt ein Vertrauenssiegel neben dem Gesamtpreis + +- Logo steht in der Plugin-Konfiguration +- Gilt für den ganzen Verkaufskanal +- Ohne Logo erscheint nur der Text + +- Plugin-Konfiguration öffnen +- Logo im Medienfeld wählen +- Modal zeigt das Logo am Preis +---------------------------------------- + +Optionsbild am Datensatz pflegen + +offen + +Hinterlegt das Bild einer Option am Datensatz der Variante + +- Feld liegt im Formular der einzelnen Variante +- Heute stammt das Bild aus der Eigenschaftsgruppe + +- Variante im Admin öffnen +- Bildfeld der Variante füllen +- Variante speichern diff --git a/daten/MtoVariantConfigurator/option-ansehen.md b/daten/MtoVariantConfigurator/option-ansehen.md new file mode 100644 index 0000000..bda54d3 --- /dev/null +++ b/daten/MtoVariantConfigurator/option-ansehen.md @@ -0,0 +1,51 @@ + +Option ansehen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde prüft eine Option groß, bevor er sie nimmt +---------------------------------------- + +- Nur Optionen mit Bild tragen den Hinweis +- Ansicht liegt über dem Konfigurator +---------------------------------------- + +Optionsdetail öffnen + +Zeigt Bild und Namen einer Option in voller Größe + +- i-Icon öffnet die Ansicht +- Enter öffnet die Ansicht +- Leertaste öffnet die Ansicht + +- Konfigurator öffnen +- LMB auf i-Icon einer Option +- Große Ansicht erscheint +---------------------------------------- + +Option aus Ansicht wählen + +Übernimmt die betrachtete Option in die Auswahl + +- Knopf übernimmt die Option +- Knopf schließt die Ansicht +- Schritt bleibt derselbe + +- Optionsdetail öffnen +- LMB auf Wählen-Knopf +- Option ist gewählt +---------------------------------------- + +Ansicht schließen + +Kehrt zur Optionsliste zurück ohne Auswahl + +- x-Icon schließt die Ansicht +- Escape schließt die Ansicht +- Konfigurator bleibt offen + +- Optionsdetail öffnen +- Escape drücken +- Optionsliste erscheint wieder diff --git a/daten/MtoVariantConfigurator/schritt-zeigen.md b/daten/MtoVariantConfigurator/schritt-zeigen.md new file mode 100644 index 0000000..3ceb620 --- /dev/null +++ b/daten/MtoVariantConfigurator/schritt-zeigen.md @@ -0,0 +1,49 @@ + +Schritt zeigen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde weiß im Modal, wo er steht und was er wählt +---------------------------------------- + +- Optionen stehen rechts +- Bilder links +- Lange Optionslisten lassen sich scrollen +---------------------------------------- + +Eigenschaft benennen + +Zeigt den Namen der Eigenschaft des aktuellen Schritts + +- Name steht als Überschrift über der Liste +- Name kommt aus der Eigenschaftsgruppe + +- Konfigurator öffnen +- Überschrift nennt die erste Eigenschaft +---------------------------------------- + +Schrittstand anzeigen + +Zeigt den aktuellen Schritt und die Gesamtzahl + +- Zähler nennt Schritt und Gesamtzahl +- Balken wächst mit dem Fortschritt +- Text kommt aus einem Textbaustein + +- Konfigurator öffnen +- Zähler zeigt 1 von 3 +---------------------------------------- + +Optionen auflisten + +Zeigt alle Optionen der Eigenschaft mit Namen und Bild + +- Jede Option nennt ihren Namen +- Bild erscheint nur bis zwei Schritte +- Ohne Bild erscheint der Farbwert +- Ohne Farbwert bleibt die Zeile ohne Zeichen + +- Konfigurator öffnen +- Jede Option zeigt ihren Namen diff --git a/daten/MtoVariantConfigurator/varianten-waehlen.md b/daten/MtoVariantConfigurator/varianten-waehlen.md new file mode 100644 index 0000000..c732ab7 --- /dev/null +++ b/daten/MtoVariantConfigurator/varianten-waehlen.md @@ -0,0 +1,109 @@ + +Varianten wählen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde findet Schritt für Schritt eine bestellbare Kombination +---------------------------------------- + +- Erster Schritt zeigt alle Optionen seiner Eigenschaft +- Folgeschritte zeigen nur kombinierbare Optionen +- Der Ablauf trägt beliebig viele Eigenschaften +- Reihenfolge der Schritte kommt aus dem Backend +- Ohne Auswahl greifen die Standardvarianten des Elternartikels +- Schritte ohne gültige Option werden übersprungen +- Eine Auswahl wechselt den Schritt nicht +- Ungültige Folgeauswahl fällt beim Wechsel weg +- Auf kleinen Bildschirmen bleibt der Ablauf derselbe +- Escape schließt den Konfigurator +- Tabulator bleibt im Dialog +---------------------------------------- + +Schritt öffnen + +Öffnet den Konfigurator beim angeklickten Schritt + +- LMB auf einen Schritt öffnet das Modal +- Offener Konfigurator wechselt nur den Schritt +- Modal hängt am Seitenkörper + +- Produktseite öffnen +- LMB auf zweiten Schritt +- Modal öffnet bei Schritt 2 +---------------------------------------- + +Option wählen + +Übernimmt eine Option in die laufende Auswahl + +- Gewählte Option ist hervorgehoben +- Nicht kombinierbare Optionen sind gesperrt +- Auswahl verwirft ungültige Folgeschritte +- Schritt bleibt nach der Wahl derselbe + +- Konfigurator öffnen +- LMB auf eine Option +- Option ist hervorgehoben +---------------------------------------- + +Nächsten Schritt anzeigen + +Führt zum nächsten Schritt mit gültigen Optionen + +- Weiter-Knopf heißt am letzten Schritt Fertig +- Leere Schritte werden übersprungen + +- Konfigurator öffnen +- LMB auf Weiter-Knopf +- Nächster Schritt erscheint +---------------------------------------- + +Vorherigen Schritt anzeigen + +Führt zurück zum letzten Schritt mit Optionen + +- Zurück-Knopf ist am ersten Schritt gesperrt +- Leere Schritte werden übersprungen + +- Zum zweiten Schritt gehen +- LMB auf Zurück-Knopf +- Erster Schritt erscheint +---------------------------------------- + +Auswahl übernehmen + +Wechselt das Produkt auf die gewählte Variante + +- Fertig überträgt die Auswahl in die Auswahlfelder +- Unbesuchte Schritte bekommen die erste gültige Option +- Shopware führt den Variantenwechsel aus + +- Alle Schritte durchgehen +- LMB auf Fertig-Knopf +- Produktseite zeigt die gewählte Variante +---------------------------------------- + +Konfigurator schließen + +Beendet die Auswahl ohne Wechsel der Variante + +- x-Icon schließt das Modal +- Escape schließt das Modal +- Fokus kehrt zum Auslöser zurück + +- Konfigurator öffnen +- Escape drücken +- Modal ist geschlossen +---------------------------------------- + +Konfigurationsdaten bereitstellen + +Legt der Produktseite alles bei, was der Konfigurator braucht + +- Kombinationen stammen vom Hauptartikel +- Ohne aktives Layout bleibt die Beilage aus + +- Produktseite mit aktivem Layout öffnen +- Seite trägt Kombinationen und Vorbelegung diff --git a/daten/MtoVariantConfigurator/vorschau-zeigen.md b/daten/MtoVariantConfigurator/vorschau-zeigen.md new file mode 100644 index 0000000..d4704fd --- /dev/null +++ b/daten/MtoVariantConfigurator/vorschau-zeigen.md @@ -0,0 +1,53 @@ + +Vorschau zeigen +---------------------------------------- + +kern +---------------------------------------- + +Der Kunde sieht Bild und Preis der gewählten Kombination +---------------------------------------- + +- Preis stimmt mit dem Preis der Produktseite überein +- Antwort wird nicht zwischengespeichert +- Späte Antworten überholter Anfragen werden verworfen +- Ohne eigene Bilder greifen die Bilder des Elternartikels +---------------------------------------- + +Vorschau laden + +Holt Bilder und Preis zur laufenden Auswahl + +- Jede Auswahl löst eine neue Anfrage aus +- Titelbild der Variante steht an erster Stelle +- Ohne Treffer bleibt die Produkt-ID als Rückfall + +- Konfigurator öffnen +- Andere Option wählen +- Bild und Preis ändern sich +---------------------------------------- + +Galerie blättern + +Zeigt weitere Bilder der gewählten Variante + +- Pfeil-Icons blättern vor +- Pfeil-Icons blättern zurück +- Nach dem letzten Bild folgt das erste +- Bei einem Bild bleibt die Navigation aus + +- Konfigurator öffnen +- LMB auf Vor-Icon +- Nächstes Bild erscheint +---------------------------------------- + +Bild wählen + +Wechselt das große Bild über die Vorschaubilder + +- Aktives Vorschaubild ist hervorgehoben +- Großes Bild folgt der Wahl + +- Konfigurator öffnen +- LMB auf drittes Vorschaubild +- Großes Bild zeigt dieses Motiv diff --git a/daten/PLANER2GEN/.pruefung.json b/daten/PLANER2GEN/.pruefung.json new file mode 100644 index 0000000..fa7e340 --- /dev/null +++ b/daten/PLANER2GEN/.pruefung.json @@ -0,0 +1,1024 @@ +{ + "abdeckung": { + "bedienen:ablehnen": { + "abdruck": "e9cce25d92b81ff6", + "funktion": "Vorschlag übernehmen", + "trug": "623a7051f333b927" + }, + "bedienen:alleAblehnen": { + "abdruck": "ac9262c7cafe9537", + "funktion": "Alle Vorschläge verwerfen", + "trug": "ebd934ac7bd2fd98" + }, + "bedienen:alleAnnehmen": { + "abdruck": "4d75c7726bfa3495", + "funktion": "Alle Vorschläge annehmen", + "trug": "b10259f43d181352" + }, + "bedienen:annehmen": { + "abdruck": "2742ad031b3d3cca", + "funktion": "Vorschlag verwerfen", + "trug": "3cb8a045b150b0f4" + }, + "bedienen:auswaehlen": { + "abdruck": "d061bf62466085ce", + "funktion": "Projekt auswählen", + "trug": "2ea2bcb2d50dfcdc" + }, + "bedienen:bereichsMenue": { + "abdruck": "4277536d43c7bcd5", + "funktion": "Feature anlegen", + "trug": "df125001c2129150" + }, + "bedienen:bestaetigen": { + "abdruck": "db1f954b9ad01749", + "funktion": "Eingabe bestätigen", + "trug": "fc9047b1df0fc4a4" + }, + "bedienen:erledige": { + "abdruck": "1b80ae13958bb11a", + "funktion": "Vorschlag übernehmen", + "trug": "623a7051f333b927" + }, + "bedienen:funktionsMenue": { + "abdruck": "bacdd0a7cc9d0f92", + "funktion": "Funktion nach oben bewegen", + "trug": "df54203089276209" + }, + "bedienen:karteAnnehmen": { + "abdruck": "bf348251763e402a", + "funktion": "Vorschlag übernehmen", + "trug": "623a7051f333b927" + }, + "bedienen:kartenMenue": { + "abdruck": "d3ba136a562eb1e9", + "funktion": "", + "trug": "" + }, + "bedienen:leeren": { + "abdruck": "f2af432a5ae3b255", + "funktion": "Chat leeren", + "trug": "ad6f39b2df93ae9d" + }, + "bedienen:leistenMenue": { + "abdruck": "ed951fbeaaa9bc70", + "funktion": "Projekt erstellen", + "trug": "8cfce050cfef424d" + }, + "bedienen:oeffneChat": { + "abdruck": "7fc878caea678882", + "funktion": "Chat öffnen", + "trug": "449b8c9136c0c593" + }, + "bedienen:projektMenue": { + "abdruck": "ea73f8c2597c0443", + "funktion": "Projektmenü öffnen", + "trug": "03a14d06cae6f470" + }, + "bedienen:schliesse": { + "abdruck": "919b104c012c034d", + "funktion": "Panel schließen", + "trug": "24e867bc1277dd05" + }, + "bedienen:schliessen": { + "abdruck": "1e12f9ae001e93e1", + "funktion": "Chat leeren", + "trug": "ad6f39b2df93ae9d" + }, + "bedienen:senden": { + "abdruck": "8df3402ed3373acc", + "funktion": "Nachricht senden", + "trug": "0065319137cd6852" + }, + "bedienen:springe": { + "abdruck": "0b134efa50c03bff", + "funktion": "Fehlerstelle anzeigen", + "trug": "453d3d6f073b279b" + }, + "bedienen:starte": { + "abdruck": "761c2f62c917a3db", + "funktion": "Feature bearbeiten", + "trug": "69af0692497e5bfd" + }, + "bedienen:startePruefung": { + "abdruck": "b31edc2e13f73aa1", + "funktion": "Prüfung starten", + "trug": "28b659d9245434ad" + }, + "bedienen:umbenennen": { + "abdruck": "6185b6b39708bf02", + "funktion": "Projekt umbenennen", + "trug": "b173e09e1f84276f" + }, + "bedienen:wechsleAnsicht": { + "abdruck": "e3193fce50eaa58e", + "funktion": "Ansicht wechseln", + "trug": "49670ec2cf4bafa6" + }, + "bedienen:wechsleArt": { + "abdruck": "67250a1e8d82e960", + "funktion": "Badge umschalten", + "trug": "4369915490203cfc" + }, + "bedienen:wechsleDarkMode": { + "abdruck": "b83524eb0e12a7d7", + "funktion": "Darkmode umschalten", + "trug": "10c8c8aea8a9dcb5" + }, + "bedienen:wechsleStand": { + "abdruck": "8c2e3bf3be58ec00", + "funktion": "Funktionsstand wechseln", + "trug": "eba0447774607720" + }, + "bedienen:zurueck": { + "abdruck": "e378014fbce96d10", + "funktion": "Aktion rückgängig machen", + "trug": "3527aa90cc51d6ac" + }, + "hoeren:systemDunkel.change": { + "abdruck": "d3ef681b987557dc", + "funktion": "Darkmode umschalten", + "trug": "10c8c8aea8a9dcb5" + }, + "hoeren:window.click": { + "abdruck": "620812522ed2d900", + "funktion": "Kontextmenü verbergen", + "trug": "ae4fafc64d2c9eca" + }, + "hoeren:window.keydown": { + "abdruck": "c3e1df2d60fcc067", + "funktion": "Aktion rückgängig machen", + "trug": "3527aa90cc51d6ac" + }, + "menue:+ Feature erstellen": { + "abdruck": "82c40072137d5757", + "funktion": "Feature anlegen", + "trug": "df125001c2129150" + }, + "menue:+ Funktion erstellen": { + "abdruck": "b44457d64a5ec9d1", + "funktion": "Funktion anlegen", + "trug": "90e0b650ae301b45" + }, + "menue:+ Projekt erstellen": { + "abdruck": "2be770390433a2ce", + "funktion": "Projekt erstellen", + "trug": "8cfce050cfef424d" + }, + "menue:+ Vision erstellen": { + "abdruck": "cb22a654070e58b4", + "funktion": "Feature anlegen", + "trug": "df125001c2129150" + }, + "menue:→ Feature verschieben": { + "abdruck": "38e6b244668ee164", + "funktion": "Funktion anlegen", + "trug": "90e0b650ae301b45" + }, + "menue:▲ Nach oben": { + "abdruck": "4e6fd1617d817357", + "funktion": "Funktion nach oben bewegen", + "trug": "df54203089276209" + }, + "menue:▼ Nach unten": { + "abdruck": "183651450e546c4f", + "funktion": "Funktion nach oben bewegen", + "trug": "df54203089276209" + }, + "menue:◇ Quelle festlegen": { + "abdruck": "e4bb1781bc375d6d", + "funktion": "Projektmenü öffnen", + "trug": "03a14d06cae6f470" + }, + "menue:✎ Projekt anpassen": { + "abdruck": "ad505addca45b06c", + "funktion": "Projektmenü öffnen", + "trug": "03a14d06cae6f470" + }, + "menue:✕ Feature entfernen": { + "abdruck": "bc968582260c45b9", + "funktion": "Funktion anlegen", + "trug": "90e0b650ae301b45" + }, + "menue:✕ Funktion entfernen": { + "abdruck": "d29458b150c55777", + "funktion": "Funktion nach oben bewegen", + "trug": "df54203089276209" + }, + "menue:✕ Projekt entfernen": { + "abdruck": "aca25c0b5feaf752", + "funktion": "Projektmenü öffnen", + "trug": "03a14d06cae6f470" + }, + "menue:✕ Vision entfernen": { + "abdruck": "88520b1f105d3fb5", + "funktion": "Ansicht wechseln", + "trug": "49670ec2cf4bafa6" + }, + "route:delete /projekte/{name}": { + "abdruck": "b4f871be35d10e5f", + "funktion": "Projekt löschen", + "trug": "872516903886a778" + }, + "route:delete /projekte/{name}/chat": { + "abdruck": "4ba7a240985a83b4", + "funktion": "Chat leeren", + "trug": "ad6f39b2df93ae9d" + }, + "route:delete /projekte/{name}/features/{id}": { + "abdruck": "c1db81de98835c39", + "funktion": "Feature löschen", + "trug": "1923fc64038bc60b" + }, + "route:delete /projekte/{name}/pruefung": { + "abdruck": "7a480f33ddf55165", + "funktion": "Prüfung beenden", + "trug": "5fe1d7854fed1dee" + }, + "route:get /health": { + "abdruck": "65257319741edf35", + "funktion": "Systemstatus prüfen", + "trug": "bcfd8dfe1476c1e3" + }, + "route:get /projekte": { + "abdruck": "276556054437c303", + "funktion": "Systemstatus prüfen", + "trug": "bcfd8dfe1476c1e3" + }, + "route:get /projekte/{name}/chat": { + "abdruck": "fd2a22c36ea85545", + "funktion": "Chat-Verlauf abrufen", + "trug": "00a373d5a8aa27ea" + }, + "route:get /projekte/{name}/features": { + "abdruck": "122f93cbd0d07881", + "funktion": "Projektfeatures anzeigen", + "trug": "9c5e510b15780d20" + }, + "route:get /projekte/{name}/pruefung": { + "abdruck": "e651ac90b7b2c520", + "funktion": "", + "trug": "" + }, + "route:get /projekte/{name}/quelle": { + "abdruck": "834d3af3203ca3a8", + "funktion": "Quelldaten laden", + "trug": "0331b57c96312672" + }, + "route:get /projekte/{name}/verlauf": { + "abdruck": "5a3dcc678733fad8", + "funktion": "Projektverlauf anzeigen", + "trug": "3702fe42929b0778" + }, + "route:post /projekte": { + "abdruck": "fa1628d7e469885d", + "funktion": "Projekt erstellen", + "trug": "8cfce050cfef424d" + }, + "route:post /projekte/{name}/chat": { + "abdruck": "c3edc89cec5d2f6f", + "funktion": "Chat-Nachricht senden", + "trug": "6a5b29958d030562" + }, + "route:post /projekte/{name}/features": { + "abdruck": "00eb9c16560bac73", + "funktion": "Feature anlegen", + "trug": "df125001c2129150" + }, + "route:post /projekte/{name}/pruefung": { + "abdruck": "6d7444a9dfad7d54", + "funktion": "Prüfung starten", + "trug": "28b659d9245434ad" + }, + "route:post /projekte/{name}/pruefung/verworfen": { + "abdruck": "a43f7221e01c386f", + "funktion": "", + "trug": "" + }, + "route:post /projekte/{name}/verlauf/zurueck": { + "abdruck": "308fec6d21b01d60", + "funktion": "Änderung verwerfen", + "trug": "8e65186dfd7d0718" + }, + "route:put /projekte/{name}": { + "abdruck": "75383ac009961cad", + "funktion": "Projekt umbenennen", + "trug": "b173e09e1f84276f" + }, + "route:put /projekte/{name}/features/{id}": { + "abdruck": "b24c7000fd2ec94c", + "funktion": "Feature sichern", + "trug": "304dcd2dda365217" + }, + "route:put /projekte/{name}/features/{id}/projekt": { + "abdruck": "fafc7a8a1656f93b", + "funktion": "Feature verschieben", + "trug": "0a80fa98ccc72643" + }, + "route:put /projekte/{name}/quelle": { + "abdruck": "d342055e3163548a", + "funktion": "Quelldaten laden", + "trug": "0331b57c96312672" + } + }, + "belege": { + "[\"ansicht\", \"Ansicht wechseln\"]": { + "abdruck": "c3877694357a5933", + "beleg": "function wechsleAnsicht() {\n gross.value = !gross.value\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"ansicht\", \"Darkmode umschalten\"]": { + "abdruck": "e6006f976ba25e5b", + "beleg": "function wechsleDarkMode() {\n modus.value = MODI[(MODI.indexOf(modus.value) + 1) % MODI.length]\n localStorage.setItem('darkModus', modus.value)\n wendeAn()\n}", + "datei": "frontend/src/App.vue" + }, + "[\"ansicht\", \"Panel schließen\"]": { + "abdruck": "8e3956fd63c3a392", + "beleg": "export async function schliesse() {\n stoppeUhr()\n offen.value = false\n probleme.value = []\n laeuft.value = false\n if (projektName) await pruefungBeenden(projektName).catch(() => {})\n}", + "datei": "frontend/src/composables/pruefung.js" + }, + "[\"ansicht\", \"Systemfarben nutzen\"]": { + "abdruck": "52b537e262b3b777", + "beleg": "systemDunkel.addEventListener('change', () => { if (modus.value === 'auto') wendeAn() })", + "datei": "frontend/src/App.vue" + }, + "[\"chat\", \"Chat leeren\"]": { + "abdruck": "a0bdc6bf618937a7", + "beleg": "def leeren(projekt: str):\n _pfad(projekt).unlink(missing_ok=True)", + "datei": "backend/chat.py" + }, + "[\"chat\", \"Chat schließen\"]": { + "abdruck": "413d7ffe543690eb", + "beleg": "", + "datei": "frontend/src/components/ChatPanel.vue" + }, + "[\"chat\", \"Chat öffnen\"]": { + "abdruck": "c00eb93f9adfbe45", + "beleg": "if (pruefungOffen.value) schliessePruefung()", + "datei": "frontend/src/App.vue" + }, + "[\"chat\", \"Chat-Nachricht senden\"]": { + "abdruck": "ed02394bf1ef6d86", + "beleg": "@router.post(\"/projekte/{name}/chat\")\nasync def chat_frage(name: str, body: dict):", + "datei": "backend/routes.py" + }, + "[\"chat\", \"Nachricht senden\"]": { + "abdruck": "9b2f165ec8491c5d", + "beleg": "async function senden() {\n const text = entwurf.value.trim()\n if (!text || laeuft.value) return\n meldung.value = ''\n laeuft.value = true\n // Die eigene Zeile sofort zeigen; auf die Antwort wartet man sonst vor leerem Feld\n verlauf.value = [...verlauf.value, { rolle: 'person', text }]\n entwurf.value = ''\n nachUnten()\n try {\n const antwort = await chatFragen(props.projekt, text)", + "datei": "frontend/src/components/ChatPanel.vue" + }, + "[\"features\", \"Badge umschalten\"]": { + "abdruck": "e2965c14555f8096", + "beleg": "function wechsleArt() {\n s.value.art = s.value.art === 'kern' ? 'optional' : 'kern'\n speichern()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"features\", \"Doppeltes Projekt verhindern\"]": { + "abdruck": "766dc883e27f42c2", + "beleg": "if ziel.exists():\n raise ValueError(f\"Projekt „{name}“ existiert bereits\")", + "datei": "backend/projekte.py" + }, + "[\"features\", \"Feature anlegen\"]": { + "abdruck": "4b203078599f8166", + "beleg": "async function erstellen(titel) {", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"features\", \"Feature bearbeiten\"]": { + "abdruck": "6d66b9d5a4f5d6ab", + "beleg": "async function starte(feld, i, j) {\n if (!gross.value) return // Bearbeiten nur in der ausführlichen Ansicht\n const original = wert(feld, i, j)\n aktiv.value = { feld, i, j, original }\n entwurf.value = original\n await nextTick()\n const el = Array.isArray(feldRef.value) ? feldRef.value[0] : feldRef.value\n el?.focus()\n if (feld === 'titel') el?.select()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"features\", \"Feature löschen\"]": { + "abdruck": "166de85192ae758b", + "beleg": "@router.delete(\"/projekte/{name}/features/{id}\")\nasync def feature_loeschen(name: str, id: str):\n try:\n features.loeschen(name, id)\n except (FileNotFoundError, ValueError) as e:\n raise HTTPException(404, str(e))\n return {\"ok\": True}", + "datei": "backend/routes.py" + }, + "[\"features\", \"Feature sichern\"]": { + "abdruck": "7dc961261c1bdd97", + "beleg": "return features.speichern(name, id, body.get(\"roh\") or \"\")", + "datei": "backend/routes.py" + }, + "[\"features\", \"Feature verschieben\"]": { + "abdruck": "9ef1a4e4d2c83cd5", + "beleg": "def verschieben(projekt: str, id: str, ziel: str) -> dict:", + "datei": "backend/features.py" + }, + "[\"features\", \"Projekt auswählen\"]": { + "abdruck": "9a18227bae730ca9", + "beleg": "@click=\"emit('auswaehlen', p.name)\"", + "datei": "frontend/src/components/SeitenLeiste.vue" + }, + "[\"features\", \"Projekt entfernen\"]": { + "abdruck": "be42cdf553979c24", + "beleg": "def loeschen(name: str):\n ordner = _ordner(name)\n if not ordner.is_dir():\n raise FileNotFoundError(f\"Projekt „{name}“ nicht gefunden\")\n shutil.rmtree(ordner)", + "datei": "backend/projekte.py" + }, + "[\"features\", \"Projekt erstellen\"]": { + "abdruck": "71330de60c424239", + "beleg": "ziel.mkdir(parents=True)", + "datei": "backend/projekte.py" + }, + "[\"features\", \"Projekt löschen\"]": { + "abdruck": "0990bba6500429a1", + "beleg": "@router.delete(\"/projekte/{name}\")\nasync def projekt_loeschen(name: str):", + "datei": "backend/routes.py" + }, + "[\"features\", \"Projekt umbenennen\"]": { + "abdruck": "466815ae4cd070b5", + "beleg": "def umbenennen(alt: str, neu: str):", + "datei": "backend/projekte.py" + }, + "[\"features\", \"Projekte anzeigen\"]": { + "abdruck": "034ffb0e08d0106f", + "beleg": "return [{\"name\": p.name} for p in ordner]", + "datei": "backend/projekte.py" + }, + "[\"features\", \"Projektfeatures anzeigen\"]": { + "abdruck": "fef0253d82b979bd", + "beleg": "return features.liste(name)", + "datei": "backend/routes.py" + }, + "[\"features\", \"Projektmenü öffnen\"]": { + "abdruck": "20b34708dcae5e40", + "beleg": "function projektMenue(e, name) {\n oeffneMenue(e, [\n { text: '✎ Projekt anpassen', aktion: () => starteUmbenennen(name) },\n { text: '◇ Quelle festlegen', aktion: () => starteQuelle(name) },\n { text: '✕ Projekt entfernen', aktion: () => oeffneModal({ art: 'entfernen', name }) },\n ])\n}", + "datei": "frontend/src/components/SeitenLeiste.vue" + }, + "[\"features\", \"Quelldaten laden\"]": { + "abdruck": "655e0069db84a8ac", + "beleg": "def setze(projekt: str, pfad: str) -> str:\n ziel = pruefe(pfad)\n _pfad(projekt).write_text(f\"{ziel}\\n\")\n return str(ziel)", + "datei": "backend/quelle.py" + }, + "[\"features\", \"Vision entfernen\"]": { + "abdruck": "470551c11e26d3be", + "beleg": "function kartenMenue(e) {\n oeffneMenue(e, [{ text: '✕ Vision entfernen', aktion: () => emit('entfernen') }])\n}", + "datei": "frontend/src/components/VisionKarte.vue" + }, + "[\"features\", \"Vision erstellen\"]": { + "abdruck": "eedd0343c63f6174", + "beleg": "async function visionErstellen() {\n meldung.value = ''\n try {\n features.value.push(mitKey(await featureAnlegen(\n props.projekt, '\\nVision\\n\\nvision\\n')))\n emit('geaendert')\n } catch (e) {\n meldung.value = e.message\n }\n}", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"funktionen\", \"Funktion anlegen\"]": { + "abdruck": "3b9cb4fbae4dc4d0", + "beleg": "async function funktionErstellen(titel) {\n // Von Hand angelegt heißt: es wird beschrieben, was es gibt. Bestellt wird im Gespräch.\n s.value.funktionen.push({ text: titel, ziel: '', regeln: '', testen: '', stand: 'gebaut' })\n modal.value = null\n await speichern()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktion löschen\"]": { + "abdruck": "3e13d8d2db286a9a", + "beleg": "async function funktionEntfernen() {", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktion nach oben bewegen\"]": { + "abdruck": "edb543e0eb422f82", + "beleg": "async function schiebe(i, richtung) {", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktionsstand wechseln\"]": { + "abdruck": "91bb0f08f7bbb6e5", + "beleg": "@click.stop=\"wechsleStand(i)\"", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Kontextmenü anzeigen\"]": { + "abdruck": "338f555e81f96982", + "beleg": "export function oeffneMenue(e, eintraege) {\n kontextMenue.value = { eintraege, x: e.clientX, y: e.clientY }\n}", + "datei": "frontend/src/composables/kontextmenue.js" + }, + "[\"funktionen\", \"Kontextmenü verbergen\"]": { + "abdruck": "4c7978801a55e0e3", + "beleg": "window.addEventListener('click', (e) => {\n if (e.target.closest?.('.kontextmenue')) return // Auswahl darf zuerst laufen\n schliesseMenue()\n}, true)", + "datei": "frontend/src/composables/kontextmenue.js" + }, + "[\"pruefung\", \"Eingabe bestätigen\"]": { + "abdruck": "1913b85008d85b53", + "beleg": "@keydown.enter.exact.prevent=\"senden\"", + "datei": "frontend/src/components/ChatPanel.vue" + }, + "[\"pruefung\", \"Fehlerstelle anzeigen\"]": { + "abdruck": "3df860fd942c7991", + "beleg": "function springe(p) {\n const karte = document.querySelector(`[data-feature=\"${CSS.escape(p.feature)}\"]`)\n if (!karte) return\n karte.scrollIntoView({ behavior: 'smooth', block: 'center' })\n karte.classList.add('gesucht')\n setTimeout(() => karte.classList.remove('gesucht'), 1200)\n}", + "datei": "frontend/src/components/PruefPanel.vue" + }, + "[\"pruefung\", \"Prüfung beenden\"]": { + "abdruck": "f037280e771e00bf", + "beleg": "def beende(projekt: str):\n \"\"\"Ergebnis verwerfen (Panel schließen).\"\"\"\n _laeufe.pop(projekt, None)", + "datei": "backend/pruefung.py" + }, + "[\"pruefung\", \"Prüfung starten\"]": { + "abdruck": "d64e34a6115050f7", + "beleg": "async def starte(projekt: str, art: str = \"stil\") -> dict:", + "datei": "backend/pruefung.py" + }, + "[\"pruefung\", \"Prüfungsstatus anzeigen\"]": { + "abdruck": "e24503b308960f41", + "beleg": "def status(projekt: str) -> dict:", + "datei": "backend/pruefung.py" + }, + "[\"pruefung\", \"Systemstatus prüfen\"]": { + "abdruck": "3077f4e6b74b05d0", + "beleg": "@router.get(\"/health\")\nasync def health():\n return {\"ok\": True}", + "datei": "backend/routes.py" + }, + "[\"verlauf\", \"Aktion rückgängig machen\"]": { + "abdruck": "55f06794c134c176", + "beleg": "async function zurueck() {\n if (!aktivesProjekt.value || !letzterSchritt.value) return\n meldung.value = ''\n try {\n await verlaufZurueck(aktivesProjekt.value)\n stand.value++\n await ladeVerlauf()\n } catch (e) {\n meldung.value = e.message\n }\n}", + "datei": "frontend/src/App.vue" + }, + "[\"verlauf\", \"Chat-Verlauf abrufen\"]": { + "abdruck": "17c011bbb9139778", + "beleg": "def verlauf(projekt: str) -> list:\n try:\n eintraege = json.loads(_pfad(projekt).read_text())\n except (OSError, ValueError):\n return []\n return eintraege if isinstance(eintraege, list) else []", + "datei": "backend/chat.py" + }, + "[\"verlauf\", \"Projektverlauf anzeigen\"]": { + "abdruck": "3b4218f351f981fa", + "beleg": "@router.get(\"/projekte/{name}/verlauf\")\nasync def verlauf_stand(name: str):\n try:\n return {\"letzter\": verlauf.letzter(name)}\n except FileNotFoundError as e:\n raise HTTPException(404, str(e))", + "datei": "backend/routes.py" + }, + "[\"verlauf\", \"Änderung verwerfen\"]": { + "abdruck": "6f3ee47a0288fb55", + "beleg": "def zurueck(projekt: str) -> str:", + "datei": "backend/verlauf.py" + }, + "[\"vorschlaege\", \"Alle Vorschläge annehmen\"]": { + "abdruck": "4122340679eb1d89", + "beleg": "async function alleAnnehmen() {\n const weg = props.probleme.find(p => p.feld === 'karte')\n if (weg) return annehmen(weg) // was ganz wegfällt, muss nicht erst gerichtet werden\n props.probleme.forEach(p => { if (anwenden(p)) erledige(p) })\n await speichern()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"vorschlaege\", \"Alle Vorschläge verwerfen\"]": { + "abdruck": "55300c2b4d39c005", + "beleg": "function alleAblehnen() {\n props.probleme.forEach(verwirf)\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"vorschlaege\", \"Vorschlag verwerfen\"]": { + "abdruck": "3c1c6dd5d5021046", + "beleg": "def verwirf(projekt: str, problem: dict):", + "datei": "backend/pruefung.py" + }, + "[\"vorschlaege\", \"Vorschlag übernehmen\"]": { + "abdruck": "e1ea537facc45346", + "beleg": "async function karteAnnehmen(p) {\n try {\n features.value.push(mitKey(await featureAnlegen(props.projekt, p.roh)))\n sortiere()\n erledige(p)\n emit('geaendert')\n } catch (e) {\n meldung.value = e.message\n }\n}", + "datei": "frontend/src/components/FeatureListe.vue" + } + }, + "ohne_code": {}, + "ohne_karte": {}, + "paare": { + "[\"[\\\"ansicht\\\", \\\"Ansicht wechseln\\\"]\", \"[\\\"ansicht\\\", \\\"Darkmode umschalten\\\"]\"]": { + "abdruck": "b8ff91dfce2253eb", + "gleich": false + }, + "[\"[\\\"ansicht\\\", \\\"Ansicht wechseln\\\"]\", \"[\\\"ansicht\\\", \\\"Panel schließen\\\"]\"]": { + "abdruck": "a633805898584a0f", + "gleich": false + }, + "[\"[\\\"ansicht\\\", \\\"Ansicht wechseln\\\"]\", \"[\\\"ansicht\\\", \\\"Systemfarben nutzen\\\"]\"]": { + "abdruck": "9ab009b3f3b7faa8", + "gleich": false + }, + "[\"[\\\"ansicht\\\", \\\"Darkmode umschalten\\\"]\", \"[\\\"ansicht\\\", \\\"Panel schließen\\\"]\"]": { + "abdruck": "80aec0f1ade023d2", + "gleich": false + }, + "[\"[\\\"ansicht\\\", \\\"Darkmode umschalten\\\"]\", \"[\\\"ansicht\\\", \\\"Systemfarben nutzen\\\"]\"]": { + "abdruck": "1832c75969ec0d3c", + "gleich": false + }, + "[\"[\\\"ansicht\\\", \\\"Panel schließen\\\"]\", \"[\\\"ansicht\\\", \\\"Systemfarben nutzen\\\"]\"]": { + "abdruck": "66016c3bbab7f8cb", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat leeren\\\"]\", \"[\\\"chat\\\", \\\"Chat schließen\\\"]\"]": { + "abdruck": "3d1c556a261aed69", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat leeren\\\"]\", \"[\\\"chat\\\", \\\"Chat öffnen\\\"]\"]": { + "abdruck": "fb3a179776970c7e", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat leeren\\\"]\", \"[\\\"chat\\\", \\\"Chat-Nachricht senden\\\"]\"]": { + "abdruck": "4d87ce17477e3f93", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat leeren\\\"]\", \"[\\\"chat\\\", \\\"Nachricht senden\\\"]\"]": { + "abdruck": "1be51eee6f81d539", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat schließen\\\"]\", \"[\\\"chat\\\", \\\"Chat öffnen\\\"]\"]": { + "abdruck": "3710797d87d7c5db", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat schließen\\\"]\", \"[\\\"chat\\\", \\\"Chat-Nachricht senden\\\"]\"]": { + "abdruck": "9d1af4e7a844e7fd", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat schließen\\\"]\", \"[\\\"chat\\\", \\\"Nachricht senden\\\"]\"]": { + "abdruck": "c6d925ffc6496c31", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat öffnen\\\"]\", \"[\\\"chat\\\", \\\"Chat-Nachricht senden\\\"]\"]": { + "abdruck": "d6a902592aba793a", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat öffnen\\\"]\", \"[\\\"chat\\\", \\\"Nachricht senden\\\"]\"]": { + "abdruck": "2d917f1f5f4c3520", + "gleich": false + }, + "[\"[\\\"chat\\\", \\\"Chat-Nachricht senden\\\"]\", \"[\\\"chat\\\", \\\"Nachricht senden\\\"]\"]": { + "abdruck": "7238fdce9419ad3c", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature löschen\\\"]\", \"[\\\"features\\\", \\\"Feature sichern\\\"]\"]": { + "abdruck": "b9ee835ba4ddc55d", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Projekte anzeigen\\\"]\", \"[\\\"verlauf\\\", \\\"Projektverlauf anzeigen\\\"]\"]": { + "abdruck": "eabdd6ac2db9913c", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion löschen\\\"]\"]": { + "abdruck": "6f2afa331454f7d0", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion nach oben bewegen\\\"]\"]": { + "abdruck": "6fee1d8cf3ae0b66", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktionsstand wechseln\\\"]\"]": { + "abdruck": "50f1b4e63602fff9", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü anzeigen\\\"]\"]": { + "abdruck": "08f04c5839faa289", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü verbergen\\\"]\"]": { + "abdruck": "afbf929644e7cb59", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion löschen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion nach oben bewegen\\\"]\"]": { + "abdruck": "c13feb60224326b6", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion löschen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktionsstand wechseln\\\"]\"]": { + "abdruck": "5c21e7fc396f9748", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion löschen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü anzeigen\\\"]\"]": { + "abdruck": "ee2d3372abc96036", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion löschen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü verbergen\\\"]\"]": { + "abdruck": "d85e188c59c915bb", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion nach oben bewegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktionsstand wechseln\\\"]\"]": { + "abdruck": "24cff359c222b63b", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion nach oben bewegen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü anzeigen\\\"]\"]": { + "abdruck": "3d62226712507269", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion nach oben bewegen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü verbergen\\\"]\"]": { + "abdruck": "138d7599fdeb4f90", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktionsstand wechseln\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü anzeigen\\\"]\"]": { + "abdruck": "4e984f0f2a5512ac", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktionsstand wechseln\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü verbergen\\\"]\"]": { + "abdruck": "ce2e9b52235a0d11", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Kontextmenü anzeigen\\\"]\", \"[\\\"funktionen\\\", \\\"Kontextmenü verbergen\\\"]\"]": { + "abdruck": "b6430e74878bc7c4", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Eingabe bestätigen\\\"]\", \"[\\\"pruefung\\\", \\\"Fehlerstelle anzeigen\\\"]\"]": { + "abdruck": "1419cb12e0e111d0", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Eingabe bestätigen\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfung beenden\\\"]\"]": { + "abdruck": "a99636ab1282d21f", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Eingabe bestätigen\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfung starten\\\"]\"]": { + "abdruck": "7631cbce07126ff0", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Eingabe bestätigen\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfungsstatus anzeigen\\\"]\"]": { + "abdruck": "a3fdb382bf6a9884", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Eingabe bestätigen\\\"]\", \"[\\\"pruefung\\\", \\\"Systemstatus prüfen\\\"]\"]": { + "abdruck": "0ba815a92cfdeaad", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Fehlerstelle anzeigen\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfung beenden\\\"]\"]": { + "abdruck": "dbf994253e72632d", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Fehlerstelle anzeigen\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfung starten\\\"]\"]": { + "abdruck": "fb95eec76e3b64ea", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Fehlerstelle anzeigen\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfungsstatus anzeigen\\\"]\"]": { + "abdruck": "555964bcf58c8ea3", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Fehlerstelle anzeigen\\\"]\", \"[\\\"pruefung\\\", \\\"Systemstatus prüfen\\\"]\"]": { + "abdruck": "80644693a6a57689", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Prüfung beenden\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfung starten\\\"]\"]": { + "abdruck": "7e9d8831578a924a", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Prüfung beenden\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfungsstatus anzeigen\\\"]\"]": { + "abdruck": "50f0a18032fad301", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Prüfung beenden\\\"]\", \"[\\\"pruefung\\\", \\\"Systemstatus prüfen\\\"]\"]": { + "abdruck": "36bbb6b2441ef0f9", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Prüfung starten\\\"]\", \"[\\\"pruefung\\\", \\\"Prüfungsstatus anzeigen\\\"]\"]": { + "abdruck": "b4a215965df637e6", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Prüfung starten\\\"]\", \"[\\\"pruefung\\\", \\\"Systemstatus prüfen\\\"]\"]": { + "abdruck": "265be18c33789c97", + "gleich": false + }, + "[\"[\\\"pruefung\\\", \\\"Prüfungsstatus anzeigen\\\"]\", \"[\\\"pruefung\\\", \\\"Systemstatus prüfen\\\"]\"]": { + "abdruck": "7ef6d65f5e3894f9", + "gleich": false + }, + "[\"[\\\"verlauf\\\", \\\"Aktion rückgängig machen\\\"]\", \"[\\\"verlauf\\\", \\\"Chat-Verlauf abrufen\\\"]\"]": { + "abdruck": "6f6e0e1b49b03b13", + "gleich": false + }, + "[\"[\\\"verlauf\\\", \\\"Aktion rückgängig machen\\\"]\", \"[\\\"verlauf\\\", \\\"Projektverlauf anzeigen\\\"]\"]": { + "abdruck": "2ffccbb98362d6df", + "gleich": false + }, + "[\"[\\\"verlauf\\\", \\\"Aktion rückgängig machen\\\"]\", \"[\\\"verlauf\\\", \\\"Änderung verwerfen\\\"]\"]": { + "abdruck": "f96bb9ecbad1cbbb", + "gleich": false + }, + "[\"[\\\"verlauf\\\", \\\"Chat-Verlauf abrufen\\\"]\", \"[\\\"verlauf\\\", \\\"Projektverlauf anzeigen\\\"]\"]": { + "abdruck": "155506aa734b59d7", + "gleich": false + }, + "[\"[\\\"verlauf\\\", \\\"Chat-Verlauf abrufen\\\"]\", \"[\\\"verlauf\\\", \\\"Änderung verwerfen\\\"]\"]": { + "abdruck": "5db147adddb92031", + "gleich": false + }, + "[\"[\\\"verlauf\\\", \\\"Projektverlauf anzeigen\\\"]\", \"[\\\"verlauf\\\", \\\"Änderung verwerfen\\\"]\"]": { + "abdruck": "8cc5b7624b61d780", + "gleich": false + }, + "[\"[\\\"vorschlaege\\\", \\\"Alle Vorschläge annehmen\\\"]\", \"[\\\"vorschlaege\\\", \\\"Alle Vorschläge verwerfen\\\"]\"]": { + "abdruck": "4303c231f9026165", + "gleich": false + }, + "[\"[\\\"vorschlaege\\\", \\\"Alle Vorschläge annehmen\\\"]\", \"[\\\"vorschlaege\\\", \\\"Vorschlag verwerfen\\\"]\"]": { + "abdruck": "5dbf2f5134af09ef", + "gleich": false + }, + "[\"[\\\"vorschlaege\\\", \\\"Alle Vorschläge annehmen\\\"]\", \"[\\\"vorschlaege\\\", \\\"Vorschlag übernehmen\\\"]\"]": { + "abdruck": "1efb0d83189dc7a4", + "gleich": false + }, + "[\"[\\\"vorschlaege\\\", \\\"Alle Vorschläge verwerfen\\\"]\", \"[\\\"vorschlaege\\\", \\\"Vorschlag verwerfen\\\"]\"]": { + "abdruck": "ebe45407735822f1", + "gleich": false + }, + "[\"[\\\"vorschlaege\\\", \\\"Alle Vorschläge verwerfen\\\"]\", \"[\\\"vorschlaege\\\", \\\"Vorschlag übernehmen\\\"]\"]": { + "abdruck": "991d416dd30847c9", + "gleich": false + }, + "[\"[\\\"vorschlaege\\\", \\\"Vorschlag verwerfen\\\"]\", \"[\\\"vorschlaege\\\", \\\"Vorschlag übernehmen\\\"]\"]": { + "abdruck": "873c3ffb4f31cf30", + "gleich": false + } + }, + "stil": { + "[\"ansicht\", \"\"]": { + "abdruck": "3050ad182b423922", + "probleme": [] + }, + "[\"ansicht\", \"Ansicht wechseln\"]": { + "abdruck": "efeb03b002f19ade", + "probleme": [] + }, + "[\"ansicht\", \"Darkmode umschalten\"]": { + "abdruck": "3b1155e8587bb206", + "probleme": [] + }, + "[\"ansicht\", \"Panel schließen\"]": { + "abdruck": "2e52617f09b796ee", + "probleme": [] + }, + "[\"ansicht\", \"Systemfarben nutzen\"]": { + "abdruck": "9ee92ae09d0085ed", + "probleme": [] + }, + "[\"chat\", \"\"]": { + "abdruck": "fa8047957d054f3f", + "probleme": [] + }, + "[\"chat\", \"Chat leeren\"]": { + "abdruck": "0b73a91c7a75f49e", + "probleme": [] + }, + "[\"chat\", \"Chat schließen\"]": { + "abdruck": "190f2ccdce030a31", + "probleme": [] + }, + "[\"chat\", \"Chat öffnen\"]": { + "abdruck": "f2e5bdba8f160d90", + "probleme": [] + }, + "[\"chat\", \"Chat-Nachricht senden\"]": { + "abdruck": "9aaf53507344ca71", + "probleme": [] + }, + "[\"chat\", \"Nachricht senden\"]": { + "abdruck": "9109d06a608fd0e4", + "probleme": [] + }, + "[\"features\", \"\"]": { + "abdruck": "3c6ad3dc7eab3ce8", + "probleme": [] + }, + "[\"features\", \"Badge umschalten\"]": { + "abdruck": "00f783fe76e9192a", + "probleme": [] + }, + "[\"features\", \"Doppeltes Projekt verhindern\"]": { + "abdruck": "0fbdc39af753e723", + "probleme": [] + }, + "[\"features\", \"Feature anlegen\"]": { + "abdruck": "1fbb1c23e74ae11a", + "probleme": [] + }, + "[\"features\", \"Feature bearbeiten\"]": { + "abdruck": "1147716db006f333", + "probleme": [] + }, + "[\"features\", \"Feature löschen\"]": { + "abdruck": "21185eba2ea766c3", + "probleme": [] + }, + "[\"features\", \"Feature sichern\"]": { + "abdruck": "b128b487c64cc380", + "probleme": [] + }, + "[\"features\", \"Feature verschieben\"]": { + "abdruck": "60cf50ba769b49e3", + "probleme": [] + }, + "[\"features\", \"Projekt auswählen\"]": { + "abdruck": "c1657e61456ba324", + "probleme": [] + }, + "[\"features\", \"Projekt entfernen\"]": { + "abdruck": "15d6f5df73954031", + "probleme": [] + }, + "[\"features\", \"Projekt erstellen\"]": { + "abdruck": "60369bae08bbe631", + "probleme": [] + }, + "[\"features\", \"Projekt löschen\"]": { + "abdruck": "11e09848a6305713", + "probleme": [] + }, + "[\"features\", \"Projekt umbenennen\"]": { + "abdruck": "3a4f6691535031ac", + "probleme": [] + }, + "[\"features\", \"Projekte anzeigen\"]": { + "abdruck": "36926f0eabaaf4d3", + "probleme": [] + }, + "[\"features\", \"Projektfeatures anzeigen\"]": { + "abdruck": "06aba866e8ffd9b8", + "probleme": [] + }, + "[\"features\", \"Projektmenü öffnen\"]": { + "abdruck": "4c35d6392aaf4c48", + "probleme": [] + }, + "[\"features\", \"Quelldaten laden\"]": { + "abdruck": "2c9ec82467e0bca5", + "probleme": [] + }, + "[\"features\", \"Vision entfernen\"]": { + "abdruck": "27f241eed1b7f392", + "probleme": [] + }, + "[\"features\", \"Vision erstellen\"]": { + "abdruck": "5c1afedaaa2de937", + "probleme": [] + }, + "[\"funktionen\", \"\"]": { + "abdruck": "2214346c0c57f6e3", + "probleme": [] + }, + "[\"funktionen\", \"Funktion anlegen\"]": { + "abdruck": "0ed86e888757740f", + "probleme": [] + }, + "[\"funktionen\", \"Funktion löschen\"]": { + "abdruck": "dd9cbd8a88835994", + "probleme": [] + }, + "[\"funktionen\", \"Funktion nach oben bewegen\"]": { + "abdruck": "148531c6056ee45d", + "probleme": [] + }, + "[\"funktionen\", \"Funktionsstand wechseln\"]": { + "abdruck": "6a71b514e8d54be7", + "probleme": [] + }, + "[\"funktionen\", \"Kontextmenü anzeigen\"]": { + "abdruck": "0a12c9439ba0b213", + "probleme": [] + }, + "[\"funktionen\", \"Kontextmenü verbergen\"]": { + "abdruck": "7b141c49d7c799b7", + "probleme": [] + }, + "[\"pruefung\", \"\"]": { + "abdruck": "5eeaa019b5a5ad39", + "probleme": [] + }, + "[\"pruefung\", \"Eingabe bestätigen\"]": { + "abdruck": "8ad5471c392b0a1c", + "probleme": [] + }, + "[\"pruefung\", \"Fehlerstelle anzeigen\"]": { + "abdruck": "95a0d0915331a5fb", + "probleme": [] + }, + "[\"pruefung\", \"Prüfung beenden\"]": { + "abdruck": "dd15f32e33af9e13", + "probleme": [] + }, + "[\"pruefung\", \"Prüfung starten\"]": { + "abdruck": "cda9e8d0950338e9", + "probleme": [] + }, + "[\"pruefung\", \"Prüfungsstatus anzeigen\"]": { + "abdruck": "c5a89bfb14e802e4", + "probleme": [] + }, + "[\"pruefung\", \"Systemstatus prüfen\"]": { + "abdruck": "16e4c8f4eb5032cc", + "probleme": [] + }, + "[\"verlauf\", \"\"]": { + "abdruck": "60981e43b8753616", + "probleme": [] + }, + "[\"verlauf\", \"Aktion rückgängig machen\"]": { + "abdruck": "56bf9d34786ab1ff", + "probleme": [] + }, + "[\"verlauf\", \"Chat-Verlauf abrufen\"]": { + "abdruck": "08f9e4455271574e", + "probleme": [] + }, + "[\"verlauf\", \"Projektverlauf anzeigen\"]": { + "abdruck": "cc754d0256a98ab3", + "probleme": [] + }, + "[\"verlauf\", \"Änderung verwerfen\"]": { + "abdruck": "a19f22e3590801a9", + "probleme": [] + }, + "[\"vorschlaege\", \"\"]": { + "abdruck": "d9f2d6a2457d21e3", + "probleme": [] + }, + "[\"vorschlaege\", \"Alle Vorschläge annehmen\"]": { + "abdruck": "55894513645bf1cf", + "probleme": [] + }, + "[\"vorschlaege\", \"Alle Vorschläge verwerfen\"]": { + "abdruck": "c83c7e38cd63b8e2", + "probleme": [] + }, + "[\"vorschlaege\", \"Vorschlag verwerfen\"]": { + "abdruck": "6e6522ded1f752e9", + "probleme": [] + }, + "[\"vorschlaege\", \"Vorschlag übernehmen\"]": { + "abdruck": "bd60f0d480fc39ad", + "probleme": [] + } + }, + "verworfen": {} +} diff --git a/daten/PLANER2GEN/ansicht.md b/daten/PLANER2GEN/ansicht.md new file mode 100644 index 0000000..7afb18f --- /dev/null +++ b/daten/PLANER2GEN/ansicht.md @@ -0,0 +1,53 @@ + +Ansicht +---------------------------------------- + +kern +---------------------------------------- + +Umschalten zwischen Ansichtsmodi und Farbschema der Anwendung +---------------------------------------- + +- Systemänderungen wirken sofort im Auto-Modus +- Kompaktmodus zeigt Zusammenfassung +- Vollmodus zeigt alle Details +- Panel schließen entfernt es aus dem DOM +- Auge-Icon nur im Vollmodus +- MMB in beiden Modi wechselt die Ansicht +---------------------------------------- + +Ansicht wechseln + +- MMB auf Karte drücken +- Kompaktmodus wechselt zu Vollmodus +---------------------------------------- + +Darkmode umschalten + +Passt die Farbgebung der App an die bevorzugte Umgebung an + +- Zyklus: Auto → Hell → Dunkel → Auto +- Auto folgt der Systemeinstellung +- Auswahl bleibt nach Neuladen erhalten + +- Klick auf Darkmode-Icon +- Modus wechselt zum nächsten im Zyklus +- Seite zeigt den gewählten Modus +---------------------------------------- + +Panel schließen + +- schliesse entfernt das Panel aus dem DOM + +- LMB auf ✕-Icon +- Panel nicht mehr sichtbar +---------------------------------------- + +Systemfarben nutzen + +- Nur wirksam wenn Modus auf Auto steht +- Systemänderungen werden sofort übernommen + +- Auto-Modus wählen +- Systemfarbschema wechseln +- App-Oberfläche passt sich an diff --git a/daten/PLANER2GEN/chat.md b/daten/PLANER2GEN/chat.md new file mode 100644 index 0000000..f2da2f9 --- /dev/null +++ b/daten/PLANER2GEN/chat.md @@ -0,0 +1,83 @@ + +Chat +---------------------------------------- + +kern +---------------------------------------- + +Beschreibt ein Projekt im Gespräch und erhält Karten als Vorschlag zurück +---------------------------------------- + +- Unbekanntes Projekt gibt 404 +- x-Icon schließt Chat +- Prüfung wird geschlossen falls offen +- Chat verwerfen nur bei vorhandenem Verlauf +- Chat verwerfen ohne Backend-Aufruf +- body enthält Pflichtfeld text +---------------------------------------- + +Chat leeren + +Entfernt alle Nachrichten aus dem Chatverlauf + +- 404 bei unbekanntem Projekt +- chat.leeren aufgerufen + +- Chat öffnen +- Nachricht senden +- Löschanfrage an Chat senden +- Antwort {"ok": true} +- Chatverlauf leer +---------------------------------------- + +Chat schließen + +Schließt das Chat-Panel und kehrt zur Projektansicht zurück + +- x-Icon +- Schließen ist immer möglich + +- LMB auf x-Icon +- Panel entfernt +---------------------------------------- + +Chat öffnen + +Tauscht die rechte Spalte zwischen Chat und Prüfung aus + +- Schließt Prüfung, falls offen + +- Prüfung öffnen +- LMB auf Chat-Button +- ChatPanel sichtbar, PrüfPanel geschlossen +---------------------------------------- + +Chat-Nachricht senden + +Holt eine Antwort des KI-Agenten zum aktuellen Projekt + +- body enthält Pflichtfeld text +- Leere Nachricht wird abgelehnt +- Projekt nicht gefunden gibt 404 +- Agent nicht konfiguriert gibt 400 +- Antwort enthält gesamten Verlauf + +- POST an Chat-Endpunkt mit Text Frage +- Antwort mit Verlauf enthält Nachricht und Antwort +- POST mit leerem Text gibt 400 +---------------------------------------- + +Nachricht senden + +Schickt eine Nachricht und zeigt die Antwort der KI + +- Leere Nachrichten nicht senden +- Anfragen werden nacheinander verarbeitet +- Eigene Nachricht erscheint sofort vor der Antwort +- Fehlgeschlagene Nachrichten werden wiederhergestellt + +- Text ins Eingabefeld eingeben +- Enter drücken +- Eigene Nachricht erscheint im Verlauf +- Ladeanzeige erscheint +- Antwort der KI erscheint im Verlauf diff --git a/daten/PLANER2GEN/features.md b/daten/PLANER2GEN/features.md new file mode 100644 index 0000000..96f5ce0 --- /dev/null +++ b/daten/PLANER2GEN/features.md @@ -0,0 +1,260 @@ + +Features +---------------------------------------- + +kern +---------------------------------------- + +Verwaltet Features und Projekte einer Software, einschließlich Bearbeitung, Suche und Überprüfung +---------------------------------------- + +- Seitenleiste zeigt alle Projekte +- Features stehen in Spalten unter dem aktiven Projekt +- MMB oder Augen-Icon wechselt Kompakt- und Vollmodus +- Fehlerhafte Karte öffnet sich im Vollmodus +- Suchergebnis blendet nicht passende Karten aus +- Vorgeschlagene Karte als Umriss dargestellt +- Feature verschieben nur bei mehreren Projekten +- Kontextmenü der Karte nur im Vollmodus +- Problemanzahl als Badge auf der Karte +- Sammelaktion ab drei vorgeschlagenen Karten +- Stand wechselt zwischen offen und gebaut +- Funktionen sind über Kontextmenü nach oben und unten verschiebbar +- Einzelne Felder lassen sich zu einer Funktion hinzufügen +- Verschieben unbekannter Features wirft 404 +---------------------------------------- + +Badge umschalten + +Markiert ein Feature als kern oder optional + +- Toggelt zwischen kern und optional +- Nur im Vollmodus verfügbar + +- Vollmodus öffnen +- LMB auf Badge +- Badge zeigt optional statt kern +---------------------------------------- + +Feature anlegen + +Legt ein neues Feature im aktuellen Projekt an + +- Titel ist Pflichtfeld +- Erstellt leere Feature-Datei mit Titel +- Neue Karte öffnet im Vollmodus +- Alphabetisch einsortiert + +- RMB auf den Bereich +- Klick auf "+ Feature erstellen" +- Titel eingeben und bestätigen +- Karte im Vollmodus sichtbar +---------------------------------------- + +Feature bearbeiten + +Ändert Titel, Ziel, Regeln, Funktion oder Testschritte direkt in der Karte + +- Titel-Klick öffnet ein Eingabefeld +- Nur im Vollmodus verfügbar +- Escape verwirft die Änderung +- Enter oder Klick außerhalb speichert +- Leerer Titel wird verworfen + +- Karte im Vollmodus öffnen +- Klick auf Titel +- Titel-Feld ist fokussiert und markiert +- Text ändern und Enter drücken +- Titel aktualisiert +---------------------------------------- + +Feature löschen + +Entfernt ein Feature dauerhaft aus dem Projekt + +- Wird über das Kontextmenü der Karte aufgerufen +- Erfragt eine Bestätigung vor dem Entfernen +- Löst das Entfernen über ein Event aus + +- RMB auf die Feature-Karte +- Klick auf "Feature entfernen" +- Bestätigung im Dialog +- Feature entfernt +---------------------------------------- + +Feature sichern + +Speichert Änderungen an einer Feature-Karte dauerhaft + +- Akzeptiert rohen Kartentext als Text +- Gibt 404 bei unbekanntem Projekt +- Gibt 400 bei ungültigem Kartentext + +- PUT api.projekte.name.features.id mit body {"roh": "Neuer Text"} +- Antwort 200 mit aktualisierter Karte +- Karte enthält neuen Text +---------------------------------------- + +Feature verschieben + +Verschiebt ein Feature in ein anderes Projekt + +- Nur möglich wenn mehrere Projekte existieren +- Zielprojekt muss existieren +- Feature bleibt unter neuer Projektzugehörigkeit erhalten + +- RMB auf Karte +- Klick auf "→ Feature verschieben" +- Zielprojekt auswählen +- Feature im Zielprojekt +---------------------------------------- + +Projekt auswählen + +Zeigt die Features eines anderen Projekts an + +- Aktives Projekt ist hervorgehoben +- Klick auf aktives Projekt bleibt aktiv + +- Klick auf Projekt in der Liste +- Projekt ist hervorgehoben +- Vorher aktives Projekt ist nicht mehr hervorgehoben +---------------------------------------- + +Projekt entfernen + +Löscht ein nicht mehr benötigtes Projekt mitsamt aller seiner Features + +- Fragt zur Bestätigung nach dem Projektnamen +- Löscht das Projekt und alle zugehörigen Features +- x-Icon bricht ab +- Entfernen-Button bestätigt die Löschung + +- RMB auf Projekt in der Seitenleiste +- Klick auf ✕ Projekt entfernen +- Klick auf Entfernen +- Projekt nicht mehr in der Liste +---------------------------------------- + +Projekt erstellen + +Ermöglicht das Anlegen eines neuen Projekts über die Seitenleiste + +- Projektname ist erforderlich +- Leerzeichen am Rand werden entfernt +- Projektname darf nicht existieren +- Erstelltes Projekt wird automatisch ausgewählt + +- Seitenleiste mit RMB öffnen +- Klick auf "+ Projekt" +- Projektname eingeben +- Klick auf "Erstellen" +- Modal geschlossen, Projekt ausgewählt +---------------------------------------- + +Projekt löschen + +- 404 bei unbekanntem Projekt +- 400 bei ungültigem Wert +- Erfolg gibt {"ok": true} zurück + +- api-projekte name per GET aufrufen +- Antwort pruefen: 404 +---------------------------------------- + +Projekt umbenennen + +Ermöglicht das Umbenennen bestehender Projekte direkt in der Seitenleiste + +- Umbenennung über Kontextmenü +- Umbenennung über Enter-Taste +- Escape bricht die Umbenennung ab +- Leere Eingabe verwirft die Änderung +- Gleicher Name wie zuvor verwirft die Änderung +- Projekt mit gleichem Namen erzeugt Fehler + +- RMB auf Projekt in der Seitenleiste +- Klick auf "Projekt anpassen" +- Neuen Namen eingeben +- Enter-Taste drücken +- Projektname in der Liste aktualisiert +---------------------------------------- + +Projekte anzeigen + +- Projekte-Endpunkt aufrufen +- Rückgabe prüfen +- Liste aller Projekte zurück +---------------------------------------- + +Projektfeatures anzeigen + +Zeigt alle Features eines Projekts im Rohformat + +- Rohformat enthält Karte und Funktionen +- Fehlendes Projekt wirft 404 + +- GET api projekte MeinProjekt features +- Antwort enthält Liste der Features +- 404 bei unbekanntem Projekt +---------------------------------------- + +Projektmenü öffnen + +Bietet Zugriff auf Anpassung, Quelle und Löschung einzelner Projekte + +- RMB auf Projektname +- Drei Optionen verfügbar + +- RMB auf Projekt in Seitenleiste +- Menü erscheint mit drei Einträgen +- ✎ Projekt anpassen startet Umbenennung +- ◇ Quelle festlegen öffnet Modal zur Pfadwahl +- ✕ Projekt entfernen öffnet Bestätigungsdialog +---------------------------------------- + +Quelldaten laden + +Legt fest, woher ein Projekt seine Daten bezieht + +- GET gibt den aktuellen Pfad zurück +- PUT setzt einen neuen Pfad +- Leerer Pfad löscht die Zuordnung + +- PUT quelle mit projektname und pfad data input +- GET quelle mit projektname +- Rueckgabe enthaelt projektname und pfad data input +---------------------------------------- + +Vision entfernen + +Ermöglicht das Löschen einer fehlerhaften oder überflüssigen Vision + +- x-Icon +- RMB auf Karte öffnet Menü +- Klick außerhalb schließt Menü + +- RMB auf Vision-Karte +- Klick auf "Vision entfernen" +- Vision-Karte entfernt +---------------------------------------- + +Vision erstellen + +Erstellt eine einzelne Vision-Karte für das Projekt + +- Nur eine Vision je Projekt +- Vision steht über den Features +- Karte vom Typ vision + +- RMB auf den Bereich +- Klick auf + Vision erstellen +- Vision-Karte sichtbar +---------------------------------------- + +Doppeltes Projekt verhindern + +- Projekt mit Namen erstellen +- Projekt mit gleichem Namen erstellen +- Meldung erscheint +- Projekt nicht erstellt diff --git a/daten/PLANER2GEN/funktionen.md b/daten/PLANER2GEN/funktionen.md new file mode 100644 index 0000000..ec1447c --- /dev/null +++ b/daten/PLANER2GEN/funktionen.md @@ -0,0 +1,102 @@ + +Funktionen +---------------------------------------- + +kern +---------------------------------------- + +Beschreibt einzelne Schritte einer Feature-Karte +---------------------------------------- + +- Leere Titel werden verworfen +- Bearbeiten nur im Vollmodus +- Stand wechselt zwischen offen und gebaut +- Jede Änderung speichert sofort +- Kein Verschieben bei erster oder letzter Funktion +- Kontextmenü schließt bei Klick außerhalb +- Funktionsmenü in Kompaktmodus öffnet Kartenmenü +- Ziel, Regeln und Testen ohne Bearbeitung im Kompaktmodus +---------------------------------------- + +Funktion anlegen + +Beschreibt eine neue Funktion der Karte + +- Funktion enthält Ziel, Regeln und Testen +- Neue Funktion beginnt mit Stand gebaut + +- RMB auf Feature-Karte +- Klick auf "+ Funktion erstellen" +- Titel im Modal eingeben +- Klick auf "Erstellen" +- Funktion erscheint in der Liste +---------------------------------------- + +Funktion löschen + +Entfernt eine nicht mehr benötigte Funktion aus der Liste + +- Nur im Vollmodus verfügbar +- x-Icon im Kontextmenü +- Modale Rückfrage vor dem Entfernen +- Speichert die Änderung + +- Vollmodus öffnen +- RMB auf Funktion +- x-Icon betätigen +- Funktion entfernt +---------------------------------------- + +Funktion nach oben bewegen + +Ändert die Reihenfolge der Funktionen + +- Nur verfügbar bei nicht erster Funktion +- Vertauscht die Funktionsposition mit der darüberliegenden +- Speichert automatisch + +- RMB auf Funktion +- ▲ Nach oben wählen +- Funktion eine Position höher +---------------------------------------- + +Funktionsstand wechseln + +Markiert eine Funktion als bestellt oder gebaut + +- Nur im Vollmodus verfügbar +- @click.stop verhindert das Kartenmenü +- Toggle zwischen offen und gebaut +- Speichert sofort + +- Vollmodus öffnen +- LMB auf Stand-Button einer Funktion +- Stand wechselt von offen zu ✓ oder zurück +- Änderung gespeichert +---------------------------------------- + +Kontextmenü anzeigen + +Bietet Zugriff auf kontextbezogene Aktionen einer Karte oder Funktion + +- Kartenmenü im Kompaktmodus verfügbar + +- Vollmodus öffnen +- RMB auf Funktionszeile +- Menü mit Verschieben und Entfernen sichtbar +---------------------------------------- + +Kontextmenü verbergen + +Schließt das Kontextmenü, wenn die Person woanders klickt oder Escape drückt + +- Klick außerhalb des Menüs schließt es +- Klick auf Menüeintrag führt Aktion aus +- Escape-Taste schließt das Menü + +- Kontextmenü öffnen +- LMB außerhalb des Menüs klicken +- Menü geschlossen +- Kontextmenü erneut öffnen +- Escape-Taste drücken +- Menü geschlossen diff --git a/daten/PLANER2GEN/pruefung.md b/daten/PLANER2GEN/pruefung.md new file mode 100644 index 0000000..582be22 --- /dev/null +++ b/daten/PLANER2GEN/pruefung.md @@ -0,0 +1,92 @@ + +Prüfung +---------------------------------------- + +kern +---------------------------------------- + +Prüft Feature-Karten auf formale Fehler und zeigt Stellen mit Problemen an +---------------------------------------- + +- Prüfung beenden gibt {"ok": true} zurück +- Fehlerstelle wird 1200ms lang hervorgehoben +- PruefPanel zeigt eine von vier Prüfarten: stil, feature, code, erzeugen +- Leerer Status ohne aktive Prüfung +- Eingabe bestätigen erfordert Bereitschaft des Systems +- Klick auf ✕ schließt das Panel +- Chat öffnen schließt das Prüfungspanel +---------------------------------------- + +Eingabe bestätigen + +Ermöglicht schnelle Bestätigung der Eingabe per Tastatur + +- Nur auslösbar wenn bereit true ist +- Emittiert bestaetigt-Event mit getrimmtem Wert + +- Eingabefeld fokussieren +- Text eingeben +- Enter drücken +- bestaetigt-Event mit Wert +---------------------------------------- + +Fehlerstelle anzeigen + +Navigiert zur Feature-Karte mit dem Problem + +- Scrollt zur Feature-Karte +- Markiert die Karte mit gesucht +- Highlight endet nach 1200ms + +- Prüfung mit Problemen öffnen +- LMB auf Problemeintrag +- Karte scrollt in die Ansicht und zeigt Highlight +---------------------------------------- + +Prüfung beenden + +Bricht die laufende Prüfung ab, ohne Ergebnisse zu übernehmen + +- Löschaufruf an Endpunkt +- Gibt ok true zurück +- FileNotFoundError als 404 weitergereicht + +- Prüfung im Projekt starten +- Warten auf Status running +- Löschaufruf an Prüfungsendpunkt senden +- Prüfung beendet +---------------------------------------- + +Prüfung starten + +Prüft das Projekt auf Probleme und zeigt gefundene Stellen + +- Vier Prüfarten verfügbar: erzeugen, stil, feature, code +- Progress in Prozent während der Prüfung +- PruefPanel zeigt Ergebnisse nach Abschluss + +- Prüfung starten mit Art "stil" +- Fortschritt in Prozent sichtbar +- PrüfPanel zeigt Ergebnisse +---------------------------------------- + +Prüfungsstatus anzeigen + +Zeigt den aktuellen Zustand einer laufenden Prüfung + +- Ohne aktive Prüfung wird ein leerer Status zurückgegeben + +- GET-Anfrage an Prüfungsendpunkt senden +- Status der Prüfung im Response +---------------------------------------- + +Systemstatus prüfen + +Prüft ob der Backend-Server erreichbar ist + +- GET api health +- Antwortet immer 200 mit {"ok": true} + +- GET api health +- Statuscode 200 +- {"ok": true} im Body diff --git a/daten/PLANER2GEN/verlauf.md b/daten/PLANER2GEN/verlauf.md new file mode 100644 index 0000000..508cc19 --- /dev/null +++ b/daten/PLANER2GEN/verlauf.md @@ -0,0 +1,62 @@ + +Verlauf +---------------------------------------- + +kern +---------------------------------------- + +Verfolgt Änderungen und macht sie rückgängig +---------------------------------------- + +- ↺-Icon zeigt letzten Schritt als Tooltip +- Leerer Verlauf ist kein Fehlerzustand +- ↩-Icon ist ↺-Icon im Code +---------------------------------------- + +Aktion rückgängig machen + +Nimmt den letzten Schritt im aktiven Projekt zurück + +- ↺-Schaltfläche bei fehlendem letzterSchritt deaktiviert +- Strg+Z gilt nicht in Eingabefeldern +- Fehlgeschlagener Aufruf zeigt Meldung + +- Projekt mit Verlauf öffnen +- ↺-Schaltfläche anklicken +- Letzter Schritt aus Verlauf entfernt +- Meldung bleibt leer +---------------------------------------- + +Chat-Verlauf abrufen + +Ermöglicht das Lesen vergangener Chat-Nachrichten eines Projekts + +- Gibt den gesamten Verlauf als Liste zurück +- 404 bei unbekanntem Projekt + +- GET-Anfrage an Chat-Endpunkt senden +- Verlauf als JSON-Array mit Nachrichten +- Unbekanntes Projekt gibt 404 +---------------------------------------- + +Projektverlauf anzeigen + +Zeigt den letzten Stand im Projektverlauf + +- 404 bei unbekanntem Projekt +- Feld "letzter" enthält letzten Verlaufseintrag + +- Endpunkt für Projektverlauf aufrufen +- Antwort mit Feld letzter prüfen +---------------------------------------- + +Änderung verwerfen + +- LMB auf ↩-Icon verwirft den letzten Schritt +- Strg+Z außerhalb von Eingabefeldern verwirft +- Ohne vorherigen Schritt ist das Icon deaktiviert +- Nach dem Verwerfen aktualisiert sich die Feature-Liste + +- Projekt mit einer Änderung öffnen +- LMB auf ↩-Icon +- Änderung in der Liste zurückgesetzt diff --git a/daten/PLANER2GEN/vorschlaege.md b/daten/PLANER2GEN/vorschlaege.md new file mode 100644 index 0000000..d7ba6bc --- /dev/null +++ b/daten/PLANER2GEN/vorschlaege.md @@ -0,0 +1,55 @@ + +Vorschläge +---------------------------------------- + +kern +---------------------------------------- + +Zeigt Katalogprüfungsergebnisse und erlaubt Übernahme oder Verwerfung +---------------------------------------- + +- Fehlerhafte Karten öffnen sich im Vollmodus +- Nicht anwendbarer Vorschlag bleibt stehen +- Verwerfen entfernt das Problem dauerhaft +- Vor dem Übernehmen ist der Unterschied sichtbar +---------------------------------------- + +Alle Vorschläge annehmen + +Nimmt alle Vorschläge auf einmal an statt einzeln + +- Kartenentfernung hat Priorität +- Nicht anwendbarer Vorschlag wird übersprungen + +- Karte mit N Problemen öffnen +- LMB auf Übernehmen-Button +- Vorschläge angewendet +- Karte gespeichert +---------------------------------------- + +Vorschlag verwerfen + +Entfernt einen Vorschlag aus der Anzeige, ohne ihn anzuwenden + +- Entfernt das Problem aus der Liste +- Die Karte bleibt unverändert + +- Karte mit Vorschlag öffnen +- Klick auf ✕-Icon +- Vorschlag verschwindet, Karte ist unverändert +---------------------------------------- + +Vorschlag übernehmen + +Nimmt einen Vorschlag als neue Feature-Karte ins Projekt auf + +- Feature mit Vorschlag öffnen +- Klick auf ✓-Icon +- Neue Karte im Gitter +---------------------------------------- + +Alle Vorschläge verwerfen + +- Vorschläge erstellen +- "Alle verwerfen" betätigen +- Alle Vorschläge verworfen diff --git a/daten/Planer/.planung/.pruefung.json b/daten/Planer/.planung/.pruefung.json new file mode 100644 index 0000000..59af213 --- /dev/null +++ b/daten/Planer/.planung/.pruefung.json @@ -0,0 +1,928 @@ +{ + "abdeckung": { + "bedienen:ablehnen": { + "abdruck": "e9cce25d92b81ff6", + "funktion": "Vorschlag annehmen", + "trug": "089e774256dcce89" + }, + "bedienen:alleAblehnen": { + "abdruck": "ac9262c7cafe9537", + "funktion": "Alle Vorschläge verwerfen", + "trug": "6869d68fdbd6d0a7" + }, + "bedienen:alleAnnehmen": { + "abdruck": "94f23cae75fdc531", + "funktion": "Alle Vorschläge annehmen", + "trug": "94ebeec7b03abb70" + }, + "bedienen:annehmen": { + "abdruck": "2742ad031b3d3cca", + "funktion": "Vorschlag annehmen", + "trug": "089e774256dcce89" + }, + "bedienen:auswaehlen": { + "abdruck": "d061bf62466085ce", + "funktion": "Projekt aufrufen", + "trug": "e24c2ab0a27ace24" + }, + "bedienen:bereichsMenue": { + "abdruck": "4277536d43c7bcd5", + "funktion": "Projekt aufrufen", + "trug": "e24c2ab0a27ace24" + }, + "bedienen:bestaetigen": { + "abdruck": "db1f954b9ad01749", + "funktion": "Eingabe mit Enter bestätigen", + "trug": "43fca3b0e83b3701" + }, + "bedienen:erledige": { + "abdruck": "1b80ae13958bb11a", + "funktion": "Vorgeschlagene Karte anlegen", + "trug": "de2b733c447db595" + }, + "bedienen:funktionsMenue": { + "abdruck": "bacdd0a7cc9d0f92", + "funktion": "Funktion verschieben", + "trug": "6a33d1b7b5a7f28c" + }, + "bedienen:karteAnnehmen": { + "abdruck": "bf348251763e402a", + "funktion": "Vorgeschlagene Karte anlegen", + "trug": "de2b733c447db595" + }, + "bedienen:kartenMenue": { + "abdruck": "d3ba136a562eb1e9", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" + }, + "bedienen:leeren": { + "abdruck": "f2af432a5ae3b255", + "funktion": "Gespräch verwerfen", + "trug": "1f848fba8b2a5e56" + }, + "bedienen:leistenMenue": { + "abdruck": "ed951fbeaaa9bc70", + "funktion": "Projekt anlegen", + "trug": "44b8a59e1dcb20d4" + }, + "bedienen:oeffneChat": { + "abdruck": "9bf171761edca141", + "funktion": "Gespräch öffnen", + "trug": "c71610a339bb298e" + }, + "bedienen:projektMenue": { + "abdruck": "ea73f8c2597c0443", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" + }, + "bedienen:schliesse": { + "abdruck": "919b104c012c034d", + "funktion": "", + "trug": "" + }, + "bedienen:schliessen": { + "abdruck": "1e12f9ae001e93e1", + "funktion": "Gespräch verwerfen", + "trug": "1f848fba8b2a5e56" + }, + "bedienen:senden": { + "abdruck": "8df3402ed3373acc", + "funktion": "Nachricht senden", + "trug": "e61022551a98250f" + }, + "bedienen:springe": { + "abdruck": "0b134efa50c03bff", + "funktion": "Problemstelle anspringen", + "trug": "7486526f6867c436" + }, + "bedienen:starte": { + "abdruck": "761c2f62c917a3db", + "funktion": "Titel anpassen", + "trug": "d0b7a430e96e2599" + }, + "bedienen:startePruefung": { + "abdruck": "31c3fef23c6319d8", + "funktion": "Gespräch öffnen", + "trug": "c71610a339bb298e" + }, + "bedienen:umbenennen": { + "abdruck": "6185b6b39708bf02", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" + }, + "bedienen:wechsleAnsicht": { + "abdruck": "e3193fce50eaa58e", + "funktion": "Anzeigemodus umschalten", + "trug": "fccea553715951de" + }, + "bedienen:wechsleArt": { + "abdruck": "67250a1e8d82e960", + "funktion": "Feature einstufen", + "trug": "90b6c77ff0c412e6" + }, + "bedienen:wechsleDarkMode": { + "abdruck": "b83524eb0e12a7d7", + "funktion": "Darkmode umschalten", + "trug": "4033fc55c753db3e" + }, + "bedienen:wechsleStand": { + "abdruck": "8c2e3bf3be58ec00", + "funktion": "Stand umschalten", + "trug": "37a3835d1d2a3e6c" + }, + "bedienen:zurueck": { + "abdruck": "e378014fbce96d10", + "funktion": "Schritt zurücknehmen", + "trug": "10e46c458040a5e3" + }, + "hoeren:systemDunkel.change": { + "abdruck": "d3ef681b987557dc", + "funktion": "Darkmode umschalten", + "trug": "4033fc55c753db3e" + }, + "hoeren:window.click": { + "abdruck": "620812522ed2d900", + "funktion": "Kontextmenü schließen", + "trug": "87216235bbe42a1a" + }, + "hoeren:window.keydown": { + "abdruck": "c3e1df2d60fcc067", + "funktion": "Schritt zurücknehmen", + "trug": "10e46c458040a5e3" + }, + "menue:+ Feature erstellen": { + "abdruck": "82c40072137d5757", + "funktion": "Feature anlegen", + "trug": "df7a1452a32da410" + }, + "menue:+ Funktion erstellen": { + "abdruck": "b44457d64a5ec9d1", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" + }, + "menue:+ Projekt erstellen": { + "abdruck": "2be770390433a2ce", + "funktion": "Projekt anlegen", + "trug": "44b8a59e1dcb20d4" + }, + "menue:+ Vision erstellen": { + "abdruck": "cb22a654070e58b4", + "funktion": "Feature anlegen", + "trug": "df7a1452a32da410" + }, + "menue:→ Feature verschieben": { + "abdruck": "38e6b244668ee164", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" + }, + "menue:▲ Nach oben": { + "abdruck": "4e6fd1617d817357", + "funktion": "Funktion verschieben", + "trug": "6a33d1b7b5a7f28c" + }, + "menue:▼ Nach unten": { + "abdruck": "183651450e546c4f", + "funktion": "Funktion entfernen", + "trug": "885e16a93460f706" + }, + "menue:◇ Quelle festlegen": { + "abdruck": "e4bb1781bc375d6d", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" + }, + "menue:✎ Projekt anpassen": { + "abdruck": "ad505addca45b06c", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" + }, + "menue:✕ Feature entfernen": { + "abdruck": "bc968582260c45b9", + "funktion": "Funktion anlegen", + "trug": "78d0329cf6eacca9" + }, + "menue:✕ Funktion entfernen": { + "abdruck": "d29458b150c55777", + "funktion": "Funktion verschieben", + "trug": "6a33d1b7b5a7f28c" + }, + "menue:✕ Projekt entfernen": { + "abdruck": "aca25c0b5feaf752", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" + }, + "menue:✕ Vision entfernen": { + "abdruck": "88520b1f105d3fb5", + "funktion": "Anzeigemodus umschalten", + "trug": "fccea553715951de" + }, + "route:delete /projekte/{name}": { + "abdruck": "b4f871be35d10e5f", + "funktion": "Projekt entfernen", + "trug": "e91a89b8d78dbd2e" + }, + "route:delete /projekte/{name}/features/{id}": { + "abdruck": "c1db81de98835c39", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" + }, + "route:delete /projekte/{name}/pruefung": { + "abdruck": "7a480f33ddf55165", + "funktion": "Prüfung beenden", + "trug": "83435eb3e1394e49" + }, + "route:get /health": { + "abdruck": "65257319741edf35", + "funktion": "", + "trug": "" + }, + "route:get /projekte": { + "abdruck": "276556054437c303", + "funktion": "", + "trug": "" + }, + "route:get /projekte/{name}/chat": { + "abdruck": "fd2a22c36ea85545", + "funktion": "Gespräch öffnen", + "trug": "c71610a339bb298e" + }, + "route:get /projekte/{name}/features": { + "abdruck": "122f93cbd0d07881", + "funktion": "Projekt aufrufen", + "trug": "e24c2ab0a27ace24" + }, + "route:get /projekte/{name}/pruefung": { + "abdruck": "e651ac90b7b2c520", + "funktion": "", + "trug": "" + }, + "route:get /projekte/{name}/quelle": { + "abdruck": "834d3af3203ca3a8", + "funktion": "Quelle festlegen", + "trug": "b8b70dd0ff9817cb" + }, + "route:get /projekte/{name}/verlauf": { + "abdruck": "5a3dcc678733fad8", + "funktion": "", + "trug": "" + }, + "route:post /projekte": { + "abdruck": "fa1628d7e469885d", + "funktion": "Projekt anlegen", + "trug": "44b8a59e1dcb20d4" + }, + "route:post /projekte/{name}/chat": { + "abdruck": "c3edc89cec5d2f6f", + "funktion": "Nachricht senden", + "trug": "e61022551a98250f" + }, + "route:post /projekte/{name}/features": { + "abdruck": "00eb9c16560bac73", + "funktion": "Feature anlegen", + "trug": "df7a1452a32da410" + }, + "route:post /projekte/{name}/pruefung": { + "abdruck": "6d7444a9dfad7d54", + "funktion": "Stil prüfen", + "trug": "d5019cdafd70efb7" + }, + "route:post /projekte/{name}/pruefung/verworfen": { + "abdruck": "a43f7221e01c386f", + "funktion": "Alle Vorschläge verwerfen", + "trug": "6869d68fdbd6d0a7" + }, + "route:post /projekte/{name}/verlauf/zurueck": { + "abdruck": "308fec6d21b01d60", + "funktion": "Schritt zurücknehmen", + "trug": "10e46c458040a5e3" + }, + "route:put /projekte/{name}": { + "abdruck": "75383ac009961cad", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" + }, + "route:put /projekte/{name}/features/{id}": { + "abdruck": "b24c7000fd2ec94c", + "funktion": "", + "trug": "" + }, + "route:put /projekte/{name}/features/{id}/projekt": { + "abdruck": "fafc7a8a1656f93b", + "funktion": "Feature verschieben", + "trug": "cd2cd705298831e0" + }, + "route:put /projekte/{name}/quelle": { + "abdruck": "d342055e3163548a", + "funktion": "Quelle festlegen", + "trug": "b8b70dd0ff9817cb" + } + }, + "belege": { + "[\"darkmode\", \"Darkmode umschalten\"]": { + "abdruck": "653c08d0647a7f7b", + "beleg": "function wechsleDarkMode() {\n modus.value = MODI[(MODI.indexOf(modus.value) + 1) % MODI.length]\n localStorage.setItem('darkModus', modus.value)\n wendeAn()\n}", + "datei": "frontend/src/App.vue" + }, + "[\"design\", \"Eingabe mit Enter bestätigen\"]": { + "abdruck": "3bace3e9c9f16023", + "beleg": "@keydown.enter.exact.prevent=\"senden\"", + "datei": "frontend/src/components/ChatPanel.vue" + }, + "[\"design\", \"Kontextmenü schließen\"]": { + "abdruck": "671fa86bccb2c2c6", + "beleg": "export function schliesseMenue() {\n kontextMenue.value = null\n}", + "datei": "frontend/src/composables/kontextmenue.js" + }, + "[\"features\", \"Anzeigemodus umschalten\"]": { + "abdruck": "b22ba2dd122887fa", + "beleg": "function wechsleAnsicht() {\n gross.value = !gross.value\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"features\", \"Feature anlegen\"]": { + "abdruck": "d2968bea16a06b65", + "beleg": "async function erstellen(titel) {", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"features\", \"Feature durchsuchen\"]": { + "abdruck": "4f249c42d46d25b5", + "beleg": "function passt(f) {\n const wort = suche.value.trim().toLowerCase()\n if (!wort) return true\n const s = f.sektionen\n const text = [s.titel, s.ziel, s.regeln,\n ...s.funktionen.map(x => `${x.text} ${x.ziel} ${x.regeln} ${x.testen}`)]\n return text.join(' ').toLowerCase().includes(wort)\n}", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"features\", \"Feature einstufen\"]": { + "abdruck": "a0ee6590c24456bb", + "beleg": "function wechsleArt() {\n s.value.art = s.value.art === 'kern' ? 'optional' : 'kern'\n speichern()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"features\", \"Feature entfernen\"]": { + "abdruck": "c6f27381a41a63d7", + "beleg": "async function entfernen() {\n const id = modal.value.feature.id\n try {\n await featureLoeschen(props.projekt, id)\n features.value = features.value.filter(f => f.id !== id)\n modal.value = null\n emit('geaendert')\n } catch (e) {\n meldung.value = e.message\n }\n}", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"features\", \"Feature verschieben\"]": { + "abdruck": "a82b97e3d4a1b533", + "beleg": "def verschieben(projekt: str, id: str, ziel: str) -> dict:", + "datei": "backend/features.py" + }, + "[\"features\", \"Regeln anpassen\"]": { + "abdruck": "0af0e4eadcaae560", + "beleg": "
", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"features\", \"Titel anpassen\"]": { + "abdruck": "7f727f71dc555492", + "beleg": "

{{ s.titel }}

", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"features\", \"Ziel anpassen\"]": { + "abdruck": "965b52779fa6aa35", + "beleg": "
", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktion anlegen\"]": { + "abdruck": "6250215b920cf0f0", + "beleg": "async function funktionErstellen(titel) {", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktion entfernen\"]": { + "abdruck": "20e8d8e507ee6310", + "beleg": "eintraege.push({ text: '✕ Funktion entfernen', aktion: () => (modal.value = { art: 'entfernen', i }) })", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktion verschieben\"]": { + "abdruck": "8435119f0dd5b891", + "beleg": "async function schiebe(i, richtung) {", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Regeln anpassen\"]": { + "abdruck": "303d6988603e3d61", + "beleg": "async function starte(feld, i, j) {\n if (!gross.value) return // Bearbeiten nur in der ausführlichen Ansicht\n const original = wert(feld, i, j)\n aktiv.value = { feld, i, j, original }\n entwurf.value = original\n await nextTick()\n const el = Array.isArray(feldRef.value) ? feldRef.value[0] : feldRef.value\n el?.focus()\n if (feld === 'titel') el?.select()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Stand umschalten\"]": { + "abdruck": "b66ea5f488899d8f", + "beleg": "@click.stop=\"wechsleStand(i)\"", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Testschritte anpassen\"]": { + "abdruck": "e303ebeaece423de", + "beleg": "
", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Titel anpassen\"]": { + "abdruck": "3ceaa19290c793b4", + "beleg": "s.value.funktionen[a.i].text = neu", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Ziel anpassen\"]": { + "abdruck": "4cb617031cbf6ef4", + "beleg": "
", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"karten-besprechen\", \"Gespräch schließen\"]": { + "abdruck": "d6de2c46300fef26", + "beleg": "", + "datei": "frontend/src/components/ChatPanel.vue" + }, + "[\"karten-besprechen\", \"Gespräch verwerfen\"]": { + "abdruck": "9e74be976a4d0e15", + "beleg": "@router.delete(\"/projekte/{name}/chat\")\nasync def chat_leeren(name: str):\n try:\n chat.leeren(name)\n except FileNotFoundError as e:\n raise HTTPException(404, str(e))\n return {\"ok\": True}", + "datei": "backend/routes.py" + }, + "[\"karten-besprechen\", \"Gespräch öffnen\"]": { + "abdruck": "c84f9a14428a019e", + "beleg": "✎", + "datei": "frontend/src/App.vue" + }, + "[\"karten-besprechen\", \"Nachricht senden\"]": { + "abdruck": "308218d682fe3dd9", + "beleg": "async def frage(projekt: str, text: str) -> dict:", + "datei": "backend/chat.py" + }, + "[\"karten-besprechen\", \"Vorgeschlagene Karte anlegen\"]": { + "abdruck": "15aa862d2e0f6f6e", + "beleg": "async function karteAnnehmen(p) {", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"karten-pruefen\", \"Alle Vorschläge annehmen\"]": { + "abdruck": "52fb2acd3d6945fa", + "beleg": "async function alleAnnehmen() {\n props.probleme.forEach(p => { if (anwenden(p)) erledige(p) })\n await speichern()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"karten-pruefen\", \"Alle Vorschläge verwerfen\"]": { + "abdruck": "f98fd3fc005b9e56", + "beleg": "✕", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"karten-pruefen\", \"Code in Features prüfen\"]": { + "abdruck": "daf5820ada5ee059", + "beleg": "async def code_im_feature(features: list, punkte: list, stand: dict,", + "datei": "backend/inhalt.py" + }, + "[\"karten-pruefen\", \"Features im Code prüfen\"]": { + "abdruck": "acc652c172671790", + "beleg": "ANKLAGE_AB = 4", + "datei": "backend/inhalt.py" + }, + "[\"karten-pruefen\", \"Funktion abnehmen\"]": { + "abdruck": "21095461d6190dec", + "beleg": "if beleg:\n stand[\"belege\"][schluessel] = beleg\n if x.get(\"stand\") == parser.OFFEN:\n # Abnahme: die Karte hat es bestellt, jetzt steht es im Code\n return {\"feature\": feature[\"id\"], \"titel\": x[\"text\"], \"art\": \"gebaut\",\n \"grund\": f'{beleg[\"datei\"]}: {beleg[\"beleg\"].strip()}'}", + "datei": "backend/inhalt.py" + }, + "[\"karten-pruefen\", \"Problemstelle anspringen\"]": { + "abdruck": "340a32321fd23834", + "beleg": "karte.classList.add('gesucht')", + "datei": "frontend/src/components/PruefPanel.vue" + }, + "[\"karten-pruefen\", \"Prüfung beenden\"]": { + "abdruck": "7400070de29ce762", + "beleg": "", + "datei": "frontend/src/components/PruefPanel.vue" + }, + "[\"karten-pruefen\", \"Stil prüfen\"]": { + "abdruck": "86c4530f5dd0bd52", + "beleg": "async def starte(projekt: str, art: str = \"stil\") -> dict:", + "datei": "backend/pruefung.py" + }, + "[\"karten-pruefen\", \"Vorschlag annehmen\"]": { + "abdruck": "e4b81d800fd23fec", + "beleg": "async function annehmen(p) {\n if (anwenden(p)) erledige(p)\n await speichern()\n}", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"karten-pruefen\", \"Vorschlag verwerfen\"]": { + "abdruck": "b37b74ea369ed66c", + "beleg": "export function erledige(problem) {\n probleme.value = probleme.value.filter(p => p !== problem)\n}", + "datei": "frontend/src/composables/pruefung.js" + }, + "[\"projekte\", \"Projekt anlegen\"]": { + "abdruck": "9b3598c9081155b2", + "beleg": "def anlegen(name: str):", + "datei": "backend/projekte.py" + }, + "[\"projekte\", \"Projekt aufrufen\"]": { + "abdruck": "1071109545496535", + "beleg": "@click=\"emit('auswaehlen', p.name)\"", + "datei": "frontend/src/components/SeitenLeiste.vue" + }, + "[\"projekte\", \"Projekt entfernen\"]": { + "abdruck": "e413063557fa0f13", + "beleg": "shutil.rmtree(ordner)", + "datei": "backend/projekte.py" + }, + "[\"projekte\", \"Projekt umbenennen\"]": { + "abdruck": "d4e71f8ef907393c", + "beleg": "function projektMenue(e, name) {\n oeffneMenue(e, [\n { text: '✎ Projekt anpassen', aktion: () => starteUmbenennen(name) },\n { text: '◇ Quelle festlegen', aktion: () => starteQuelle(name) },\n { text: '✕ Projekt entfernen', aktion: () => oeffneModal({ art: 'entfernen', name }) },\n ])\n}", + "datei": "frontend/src/components/SeitenLeiste.vue" + }, + "[\"projekte\", \"Quelle festlegen\"]": { + "abdruck": "fc6c20f4e8d74fa6", + "beleg": "if ziel == Path(ziel.anchor) or ziel == Path.home():", + "datei": "backend/quelle.py" + }, + "[\"schritt-zuruecknehmen\", \"Nächsten Rückschritt anzeigen\"]": { + "abdruck": "6768d8a0b83537a2", + "beleg": "letzterSchritt.value = (await fetchVerlauf(aktivesProjekt.value)).letzter", + "datei": "frontend/src/App.vue" + }, + "[\"schritt-zuruecknehmen\", \"Schritt zurücknehmen\"]": { + "abdruck": "c49332e7a679dfda", + "beleg": "def zurueck(projekt: str) -> str:\n \"\"\"Den letzten Schritt zurücknehmen. Gibt zurück, was zurückgenommen wurde.\"\"\"\n schritte = lade(projekt)\n if not schritte:\n raise ValueError(\"Nichts zum Zurücknehmen\")\n schritt = schritte.pop()", + "datei": "backend/verlauf.py" + }, + "[\"vision-festhalten\", \"Anzeigemodus umschalten\"]": { + "abdruck": "b983b82c02343560", + "beleg": "const gross = ref(false)", + "datei": "frontend/src/components/VisionKarte.vue" + }, + "[\"vision-festhalten\", \"Vision anlegen\"]": { + "abdruck": "58ceb9502d1754bf", + "beleg": "
", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"vision-festhalten\", \"Vision anpassen\"]": { + "abdruck": "dd527b57b4c9685e", + "beleg": "async function fertig() {\n if (!aktiv.value) return\n aktiv.value = false\n const neu = entwurf.value.trim()\n if (neu === text.value) return\n text.value = neu\n await speichern()\n}", + "datei": "frontend/src/components/VisionKarte.vue" + }, + "[\"vision-festhalten\", \"Vision entfernen\"]": { + "abdruck": "0aeb156d13b32b7e", + "beleg": "function kartenMenue(e) {\n oeffneMenue(e, [{ text: '✕ Vision entfernen', aktion: () => emit('entfernen') }])\n}", + "datei": "frontend/src/components/VisionKarte.vue" + } + }, + "ohne_code": {}, + "ohne_karte": { + "route:delete /projekte/{name}/chat": { + "abdruck": "4ba7a240985a83b4", + "beleg": "backend/routes.py:182", + "feature": "karten-besprechen", + "karten": "41f55589fcff4959", + "stelle": "route:delete /projekte/{name}/chat", + "titel": "Chatverlauf leeren" + } + }, + "paare": { + "[\"[\\\"features\\\", \\\"Anzeigemodus umschalten\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Anzeigemodus umschalten\\\"]\"]": { + "abdruck": "d23706be97d6369a", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature anlegen\\\"]\", \"[\\\"features\\\", \\\"Feature entfernen\\\"]\"]": { + "abdruck": "586059671bbfa75b", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\"]": { + "abdruck": "3eb9956887005cc4", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature anlegen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt anlegen\\\"]\"]": { + "abdruck": "66a7175c58b703c4", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\"]": { + "abdruck": "97a9dde3e968b1eb", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion entfernen\\\"]\"]": { + "abdruck": "9717a5c6eab69f22", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\"]": { + "abdruck": "65c43ee10d0d8b4a", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision entfernen\\\"]\"]": { + "abdruck": "60434d422bbd2ca3", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"features\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "75e90ff6d5453c2d", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"features\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "a9e849a044a7ee41", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\"]": { + "abdruck": "827215ea68dcbada", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "ea7185c230fbdd2f", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "bc79858745a7d262", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Titel anpassen\\\"]\", \"[\\\"features\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "69360dc1502aa01f", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Titel anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "01fbbfc1ca91d32a", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Titel anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "414ddf4e7bff9896", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Ziel anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "83a0a87e978c859a", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Ziel anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "5e97e3c6fe9df287", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion entfernen\\\"]\"]": { + "abdruck": "3e58148f974b6b34", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt anlegen\\\"]\"]": { + "abdruck": "202f51c53a73b452", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion entfernen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\"]": { + "abdruck": "a9d2c4dd5e70fa2c", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Funktion entfernen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision entfernen\\\"]\"]": { + "abdruck": "4090ee6826466fa3", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "c8321ad2b769d77f", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "7ce003da82080259", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"karten-pruefen\\\", \\\"Funktion abnehmen\\\"]\"]": { + "abdruck": "d2f80684e1be6287", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Testschritte anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "7a51922f327ba28b", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Testschritte anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "97a70c7ecfbb9f30", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "17b00db94f54b62d", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision anpassen\\\"]\"]": { + "abdruck": "d17a7b7bad8d947a", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision anpassen\\\"]\"]": { + "abdruck": "e25b21ca4183d372", + "gleich": false + }, + "[\"[\\\"karten-pruefen\\\", \\\"Alle Vorschläge annehmen\\\"]\", \"[\\\"karten-pruefen\\\", \\\"Alle Vorschläge verwerfen\\\"]\"]": { + "abdruck": "b9c707879cffb7cd", + "gleich": false + }, + "[\"[\\\"karten-pruefen\\\", \\\"Alle Vorschläge verwerfen\\\"]\", \"[\\\"karten-pruefen\\\", \\\"Vorschlag verwerfen\\\"]\"]": { + "abdruck": "aed348a776637c4a", + "gleich": false + }, + "[\"[\\\"projekte\\\", \\\"Projekt anlegen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\"]": { + "abdruck": "957ebec8e3096ce6", + "gleich": false + }, + "[\"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision entfernen\\\"]\"]": { + "abdruck": "8757fb8b0f89d5a6", + "gleich": false + } + }, + "stil": { + "[\"darkmode\", \"\"]": { + "abdruck": "a5b0fd59f25c55ae", + "probleme": [] + }, + "[\"darkmode\", \"Darkmode umschalten\"]": { + "abdruck": "0dbcca6954cc4d16", + "probleme": [] + }, + "[\"design\", \"\"]": { + "abdruck": "1ae7985ebcfe6c6a", + "probleme": [] + }, + "[\"design\", \"Eingabe mit Enter bestätigen\"]": { + "abdruck": "b961f168017fb01e", + "probleme": [] + }, + "[\"design\", \"Kontextmenü schließen\"]": { + "abdruck": "a3717ea52a012784", + "probleme": [] + }, + "[\"features\", \"\"]": { + "abdruck": "b4f6fe4cd065e9e9", + "probleme": [] + }, + "[\"features\", \"Anzeigemodus umschalten\"]": { + "abdruck": "8d468a73bcec5521", + "probleme": [] + }, + "[\"features\", \"Feature anlegen\"]": { + "abdruck": "7d4d6e36b4f03318", + "probleme": [] + }, + "[\"features\", \"Feature durchsuchen\"]": { + "abdruck": "3acde68ab76b942c", + "probleme": [] + }, + "[\"features\", \"Feature einstufen\"]": { + "abdruck": "10e74d934dafacc9", + "probleme": [] + }, + "[\"features\", \"Feature entfernen\"]": { + "abdruck": "509a1153b2e6382f", + "probleme": [] + }, + "[\"features\", \"Feature verschieben\"]": { + "abdruck": "5169bc85a796b6a9", + "probleme": [] + }, + "[\"features\", \"Regeln anpassen\"]": { + "abdruck": "6b4eeed76c631333", + "probleme": [] + }, + "[\"features\", \"Titel anpassen\"]": { + "abdruck": "de6e2788e24aa230", + "probleme": [] + }, + "[\"features\", \"Ziel anpassen\"]": { + "abdruck": "f26e4426663b8265", + "probleme": [] + }, + "[\"funktionen\", \"\"]": { + "abdruck": "adcc38efdb393cf6", + "probleme": [] + }, + "[\"funktionen\", \"Funktion anlegen\"]": { + "abdruck": "11c59974712619a0", + "probleme": [] + }, + "[\"funktionen\", \"Funktion entfernen\"]": { + "abdruck": "e55d43e078f1020e", + "probleme": [] + }, + "[\"funktionen\", \"Funktion verschieben\"]": { + "abdruck": "1bdf3be9b53fdb99", + "probleme": [] + }, + "[\"funktionen\", \"Regeln anpassen\"]": { + "abdruck": "e354caf2701ee79c", + "probleme": [] + }, + "[\"funktionen\", \"Stand umschalten\"]": { + "abdruck": "f39b25d34cc6e4c4", + "probleme": [] + }, + "[\"funktionen\", \"Testschritte anpassen\"]": { + "abdruck": "8fb282300c19c3c2", + "probleme": [] + }, + "[\"funktionen\", \"Titel anpassen\"]": { + "abdruck": "63e9a78a02d890fe", + "probleme": [] + }, + "[\"funktionen\", \"Ziel anpassen\"]": { + "abdruck": "a72ce3656c787475", + "probleme": [] + }, + "[\"karten-besprechen\", \"\"]": { + "abdruck": "8d330c5a71e25e0c", + "probleme": [] + }, + "[\"karten-besprechen\", \"Gespräch schließen\"]": { + "abdruck": "d1c043cd26a05d69", + "probleme": [] + }, + "[\"karten-besprechen\", \"Gespräch verwerfen\"]": { + "abdruck": "e6d601409eb48f7a", + "probleme": [] + }, + "[\"karten-besprechen\", \"Gespräch öffnen\"]": { + "abdruck": "b9a3f8340aa9e266", + "probleme": [] + }, + "[\"karten-besprechen\", \"Nachricht senden\"]": { + "abdruck": "c3ec1453a9aff541", + "probleme": [] + }, + "[\"karten-besprechen\", \"Vorgeschlagene Karte anlegen\"]": { + "abdruck": "ca0a5b02f10bbd1e", + "probleme": [] + }, + "[\"karten-pruefen\", \"\"]": { + "abdruck": "43f92e591142fa95", + "probleme": [] + }, + "[\"karten-pruefen\", \"Alle Vorschläge annehmen\"]": { + "abdruck": "5afe1e8ec40d8b82", + "probleme": [] + }, + "[\"karten-pruefen\", \"Alle Vorschläge verwerfen\"]": { + "abdruck": "c44bbe11908637e9", + "probleme": [] + }, + "[\"karten-pruefen\", \"Code in Features prüfen\"]": { + "abdruck": "ed5da2461b99ddf3", + "probleme": [] + }, + "[\"karten-pruefen\", \"Features im Code prüfen\"]": { + "abdruck": "c31fcfa6dbc75232", + "probleme": [] + }, + "[\"karten-pruefen\", \"Funktion abnehmen\"]": { + "abdruck": "dd3cf177204bcf25", + "probleme": [] + }, + "[\"karten-pruefen\", \"Problemstelle anspringen\"]": { + "abdruck": "0656bbf0d6554c85", + "probleme": [] + }, + "[\"karten-pruefen\", \"Prüfung beenden\"]": { + "abdruck": "af40481c06d2fd97", + "probleme": [] + }, + "[\"karten-pruefen\", \"Stil prüfen\"]": { + "abdruck": "8326e792e8383b53", + "probleme": [] + }, + "[\"karten-pruefen\", \"Vorschlag annehmen\"]": { + "abdruck": "6f8d17b80787b7aa", + "probleme": [] + }, + "[\"karten-pruefen\", \"Vorschlag verwerfen\"]": { + "abdruck": "cf5bda968428df9f", + "probleme": [] + }, + "[\"projekte\", \"\"]": { + "abdruck": "a59f6fdfa58188fa", + "probleme": [] + }, + "[\"projekte\", \"Projekt anlegen\"]": { + "abdruck": "2c3ab4452996ffaf", + "probleme": [] + }, + "[\"projekte\", \"Projekt aufrufen\"]": { + "abdruck": "2ca7a3ea9e79fc6e", + "probleme": [] + }, + "[\"projekte\", \"Projekt entfernen\"]": { + "abdruck": "a0c52ceb9605a805", + "probleme": [] + }, + "[\"projekte\", \"Projekt umbenennen\"]": { + "abdruck": "d41292ff010e7fd3", + "probleme": [] + }, + "[\"projekte\", \"Quelle festlegen\"]": { + "abdruck": "990ee354f1aa70fa", + "probleme": [] + }, + "[\"schritt-zuruecknehmen\", \"\"]": { + "abdruck": "f4ecff18e05ff058", + "probleme": [] + }, + "[\"schritt-zuruecknehmen\", \"Nächsten Rückschritt anzeigen\"]": { + "abdruck": "2d944c3424b6f851", + "probleme": [] + }, + "[\"schritt-zuruecknehmen\", \"Schritt zurücknehmen\"]": { + "abdruck": "28825333acb1e107", + "probleme": [] + }, + "[\"vision-festhalten\", \"\"]": { + "abdruck": "e83e9ad5470aa4b1", + "probleme": [] + }, + "[\"vision-festhalten\", \"Anzeigemodus umschalten\"]": { + "abdruck": "87c494e1e1b0a7b2", + "probleme": [] + }, + "[\"vision-festhalten\", \"Vision anlegen\"]": { + "abdruck": "7826b26956ba51d2", + "probleme": [] + }, + "[\"vision-festhalten\", \"Vision anpassen\"]": { + "abdruck": "378ea30c154f7994", + "probleme": [] + }, + "[\"vision-festhalten\", \"Vision entfernen\"]": { + "abdruck": "340343e51583e86a", + "probleme": [] + } + }, + "verworfen": { + "route:delete /projekte/{name}/chat": { + "abdruck": "4ba7a240985a83b4", + "titel": "Gespräch schließen\nChatverlauf leeren" + } + } +} diff --git a/daten/Planer/.planung/darkmode.md b/daten/Planer/.planung/darkmode.md new file mode 100644 index 0000000..11c604c --- /dev/null +++ b/daten/Planer/.planung/darkmode.md @@ -0,0 +1,23 @@ + +Darkmode +---------------------------------------- + +optional +---------------------------------------- + +Passt die Anwendung ans Umgebungslicht an +---------------------------------------- + +- Auto folgt der Systemeinstellung +- Zustand überlebt das Neuladen +- Kein Flackern beim Laden +---------------------------------------- + +Darkmode umschalten + +- Nacht-Icon: ☾ +- Tag-Icon: ☀ +- Auto-Icon: A + +- LMB auf Icon in der Kopfzeile +- Modus gewechselt diff --git a/daten/Planer/.planung/design.md b/daten/Planer/.planung/design.md new file mode 100644 index 0000000..54257c1 --- /dev/null +++ b/daten/Planer/.planung/design.md @@ -0,0 +1,44 @@ + +Design +---------------------------------------- + +optional +---------------------------------------- + +Hält die Oberfläche lesbar und ruhig +---------------------------------------- + +- Karten stapeln sich lückenlos in Spalten +- Lesefeld ist in der Breite gedeckelt +- Leisten scrollen nicht mit +- Schmale Fenster stapeln die Bereiche +- Klickflächen sind mindestens 28 Pixel +- Textkontrast erfüllt die Lesbarkeitsschwelle +- Kontextmenü bleibt im Fenster +- Modal setzt den Fokus ins Eingabefeld +- Escape schließt das Modal +---------------------------------------- + +Eingabe mit Enter bestätigen + +Spart den Weg zum Knopf + +- Gilt in einzeiligen Feldern +- Escape verwirft stattdessen + +- Modal öffnen +- Text eingeben +- Enter drücken +- Eingabe übernommen + +Kontextmenü schließen + +Räumt ein offenes Menü aus dem Weg + +- Klick daneben schließt es +- Escape schließt es +- Ein neues Menü verdrängt das alte + +- RMB auf eine Karte +- LMB daneben +- Menü geschlossen diff --git a/daten/Planer/.planung/features.md b/daten/Planer/.planung/features.md new file mode 100644 index 0000000..04d00f8 --- /dev/null +++ b/daten/Planer/.planung/features.md @@ -0,0 +1,109 @@ + +Features +---------------------------------------- + +kern +---------------------------------------- + +Hält fest, was ein Projekt können soll +---------------------------------------- + +- Eine Markdown-Datei je Feature +- Die Datei ist die Wahrheit +- Titel bestimmt den Dateinamen +- Namensgleichheit bekommt eine Nummer +- Fremde Marker bleiben erhalten +- Alphabetisch sortiert +- Anpassen nur im Vollmodus +- Verlassen speichert +- Escape verwirft +---------------------------------------- + +Anzeigemodus umschalten + +Kompaktmodus zum Lesen, Vollmodus zum Anpassen + +- Standard ist Kompaktmodus +- Vollmodus zeigt alle Felder +- Augen-Icon rechts oben + +- MMB auf Featurecard +- Modus umgeschaltet + +Feature anlegen + +- +-Icon +- Feature öffnet im Vollmodus + +- RMB auf Hauptbereich +- Klick auf "Feature erstellen" +- Namen im Modal eingeben +- Bestätigen mit LMB +- Feature angelegt + +Feature einstufen + +Trennt tragende von verzichtbaren Features + +- Kern blau umrandet +- Optional grün umrandet +- Badge zeigt die Einstufung + +- Vollmodus öffnen +- LMB auf Badge +- Einstufung gewechselt + +Feature durchsuchen + +Findet die Karte, ohne alle zu lesen + +- Sucht in allen Feldern +- Zählt Ausgeblendete mit + +- Suchwort eingeben +- Nur passende Karten bleiben + +Feature entfernen + +- x-Icon + +- RMB auf Featurecard +- Klick auf "Feature entfernen" +- Bestätigen im Modal +- Feature entfernt + +Feature verschieben + +Hängt ein Feature in ein anderes Projekt um + +- Datei wandert +- Datei wird nicht kopiert +- Nur bei mehreren Projekten + +- RMB auf Featurecard +- Klick auf "Feature verschieben" +- Zielprojekt wählen +- Feature verschoben + +Regeln anpassen + +- Vollmodus öffnen +- LMB auf Regeln der Karte +- Text ändern +- Regeln angepasst + +Titel anpassen + +- Aktualisiert den Dateinamen + +- Vollmodus öffnen +- LMB auf Titel der Karte +- Text ändern +- Titel angepasst + +Ziel anpassen + +- Vollmodus öffnen +- LMB auf Ziel der Karte +- Text ändern +- Ziel angepasst diff --git a/daten/Planer/.planung/funktionen.md b/daten/Planer/.planung/funktionen.md new file mode 100644 index 0000000..c65e957 --- /dev/null +++ b/daten/Planer/.planung/funktionen.md @@ -0,0 +1,98 @@ + +Funktionen +---------------------------------------- + +kern +---------------------------------------- + +Zerlegt ein Feature in prüfbare Stücke +---------------------------------------- + +- Gehört zu genau einem Feature +- Offen heißt bestellt, nicht gebaut +- Neue Funktionen von Hand gelten als gebaut +- Reihenfolge frei wählbar +- Ziel bleibt freiwillig +- Regeln bleiben freiwillig +- Testen bleibt freiwillig +- Anpassen nur im Vollmodus +- Verlassen speichert +- Escape verwirft +---------------------------------------- + +Funktion anlegen + +- +-Icon + +- Vollmodus öffnen +- RMB auf Featurecard +- Klick auf "Funktion erstellen" +- Namen im Modal eingeben +- Bestätigen mit LMB +- Funktion angelegt + +Funktion entfernen + +- x-Icon + +- Vollmodus öffnen +- RMB auf Funktion +- Klick auf "Funktion entfernen" +- Bestätigen im Modal +- Funktion entfernt + +Stand umschalten + +Trennt Bestelltes von Gebautem + +- Marke rechts vom Titel +- Offen ist gelb +- Gebaut ist ein Haken +- Kompakt erscheint nur die offene Marke + +- Vollmodus öffnen +- LMB auf die Marke +- Stand gewechselt + +Funktion verschieben + +Bringt die Schritte in ihre natürliche Folge + +- Reihenfolge steht in der Datei + +- Vollmodus öffnen +- RMB auf Funktion +- Klick auf "Nach oben" +- Funktion verschoben + +Titel anpassen + +- Vollmodus öffnen +- LMB auf Funktionstitel +- Text ändern +- Titel angepasst + +Ziel anpassen + +- Vollmodus öffnen +- LMB auf Ziel der Funktion +- Text ändern +- Ziel angepasst + +Regeln anpassen + +- Eine Regel je Zeile + +- Vollmodus öffnen +- LMB auf Regeln der Funktion +- Text ändern +- Regeln angepasst + +Testschritte anpassen + +- Ein Schritt je Zeile + +- Vollmodus öffnen +- LMB auf Testen der Funktion +- Text ändern +- Testschritte angepasst diff --git a/daten/Planer/.planung/k1-1024.png b/daten/Planer/.planung/k1-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..2a67485bcb179e45cac7b386d03d9851d77d6dc6 GIT binary patch literal 31445 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 YSiYuBWnqU{2m&c7s6B?uy?FaS0B_E}SO5S3 literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/k1-1600.png b/daten/Planer/.planung/k1-1600.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac7549bb99643fc6fbf677342de04aadac61ce7 GIT binary patch literal 34370 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 Fe*rD1?&AOe literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/k1-390.png b/daten/Planer/.planung/k1-390.png new file mode 100644 index 0000000000000000000000000000000000000000..2132bc6d36bdf92251b9995a791b3efc96356eb9 GIT binary patch literal 28243 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 GPyYrdu!jx+ literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/k1-640.png b/daten/Planer/.planung/k1-640.png new file mode 100644 index 0000000000000000000000000000000000000000..30419258c2818792b26309b284f093d192e21ccf GIT binary patch literal 30111 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'Wv|XmVFI;_kTo3Hnyx* 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 literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/k1-820.png b/daten/Planer/.planung/k1-820.png new file mode 100644 index 0000000000000000000000000000000000000000..485f1219504a265b59d7d7c1b4866f943d6c6c4c GIT binary patch literal 31558 zcmcG$XIN8RxGfq)MMXeGKtSMA5R@tc(m_QCz4t0oLhl_yuz}KhFH%GA5L$wQAidX6 zLhm8;l91%&+xwjR?DO2a&;4`nkL1b9%vx(^X3qB=W4vSLho(A^>JHN#002Oxr1)MN z03a78J-*($MtbK0xvB>M+yf}Rf2-@4xwk-Rs_RW49+D5d{3)0^qIejchlO}%7XgL%pgTh=!=hfC~U)#T91f>*?K6?NF_`Y(yP3lg^ zKbd3zz^$)tHvxcu?sYH%03mN~fk+M4p8S8^@cs!|Q%n5VtNfC-wzj-H?Q3o{wTmllmI)7t!1{PrE7K}_s&{?h>24<_*F z?L9)21vnw`u;2AtpT09;;@LkRbw2?AMwleLD?*4Y<~MJ9&1YcBrOfp`-|y=zrqbsL zW*HKP23+rwX|xM3Xn^;j0v7%l3UJtR1ginjcNtn@<4uDmSk{^Q%`a%86gZY_GX-87 z8JRRR4Xc+_$Dy*G0nS-3>x}G;{Iz~41LAbba)ceF z`NkFywk;_T$MGNa^=fS0sgI$u`_D84)QyN3-^NX)Gv}652hdm{OEl_01#wgXIq@hZ z`p*59tX9F<-s!C|!`Y?`JRc<5FYK^+pclBJXk1X-t|P_4=wnLAY|53&A%5XntC(ct zUZs|)FZ&y-Ue`a$g;A?up9djDtn}p{w79Sm4fHHCkj;3Oc%XC*47e1Rl zgusoz?Swp`#Hp`!^ycI_k5T(qm8ofEW5J_Ye5W3bgR zSrqb8^Zhje&5q93?Rc9-#*xT$>zhCIBXE1e4<9nB^y}8U=KWacaZT;Dc99k~lW913 zkKBIRTlp;?K40!n&_&jKEJ<^%+OH_fi_ZtTxkAyXOtlKyZGNp}hIaSWAGUXFcKJKM zNEw^<7}$unPO&Kqc z_V_z4QIrsD6H$;4b;Vt+b+#gqtP{bBt#Gd_kPcBHq`R~@vFRG%m(3dNTexxuW4h_8 zx-2rbgm^j3JbKI;v4@^-8}jnZsZ*lC%@MP!3An_k$B7#ia0#T!4g21|cS@6At`~Cj zio6UvtC*a2&1&lz;yMw~klEQaOm20z(vDUl1*)c2qw;0bS)}O4i)=aOv!L4X^Yvx4 zvq)Cx4RMy4?5m-x@r5?yboHV_f<9-n&uxV9X<1Qg>e>u{LAynkBOjf**-fCAOv}-x z>ok{l`eN&P1NBNNGbz|K2^m%|E6mDl2|S@m#vh#;975NaQs5eYP&v2lrw3vK{fNUJ zuf}~?#c*tpZA02rWdVzYd9%F?v}{nF`|yvv{?}J;mWn^2AASpbZT`I9Y++KA)L}QS z>e4oN)KeAl$q#*dl3?`8|D-m#)Z3^>sZ2}Id+BelF#Y?vm6PfsI zD_rdNvj-uRs_nsbUV7oUKlbd%QQd2RCaUGTO_HfYMXso$LCb{_lnO@|82K74g}ci% zQAc%o2jG@)3-l{WEYPo?*tMI9Jz-nOjrs!D&4l*rJ-_h02AG!`;`|jgvg@Hz4-Tb9 zLvs1X#_IwnHFOq<1i05GK0haFZ%Q4g7tN@crmi2XrLIm%OAWm#-QM_Y_`FC<$dX{ zaBmZXO5|y4qe;&FC;QaeH6?{|da2wzqilXL(;Um6h1FF(a_=n|=XW zVFb)?U!1*JQV=_REZq`gw$g3^w%TqP3>-fWXRcPa#8%2d9|ycw4}UyWR|f@c?q@l+ z7QaAVr=mJ?T3uRNTLfupX4KAmfq$5?;iPR+h7h>#_oWw1Bp4a-NvkmfOFEJ^!ySzaVOLwDF<8$!_ z?_xFIvpdbn`i7iU^4oU-`%YhlmN;i%UKsI#1?c8)0ex^yfM>rwv8t0UBDGJ|rh(>R zd>&%2Kyzkpk_ao-tY?uxWAJmPjmae=SFke8dw&2+`*L-hZsU6x*SY0jdH39Aqz%8N zl1+pAfNn7nUVyC}%T-g6SE{TWnHWJM#qC)N+D((P zZn%w$ggfW^&MX{-@J2NLSv#xxuuz)7pj7>7L>8B0p0UdC&;9dV+V+`%=dkLgml%UA z{&VD8wG#9(NTchpqQ-;C4pCQ5duf67hpAp4BR;kA&Gz z_xgc*_{$qzl{8|?0Jj&Eh+%*MX@vh9e56%1#oPA-w^l}eBfj7ed^Ku5M9<<-SHD#* zgK{(1mV~*?X1(+)di0 z5#D{ga*oSQAjKCgL8qo1PoeFNq-}d&2U2 z8Q*>pvLzTb6W*%64Uph2KVDiK~mMmJcKGDt{4*z+#5R3&*Hl7L;2w zNDQv_`U|wZL|BMMeW^qJ;>yV(^gYL2B(eR?s_$9a4Ylwg6ilClAJh?T490FFx;FK- zW(-r3lT-kjVONbmtDj`%_AWSyNv1Sz##+7k9+(v>RhZY@>RO$H`DbujTJ!|{veB75 z`|)Hilo%Uw^|k7FE{17x|BuEu$PxDy_xN)WPvx>JY6eTicYD2&28d!*?;n#;w4xs4XWv#no_uyKBE>YG=6!tvf*rEj!ESe={Q0@5)tAKWy<9VYmauaN3kyiY#y)|p zFOpdXi3DfPz&065z~6Hc654)GfqXGi0qPwUKWp`L^%XboD0Kq(FBYysHSM8mjx?id zE-gknFOt%C1SHZ_yF^E!YC|Bo&uX%49w#2^I0yKUyVn!^d> zvyXLXT`OFmJ64W6{s|=JsY=A@Oq5uy3RKolHo@ZJski!yBExSPAsluRPvdKCdJ2A! zrLRmxwWk}?xLn=H=#t;y(RIvetd(~R%LAjT<_z%F<;A~7^3ZDFn)-R`HXN+>GwLHJ z1|jB-tIQ;!716`ey!&gSD;fwMNj0UT6P+9dlZO=rETNSFFBU#8JK{r1N zKg=&X<)hU<9K5)m80)Po~}-Ujz=+mYeehsYaP}4e46~ z>2Ct&--+VI-<0gr9j4@IAcAn#RXth=G)t29+oAoccBJ{ltT;t-w<+t-vi zwK?bSBXX|a^>9U9^)+8I9zrv(g`zHc7z&~Bjk_EeVAxlz*}P)ldKJZ@+G4g(W1wsI z1b~!=t@Z5Fy3<#zB-@SKcmIedh*x^wWxBE>VxL9;hPHjGP<~5>pDy2+)St3Y_0nnm zFD-!X{?e*n{{7mmKi%u7Y#J~}Z3K2~8@g%$3HY@e2g1s_<%^`OBu-!f+rE#G(JU}opiP840ezCB(A*#0AQJg9kbGbHUiRm0<0L}a)6O0V4{%gls z^;+Q$#(h?``$N%0*Y(_CP)de!{XTqw{3(k`V1wJ4{sJ@(KqBX>Y?qrJ+QaLtlW6md z9RD|#bLA#~R;bBVpG7>)T;8`lbSqLZjC&~AX>7TRJK$OT0yQxj1=0dO=o=Zu)t#-bk4E`n9b)QJO-UE+7>F1=dmOLqZ_>O+tr-1wx)qi zO0>qGN3{1{@pZsytn34Hl>a+*+Xc4ZZ`L;f#VOqtAXwaSpGw3z{u~p(UTXGL=qD>E znk!qj%;ebG;IM24(cV|hth%*3kd#@kDjI(hyUh&1vyFNK$9 ziJ17yKX1jz)5p?iaqEytnt*@LO|Wu2?p;yckm-H*=qr6OkRZ^y4#D`Ikw&D6^DjkN zXId9GD2f`izD{?f)-9iH_f+3Qej17F?hZF5tQ-ED^u?L$;stsTrEE{} z_R3-1%zn(2;#O|!K8c6S$vUM%qd1bXBc%^!9l6G1(l~&U)8;fjtkd>0cFtORFi%!V zGaQ}%j{B3UpoyuP9mF;a<4W6Ir{n z5B-!z1FEx))8I+>z7xmp(vc<+70)^cgV{Ws(;rb4SqaCMqo2Xjhl5Puxa)u>c40HI z@ssSctH@1rqxOI^H_+`S;EY{BgMC^2aV%les&Fzv6?)nWnl@+kDi->9kW& z8Z^}~KG5_=w)v;GIvY_7k-2Cre-iXW`r{!YR!~SHI&+N|T5F5H0uh$x-Y)(uIKhiK zArtsAdVN)fx;0d!+y+ejC@=iBR#4q-zJ5!oxBN4TazJ~F^;IW*oqfguVwVPpo0Ne4 zTWT}qB_8|4iG+A-MHCm=`CS`H5NfgaFGMT{QT4MpM}J6LKCDhXJGp?OJ{Z1NMqguZ z3$h~2cBmWCjj2BC3cYq*TG5GYfz=r_I!YFs%te^g*NF(&)@#*QH*3CDk*&c|h@*{s z{rC=QM)?M5O~k_5&?$t@?6vWBE?05M^7Ai)4h9%M;uk1{i1ykSW!nZ@lnJo__I>2V zTiXf2I1Mfjb-arUqT1JPe2SgJYv~`^&5ihxCS%%aUdg{hUnY)*uh8x5DLt|g8r|De zM;Y$~rm1PB+Cyu<wr>-#0?wrm7j9Zt7stmI9@9nXe%uJ-Yl(|^)5T8r>B8t_;czA03-AqA5ACDqQ{9rt4 zXX7=XNhNFg*_G#IwuNJ5kv4K}GRq{9aQfM|U4qk1!?c6(gZ-eCnWS%0=g90DxJ$l$ zqX?=JpWkSpW#EG3lNX+hH<*)b_7&<*&Bu4ZKV z#*t;@>E|2JJf?mvq}6crM^srmp^!7po}8=7u+eS%eN_wQcTqVer9w79{Xt@3htW3T zJewMF5w|l(>$*3g@=Ll*zJCZ$k}R*dV8kNaGE7H7X>@S1E^DyCz+q$itS4DZ05U;% zD{jR|)r#sBGlC@b7tNBNZJejZuY6WnG*qU74yIgtZY=ET<9}6a&pcXT0Q9fBoI~~A zZ%w5Eh;ExAvoCm+W^+-Ae}fu4=qi35m}<>7>x8!S_qdXX00IT+%^%3ufu>fwkIn7bQb+cih~Sp-Cr}JEOsP$P&vHr z3~yQ4E$e1cSGFcz2z9Jllm+26-Glb`W7xKYUey;`{g4TE(LS>GFKY2L?8ox=*4wj8 z@l`v{`vR3~qZPgE0B+OT4)AO5u8x9)&l(4j6n?WTiio{0l?f0GMPkw8Uhq@4K`q^-ah%^Ue00XU!LI%3^Dd9_ZPpp zGh*!NW!EV>2-*y5NC-c}pJ2FXpcy7lRj4Cz`T&}{*4nEaFNA=$52>8%veF&FlDtibRo+oOXmtIj(z_zgeH zK~+i20Wj22{VybI8hl}qDUVNn*ugl$vA=t-sKFwKhbxyt&dkK3{1Y7%e-P*__3G-t zME|XSiVr#rjs;#}QC>jhKHWb3g?fb0RVOet!ubYi#jun$ReODUf)A4o?`{yLQJZQM@*ELGZ;Z9ljy9w%X8 z&Tb{Tj`W<3K_V5i_wq2d*s+Mwb7h+4rP$0=cjSYGO4kG`*6D>*WErGsnxbEn(}w2Jinfp- z?pM(t?VRG=eTS0e%y%I9FlEu9*fVspm)y*=gkV#`zzmGKG!Ph>Au{z>KL6DQ$2P}w z#x0%DJ<~5On@w&I&+ob=k2^PkDllc~|LBQrvfY%fxZib}gAvSkHMrq4_bB@Nr2S2b zRy}A*{Dg?r-!{4&$j5c|PaeNZP?_X6j&$+MGvXS$Nk6aMjPkd%H}yuVt+Psv4f}Dt z7KHjZ8vV#PW0D3^w9YDB%2t{@66Y;QFiD{{>*VB}PuGHLSPlJMr2uw6o~d(j@zac< z-tfp0v~l-?eu^l|5LsU}!g_f(mjN+h78hcI?E(Eaeo#_S1wHZUFD?E=#xmdHbtgQ? zeZkUmbjWS#RFGCi%sBN#|7)u$k-3q(>p30Ads*hJeNk8NJm?rIPmN~VW4kBeU_9|W zW{1m&I35Rejk|t{Wq*P3_b7dww4*C_w3hIRz%J%h$T!0viZmS=mg@_H-r)b zxk1CGP3@+HtzAlIKeUH!2G_e(1{Kc@*eG^Bi%82^NI$52GERF}WY})Mag9ZVE6lfD zbF>^IUxvBeS7oI?Us_!HO!CGzjZ|7(J|ckaD1vd;^{AVTc1jf@R`3Nhv)lU_Mo&&s zu4~_m2_-A@lRs^v^sSUM9H+NeoUMK_3|_m(pm*B5FcdhC94^9%*QcFq?`IC=1RJhl zo{L(jXCHXf&K;M*3imBw|LBH;u|GhfspL^vflFI5+GC*$3>{&Do|~cUr84Zemj141 zCcuj6o^4{}T)Ss~-aq)z=HbdR`y?Uy{ixvOE~>GmZPzNZ`;!KNy@JRRmP~9U__#l- z7X=nm3S3KqGPsUUKPDVH3kYcJNRZ>7~&JsFXYVPS*+)vTNRy7j`-M=W&ExB-h+ zT8t{OyaoulSvPWnZ09vu96@`f8$JoIIsr~`J;Z*aXg0^+HIHq3@w#Df>v9~3m5_8; zxW+k<&cfaGcW)#uKZKg3vi~nFz!T*L(c3A?k~p4PI~y4+X#}rV=%IVry-v19Tq=#D zG-m#kfFB>lk2~ljYpu%$_Bv{W(%d@mX>4_Z7!yb1$TN2*#VSu;?}nnjE?+OmY1~ZH z`~y!O>pfPb%3w2g)kmkZX#ouxIV#R$?gt0n2_`q|N}om~V0s8U1B16c)_aRpW)kyQ zUm^{38q9~Xy(ziwGCR4jdF{%&;~2l>>b{y{?F7iCV9yO=TfDc&HBQP}o{xe3ytFM# zYB-ro9wRTB#3p3!Cn>*Ty0c5Ae#BkM93XKdV+zjFWAL?f6kcPlVjNOFNi$N23iD-d zm0))I(4f4&^tvf#uIp&A!Mwgj<0+TOT=A*T_|)U#tf_H1v(&6~3l_b}p-*4RhzukG zn@}^a$z(iyKQ}#*k6Gu$gU7nXYD-ZT-B8NIT|)Tj`9#RBHTsrwQjLv{@>!gkiHF&{ zFl=hZ3#veR^+&A--*>;l)_h=@^;u*0e%p=H_+Bm=Csu!fb5ELm~Y?)JJ>o0I{uK6 z?pj(}u4wKx{1Mvn@}=5o1rYNoPAfvRNLcHE!_vs>l%~sNdjMb>)ce*BZF)2ESh|i- zacZ>4j%&3b5S&5k+?Rn9*eX9)yA{3 za3S{>FEfaBIv8mW#nUNWCK}%;L7bcZBwfUdU3!RHas3mDBA@M@Qf}3fI}*=kC1niT zL|UKhmaJ{4zhHmz+8h*1V`x4t;)V5uQ;N3V6Zh#ZooO-)d_c3OG~Xcfgij;B66eLF z7Az&f--61>;%u(e*oQvMOQSUPV|Uoh%<}hqR>F5*KHD(-QDG! zj}n^#?3hd920F(F*mjh~$U};(M_q4eil0-lEq$EhTzj{PSFtD0$q~_|6BVd88LsXE z-kC7hsQm6JCHt#9IcB_g!Sf!-7|1{aJ$bCXs zeH=u;+pt=!-n%{A#y2`lkmg>AyL~@qAV`3J+|P1KBu72J1UHPG#^q}7MczlipPJ9F zyyUM1q3Mb%bB|Fu`*gBa)pZ6R4#qQdb7^l%mQ`w_TCfp5U9?_zvS2P<@1cLTdVci9Okl~$#1jRwxh$|x6O^62rEDPcEGvL9!76eDt-cb<>35&VX9j;18MSRNBj zN}XGf_w^h?p@JJhQnqdvD-|`KPXhz>sn~=F`1G!V&udWvF*KqY=XV)}ZTEpcE*}7X z{x0X{;dwSs7Re~6@l9a5?Q(EVuKvMJl6T9SRXYKr4s6MWDhcW_6VI+M91b*BwH;cG zEmxWa(F>$+F8)SicY6lYX@K2W0x2i|EZr4fBc9y0>^Fg5uD9Q0w)!j6Hn5&WHJUp) zZQZlX`!U>QFL}7zzj$Docdt`5<*g3AD%*B`-+W`xGV^VhBV%^60q{@yjQJbmXP+b2LtAI7abU3PTVZ-J#W{IGRR#=vMAI(A=>WyFZEb(z z?;e2v*!~x0v}!t&yNTlb@|xd0IQ(Q2kay6v=^Ne=`A7AOasK*a-!Q-6jVm?+?ELC7 z5B`H9+do)6e<~@mTWaBxvtWcpq)gtvP<@pOxqb~=!hULou(!a4>A`?CBX@?Vz|gh`R=0`r^j<(rN=nnU5-NxvR6gH|x7` zbc6Pa<=H%=lq6vrnxj*Ofw@jM{@$H+z^VBQl|suRGFl_BJJY>=lO_G38tzTT*IvjJ-DYcE1?|+khyOBNY$^wGz7^G{IA3Gy?`24W zFwX>CLp_Xc1B4$Argv!je{FAE@6ixX+nCEWV@?L%5d8X^#rkYu8yvh~LoHkqHq^H;UkHv>_rU!+V%(~)USuJ*pIF&r92dIG88*U2-;;D14 zgXtqHc8pNVsfxp> zh$^9{rVEAb`}xJ!6Su}2`OGiOJGQ?O|Ym9vho5)d_-5Tqh1 zkl8BC&o}&`M|pv+HE56({N>zQF(PWV30nF$Bd9pgyU?K`^e}?#=Q7Fqll5l7c`V+a zJ*uput)=NaJjiTQ=+6 z*Kl`Z0z`A&_3A%=-TEFj@WqRCKC&q5V&jTTofI;1A1Raj(&UDYk>Hgi=`~3fuay7q zRQ3N>ZvQ_u?Awxv6V5y8$`F+3!fvI$w^m&(-g<`v@at5>Mr_WC(-`U&vb$i43R z!p;`4Ry|a}3F{-q20yFtw+;`w|C15VyfHm|^j#cDR ze-Ds+a}6N;U7j0sv~7(oCGuO~s{D02rKy!r8XF#6UanS3kDp@U%A$F5OC^ppnK+r|)KmQ;!c*L;h6@lmH>Sb*go? zaA<-GW8H%(RT9TrsEeorDbB3vN!FFE&Up{<7=WwTWW`=>{L1$B?EDhobt}D9M}X|z zD9dorT1_vDIWSNXFGdm=0VBl~Hpsx2M7&_}CnK zGN88eLl6^rwk_j=294t%BUQ0pzUmtqvb;yW<#n<#w|ApK1P+a1rMau%c75a`J9&%O zKE^pC&aG(&GZ6d0_syb@Pe*iQX*&?Svwzon`krf4BK)+g*A+dfz>5n8&BxcM_f{#W zS4PJGLKN)MWk9Ey>bedM-2y>VEf`ITSGV3 zjM^B>K1eE6OWIVp5+MgwxKXMN zLr=sF0e-r>v&zX-mJ@mGtKMUbS;aRY zCCK55e=X>nsS+IIQ1bVyi*dWN%gtIWi|963vNE*j>i^ zQfIPyxoXQa7@5@2foFO{JcW$Y0aXUg7t{yrX>WD2S%@d&!zGjFb1=ubrPEUWTigH76;(X z7bA{LGon{~gN@6YEOmg?squiM*@D^Q6XxvOCZ?dX$zh&NZYs2umnxoKTOTvD%ZB$|Sht*=h>uzVg ziLNLM8_H0&X*l+i%ohHcoB*eIgUNT-vYDoejKZMlmk@>|W9FTz#cJ=tn=e#$QPW** znPo5q<(aHRzUjuxx$7a!AQ!ULlmDd!H2-JX+o1r1X@N)0|nvTtf&AWF=|NcI_(q!#;xA%8bE zPw~M~@S6|`Pfyb#r07WJd<;pbd;R)-1MXCOG$Y>g&Ry{rx0z+bXMca21B@8LHkhwX zs4u!W$hjyqipQ@%tAto}{N>gvXZNx>olb)?aC{ZE!>gZJIa+`+@V{rk5yc4*==_;fKNM4@mlb-Piyq1>|Uo1ju~QpO6L0_ zX}aDuIMXL7&1YW@RK+UMI+U3HOi!ln_2Vo(P-y>1D!E)4M&c}u*cpdpOn-t23T)f> z1iWyZ>$GV7D4QO~a~7Gnv-*mAqo-IRW|AxdF=*s9`}U^vrTR!hO4at&3@DJ5R6eKr zsApvKg3R|@`S=YcU|{cqDGd?P3F*e276Xz&`ya5>=zI;&3VDAJ7pp}O_5V-XH{M9^ zP0;iZ=^3s#NmYKeNv?<;+A#ThLm>h6Zrj|%z_T^W+kg;93Eb|JOBBwmRhgcIAa+JO z3hS;g7$YDD08qI-P}QqF2n~oJc}Gr*3Ct=n7Dih7+@#CVtrvE+UtwfP#)eU~TGH+l z&6w9_VUl9aIkLyQxoVWpNN2B%bl=z<&TP||%k@rq694VrThBa4V^yyV5y!`(m^BdV zzm|;8<}iWvIlD{sC6sJ}#^e9^9Jax2dkpXD+UMH{7k_Cp7nqbpM=BTSttE5}quTIj zlP_yH#C_KilR%|p&++Af)J88u1`uq=BxaGEJ)hoHRd8ZxXVi75@^e{vI>Y%pS6E1o zciJ;=E|*K7FN_~=yVp}DRP&yJd7JIbBX2oeS|4@OVDQymnoyI^M=oOZ0ThKQ5;C3n z`owuWlk4W?d2u=&Yl9y!`7jAwuTEv`r5(`#GiYS}-o%;Ztr z)QPwMmB<=H=r{5`FM!AFUPSK;H^vX6#yl1N35g7|mvpr?wcOH4(?=LDG?kaK>b z1}*Co4JG=*Sl(aybFO_Ev{HJZSLJ)`q-wjwTP|nASAC~Qp8r`BP<+Acv(>?cEp`B< zVzy;0uFUPGMdd`M=dBD*zcoBIg-?2fzpC1kT1&cQm)89@J8K{Kx;*C2r~m-EqlE2YI2*AC zATKWfgypT&)dQ!dRtc2C7L^@Vz=grY)l#_HCU09HnlgFRWGCL6_ zp8K+Yq`~7WHebM-=hNm^F@$IXRfCeblP%gctHqg-`-|FrscISV$G9*DsScDmL$D9Se3s2E4{hdP)2kQ|teCT6=A~ql`mZ|(k2-?P4i9xcSy;HFSsl)dLW<46 z56b}VuDr4!F^sc^_-qoI-Ipdga3=$<+euxkXMIaeqn2JuuW#q!x??xk96y1EiurEGeb!xT4Y7z zuo0=~5PFl1nShmwIy6%s)Ez`ge8P;$fT%0?y_vW7G#yaL)^9 zX=!S1Ev}O7BULTNLl>~`whO}o5W14?okazTRUs-8-X-Kk!x_SaG|^-lLpuM<*Okc4 zatV2*G)H>=MMp2U$tmXvVXnH{LOx;&2)L8J8f}5{YAOGGTBd!ZSDA!ILs?aOnRV=n zZfVQ%9yfT1w022%rvjzfs(I?}j1NMe^s2_+i5KlEYGjf+&e@fXDrw=f5UFZcIh&gK z!;^kva-n;W4H|B8_0}VI;^pKE?ti>aKFjAf{1_E*EoOmsrZ(6deif$(+8~0^S7en9 zX==M7O&S?{O?oxGqM{e_t2A^ZuBWW#`SuM<=-vtZc4@kxfRh7&Yp<_xW}!CvS98WFxD=Liv|6Sjujp4WFlu)!L^Y5e(hf z;EPmPV#E4m52Iw}Q&6;5uSQGkHRr6hR{vrVFmyOvF=!*{P-}MlZ)lUFt{%%MLT#{W z?)H#f4_@%_&F`*U;kKaq6bn1I2DuvmfL&7&HK-8Fmd8cV#8pq`yGq4nJU`76!NzmG zOPcPv{mF5o996_DadgC29Q1TkBPt@uKBse1bk24Ry326V>?H50v)c6MwkxmcoR!kj z(0YbfVf?=A@fiW?Ll$Hv9HoyI5u0g$9m43@ z2tPS@Zg9j7nzqaA^wosyO6!tp#R}D><>iSXt?#C`uSMmX?+K#NY7A`$1%#& z2T^b|OD8XbPC7?{7D_7e63X7~D)ur0_T{mk!}E=7fEvkJ_B+GnE?r z^Ir#`Zfp!XZaux1$Xi`oyR&S`ZbY3VG%w9-BA#F(#Fnn3_=+50YLZfX#YQhVV^j%F zs1$mG&&K!6r@#0&+xHih=HQDBYajocnVSlESRUS@w#7 z4*FgA^TTN}fL$z(#Ywxa?-}Lt3HijTp^rSY(UhMYV0RDGNcwto@!#CAWIJ)mI*YwY z?bIY-PLdz_<~}9~sms2R9(u&hXipCqd2{rl^RoqO=Qaf?p!{!U!2fOhMOlU-?N!3O z-F?asr(3KK85`WJ!k3S1WCEJPj(>d%ylYVI(nHcPUDm39XAP85oUoq#Iq5PeCqX5* z;p!eurbcA2&SK_L$*T>}cJ#m6!dEBz&UmfLQp!3?(t6#|HMaM4`WXCXtE(!GU(sB| z=BSp#dui*Sh8^14T&$-6whbLs>py2C)%^mKY`VpDTK&$bs6B*HEKEQ9?nW#o7qG4G zXiE!0FfA+rnC~S!&OFoTzB`C}Nab2l8A%z5e3HPeq7Yc@09!*@{JZDQSLE`a`e!X> zH9x)u*C|kGZB}O11ZTKxB`kW-3)ylxAstVGT(CV7y(Fi_t-reZmfTgv#l_{t^)q5+ zDK(9?wT+G1NJAdFlTg^n4YC_08H-Wkc}FZu(2DF26I~T3o*U8BKAvcyfbXyQd^+Pk zmu~yF1m!oD#i)1-3)z+j=5>CHb|lj>IU*r1H^z{=i4%5}OJgx08>ow>P|Mc6fQ$O8u&3 zAyoZ7hA3)_hw8zI2#JyecT9`3M1J2hzmOO&Yqf!B-u&zH-bXMs>SET9MYy#JfA39e z*Q}9AseRS8mVx+Pmm)1n@{ngedS!Fj1EsxTPuL>8Fg1ImN-%5Oakfh8!D6N!ST=Bq zD{wB|dM;L;7DypE&AWuLoQI>gqiTBZQ(_~7?6J``u7jB$6a!z)qvV|t%5QSocsdPt zxX65)_Q*3HP?lkKXkq(w`CHwZMq9y|M*JCb4SQ0GjJl^n*w^qIKsZu$;Urh1*`&}VFZtOlbm@N7@`s| zA%y+L2X0*bDvK=!L$>La;6nDmV;UFb0Y=7s-i3#R=YaV;9wvDlk1k_fq%!H&_Xt=V zS~jak{50@w8po_;z5VX}2NG_vIi8+MrliHGYd(&+bT`hr?X$Q##lmRdEqbw))L+)B zhO^ZeJmQY2HWIX~<5;SUZ};tg3+HIQ4vb8|K(aF)`u@W+Kihzir+lyxDuZ~@+BtKo za+Q#mQlX?MY8M!7a&or!K`pCLm%H=RdABSbuJbm@yN$@T%E=Iscw^!{8bxq(8bGSu z2F6EkFmX_%s7nLYQ(uY9_iJ4XQ7A)LAC=Zo6%Gq~Yolsy*}Js=F4+*n2mk>RmBgX*EXgzi)qr#ja_VmA`F4VJ%{ODVh5Z1g@toAVenU|#9A~rhQtyB7aPFqS6QNE8`s=;?( zj8n0^%+ICJ|LbqoA-l^VR0ua)XqMl$5b!%MvyzWb{nuq`W;gD&CGlr&wm0yNMe}ui zKWmc}Zw1WwSw=IVHS0Dp{2-Yvk=2M%NBZdps<3PUyszhqFEJCjFpscTTujQVGUq$E zr0W+YVwMis4||C?(AQ>ky<3%OaRT7ys4CSimYroH0c52dw*D1G5g$dRzokb8fmY#WlcQ7zr}{1^*rZ=w zCRPjTv%&h>-LyKR3>V@aN7#sSi2Qb=duOo36#OMXmukalb7dB_&{p|dliU5ia7Z^# zmED_9eVUCcMAg3!r^X36rNBA~wJ1=(K1Azkf3qv6Alc%G+PYLKNhi2e)x)jYr}#Fo zLUNWcsU(qP9og@q$pGut9~vq|{}_%>WWlQW4;Tb<$yjLmRTl5flhEXY_#oc@=`#HR z?QKWgZh~2}l{kzi-j!`b{@tBK_J*!G2cF8AnN^-S+feH<@Md7_NHx8eYZrQ(3xiX= z3zr?~r7Z?GA00ms1>dU^c_AYG3>qtSb4mYs`Gpo?da>^}VNCr)7oB_Spi-H4&C`Lo zjSdrib^Eo5!Xph6(E6_2uI|LcDF}0^qM=zMwzZZunJxdf*S@ZLT;5^Z_{4>r1s;|fUS&Ic1{y+ zoNI334P4h0{rf-KJI|;lyL|0OQBgrq5s&doD3XUds#X3l!ge0bNIugS{JUG}~2f4Q#T&c|PKJ0vOU z^K`@Qy;JZGiImIbJt816VQHZLz*{4qjS4nn7}(KCTdO*$DX`Icq{Ke&Zd^&{r@P(L zB2_UJ$F0ND(%4K)%OhQV!0Q~dzVAMm$Tq*k@xWiWMst<=`rOiw%o4Pl9m}k_N6UHD z(|Q*5B=YE^uW~2D(VoCuzldXlR9Gvf-v6F`5*q_`Q!*ebdU$DC55`R$B6ZNcYglKt zK2G>D4|!yc8^O7LT2%JKU0oB*cDKW!Wc{ zGXH15PRUCqMtpbqHc;cQT68_`t=nk!5hl|W;LC(k6{oDRVg@?v)%sg5DMJ_ZVb98#>?4R2`#*MM%OE%G4x|-8W7&p z6y}He%x{C8IEDo}cikLXN>(D?G+%;>mmvC}+(E_J<+p_|6!rH@yxhLe3aHF?me)+qi3El!`dQUBOw!l& zh1L89i89`q4lf@vdpI98pDTz-M~{_}Me@1<&DbRj9EBRL5Au_%2^W z#a)4G)#{co81qHlm#iU8K0mUqU(PiB#-#)Mm$KbWy3w@_rB>x3 zUKdGqJ~coQiOe|(2ATf&7SD`77z~oD^jm`IiGJ%*J-?w3&~?rdv+mt< zax0ZKb43m{S$&D9Odp15x($2ui5fj1%d{PL)G&Wp2F$JNj>VoNl|q#R6E4*R7I-#c&J+bKo{^NW?cF~UYz%3kUAZn#buX9MAjcwBtPgGz1m-J z1ysc-Z4IK)cH%!h4k%+Q`mKk>X(@sXy>Yo{qPabL4kJK7n^KG zsxN~yu}mUbTyp5Tp%fk z0A$fG9=GzD3oj0Ifr;q0{YJb33hceB$#}XJfq^cr%%D!@hbY1WJPMK^z+lc5-kinv zQxxDwgxdt&DbdpmCcqxI@!LO|Ar)p`R}>u{wjg~%X#vTzo=pl6)uTsZdzOe zM?T27^Xug28#TWIKE=_=`8Lz@-hE?H98;Vp;j|$^Dl^fnQ+$8a7-}FiZl?eE+C@Ur z6qgH^4;#ubVFsb8f!mRF)5tE%5-7Nf2oY)B@$3q?*|}BR{Az*C&z!3_7x&z2UA4Ag zvvVxhq7{M9*H=E<@3-2&M}(n0gji@vxBW~P+hSNvRQdUBNHq6GRw(*fMFeaU>pp;fwTG$&i2sw-Eoyf)8gJe2MA;nCLGR-ey=2jr1_nWnJnwqW$*;5l+N zgZVY*P3#;tq1-=9iw#GodN03am(I?~+4EjY9Yt)$ExY?A+x?8BZ%KgHxfK};Jg=F^ zpK5*h;mYH-;-=7qpdvO8Kl6cQ#LoOIzR$1Ruh5+?*M=*~vHZV1?z$OKDXFd{T+&^v6EQ zlC7v`)pv#+df#->TPp2@NTzLTCj>-L7?FlZ*4rdkcXTI|{0RCPu-4s+6)cH2l)jqK z;6J~U@%m>%H{PP^ZD7#Jg380XVlFS*A4a5&36Z>i(&2yiee?$vzSEDD+kBM|!o58m zJ+@uFcsDn@8_Hky9$%%TFsa*}r(2Adnx4<-K<+J5wCPChkY7o@ag=#F*CcAXC`&=U zJWKb;s(UixrZZlU0#6mM5@}hTXwpYJ%G8VWo4OR-nC9p?)RcSZwm#?w=<3#60B;_i znE$N0KTlKiXy*#Tdl`oiH2YrfAYs?XTpuF7>x>yubY;jqCTZf4AdJZqU$-Z)a>dub zayp1V83k(FALwZYKjYz1#L+FD22g83pukXDpj(lDPK++5?rCdmOVr7IhhvSjBS(2s zH5c}xUS2iKUq`N{fl{6??8O6F=S`(Rx77_V4I2L?;sHj&}GqS0-}`r&IQO zY%?JY=}g3?9J>zI;05)y1^s%f!>^O1di{yO=)Cjc1jF!X@6m?#6)b!4N7UU(Fb5!{er0i4lTGo>K9ph#l}(UhjbN>(T6_ny*WuU=S!Wt+o-6cuAET{09L&y9PB|p|_KlefzN&>tsT08%0d||{we=wAboit{73l6#SQRvD`hK@JT5unWjXEvVUwZxXL#ENy z0A>5<2ORQJH~ypx$YOJw_fFl;Iv5J^6cw%Bk4TUh=yP<`dUZ-oX5;&Iif!r}dA%@` zf3o2i;X{dkD~XSrvq+bkg1nX&sScXx9T?8cq`%#{?8P0SEiWu(s8;p;+v@?tRqju#++HgnDd+2Fx{4bur zmmBKdF;)FTUWL8;E*ltMB4NK(a7wiRwcKMHsiSYz%p`m#%y_xGTB%dU2bb$Et{I`5 zt^8p)>B0T>A}=dsXcdg^65Mud=i=w=5*Hd?qhma2O<~zm#7>ne%Ol}lfZcLYLNcJd z&X$9a;WX5Ch#ep4b>Cq+)bor~!)$&nzhcBb6;+UQ9#Nt#U^Xy8cAtEGrmbtGvwqAy zmEYDbz#%NAmbjefses^1skXc?QE@c~noZLJKJgxf&W_I3nGK$gq6gGD ziySxv0yWZ;(xL*`tUddL@XG79oDZV-<9YI(e_eAHunQffJJzm^-m$;&QkuNOpi!lp zX(^f|T_6AWbMisZlf^Y`u??Gs$TzK0HuFG+XCOD1Q8I?#Bk*YQlP#hm7$0wf>tAdVxUSnk z4<>C?4~P#YWC<iMA; zgEg;wh5a77)$}DUj(4>~e;lr~C6vK_ASbk0<9p~G!({pYpwIE}T4~Ya6!6?c$hsLc z&T&F0-gGq_IA(R>hIoDKmIlj;x)50lJGYuQ#0XL6rtL5K@!QV1TY55RlH0%Yn;26F z7ANBfotk}QKVVSyZc1!8d%_~H(erb7=9Tw{jx&KNEc35)WhHl~=e`O_`uOa?6BnZ^ zRpD8saD13J1?t{3))89!xd1UR#HgEnD6kfQ;(?cHhEiRRt0p_{x{{Rt>C5>- z`m_c51lhrL)y@X$W*rQg5^7z2Z%2MyI%t`C-!0@8;8b zqi)rU3tzy>3f<-H2`-~wqCYtz))wCF9xvT?c}2@Jy(;0dK5sk3T1TUcP?IR;C|Qj2eRns5O<)ff zBntT^Ek?c)Z?_)pg6(i2PL(Sx ziB&};8@_dRWx1ZwJINTIzjuwFa97J(Y*L_gtr@zAx%Rv7Vp)pH;Di0D+}1Sm5J$Zn zp0y0C&<|;)F0rxpQN8NXWsLrbOE9AImQLIFS?Pv+6_b3YFE2&JZhe*Gd;~W5 zyx(HlLtBaQXq|g>T7q?l_JI9uTaG}PE+G1p@J<-%54=99i}W5=$c=GQo`jFmCJVvi zYfN!X5Faw631dYJI(a-YISMxY+<5L#NHFC^Aapid7D!!s^r{Gwe5}lgjz0vwpo3wd zTsFh(b`u7iD-GVZYx7h*_ORo*eI>NT(i8kiU!0m-hoOj9pa=Ty=ZMCNYOYHGqn9Kk zZS%nP##ZRGm!BdGZwf*Ft0Wk`xFst$^P!A2HO81}brmA69K5i=w44bRs3E_cXCI~Q zL$Q(hI8J2$q7Ovi*!oabW*5^I`Y3{ZKoa~7hNm*J6?sk<6DLVEj?67HpxtaNjA~lq zz3dWaA6e5@Ksm~D^@+WgK!I+?rnG791Ihm95dPeLD1(j~VW=qe$)o<-(f9A^O1Na< zcfHoTJ`MR=^dRsyIdo5KN3J&?($a2rA~&g#?0xzb-ZgSIuHVy1{6ctD@q8!Q{xF0I z!)QNOOx=(%y*=|Xo9j#c_MIqyA&ly^SwWzt@)vDcvnx|Mbm6FBpt-}Z+@^3460g7b z?gsoXI3fQyf%&I%=Kpr6FOeWURiIA{Z~-}7{Jv_`pny<-eQHnA8c6!XEmVMH{vY8? z{@bzt&KI0)AQ~;Fo$a?#23@wy`r=|Ir!A@3(zd-}s(FljC#ONFxCm)#3?rM8tiHH!Cwym-I@|1G4viXD%ElO38=@6xf>CEx5tj(1hbMq*V zM!54oso|HCXwQF0b2OenxmMRT~nFa#Gi z2G_&2?et4AJ4;u<5WnqfD>9!NIJw;_41Nk3ppL65rshrAxElADPoGHJPUN=n*IutQ zgfk^|{OHc9MTQ-`Y;fAO7f$4&>DH0FN1A_r{&_Gv{t<9H{5iC4&2?>oXH!$?R5=V9=PKs{V`(a*a>H2tJx zxomr4m2u21oCf6Ra#py3_|y4S&SxEmtEC>@Yb^cEmXkUnv=|c$FB-Gyer)u3RJ~#5 z4zFpp{e1!1?2EJp^a5)S11x+Suo*D7fy@;s$#1yvvRx6=tvDT9lJ~_T0v;qooefb*6j<1?!1(2zNbe02 z8@NTZ*|5enSC(FcyyF&V)2Y-SQ5xvaya<{+tExCb{CZm_g-jFtI9#~1;P0x9A&D*s z#Nz?&C{vzXsP#IpQGVj9{mbw&?O)J3g#hfHJ~vTfqXF?qyL`@*RsSZ25?ni>bO1<$ zt|G2_=4|rq;|(#s<)a8ma$0bW(7JoK!TM*H&(vMxH#X(AM)kps_tn zIr+8HXCC%cAE;pha!M7|>=K{tphZfL$nf0cJ!(Co@YmCK`8_oz*f+}go>qaK$WxeJ zzUY|bx&y>}a=-WViD~_(TX3EaTv%Sxg1J%;(~o+(DEpp5%{htaRXdb2-3W|U; zR09Bqa9jccr&oMgMJZ(?*Z1@%Pg9*f1UbW`Qq!^bHKt> zw_UUOB|e~nX!gr3jxP;+9C6y~tWba-u|94sIE-_q4D;ryOGfItYDv%!i%kAfwZGeNI&FG`+zwmL(9~Rl>8teU^k`}%%=_ljEmrEnIBVqJqH+lLkpCXdn+ZxHjn^u#a2q>pwPV&eLI&Fuj< zgkO3>eb>YL#FyJ+TL(mgE}}7AnEV?FnUk7WNBY zUsI%=d)L~1!g)70%jUz|??ERuvi`A(00MV1A8@j*$JNj83QuJH^x_TbH0OgWrKj-( zH~W-b+e(REBbmvGQv_Ng?2F0q{AR5jv^AHGYV*h?WhJ-ml>OTa622R)(gf0vh@A{` zUjh8Cv%LUb`oZQInHFcVE(!HLkqHwnA){@zWt~o8UeFWxHZau~vZt)+TxfV@h-0(8 zKRo3yUWd*}ZmS!*E+5?hnUR340jz~TRwVGaEH|?EDNn}PJ(ezQKLIWYlOHgD)ME)< zrzAdm9Ob{R`SZVeQ8cor3++uP-N1~-Or;r!XNS~SB#m=_pKv#jN|Kno%f+KLWx3Wa z(F*(I!L~vo9_?XnU0c6U$kU;!ChULTdgC&oniicsLcdU{%yZ%FUw)8ViI`V+%rwUM zV&3aS*6rbz%Nw?deB-tDIfMHbeDc3|M-e77>G0G`U`zj-PrkUN4yEZEpc+Xvkzvn(1c!-;Dr-^U+r*JAU> zcXnasV%lRu1;`k$QpE|&*CFMi9pZT*N^T^1zh@dXMf%knm||U*Yg;#a-|#;C00{d% zBmhQ{;*~1yzk1trCNoh2!OiCKA6jDkCjCqQd`s-_MB4v=LHNJ>1z?TPG*}@61KtPv zXAk$I{ijExNF=!j9hw^>{Xu2prnL)6oynQN&KJ>m|?Gx3Ac=j=TC;H*v$ZKvxPVrNoxme5>()Kg6FMXgr7&dD?d`~ zA#%>j{eX@nKmb5T+GJPa7i{Knuhxe~THoq|41)pmrd&)gkloo|(?469|9d>-|L)fO zd8qeN=lelU3OU0CTc%iQYhj!vIUHDrriT<^IGo+kK+AY8YWI$bLB6#fM8`Slo6)^h z*Eg*L#--)k?C`!q&MoVrI-Dn3#&YGiZCf&}# z!Im9L|AX8kBImN@(O_3j5vRVO3R8c6zQkQ%aeofn%G?J6zK^n@eUi{Brf47zLF}<` z6ZyZnE|UNu)z|E|zIG80MwL%3-@xGzN=k+f=e#qRDYi3lGU=c{MGEL=&yLqT#}SLi zzV$ke)mKc}#?#?l~DoB(03Q>%K1d>MejiB_YdIo`UhD*4Zcfvv)TWqI@!82JdUtF5iA zqpfepS=6Ox0PMkHzy&LSU+t7VYgnqY2!Ehc!DXA%FzlbwFO2DG7@sK<48d5iowgza zH}^`~@2=HKZYoxM!ICEI-Kr96QR=*_Xi zmtVC}__#T&1ciV@bT&4ONSfr-u2MQf6hL<*s%_Zi!O@h`_LH#&!r4CLK zdA!=$UVA?j<<+{%%WGLH-^Vk>;m{KUnib^aF5={(&NF6b3H6m96b}ZT-CK6j)6;ce zLjZ>|R_?gSEqUuq&x>Rc8N`j-(v?x6J0U{Al8TnIPIOd|mtYI(2^)$2=nP0@PWIAO z7g7%EpV{YD{1t1m3RqRNN@BF#H%?Ea#b@?^WDMx(y@*w^T+HctI~>OHyl5uQ^SQ3o z>L8cn=T7WzI5AJ=vZpnqi;1ZAI%}xgKV(M zQNy=P4i%QEnIIia5RHxo)C=_l{(0v>hW*Mz*r>SW5*OS7>gE4U1KAkru-BR1*)#OX zmd2%W>Sv14(cIwp2SPw&*9ZNKoF<*<=}?9lB>A~6F$6>;l=75)k4%qBvduFds)T!Rs7acr zjUwoienUUp3t_GCRakvt+bwy6cwj)q!Fx1t=iF;^I9$l?HlLP^w{Hi7T(GsQc*4M;~MS53noB%YYy@S;{xSSFuRkoqT%=@*lHSRmF3A>OX zLL|(nF`#dNbz($f-1u~If4wG5q+_+jV>)eos;*SfbEL*W(C)zQ^ty|eGLA~vVLdll zi!VUT)y#6TyKswbet>BPFK-EY&^=syx97C|5zm;WF}@&$DW`u}6_$USsC%?Tv>P)xWJIZhf7M>o)Cz<73OR0N> zZOW#qk9DJYZ0^@+cQW7-{T`TfF?`DucE)Jd=E)a{)qK_JPtf*@0kvX>yDhf!yO4*e z*hIR~D#K^%)ctKJ#9^WP$`EGCH+Q)Ibr%^ZL!*u(is_b<0r3`?Qy#!w7V(l|m z#%3Pkuf@EL=>(_N-lSVU}lIGFhrPKK`xU@~K&pya4sekOk;qPg- zxr7`Eq|}>@Heo`L%b`(X`j$?n`K}ek=4WOBh~3s_q^^MM%bGs2-~!fBjBC8> z7jz77peItw^=Y}A>R>!OAA7jMdDGyhIs*h>8K3*F?+<2>-D6P?B?h=hpksR3=ycPoj5E!Y zS{CGMt=F?mYn3X^Ovd@K-S=JdN-MMvS~g1gMzJ4<$CLz;&oG=n<)K9LV}&4MX2iAC zS#`^tRF8euW`W#!k3~0@=`Ls$B9RVQuer31uK$!uy~1=UbYuPjkvvht@A+I^Pur+0 z`Q#52d7sM&Gyp~7ifz#SY`Ta;YRJLSo5@f>}-dP8DmsA7In0L(R-&^SLO?1HAF z2&mn>Kzkl!bx&|)JXAZKFP&5 zI{V@ibnLjUC1lwIIC1MFNn%wu%=8_#!S&M=C=|oV!{y2(o~Q_s_0vNnrl;<0rt!zf z-W;~|nHZhC;iu)C^5HY1g-1U_Cir46IXVoAc!VWXi~UL-J+$qiT%VMyC*rnrPidBO zd6dP|Y_-w9Hg1j0pby`2KqB%+r-@2OWPSoEwTIRi<{x|}^uw~MKKTd_`=1AkDi{|dFjO+$`%kP zcDY0v^w|7tE2h7!8WEyDc6LgBl&SL`_%>ZRVA?%@Ub~NSUrNT>9LucB>uQHWa z8Q`~Dzz2^O-bHPQlV=00aGtxl_iVY5bAwM-_DXcQVg(6SS3aEWe#eumtv8{^t)$r1 z3AW$OqqyoagqUNt>nZp>oY;+=*WeR1_mVM(ddYYNb&HJz5A!cbrB+mU-7*XcW4yXK zrKb~iHcp{pxT3Rhbbw+Nr0Nb3{``|dy}t@%eWgJ!6#hy~2=Hp+TqlTG0F6~7NdP#H zzYK{T1eQlZpsTrOdkX&f@BTl@L)03$sX&g9m@i~HVpH93JCuP_9qr#%`{+axYxHG{ zNZ?yf2EA5lMkO$@BQIO?p|O6O!kan?|3xw5Xl+xy6K zuYEMQDuB3A0>r2P;w=*Yv%dNN0_q+h>i+xc{(A}k=a=vWA`nIqiD_f^Vu9fJ(pkt# Z0;+}ofJ~qop8}tN6l7GN7fQW&`ya1ImFoZi literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/karten-besprechen.md b/daten/Planer/.planung/karten-besprechen.md new file mode 100644 index 0000000..984d38e --- /dev/null +++ b/daten/Planer/.planung/karten-besprechen.md @@ -0,0 +1,61 @@ + +Karten besprechen +---------------------------------------- + +optional +---------------------------------------- + +Entwickelt Karten im Gespräch mit der KI +---------------------------------------- + +- Die KI schreibt nie selbst in eine Karte +- Sie beschreibt den Sollzustand +- Was sich ändert, rechnet der Code aus +- Vorschläge sehen aus wie bei der Prüfung +- Neue Funktionen gelten als offen +- Das Gespräch überlebt den Neustart +- Die letzten 30 Wortmeldungen bleiben +- Gespräch und Prüfung teilen eine Spalte +---------------------------------------- + +Gespräch öffnen + +- Stift-Icon in der Kopfzeile +- Icon leuchtet bei offenem Gespräch + +- LMB auf Stift-Icon +- Gespräch geöffnet + +Nachricht senden + +Sagt der KI, was das Projekt können soll + +- Enter sendet +- Eigene Zeile erscheint sofort +- Text bleibt bei einem Fehler stehen + +- Text eingeben +- Enter drücken +- Antwort und Vorschläge erscheinen + +Vorgeschlagene Karte anlegen + +Macht aus einem Umriss eine echte Karte + +- Gestrichelter Rand vor dem Annehmen + +- LMB auf Haken am Umriss +- Karte angelegt + +Gespräch verwerfen + +- Löscht nur das Gespräch +- Karten bleiben unberührt + +- LMB auf Papierkorb-Icon +- Gespräch geleert + +Gespräch schließen + +- LMB auf x-Icon +- Spalte wieder frei diff --git a/daten/Planer/.planung/karten-pruefen.md b/daten/Planer/.planung/karten-pruefen.md new file mode 100644 index 0000000..cd0ae23 --- /dev/null +++ b/daten/Planer/.planung/karten-pruefen.md @@ -0,0 +1,82 @@ + +Karten prüfen +---------------------------------------- + +optional +---------------------------------------- + +Meldet, wo eine Karte vom Soll abweicht +---------------------------------------- + +- Ein Lauf je Projekt +- Ergebnis überlebt keinen Neustart +- Zugang steht in .env +- Fehlender Zugang bricht sichtbar ab +- Jeder Vorschlag ist für sich anwendbar +- Jeder Vorschlag nennt seinen Beleg +- Eine Katalogdatei je Feld im Ordner stil +- Neue Katalogdatei wirkt ohne Codeänderung +---------------------------------------- + +Alle Vorschläge annehmen + +- Haken-Icon oben in der Karte +- Zahl nennt die Menge + +- Prüfung durchlaufen lassen +- LMB auf Haken-Icon der Karte +- Alle Vorschläge übernommen + +Alle Vorschläge verwerfen + +- x-Icon oben in der Karte + +- Prüfung durchlaufen lassen +- LMB auf x-Icon der Karte +- Alle Vorschläge verworfen + +Problemstelle anspringen + +Führt vom Panel-Eintrag zur betroffenen Karte + +- Karte blitzt kurz auf + +- Prüfung durchlaufen lassen +- LMB auf Eintrag im Panel +- Karte im Editor sichtbar + +Prüfung beenden + +- x-Icon oben im Panel + +- Prüfung durchlaufen lassen +- LMB auf x-Icon im Panel +- Panel geschlossen + +Stil prüfen + +Prüft die Form gegen den Katalog + +- Prüf-Icon in der Kopfzeile +- Wortzahl und Satzzeichen misst der Code + +- LMB auf Prüf-Icon +- Fortschritt unter dem Icon +- Fehlerhafte Karten rot markiert + +Vorschlag annehmen + +- Haken-Icon: ✓ +- Übrige Vorschläge bleiben stehen + +- Prüfung durchlaufen lassen +- LMB auf Haken-Icon +- Vorschlag in der Datei + +Vorschlag verwerfen + +- x-Icon: ✕ + +- Prüfung durchlaufen lassen +- LMB auf x-Icon +- Vorschlag verschwunden diff --git a/daten/Planer/.planung/komfort.png b/daten/Planer/.planung/komfort.png new file mode 100644 index 0000000000000000000000000000000000000000..84ed8477d20c714b876b2f6beab7a4c62d9c53d0 GIT binary patch literal 21904 zcmeIac~Fz-x-W`ttKE&rQbbgQbT2mwMMA>@4Y+Uwpr_nup|Po1i@cirm0-s0o?-tn1!zvp=q zdC$~9=%@2P2?z)X8Q!^VAs}#MT0r1%?GN7pPms%>)dU3oAz*m>=KY{_+Kgb>NWk0< zU$~rpJODGV-}UObR70fSNxh#B@uJ@UdjADMv+wrc`k55AN1DcP0zNI}N0+E=@i4)h z(;vS7>16wFSG~KxcX6t8^R}$5657G~ikv?Ec%y?ErqeIguS0?BaMRVEQfk;-o}nEf z9Qi%#b5x+Qs_JN<;PbI3P)lrd? z?>}`S6w_hQ4rHLW`imhtYqLd}N~_^3HBwsnsP#!KiW7}G4GN#6lg#+M5;LXZ3C{2dEf!Ut zfVHn}d2zd3TL)L*{k8nlAIEZJWYyek`C>w((e2-p(gO86Oudz1U7ru@M>SC>p!dW&ZG`}?N zyoNSsycH)XM$kg;iA#3{LJ^)rbpBn;XsJQO8LqV6xrmx^AIveF5k#E3tZS{-FM;qb zJ9Df|C;01+ibma}Am3SW(PI)b*|!k-iE*ih*wBBBTSfkwm_B`p{A~D#@d!1~@t@VC z<$Sr{T8$i!3OsA9@i1TdsNRA{tvv+Y<@Q;jf>vWcSK|5(p33sRO}FZ#X)fUgqDhy+ z2sjgjQCC(zOeX5?TDiC~E%c7x{l?`w-OwN^fv>}&pRl*+uazCFX1~ALqN=;w>di_U z8N!~`Ah!&cQiRu#Pv!?`lKIFY16KEsFE?i|b?F4J*TwaX*OOop-y^JCtV~*835lL_ ziasoS2U+HC(u|Wyd964Q#ah5aM%WQ6Q z1GH+%zlfhQ)GvZ`s%3DtxPo;?no|X~VC3gN7rD~XpuxH7%#st+!&dIr{TJBX2^%ra zM9sjS;sRnh@5M)@A{?aXivYG9>h3oYk(_lL7}RAfymHTpNdh&m@@!IyOXJdNdb|=U zHTzDR@kfG(JQ$B9FoD(-8FTs%=%}_^T-db<)FxcG_pWiAHR`@y#S3S&a#;B2=Qb?V zY%OHE)7*6=VI)%5V%wvcZz`HXm;4@K+cz1|Wf=SGvyz;PYB*bu0UrSYYHz7tDwVI0 zxrrTijR>SpvU6@WfHdM4%Ia3?NgJ9z>fV745j3IbhKr1`>&&MkudY=Mq)l=SfeFlh zid=yBQ(j^-gOdgtEu#~H%lh|vhBFn9E~>}rP)0oYKbIGcmc$p+1jBxx$G!|$)jRjs zh%NM9Dw4?v52O@`6VND!?R|T%GDl0-@w!I!eMXEg3R<3r=-H2`*39y~-xxHznk&9t z0BLbrqh2!d@V&#K5P#=9aOdLl`QM67v3+6A zGT)7^EDhP^Jgx=Tz=kv}DKnu%O$K#t7QF5Gm;A!Ww7}(>>;WYV`bDJ5iPf3>P3tjJ zBlpRD{^YNA=0qii7H|sggI( zNKR@>=Zf|bQcfQ7EIPr@I3(~4jC3U8>i7s=9||e&tIYe7sI6i3_+Ylkq0BfHxpO6^ z+N?hp&4=QUar9*s!-Jvl?q&w5m$LO3pA>&}N~G3hhC6LNpWal~Bww-o6?kD=I`l^O zZ@hcF{e;5A%6Si@+~@uKVr!D33)i=jeK=s zR-wfAensO`D~kkzDbNw^2IJSc=u1itR;eQ;D83G6=|YY7jBhJ;q=>(ZIhH4JZDC_i zYDnGl5_E$vdDebUSi-|l`g=c0ay0`K^kAkvH0VcA8 zdvf+rQ|ZdpTd(|$Gk6&6%H@JdexxT8~M0Xs!ri% z;&3sHpIL&*%~k88Bm9W2YDFohZS>7qD6w7z&uM0iYFw9B!stSIoGiP`#E!L*Fi$lh zc2mds3vm%6I{tU*w~Elkm*at>+QD71IEsI>AY+iJMf;+|5L0>w_M&EI=haC*U3){; zg=dhcY?~Hn@W&5yOfGWcZB9;gabB#3kguVsk!kGZ%ku6$Jva>;n==F+1_Se{*}SeuP$64|GUz>2 z1j-#vO{1nMf-dSAPI<@}8pc}I@dK~Qt$f`_JB;T~$YxqOLb!n%a)!?i_Km87{1IVK zesKc4_dX|TV{$;T=9YC<#^xPDvN%H~U(F-oegm$&IRqAunY<>iXxFk(!e84` zJyPrp2qaTi0;aSv#k&zm-UC3gpu1RPp zJj-pc5!U%43dUbawXsgNNh%93Dt|fxJC?Rk>`n5_*jiFOLTug`<%)_j%Ir2as@?dI z7Qx88to6cU-YuI0Xb-F5wO>**wFB;e#}}Z?kOzgGq9#_Jr6mj!hYc+ zLnm`qK%=w9T0a-rde>Ejk8ggNEP5ad8kI%e>9e#1)#Kl*7-=oPc5VzP3~vY`!_QN; z`E$F+OfuBzZ?&;IVSefbqqgO4mgw=$rau(tlpu{2vvZ-G{GakHu1DK)cSU_Z~WeFoI%#=E7aTzn`WKGNRnwV!7ZZp z7=ClI`<7O58kbEfb-Nlg{$4U-xbNrm_}NS~9zBPL6En%+?pGkwZqrT*iK{=T^G432 zq@MMSmO74=|A9IK_&(L9mb~7yMN8S!wYsbJn5etI2bcs5Z!IubJ(q2h(&L z_E7qFR(th8{%3DIx>vPWW`*#yWNwKN33wUKJdT8AwLxdUfL9wIO5j}g=ej|Tp-e}S zGZzD|vt?m5p%i5TcH7%(>qwH~Sq;uWdrA0Hax$>Pp9fOiCNj)8pUm|4{O^%h;`bhQ zPl=jKTncrb^k`4*Jh3*t6PpT0+ZfQ!848J8j}*rW)F$k}ekpu=>9D|W851*?Hb2eV zmOb`oWHgQZnX!<=gKM*>(<=+TfiThVw^!c!Jz;~6yHDZG2y4=+`*wqmzP@iwAz1In zs*757f(d)kh*VsH-Vn)Dw}AmfmuEM78r)u>ROYkDmpgb25jf6Xh>B^UwvSoULl`?w zYtV4$_|mb~5Q&Pu;;e%2aJBH~n20 zt1PX#lKqp=@o{}1oJmU3KPezE{B|ZrWdxLbpN4vp=!Jf4$QZBdJb5lw_{PPCoeVbN z>kml_G_t9trt_kGM0HoV*T$c9RU(eAiylR6=q95ux+hCHr_q1JfUDLwTlQ#VYJ{{L zI#>}AUV!CQWiWb(BZ6bXV9K0f?Go^@i z-i@xBeQme3HeKyD|16@JzgMjXx=s7BP)=y949dP4?DBp2CsdD!Z5YyhW47@(9RUI8 z%_cBXP7{Zl-GBC+N{yO%P$e_q!eQa|+4ASSD#iFN4iAThLe#^_8BrtAHsPm{C%d|0 zEphTXQ2=FkK86RyX))R5bu?!g%?HodS} zqbGQ(uDz&;U9|r`XI@aPuy3?k4Y}0K)Anb)OT9ox&oogUj+FIfO7K(2PNAEXQ);G4xiglML zK_O?=Rx$f}qe&Av%#-;-rm4H=LUT-Us&jaw40oZ*)GV_pY%#6YfW~Q0uuy?x^x%}! zqYl@eJY_`aL&FB@FEto49#R5{#SgB}l~8Y)POt>8SQQtx%nzraGs3?8;^qO_attEPRt<&ibB4oEJMpP#p->#P*CPmZ;OmD0fV?cQNl6GtL7oRY27TtFSbg6!)6 zcuWgDum0rCaKS@`hKCBSF$b}~XCSKWuIAQwqH5*^jjDD%WM$puBO~(A^u4`sN7U10 zZ^(s4-{{PIcG@mFawJx`_YN+cG9x@I=dfv7Cgm5%3rs#&N)q8rlmyxlZhzUWD zLhziA3sHu1H1xl?fW@KA9r}FrALxMVS0?qkOwy#$qG)S_RBZbj!x_ zyOq>fLJ+txoS*9!JsQ@sTK*|R{a9I)jZ6$?XTJC)(%#?Siw2ekke$`x!+@(YE}tT> zjZJkC>nk3aJDXr15JtDaGCF3Vz<+TQ#p@YXGYIDw_nWLby$>Wyg`B`w!sboeyW7i5 zh<7;et8YZ%KPG=jtm3A#vZ=C?dn9wg(9Gc?6FVc;;G!yjf2v^KZj+fl^@wk#Ygg&d(KczqZnu{?IkNhv3tyTyRdHDKJ?2fjiv%?aWiwAHoIv(1 zjTHhM4Ae_#bgVBYCTc97=Q7>92)aM!nkE&J>1U0l=SH=BJob_pkGVo&4Ni)H*T0&+ zI2!1KW$FzLq%Dd_hHPi!Nqvkrc=~o=zAk4WU7f@;$Ce=nuAUJUl#~eQoVOmExn9p3 z-NfNY85^7CX196Xe8VzNdGWCBzX%Zo{3&3i1!%tnh`MZ>TQQoq+pw$JUoz?YmDHrZA%2R!VvvVWMnvaQOL!n{VSZHFj$mbq(@b0|W0 zw_aUQW$T^5?F09T|NZtks_;MGfAb13O#%X;>40$sj{n*Js`<_0d)l9J@FKC&2i%Z> z#&-EJyvaImEsa_hst>$gv{2GP8|}shibT}&gw+_8`9!0k3sj>)3y~8 zgtgv3oVt}bsczQYeWmUAPUUHIseN^p>%f#6167Y;PI)kz-usf1jslZmy}fjc$8@=! zDuy182@2|afzAo^S!IuW%v6Wp9MKa_;!(4Bal5bHmH_X*0c|)%Ktho8L{%Jg*UI(# zfBa6|mfHk%H-AIt3Z1{UJcu*@Uf?(0qnzU`gPFLb-2y)z-vL_sMIiLWiB{wNt15~k zH)I5!aoPvZmLt*pTEwWu_vK+@SZDEpJZatJ{1DPg%}U8k!sp{4Q>GLJFHyYO~q znNfBh;H`$GvW|OpW{G+TYkk}h`UqKgU#%}_1Gp@K0)yM<#^a>r$7;aCD&rp^IWr#& zqpgdh5B}3k|C9c}qPo@#F6Hv9<<76&3Q8&#M+M$PPP#a08+DJuT+SLCrRkmGUuv;g zdL9X^Gpa7*;Fu1*R{7s-F6s%CixrgG+Oz1052^56X1nkP!@`o=L^o0@=_e{SN zc(xA6#qUO^-vzNIacMOJXyvz|qa}{eDukn+RZ_z6rIhJ{n=b(5`TI#1fgkd;1`Oua z%zubHo>Z@9YN+B45H|M^T-kx0`D3PZzt1dHV-24NVCRKr*&)IbO+h^=-B~~0il;uE z&Lx(_2{lwYl8}gzk5V_#|5}7av_3B(q9|lF%d>=b_r5xg1}3cJ&VJ z`N~W1tA&nV3ka751^abaFy;GRoGU4ar`~JkGn=oD_pDA#vvoXkajtZT#jR8M1MhFr zJ@bIsZWlLRsB+Zu+0sLsnu00<-bQ9s?j9kd)j(ImoH%>W<$5kljYqWgknDH5s|~!* zW(Kya7Ll<8RMyHu-P%{?bJ%hD?C>JnrqW7x<@4Bt>#1#WdIAFFu#tf~sX_PE85JH% zig!T!Jzi0F>Eo%-yV?~a7Bj|mte@`hM8Y?x{LSLuSwIlb`R2#8KbORQCAhL$*IA zC5!97N$w3CCC(Kl~&N&`ifHKFc zvog*G91bl4q>J(Nfe~wx&kdfqs=NPWFmyHh2``}#gdh~tiupEes$3=VJp%Qn_=$DHmK6G+2{5n(sJJ@1gHqmFD9z zx6rwidjUI^9jsu~2ljp1gj;cjm98Takhfg2@_R#eEWbn? zr4|tWFxV)>$Z8zlWNuc?9B+Nd)uYo}2)4M0d^MgdugG8#!KsfuYi|+ARj6^art`1_O6D`{(_|-nzx#~ zJCx@TaQ~5I*Z`b(2B#8cWi=KSeyK2oz@a!7LCxI#4a19DtqZen#Sde{@|kA%#K}Zbt&R9NAoED+L!CLO|4REyKF`$1F#xD=eo`$>00eC@|Jge zI`N4^POAoxQ2YjkZ{y1!#z}kBYTntUrj3!}vpR$Z6V&P0!Hc`x4Ds9YMJU}sy6Jwv z0Z%U-&F9RcvO5}J8M@2M9X0Yj#Y!a*OAbl6c2ZhX4hLcGwT;aJY>ZPVbvt1^6 zOn&|l2)T;mfy%sfa-Bl<3PAB^$0_6MM*A6hYGyL~YZptr5cmC7WyIA-idz;_HtbIYp4ZS~Pl>-8@qBmXzNnr= zNd5)FB^|Pl6~DWX+vAA3zcGr7%0ZAM!l=IH8`U{Bq;xnV8D2a4%kKKkK@JGDl+Om|L)S)i&GQ5MbtyZQ6hYTw ze=kpJ%W#`w(IOKWKXIkjWn}O(`?7PYiH3s6&{_ofCv;1#UyoN;S>V%$c{_tl4Tr7O zNFu)SM&=Y_erin;>5NVPfl83l*3eRrOH(PNLS3d}AS>FmXK20#ZxMQ7J)>kSY31v3 z`R$*)CZBxNsNIdXGa6bDjPp9%0_Ckodx*r!NaKvTpuv@4NeQi`y!?wAD?!r_v5ox} zgBo!jiOCL3bHAx7Q;*y)fc`o*Nw_@nQVQlk`SmT7lxU^gr7e)!CRBOfdxs_B$|KK; zV7!|`-Phh!Y{Fu@dQ4;AXBNfG=e|@G?6_g`fNQP*24d_Y6Nc$AS)B*hUFN6fO`4L= z^rzN5C0lh_s649i5$}mQQ+CPt`_#(8ps;|4hV-*(z2Sl2Fk-+iPaD?WYd>F9dh-Qw zN~&-mkfVVwHF$B`tbyN7#DoFfXiN1xzuKl1SBKN7fw!J$u?)%8upH5v6MELw@W zRV9zBwdm89m5{y7aWNavIDB0XoaWWi?W3Q6lccK@JXftb0yfi9A4;w`BruL|%)o!| zS^e+>Nxp9K=}zRWMi<$A8u(G$xhkJ9YG3Cu?3P1QaY6kPD_^Um&{?vjclX^`mnDSz zxt98i_$R&R4B{iRTw624_R^<&A5>q4Y)li&2oL=xiir67>F)?(BWmvBPb1K6v%ePJ zM9)^>;qv)=iaLu0`iJqgZg6^EIiFz7M8oEltG%YRkwxSS z>0vh+I5C+L?v$;n$lZhDV%f!!xBAueH&^>M^ z=!T}^^RmhueeE%wQ{Y@w_TkH;I(v5mx|Y0ZJi2=e!u|9|k^<`-lQh69T>jAVvyC(^ z-`cXW@34>^NNjcLalXz&i)`g}QrnhPNcigf%@T{*aIepQo~!yv9#gY2+(fC!7t#Xr zt0A42foL-<4U zri=kV7uF={kdv9maQRL5Zpi7Ir(~;oiuS$}_~;EJgn#&1y3pK{aW*~SdTd+Qfv4{T zP=>(6i|%(?j|yGJxo15+-e>Ok*?9D0L$Asa9n$^*^}{E&9ME^;KmL{c5h(W&ae1#4j6QOZh5-n0;H#gX&BUp+S9#wkG%l*`#Ih+? z;u@!U^d-EPh`lL+id~q$_b)DB#foVX@7-9Vy}fk^2Jssq%J#{}0bK}ey9C@o7J3ed zXh7I#jqD_Hco;<}Up-n>nN$y!uF~_iYYv*wj)s^_LxOS_zA*z4W(Tg;#&_A4Pt?!w|81U}r`edhHJLgq2V(JEkyV+cWXq-skm>9v9wS`$#C1fV0 zPA{*k3SVcpY#7*F+rd@|@2q_g${rL7)$sPGR&?2RnJL|lYNvfIR=d~+}+agj8C4{}#m!n=8fM%D;BR{JoD&N?AR@-&3;anN>qtxk1 z)D6}EmgKSCSH;$*tIGVEe4oD*4|0_@m@vo-XMeefmI5?xe2nIq^1CTtLFLB^()^3Iwdh%RFH0%zaD*?0N$TVjDR`3tC;)H=h1z;PkhfTzRz67jz3tu zV=TVbvdg-EKtsKk^e7K+Y5W~r@t23`Fn7GpNvIqHb;Ss5%NQJ&4`%(b^#efCd}hoY zq>lbiYl8|p&1LXTy~1YK;ai06tQNbl#p<_cq2)>GCYOjf3V`2{`(0wE6=DwxlYZmX zP64m){9&mLs8NE3tLCWQgWfJKP;Or1h&JA z>L%<|b_Zv@%vyXtDVM$`CsR~pf+Kw<{twc-k?64OSr2V z5u5jn85rxWb}6Hk<^hfPU`^z58AUNXxPy0CJJ5Ybr_Pomrb}_GoDnk^I4sLt{HsE*lZeU0zOa~HSBN3n3$1Rbv8%uI$0 zW-m3JH1CeGPR<3vO(A2GL8qf#7G|zpp0upp{0=ypXW$$q0CWx7v9v0znD8Tlx{{q1 zwmS|tA1=wY*m)OUN)`lZb9!ybq?Z4Bk>X>~qR@F0C(+Zy#)L*IryDfCA7)Ndfe;bT#wQsz@E|KS7X?je4YYZcW zY#7>{xqBYGm$Md8NBdd}+gEdjmPq7Ss#D@rBlg|Rcc+_9IAOGVQ(K9509r&k|8T zzAKlizR}z)k5yJmMeJ8Z($OXgms10Ha$W@1c;1S!OOK4V&bJ>)jdOL*K6lco3zH8G zT&8H&T&iS`Hje%JoC^jzAe2Y}vp*gQme7cGnw%B$3RS+s3~;#Wvb8Q0T1!vW*y21# ziTdnah*Wmn|55Dj&R9&RepnHEuH@MCRUc)nXssA0sy81nW=>{>(U(NZqWnxROqYgD zj-xe*nwRabgwIo_|KRyO5+@Di*J@Lkx^c_tqn_i5#4?BNNnLM7n)x>Mu-NgIU`P-4 zhF0*Lv9r&LxTr(O>>}CYmcF}p{4X0s=mH6{or)&+nMcTpZYM`(u4+cLrmW>xNm1U=_LEc{`xw(s#ddec&j>ZrXRmb99rVh$670w z_*;W-6Qeb-`&J}DmSoYEuJ8W2(qITb%-j3dMyr7 z>f)1oGqxPeO$pJPlaIqV(dA@x)!cw|yaPXI;@Q-xeDLCS_&`!qS@816;H4_!2tgcW z7GK;Oo(&E0THNDHyi2ScIcXyk)w^h!^$S}^jgeasxY#bJZ|YDFXHdv`#F?;9NI3k} zG>dyRQ0PfYPx%MRYk{ zAF`FrKJHN`@0_wN!E_<;tm)0QUOqDsanRk!UH@EF@4hCd&p$;U15}FEN`1_+IGwAp znn_~4U6pOVH|*?Ws&F||*IPfBauSRYGnpMwHKLd(JQ(-fZ`WNmwWv+$){Cuyo`_Z4v%$9Q7`e}6O`#ms?uXV%qU zcdwfJ5Oiad+{pEry0PLm#cr~7j9Bn#MhEx5{>3aq^P#u7EunZzh?~oj)R_-$sT5&j zPP9Dvl=DFZR#r?)PUS?Z#-SAy70iIF<7K26wEvZaANK@7ov|Dfn-31%(A!)R>x}Q; ziE%U2gUiU^U$vG=j@G%%-%VSB@)9TD{a6WlOpsOc%Gaqi@$jvspwm-KF|XBpMU49P zZcts3_qoZc;Q6*n4u2=l3Qi28Rh**)g5K25l~;tJK#6^3fLXNK> z*5lamVq%K&ralvzFypy99wUV=_xGqB6^Bi^4e^|(%_?ERCb z#D2uJWY13cntFjkI7@hp|Ma&pr3k>N&E{syik*)IY)Ls9*JS(%R-=>cv-I3hPqoWRbB$!so#-)xaTJ& z-hlE?_K>}0O8~}u-SPaqNP%cp+(85CIW9ipm=rlUMG^9}+M0GIgT!sdJ)c4_boJMY z48{=LJ`b&kv9Hd3nxvdjr_k-5TD5{ig;1JrMrMOmmMXgR`i?G1SZS|G;oU!dPAJBU zIi?5t7fq%bEXqf9leL-QRmD&H2ZL7O`o~v>l(ePJB#SEBw`?*jbWN{JWN;-#LpM_m z@)WqkYB{>>MOx)>aZ2BiF~CyS?84h^6dY<6mm}Lm+Kp?QUsnQfsweR2dm=9j8TPez zy7&R}vrD`EsIU^G^1VWdRa5UwuOT;Ur~A3RPe!KNPU%UoDq`cDxNOGEwH#ydUi}+uNi$Fp<61*g-OBn!lhK#fQdx=6qyI?$ zsVZXTS{9Iw$kTKrp7jl*C{98Nw zOGd7-Nbj4r%_@?_CmI(k;Gasee_AS0P=u&^^nTHHZ8JTmlhd;#r&ZV>n>kRrP)IV7 z_tq#Ub!4}z*e|+vL_-`a=6<>@*b%okB5$P)f3%`$pcbF3JpPaCm!mVeBVS-qh^62P zS2{c^SM{enu@q_3>&)pTq`}@!{YHLiuP!%g;E1Jbe;ODzN=qGbRe(t7VYz+?+xh5; zx{2wlQX)c60+`*l&J29;Ag-_GVvAdT%8DM*3}bVuy(gt#sXln2ElUC)C4m~yVSeYV z$Q1%#MQ#^hI(r@L9BM=6R0;L0irfZ@L*>I734~tQr*Z7e)w0ESAHov~;ZSX=|8}rt z7vc&<3DW$uYcOFqFcZ<+q4o++2qtfBY*bcmbORCKvldeT`&~*whRsH5%Jqd%Sf2YU z22~+@3)KAzIgM>F=iMPG3OcWD_fxC$8r9n3>B=`m=aS>K+GY}+fOq+54S<9`&SHQ` zyoHu*T*FF<+Y+-i0tCIW6yxkMrhiT+JC9KURBiq9j=*9&MIyOIwRa=P%W;a;k_JquN%@K;{Fx_+$Lt$!-@AsYBSyxmX171(1SI9M-B7 z{=0eO&b=#)54}y9_o94Yq95*{2jW<)H84uQAf*qh-KaIlCS5kBRtzk4KFAcggQSp0w*s7u0nPzF0+( z4EV+q@`+?Y17V%biu9>YoohdHhqU?Iy?dRLGhiT8GN1nd$F7F)cg&HBUB_8p|Kiqu zlRG9*piA}7IS$R*$gM&r=fYfVJp#+DRp_JQl5*}7Wj>RG!Ep7vPm5XbziTXsU4J+i!cz!&c-g92~&|W=CF}6CGq{D67@Q52GdZZX2She zF>-c9jELXpXRw=8OFEHe{EZ|t3Afh!mCvEE=aO~Z4SkDkDG*9L-t7y;Ogg$|ced3z zP3Ib?;_WRI)0Lh)1CJ9AfgZ46A0c11a$Bs!R(7zC;j3*8;z~tH$updty_0pv=@Y|u zQYEJ3^OO&TxgFFN7QkYXCOq2h7H8Du7_|ogsUW^s4)9R_A9W4?%VLNB!-pTy=Uk!y z2vEcR%9NJ^h8CzzK26U9Qsa2Foqj!W-8)^H%_bE53*~b<1;`L!i2@(vXo#f3dBATk2u0+O;<`jqGQF`eyP`KGS%o$NN80bku`;lMgo{y1XYA>n)YJ^qAyi z4A#2w>1PSC1<+XIt*Ol2Rv)D6&4~`#lD*c3{Dt^bRS%j_Fu3W$?B*-C_P?kpn=k09 zyt@jELzuxKRc(qRc$+cg%J;qPJ@*0))%9KJP!MU4-oHwXoA3(XTdvyN-(HQLQslOa zN?{cz*Y6CdjyXJK3);Q_?QyH+*w`8WS>lFrkmpd<{GxJ9<3<{DKu&5ccyDg56ZRL4 z2mK{L%w?WA@)9l+e=fMMV0UGP1Hx{0b*gHy_z(zjTQjv!n?-oMY;HccC+dO$8Ed+a zkHFY&=!t7}t8eBg{&C8|0K@hmY$fKo*dtzPOUOO65V0{RD1Q8N*U(QIR;fY7s{w4% z_KRkbraB<2a&TC9BkE(5RNQCTS9PI}$h;TY*zl1T8Y~}97qUCWG59}1qC@UJ%?$`KlSI%odCBwGrOX7yIuH%`(73rox_!s%D z=S}MD`+9#z>sKBfheM;=bd8SXYrH-v2%&m^AkB4NBf6zx67e%P<>h5&-k>IWO2UJt z-i5|@_ZiAd^0N;~)rDL?`3UiJc`MGwghSRW(P2Jq4r_JR4mm|D9o39IQ}RH*TOc(4 zh|fs1*X$*LfR`+6dKum%F%y1FPbR9{nrLs02qHvBV8?Z2Rn?-(AoZ2B&G@v@W=Gfi zJA2bvLEnd3uhL#c&z43CY@d&|9}3z{-;;6y zNbqFvmUi6|Qu+L-H?t<6^~HPQ1EVB56i8KS@;0%_X{yV3T^)bl{>o!Y*Ry8^c${$l zTK-Sc=eGaEXC#Uck}@0KU;b`f@Gcf=RqsxZG?4wP4o7IT3<|p0QvM$dl0;#F9f?cb z*cEos7x+*^C|`Jq&6k$7T^0kV^Q+ntwPn6WFQAUqB;jz|^M}4y^Sr;(ieAhA^3UW1 z?dw(29W6@R!a+4`f+jk=Jc*yNW-b{&sR-)N#)VtvWRU4O_Tzn~wPkV0w5Ut>cI8Q)msvjhw8$R5-H%a;T=4-S24k7Hu=ONU4OSN?hB&T9ww!Wa z>1*^~oxpE9@rX~v6tBbQ+k&N$9M{_JCYa}J9y0C3*?sZ^F+-QTE9wHqDxU+P=60DZ_3r7R!kk?>2+Gm*TMHKd-j^a`4GT?UGJ=&Lbnw&xg)Qy{O z+k(TxhCV(S`~vN}G%>qb^b_{%tas0^%8owotoK&Tu2L$@MFfYMwmsNgla(Rc%LcCb zEOCG<@Jh06s0JWTT?*#tr=-5-JjzmQW(euIqWqx3`62eQqDS}fdS}RlDfTijuaAh~ zuB}|5$c4yQw(wdQ$4Yp1n6Lt)gP>P|stVgx5Zf#De0v)Ee9&G2R`jkNqGMgX5X2Di znDp3D42CP6*W@H2Yy$TePS!eF%A`z$Zw`MDVmN2d7c7~;t8~q=- z%qpXrXFgnAF>nmyzf?M^_Tokto7*5Q6tWT{5k~t*Q92CC$z@9We%xm$bwn$ zz<6cM_5I!Xjpa$c=F+61c&Ax9hLp!ukFL!L1o@K7;V6H~E!nt!{=!v6eO_-z$SK88 z+UQ&5wxKkb7dW`E_RH~>`G%OiP~ge~CC~G8k7p)C$7{ASD7;4qmO0yOIkseOdrkVx zlvX#*$s{#H(+b#|XJ!Y1NKItU)BrsYs5diTX^uQ1D6F%HgT{sW^}d?AmF+`IwA{M; ziDqWPH`L{%WBMaa&g~WjFAnriJTPlyOZfHBZ&kX+HwN#eta^3Y+&!uW8}*phE821t`N(!Q#uP?U@n8D-_K5k7+>sN)7{JqEmZnZP7iL%_ z=~DLI)}8U^u-KD&@-jRHeiQ|upVY48KVHk@Bo0>343rG2#)EuW-zIc9D-EsD`sp*; z8mhGqKcvFMQaoD#6_hw*$)V=Xa(E3+t@* zZ(8@o#Sucjs9XN=$m{3{I&+*wmJ!Jjnwbe`DR8y}!m0UzxUVt$q*LtX>4aeds5u?3E|a=5 zSV57%yFE->Yn4s@=b&~OxBnUKPQAH5nX&CO@hlW@mXC*?tGH|mb}08#wbyrUXB+BL zWAKX6dFK+Nod3lIoNm6iw<6W%$AN&?x~|5PRO=m$4$#a!#>m|71cUY{Yy+7S$=rGY zS1%iG3PF5Y&?t(Uy)e5Lsi<9c`CUb2AjEYjz4rk#;fNk{jqc7haks`O*_yk|RpwPt zfLj|tzOVFz7>AyAvc^;y;OqeJNV;~&7-72uWvO{ncCd7qE{)3`!^wD>07toMT!wI4c8zeng_nC zfI?O8zF2t|1NT0!!|OF4i=l>Dg?%1O-`C~Ue;Ib4q|@Mj5xVNzi_uLP<1Ra8vWqc| z&ckFh^tuf5p2Fg{^z`1m3{zU7hvPv=_dXNIfbuv$P+y8NQe0iH9b~n?6}^vBjsz-W z1U~lvyMGPgKQZ2&D1;eg^@Q?$q`Sw`$4;QWiAU?LlJJi zOl${aOb#dr0**q1=AG2A81HOEHa`vB9WK$uqz7y}wua_)W?f2|(2+OtjI*#yhjT|@ z3vKFa7kaw8Uk7SuEBMxht-P~GX)y}0vpP9ebdkX{%0YD!z~4U(%)ZMtb@brBhAG{N zZ}*E^n=bMg>Ju(8z5nikYm=#C6Q!dzL_gYEJo6uzgfsHJ-lP(knA%^0!G2(Q(Ej{P zS);qH2a4ZD#Q`Y!VQY!;>^qm_1KcYBTzp!Adjinc2q-2V{tJsMYj%73m>e9Nz<d}E9Kux`L|O3t&{+`_%Bg}GG^>&;Ku}iJoxRv|Dq}UJ?wwg;s3q!|G(Jz zk9=aBgdngKf#Vx>k{y|!e-JqO*A)+^pMgZJz~6uTZ|niU2lM%->lQyAd~;wF4-3e> X+Rp#8I{n}pkbt3{>Fv_rou2;>7-K^% literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/offen.png b/daten/Planer/.planung/offen.png new file mode 100644 index 0000000000000000000000000000000000000000..382a2d5f9a801963fe0b582a1fb753ef32c50ae7 GIT binary patch literal 25795 zcmb@uXIzun*DmZ>24@(=h72HNMnzNvMiGz_GL8ZR3?Lw(7YiU=NHN<7;hgj7CU@EQ-fOLU?X|9TE#mK5nn?XD z|MP(Z2c%5@zGHLXz>j|(IB=-p=t1!rP+p(yfdj`6nBKW{FCuqi=BJ2zV{=<`3V&Ze zY%%}t`(MuweyWMD`F76c2ienV32Ix8-wPV+8f7>r2*#I(8nXzw_Ki{ zIbrley}#MZo(IZ9*>`?QJIu70JbdI)eAG)$Ec4sqz_h;3wV(PlR&sM(93ACa1Mhdo z899FNIU$}#RdnfzAH>H$zZ||QJ{)*{(PRJT@f$x#iVsge{^YQK_OQj5{W<^k_~4oS zpSMm`?H`V2KRqHo{Q3R={?W{{KRC;3I4f$nyH;QPbp0UPK7Pe5S!d@Sli!Po*mAzD88l#&eYMhf6U40xjA2jeSVzszy8SEeB%gcYVwB)@g6SVf*iH(FovtGZ^ z^0y!IBW9dxjpyyIR;@VVqAVOc)-%d_PJxcI&CKJ)k_>7~5g6(&@g&0aK0aWOwh;jK zV_LH;YtWojh4aBSFD0%F0(dKPOCMegKF*$W)AJs6-;976rGx3;*%Fy6gYZ!1YPh6r zAfY5SPff%F;kYN%6h@1ml%S?-(E+e?kY@J!m=-lr?_?awr)}Ea&uPzRXkg82D;L^_I1<||GGi44?w0ODa)?C zPx-J|s?!5})s~hP-(okeEGF}6zG$weWZdwBPpLJFD6vhsoa~DUq@XsZa?^>8=5cz1 zARc4dqGrPD3iux-O|M|uVtTWh)y8xLVn+(~fH-PhE1UkP0TlbC^FutTYU#z7W2&mo zc^}+V4^G~pIbH5RRGt)@{%j8Bq3CDPBVi&($X*~yg40cQvR7zX&A&gC`3Jw!*KMa$ zL*i^sco9l`7w`GZSK_X7NPca2-lHPq9aTfsD>FUS=F514fWY}dIjNhQt8S49 z&Zl&`PJmrBBZ)Jd9sc-3EtFB3K4oV@7tekR@QLH{cf#SvR20a#~vf;yYaoS7Mm}cAdt0L zQ-~ekTDP+GAkTzsmfd*CI@&(tP z(wq3e;Fs%H^0vMg^D+n^_$FMnU{4L}A8>l?^-@_u-ytm2ueMw3a2mDFpmMNvTZzvJ zE%ee>n7&U4$ZH2n?>nq7;bSSuU#5!Ff6RlA?(k&jhTE(~>7K$%6-EezsD}EiJ~4~H zog$ptxx$+*MB`UYBm(|5^K_ra`EpU-2+>OI!(ufz?yEy^`oC@_fcGxf1N!#nT%9pH zFT|rC*qTYd$5p$!VvXPZ5M3!JK>Uc)zzW-Q6+c)XCDkmp6_od(oh}9NPM^sb7rA*I zu4?k->mE9Az@HGb=QQg{Cp_uj8RV-3t1iqwB#m05_s5)U2-5Q?^3pbBygV;!0&#-) zQF@jR?)&83E0nM=3D*_EXd}NJ99I<$)`m;xq=kG~YA5XX5EBRlA5D}rbg(N6Oap^lKs~CA8*Q&~k$ZRJW4Eb5!>=aDRJf>u;BPaB z-E()^qU`iDT0q>=#Q_zm#;Y2*N3G(E^4vu{WMJ>pOY!daWfN(9c%xA-Zihyy9%m7z zV@NaS^P@al6NYJ%$VaWCM8IbZ4GtBZI;P)fn)bq3u_d^>d@(97IxNse1BkP9>w2g^ zQRaaE=wWv{LliVH%C7^f^d5f1K&0{a? z>Q;2T4vHG0rNxg=D*oh9rFn)=CBpmN zss;$|aA9dTU1gC^CX|JIN#ZD9%+M2*bnI9Wa5-on_=q#2Cvcm%FgIZZCU4w3J zHcmD3ATGBTqgZQGqc5y7WkxTUq#y){RC9BX8-7-7$3ol#i4d@l&^DYBMruRb(`;*I zyD6?5>xSBn(SwRTu=9ofEsg zr}XEadwP0~LM6=&ulDr(lZd)~-`Yn&_cT6`Q`U*l6k9D@^VMP* zzcXucVB=&@#{N=(R$7P42bu1_?yV*~l-Th@)UyTYi&K}2j)>GK$fY4y{l!Q0-Q&ob z0?#85eMp4>K}4(bF4P8Nivg)}J5Fd^W4?#kl)h$O4lN0HN0mpD&wx3 zwbGa_+q=tKR^6(5N<(WZc&RAS+cMH?y~WCjEjL|8p2yhN`#SAy6lxG^uTMoT0j#1~ zYvJ2_uCdVGno>BHpJksXB3%o$aXQvm=e{kS4|_Zu=Q(6~DPPlfvTa)d5lUOilD^6O zUe3zZHbI20%_>9{S-`e}PEjE(@-IVJ{ngIFz`ZsUAX@r~vk0eN4!gDtL8A47T2 zyd2t&FsYk6cCusFxAby1B4hp47q63`Gd8w<#$wyo36wnq=6b&>idL+mESvxBS+@>r zzxBa~H)?TtcXlC9o|yh_WUld{W|jaMIFgG|Ns0ui3{_>~a1YQKA{Y!7TxZ*pmGCHx{$a7R_rn^z`a}7ODuwxH29r7L>hMr?s49hSBcu~QScEQvfL90u@p&U;!N;%; zz9+&+|GcuYT73(v_ELr0OuDD0EX+nJmMv@{8u0|bsp>j8I_1C1tSM9lXNa?}55gDy z<9=v|w>Otb+shZo%jipJSE1?sHOn2W6jkdFXQJXn1- z&zV2EyBx-~JPL;0Lq~TGls~I?o4TdKHqF~(ZCj6Ql(q#qd^Z(jU;GC;#N+J-4t`xX#b@P2RM3{nALfc?0cRP8|%5}Wn>V@lWdCehlW@MjX zcN#8_cEEXAczPb*i1fXntUOVE!o2iEqFl7t&r`Bp1uGHjKhRS9WBf-)e_Vm|5A8k&R*UXak!gQMb=t%>#OkPTC{;Y2=S~UhO)CVBZim z+`iYx+hO^<#q=b0EUb<>1m|xG*n;T#z&9UG%BV$iKOhnAky~C|t$C<@GSzL$2Ay$V?3vgPjgcq1~)>9)sa%{Jtppzqze2lawJ|qIG>sk`^PqyUlK`Jz+$-k-=u7WnhTuT ze1s^t?3h0M(Y{ZoXMXNk|M08b-oR(1iG?fQG}3NZuVgz|&>V1?dU!UCpJkH#fnjMq z7QY$#C)F)hum0OKv9BS7@t&8@E9Y79FnyCTytp&~%-?tfArvQNQ0Ru`T5en%S&zUN zn_&A?uT6I{rB#Hm)xseLp{dS1CBp&#=s)-f_U7t-q;b>|a-wonIxyu z#!FpC=tY$-+R^Lj-fpheNM}T7vkuwh;hxuj@RBO$lT}bxZUP^Jw8++uT!tI=`cC6R zkq`B61iUGAjg|ZlU^1!plf#DLfB!l5ulQ95e)IVM1z5x=3F-cPAG66EOsEa(=X;ic zu0Uy)v)BMp(&u7bE$N<$q4}rsT@9AW;<5ZqGcw!~YI7Wz_pQNRPWNUEo$VqS0#)Z5 ze-p#$^8LsD4g`aA^+&!N&0;G)KJIT(mf0qwcXvm|wkhthD@{H=rKaM~_NCdE2OI|E zaJjwgyeEtQm#JELtXr~$xIOIm z!ThNBhO0}5oS}?EcA66Bp8`8^E8Z^rKYhd=aPCBvhvdb9t3kmY2@v#CV2`x4CGZk* zIkC3)yjWLBPmehN5!AgN%V{|NOH~(92e&+}T=qX#syv9mDEpn; zeWE}!WgwVx^r}Z{+EIt?Ecs_g4*dB<9P5h1ot}+<7EV0_TF#qLOghx9ei2`2 zxg)W!t^X4^OilOTQ{e5$j%?;$vEKuxW#!B9%+teDH)wqlCxIgPpR2`V? zSN64QiGhfbq*ZFx-w*x3_TX|iTcy>o~93z}jsq6EZY~XAem1z^aJKB5oZ}@*0;ZCIeJPr&Qq72aB0v3ARv?GWd`xoh0 z7Ow6=ZN;lo>KjuVFZEY8{!C8rT+#L)X>rSQsH>e1nhy68@s@*x!5#K}@}blwL8`%L zPrH!yX{_i~xTRC`c5CV5@hWN@A^+OeVC^!&aH%qlR2MjW4(--CfY?4poR>IS#rro4 zt)6Uuhk_ceNoe=EBi_E%OEOP5l*+9QQtCBJkw12E?HX5yng^*vWg8Hhq91K z#WPVlYWdf_mWM60)$^`FqZ|{-K<4!Vnmv-2aT`swh9e)|W$;%z)h78#iIhgVtSc;r zHaUMW7TqGCOG^{8_8izgs?onAvhh@fAmc zQd*Y#>TiG0Q;c3;3b%6MoCIc0EG=p?Fvgbd4UEU;#i_B%oG>KIRtie6Us z%QyIk{XO_hC)vGmQ+J_Ps6E>#Z1es{fk7qbk+f0rY#D^+=kVIXxbmF8-rq!EHC%N3 zQ2}wb>LL>BE5t-S8#YpH;%*o+U3JSO+;_CfvvxoL*P8D~P2V+G7`K%mYoZ@5(_)z? z<>p`B51qFjO8+D)?fQLr%K8+5u=!jFY=-zult!Z^f86nH*?ck0j7ys|gxy^sPoyfq zsZaCcM+S5k8-)`|j{524Pln%UM!O3`Zq0qJol?&01=38=Hn4&>ZM4JhV`cti2GjEz)F`k-48deD~2YAeH zH$IxLy5$ETmWR@xO(ew>dd!4gF#I64$M8M{TP3*|vk7C1D6*dU?o=^q(Wz$BtCht- zUrl}*`^_&VN5r=Moi?vq*j4#WpSwFf z*(|g!QQjanv&JY$w5>zCo=9ooO+T9$^o>|+JGG40p6}co`X)Kp5)o#{ zD$NMLLrEFx8`3~a-(VP}853lv5zM*B>Pu$*eSuNTS&(H+z;GiaO#N2@HPOWX{SUGl zk)Eqd1bIb8o!xLa0seiCn3MOgB8jD^XvL#}F7`*w4SIVMAZ@R1Up(!9Q^2|C0;llX z&gKYeI(y-O4WEo5oiC-u0q*frjRz9&?3bvKKOnz|4atj}^5 z=qG2K}WZ`y@X`!|{ zy7M)6aLo}9MmZ@+FP!!~2DflNE-4QiJ9Y`rDxwbJLcIbh6vG>Q43IiDHLnsN3Gk?U zG>wjSzj>X!of(YA87v8F_rbAv> z1?HuFn5i21qKe*BvQQEZPr;K{&XTdN{+pAgTssrz4A4$#Q)!$^N(1|Yd^nwi;eFbv zt#x72tY(QwhVl6-fXF)GhB}a93UWZ~?x;S&(oz`sK;Ldjy26c~n&}Eqk`cdENn(SUI>)r4nmT!N+1n%Yr9Z!@Q z+--ZBUooCCON}L-AJK;GoNmz#`L-mmx>@P_#J$Z@(Xw%Md}urI+~i0_Y58>L6Xd%l z)o8bS)7zq+vQAUjJ!qR$N1Q8{*eIRFfdgrgr;zD4s~^Y73@Sl5TzhFaYl%x2Vje9`SuAykqB-@l zqKMx92?ITP+CC%=jUI!@e02z<;%Bat<#mI(D3l!hJkrR7MQco+J*nZ)T=HAt{haA! ztxLFI>g#y>1@m$I^^%dj#Xz~l{Op>?cBcms*P)i3*0Ijs6*ED^x)VB5E}{?|$#D>V z&&B0ThfaQ*bwCJ)A7d2SMTwpJU{Z;jbSKB(_RdW2&^i6oAqsbg1BYno*asJUcqUk^#S88{<4(h#tg^poAT1Se<&H!}w$ zErI*bs_yC)H})QIMaX>C|C*Fx5YDUT@I!;`pjRD*J*O}T z2ys&C)Zd_N?WnJdk-ZCRJnuWo<|`J>E6isEc^vf+UL09I*kMBom}3jZl~H>OpEqOu zAR@Qn=73U&udva)#|rzI<@ceEL4V!e38*h`;&hb(V2!NJa2<<>8K=6k)EwjjkThVm zg=H}Dv-NF6KV|oq`jK}!Kr(ia0>52w-$-1;%qgpUDq}>nuw2jA@}7RLdnEBuJHAmp#cc zi-h{m5nZ6%OIjx?e2uUdf>WG;sf$=)0}#=P_#0Nr*>&^Qm#g=zDUc=GuXIA8Z-VZg0=4_x& zN5_oaZGUIq+3!$Ofo_hP`7wX`vPN0(V6FPin)RZ!VMom~f$z+=qw*n9S+94tQ}l3f zEb3VV<6XgyNcQ25b9f+@O)UoprUgdY@d6`XDsGs9(cJZCmdc5}fr^;sa?2h&m7+&Q zF?c~?c<*M^SwpMc|G@$ZSRAYJZ2qh6r%Qh1$nbt-{QHczbqtee(y_}DDkir18qtLj z*wg4t=|M+;l@=dcWIS)!gv%RM@ab$o%aO?7q72hUnA3ifekZ zb`QUpwZIJ5S>u4@=Gf79%PQf$ya!FCc6OmZBa#%l_m z8;!h{Zi1L?G~S9O1-`#%uSzdT%a%3VnJ_)lZ)FIZ8G7KDyj?SIPI0MWo5h40|I*|Q zC9-oJj5mMZd8iyZ-ucna+`ZZR+inr5*1g;Y%d)t9(=DIyZ-s|w*8$Ud)Q6=tBmdqx1i;%-{ajH3OvMq72^&HHb|=uQ`nbuqYa2R&1J3~*z0>-n5YJ$n7%i{cvwqQ2WTn1}z`RxAV6*AQA< zW*Sqzp-{vkWZJ_K&#_;+uq_GU*rblPb%2m%^^foY;yJu7<}*Th`_{T z)Iv-L@!(|KYZ4d8=W}G;Z}Mev^xi#MEkWN<|3PAAj6-_Hhck9@w>2)oR$B8Ms$s;* zP+l%4#&pzwwjJ&={lFEHFbJO=HPq=#xt`JjofpJXWs?9AUu6a}K0|SytSX_@f-P)D zkc9dnEE2?BSf!lJs1ECkM7r=?Ow(gGXs76OYwtBLY0Dcu$_wi2u%XZMqiuoF?7`T= zYVW)!+lw_N{W68dQoc@Q5yBZHyD7l!H1!EBJ&reyc_0^E^=`N(fWHL39_~p1+21kw zEU2euD~OK6m36r(=EKdKh`L~2p-4kHR#LjMg(h8A{29q#dgm12hlW3SA&j0G`_xIY ziiIvq`mrq&4b{-W-OABBy))}~%jHc?qmeWRpS?#y$wD`awXg@s+^?582D^PZfPlvH zP2`_s^Tt#{=SoVKT%#4MeZV9mi9FZcn z2YNqIy}i6J+gI2gEwyC4T6jGJ zj9Sm-e=V5z9C=L%qizG1AiAh(_XG+5?sA4^+1{8iulYtFU+jVx)M?BDl%Hfu9zI63 z_NW4DZK5J_Y@?91+;!|Mdt*z|DX2@dwgFvnpFpm^%YKDUjhbI7>Fu`y-l(!Te5YFr zQ+rBTYwbACI&T$(?(7P1sEKWpcUVfryE-z9Bt)MrS#;TXD|jP!w=yX`G_|4$xGj<9 zx7p{8Ep_a-Jo|lRvV30G*8Qv|1a`~I5<5_Vh3YrE699RWjyUn6QaygYUo|gjLWyBm zJe>IP?InF=_nbh2azV}I^=XX`6Z|3&PS z?|eDv5uW+ZrO+!m-Of`+#t*-yHIr6WeC=Y6t~k-aT8gjhWc~ejyR;FT zX(+n~t?D)Qw;9U%Jj$`qIHdp1&9q8!jWufH$rq=*-3ieYTo?xl4uPIGwL@!*d1sD0 zXMVVscE{3;?_$aqL#qcUTKdPUP7=`S8tA)~yUoh@uP2jlFu)HXHfCla$ro;m_kXeA z8xEa!>FFI+#aqXtG0Y&yn&&>Ad6=Y7g({W;qwHfwPP#+l(YSqv!Q_j8pf4x~oZj=G z7ii%AiM9Z`yu(FlW&opp9|w)TX&)(Owfrx5=oGv1*%AL#WxyGu1NTcrxW4@aOVZfm zKLo?NpvQ;7F~m9o89MP$6y@#cc)AE+xX7RY6aeA9$!Y_J`@(RlvJZJ^LDR|3J`3UN`oL4Pt+>8CPlOAWn!-h8pVy&a@Jz|>3!*LJJrFXT2Ey*( z&6_<{eDAhAT8joKZw9bLoAR-@k*Irif6%H?)efay(|hd*t5R87u7fYMwxPo8q=~wt z9>Mp5eYzXQ(K704W`33oY3QgOfB80MdiM@vXa^SdPus@65}w|@UV4lbD4X9RFl z=6xpeL*^d#7M74xUmHHzNtIXrYCTs*Ah7x*M6PFOv3(V(0`BTN6EuD=Q&u);n&61m z%vO^ZEao5rC#yuMboe|QV9eD>682Iq;`f&Ik5o5Tq;7^2l|eqPb_6qFZTaEq`8`q&jZ(CF+wMgL6@^v)PsZfx&M1T2me+QNMS85VpcE8OjmIGHnmhnf^CD zz??ZNGW2tbOj4awDQUY(Y&V{s#YSUu-z5_$k$;FOc-v>gpmRClIb+gdR}Y1p;LLN= z+$~1S9*a(C;GP8F%)YHZ8SoUyUkr@V<8@#p3u@*g*7x8?krM&qbpf?W5e8;f?%3b8 z%5Ih2cGfo6=!Nr9WLdIUD4xl%N!;ym6LbnU7V!f?lF2-@u(4No{Vc$Ym? zwg88B1PsdfFVy{9Jac_^WkL|Z9NuWNG}!w%Szs>=S(76~#8?~P`D>&~{6oINcEJnF zjUg?K20lXMbi622EeF&18-DX8J7}Es@mQQvdZ7I8V$J^fD-`nceMU_x>MtAL7so6{ zK$L82%rYJZI8Ty#Nd5&@~6R-4M+l`MeO)YMB$b=+kpcd;acM6-kaE8%5wV zUY3{a?l@P%iY}M|mtSL1UZ*={`H(MigvjkC6J&ny;$?+nIZ<1l(iA}=m|-7;trAhl zj_l<+&d({mi6w&w zpS-t|N*Wt4oIek2X1#WoWh>lVE-VMQ>G3xgei3_haYdzTB39<>E))2&UcDM`LOlfbtzAe7$ZX6bmxsP6C*W)ym}}!E9vN422#vmavjtsyVG$eK z{jUJ0jipjH#@HH!*oVYj1xtCjeVh^qxR6Wk%2xT07pZcUa*)&Id8;H?6X)$$vRHm~ z_sOmd3G@KksUCQ~%+1(eOl>+%6SSEJ?sj}aq%N8b`W#OjN9Sd{&B(77Zk4+0;(`Rv zO{L&B7E$?43V^(3cHfZq5fB^Bk54`lrLLT?36L5=WM3HOlo{9NNG4mssM`OteAO~#Uy>#;CN*3a7 z5bs#XcdNm*J=RznMIqF2kQ)ae-oSYXNwty+)BN2TP)|JcugxJ4Z6a*SeVM?>v4!t_ z9SR8TF?`RNA`OYKaF%Xq>am*(pCWqClK|<~eD+lDG401=f8czzxW+t{>n?MN_8fyb z;YQL6n2<+;ZkFzArNj-3{}FtZ^HRb1Gk}E!8L;~JR+5sSlBvw8+4qRNXzr1&r2u+8 z|3MRSTJN0q^li8TXK=zTG6XhOY@Eki`fQ?qd7-Ko04pILN;SN;lVRTl68Jta-@640 zXneP&G&K%0BfCeh1gyNhj7^A1PRWvU;S0Ztz~_hmFW%df2UgF(4~u6<2Mn%kQ(@ z4s6x$(|yGjJynSoZ)J5}$9;zdNc}VxKkx{;#4TJlHe!P-f=wCa2qvzOd&GCPykBU`^?d4~gyRW|EFEl&Lop!`~ zkr%DdIkvmnx^63K+b#lUNG1|v!dXS^W60DZX(4hunz89_N<at zvmYya++Svuo-6vgeyL*l8qN1K!Cr{IjObTS>U4XPnN!2~o-t@(7iFA=%NZko9Vv!^ zmbxS+l9UY#Uidxo7ZJt&YfCtib7GXvl(to6tj#dNjsg%+AUOV{g+G zcl}R`FfmY{bn*pu8{~G;bz9i9;fV$?VUN7NyBBu>a>*A8Ln=8eF0;1r@hJ`)ti_xt*p%Y zQ4X=9-Q60d#*A~zUj2Og!*|zxP4o+{<7=*;KwZD?7x?R68R_-#KaidNca^M=kBnRDyk%sYsHM0r|S*4AIiiz(2w^S{pK-q%H#ri zwz1lSLn)<@P1EWfN%M+43g-Uzkrf^7ge(rWH}271PcLsIM|=?Tt%w0OyeA zdsJyJ-1e-H(_lsZpUE8Z`AwPl+%aav#s;5wTQpwz46;tn%6l_j?%U~Z6E)U|?C}JY z=QY~ny&T7?%0F+^^@pSKV&+Y&b07CFr1eVTpR_bz27zMf^{tPW1a#V$a$J&_iEozp zvut|5x|9C#@|c~nT6>lJX2+TA956Dee6q>a&lr$F0r^3QP^BmZ@BRLmu>gsK;ADAI zpL!cx+joBQi5(M{eQ00G+U=d@scM&fbatK0djb^oud7ATL$R6sdNEGcdw(Q z9IJmY8BI#)9Uw5$wuLrfQ^`gcysXjALr@^=6|!<@{e9i3>jm$IHI#zIi5kL?O;1p~ z=`5aU30U8t1m)E)ACEaY8CYHJM8FyB^;7H(Yd`XFN!g%{^eErdIx$-D{faX8ecA(y zmGW%DtA`gnZ)%sSv=@?WuA%Oncm8gST-r7 zuiJt4L!PIuc0k*snjtx7$wi@l-BwMRihOD*5 zHImD5i|L~Dfel~;O z9?N)TYm7gsFGQ(E*SlgTxGz%v?a%w;GCa05p=-)Dc0z51Wr(uf&UHF*T*iV>%NZi< zlJ@BP%A2&f*DLSf$xS`xD_m_R@i5#W8IIdT;eaf_w<Eq(oe5?hQZ2a812JO^r7G zTZ-q(je(R3tgC9KQesD9!YS!1&NpMNTcgn&-LTP%T|Re@yJOt1Vs^w8y7Rj!P8lF( z`KiEsmxk`*@&%D_gWgR0_T+29Wt}{&`8WDv-NR`*cduf75|^zPk{tG>f_=O0+#dV= z{!XaE@{*T-@E@b^f(e`OA!;%_xOYqcSa+|5#;=0j{M*`1`X?$HLROQ&_DRuvR;PQT zzFQ635IxLINh|`8MN{U@-T@IhWgRINuhnvO13TYEj3m=1dZ@t*uE2BqYscNAoZD2C z4yewEk}>K~^-{YM7{(V1&-ZPPooWL5J+^$eEH&GW5D88fG5d;^Z&zc@`U7VwZM&p` zDipjbXPTG%WKSmn!oujz$QE68vHRJ`zk9(eDSSfj9)jIIUnFX2dN`7)YcX)P>Bbc? z736Ik3+}Pm9Q0vc$Cw{AQ-8uqF?M;U4Imd5HYn~K=n7X7&+G6q)v;ZWczyjw(0l8a zn7Lt;?4W9KYI6W)-pJDG;`;eq@D!^KW(M1!@;+SeOR@A=a37osMRVSTOF@G(Xw)-ueE) z=IxY39+W<<9iBt^i?NhuJovBPvF2ttc8}F;666;`_z*7tF+LFU?)p9 zMA$=9d0zewDJq3)y3$sL-f8+8zc#`|XY5n*!@m+!#uA~gC#4x_= zf}&%l2G1QG>ye@3wI5FT*{;`b4x2W?)@C}Gnw8%2bC)ynv%tH8zzMXWnqDd zgpRBw**ioLL32yF>S9tj9 z?%st7zgU(hhJ1rn00@AbnUke`ua`vm+Q)28R*z&=B*>ztHvZVJ!`$)Ti^Zh8um1e; z$y~ZgC4g!3OiK*59oP*#SvBi-7ds$51&Adk>!(+alirG#V60OFRYmmTLet5p8g$m5L_$8vNcWsJ_=??|nj>^rKhPRrhhMt(o&4t$|m-+TQJNNP(43O~6by zv;{|12wPfHW2x?o=!KX?2=vsZM^h4G>51Yqv-*Q}NB1+6|A+mv|J}7)=X%V6!3{@z zzmA-1#xy9VY=Rztd#~G}K=+Ma)Ur)%sG%mrXN5nWEEWALCi%_W+$;b~IV(jH%~iFD zjaT50L{K0a;l?lWcHuy$r?3e~*U;(CChjo7)oQ_RE(KtY6X(r>_^!Ie}WzN2(w zu}GQGZV0=Lr=Bt+44?RJYhR(@HV*;xHO zX!qdDC*|C_>q0lrwcH*ncQijNsveJXgG}y5$0Pq01C*G|vvw~=H_i|8XkRW?&wo`m zr$hzr_8;0V917n-5omd0mSgIB>s+ONIe`s~UhCAZO}2)pisFBVufo0sVZ8&k<)phE z2=-BeWx4p_d-b6M3>}y7kOhbC;i7G1vJ!;+H1)M$Av2K3cy%f+`RZoOnqZ>7+rss_ zfR1qujTFs;QiK*OdUoD5k2kckM7}Qf6E}gDfEcHR>2imAH8%)<=!Dv#{Kpxlg|G4xG`Dc?m1UWL+`ujGjc+jl~J-G>&>fLO7=QYTm#UCNmWb9;BLDF=4+2+6p zJDupT1hrM&u&;g3-F9j*^}Q(mPv^ZmQWQqdi}2UZd+#(=FRY*^G((yd5g3n+H_@qn zv96en0E36vK8=7>&rv^8_4bsk2x#f6)UONKm~?zK)9kIaDZrk7r7&oBX@1tARR{Eht29)|kFrXD+oh@Iq`S#mlU?oUOId5=zhe5PXM1M&=nb z-VZbuXJU`uRn;*5L8Pe`N6cXL zz-;f7Ka(*RpiE8=o&|bYvaMsI^J8qtCZ~*B@M~9FB2H7ImNHaKP6aCJL5%8pAGnk6 zf$ttqUD7U1Yb=XswLK;49S)*zsOxLKL}goL0J~8|57m|a2)j>J6?Z`*6~vJSCVItE zkp!UXhN1CVEdt zt$&GL&gg5wS-G`k>Z<&bb1L;|Ufo_H4P|dsyCPc4jrTsgv!QFR9wibiNxO5u>Y4zf zJFUENg5bKs@$&L0@qY@KRJ3#dlF((pIQagLm~ZIUc$=MNvCsG~EFfd3x@)e96!WB& zdR_%K+Q{h+2vJa?@ZRjQ-lh?@nEJeb#Y8S$d7Z`l%decL2vbZTg74t{_Or_Cg zv&Q`H*As+QA$4M6xs;VAWR1oGM`SJKxMmx>(ddmaZN^e2X@P%B!=lmu>t{Ybc^jp4 z+7G%nX3sA9`JblPpq7wzRax8(-|>$PuG-R;MA{zPJzSN_YK=wcLHhcNI=aw#AAe09 z#vYUB*Q)ErlOR9l>v&Ip+26v~-+9icmMF;_ah`M#3Ypf@E&4n4gW%#~Enq2;c!;eL zwO(Q3?v}Ru=^A8}0J<57$k4FsKyp)YcBdhY4Gfc0bUx>ODWYOJ8l4I9x&D#EsWo)n z^n?-wPg2j!$g6Y?hO>*vngE#Sy zH&(MG%?ip=bT?4R3MQ#}M1l{pKU3JfdSiF0R)WuL;HAiqixRsg#TXvd%(iazZO-eK zlU8U1ZjH)CMQLr-WL@WpHp!~`XePP-_)2U|JCo5U3(h%2q&SH!LC;Bq*3b zf+4mPQ7NLJgc25&MF@m|1R{hafRb1cco34XCK~oF2p9;EkoQ5`dF^zje{|aSW;*h6}x%d9=z31F>&IiSRK3SnF_KY0m4Ufzr*mPLDJA58&Gx%^P1cV(o+`)zGdi)AX zsDuDe!sr8VYNlIQzgwjBc#dZ-gMMMursxS8uSE_PNo+(K#^H-z3vq!VMjavLez^g9 zG(Z&dKCx9R!D?EV{4#U>?lVaoFoRrJ9Mzr~=8%EsUi>1Z7?p4UK=sbeF~=Wa;PJ!e zS?>k1Mel{!Q~}h0F_B`UlXva8@QsM*zo24|z2?$e0WiwedTL*f4AZy61a;j6q&Xvk6vy!!f(6SNa3ofou zl6=*26aQ#V0|F}xow}LL_^K6-_GY1z>@|;tbNzlb4QKSS#X?YdWm=g( zBD~yx>=9(+`~q_g{Fim|+sm-cdj}SIfKLFsep*fR!?S*vh+rT&}wjBZkQ- z%%$?-X6yoXaB{wo3QZhgcdjGOS@=%PJY32Stdo4!`!MEa9_D zinq8se?_&HErQ&m{YE=*yVdk{Ax@VU2v0Ww#wGgLX7`@2Yp&ISUH!+07p)4#_~F;; zpVL2{8Zceb<{$$gu*`}p-f~47d!P0^p4xerpi1*e<~Od2%IfM3t{P$D(or$qh{!-; z2zO&8qL{Q)QcM@ z?G&@Qh7fQi(yw@UXg554gRr4VkY=6}EOX7hIAj=lU)G=|_cA@(nd}b7<#_(9N_PJ( z1SH36i7EGzw?jD|Z4YokhbMcEPc=odwx+f~4vL(ECV2yQq&zhy+jLOG7?l+MSC`k* z{RN=PYP&NDy-z#79%<{6SP(8&t0dk=ehJ%&ffNZAlvLbJZ9fZSV2pf9AP(w)`8_w|eot8$RDNV%2vgvO+egP2(s}-di3Y-Td#)hquXl z^fL_uJY$&CvLpfnIWMW%%+PKVF_+^{N3ek3bmpO+iVOFglAv-LUzz2`Oc0GDa3mQ2 zGtb3#GfO5!zvr%9D08ghRid?{x^dO~o06)sgS!n1w;`<)yW7T|G*^DQt2Bg&mxIIA@MaI0u`|Z)Rtqg#ETDM;uSUv%9r%sZ+p7giLc%0{Dqc03np+ ztDRV4ZuFv!PwMv~#%@5uiUhMxq&e^CqJ=50Kq5V^gq@R+voV8yIR)&nEIeg&Nj?6& zY(m40MC$5dQb&AhEw>AMerF`oJ`UxC0h0FIMS`W zIQzW!F-2Ln)L=oXp7}x#A@A)iHX$aBrQ*_~DCgiLQ|(st0G%Pgh-`ia+B=L;%W zB!N+Cfr;w2Cyj=AZH<)eSZe`!kMpEuGHjy#-#^B-9KJp) z@^Rk@Bz4d?8GfSh$a6pEOS`X#+L-=ie{p2lc|gCE1_(+DVjk)u7^8y)u#OV@*954`sma)!4s@H*zP$6o(e15(+M`x9GEU#J_iI3ZSF%e%plX=xqH-&FzDN(M zO4Lm}hqHFJI+K~4lYYrLk(~R$#5s`$;N(sWU{ZXCAe2SA*!!#ps7wDXdjT~1H>5iK zah4QSvs5@cW&SwO@dY9*)C(c97|H)U;toTSrs#MHAMxISeTPAgo_?} z;Ze9>;MUmBa4Uk>=OJmlh1-%oZ)_1zAGlepHDnF4*9W7)I;K_V zL-~-7@ldzjXch9zpt)@0oZfA1%u>*&fLMK78c8NzAV>@MJ;jkn`^F{w_|xUq4zH3( zeVR~{zzOj5fglxgR0?|I4Zo}J8Q&4JwBs@_O|`@KB%r_M%BNnkEAK?e8-TNIL&r^NJlh}@uY&MfXpX4<7E5cW*%N2tuf2>(~+T0PCvuhIC@kby2JUg z`OYrAwDN0x-`5wML$WJDJs^JdrOdQ%8z`h``~%=G=eOu4D9nA7A~@6pr7sp(x&pl4 zhxTIo9q!ay(Ns81QI5RAHlFWWep4(Y5LY~cHQv3&t(huH+TzY`N<7@0>LGoox?`rl ztoN`@#VtPig2c{FsQST3OGJAMm3n-AXFvwl>8j8M3RK|R!mOfg@Oy2Q@(P^2x+Fg2 zCTLmGpr7g(b>SS0C&=JX>{@Orl0!7HsQS17>z1*I09FcVkF@;~1^Rhu)Uq+HXYk_7 z?F~h~+>W^EXU9~pFSWa*hydfPF;)-#2KR$%tw=QS*lHf?Zo0o~Kfn%s=q%n;e7YWn zUPQzm$ToTJX4&Jds$KpWg{73uD>{TQ$wH#}k8G@KVq#c1zgcFrvz~)ftFdtSxlFDN zqRAlP-p87Au>*|n)TX1eY)BFp3Wq)kwZ+j|~Ts!l>2>8&dGv_cAg^xBJvadYx=bH=KXX zHU1;UmzcmBw(ZEeggzE;XDJuuhg^{6g$&Uc=;d}!TmwDi##E)uAQ_m*T}LTEb1=^e zkiw03D=ug{cQs1xy4UOPR<2Y2l(Y74%cx7v@nKVKo7@`dWW(_RhDEep!l)X85$sZT z0B>ND89jrY!Vb_N+WB=0PIsSIBdk|$0u=B)oEwP#{uc>C=bg~G4hJKrSLTzHSd*Za zPY$MXJ~933@?95=jAcC7sWFileMQgI)PO&oD}33U9QPuu+K;=}NSYtkPXM)#4;Q+v zGL*#k?;JLEmAz}}rF(LGsO)N7c z@|J^r(%>+8q_c_`4h*wGE!SfMaK;D1UofzUI3t1KL)hd^6TG0;tZrk|vBr?!n8BHYQXU*UL zI8^YDx1T?B+OIwOw^h?>;KBbZXL4;^*T(g)OD$cSO>47hZ8oj#>VGB&X03A8Drc>7 z)+*;O2v1)-hWt|(QyCUHv1&x{y~hwAMeYOwq!bj2H?Jo3b3a&x-);$W06Xx(XDja! z2wA_1>kR?I4S?|JwJYG;*I^Z|mmXL(GPv(pZSJ>CtUdO-UR~>wwJ!N57tV@@MJ{(u j*!BYWuxVxO*r0%!F<3TISFQ%WQLwdgJY90i_uKyf(vZne literal 0 HcmV?d00001 diff --git a/daten/Planer/.planung/projekte.md b/daten/Planer/.planung/projekte.md new file mode 100644 index 0000000..8faed7a --- /dev/null +++ b/daten/Planer/.planung/projekte.md @@ -0,0 +1,53 @@ + +Projekte +---------------------------------------- + +kern +---------------------------------------- + +Gruppiert Features für ein Projekt +---------------------------------------- + +- Ordner unter daten ist das Projekt +- Alphabetisch sortiert +- Aktives Projekt ist hervorgehoben +- Auswahl überlebt das Neuladen +- Entfernen nimmt die Features mit +- Verlassen speichert +- Escape bricht ab +---------------------------------------- + +Projekt anlegen + +- +-Icon +- Projekt wird direkt aufgerufen + +- RMB auf Sidebar +- Klick auf "Projekt erstellen" +- Namen im Modal eingeben +- Bestätigen mit LMB +- Projekt angelegt + +Projekt aufrufen + +- LMB auf Projektname +- Features angezeigt + +Projekt umbenennen + +- Stift-Icon + +- RMB auf Projektname +- Klick auf "Projekt anpassen" +- Namen ändern +- Außerhalb klicken +- Name angepasst + +Projekt entfernen + +- x-Icon + +- RMB auf Projektname +- Klick auf "Projekt entfernen" +- Bestätigen im Modal +- Projekt entfernt diff --git a/daten/Planer/.planung/vision-festhalten.md b/daten/Planer/.planung/vision-festhalten.md new file mode 100644 index 0000000..0086aa2 --- /dev/null +++ b/daten/Planer/.planung/vision-festhalten.md @@ -0,0 +1,53 @@ + +Vision festhalten +---------------------------------------- + +optional +---------------------------------------- + +Hält fest, wie es gedacht ist +---------------------------------------- + +- Höchstens eine je Projekt +- Goldener Rand +- Steht als erste Karte +- Nur Titel und ein Textfeld +- Text wird als Markdown gezeigt +- Keine Prüfung ändert sie +---------------------------------------- + +Anzeigemodus umschalten + +Kompaktmodus zum Lesen, Vollmodus zum Anpassen + +- Standard ist Kompaktmodus +- Kompakt zeigt nur die obersten Punkte +- Augen-Icon rechts oben +- Vollmodus geht über alle Spalten + +- MMB auf die Vision +- Modus umgeschaltet + +Vision anlegen + +- RMB auf Hauptbereich +- Klick auf "Vision erstellen" +- Vision angelegt + +Vision anpassen + +- Anpassen nur im Vollmodus +- Verlassen speichert +- Escape verwirft + +- Vollmodus öffnen +- LMB auf den Text +- Text ändern +- Vision angepasst + +Vision entfernen + +- RMB auf die Vision +- Klick auf "Vision entfernen" +- Bestätigen im Modal +- Vision entfernt diff --git a/daten/Planer/.planung/vision.md b/daten/Planer/.planung/vision.md new file mode 100644 index 0000000..3f87d66 --- /dev/null +++ b/daten/Planer/.planung/vision.md @@ -0,0 +1,19 @@ + +Vision +---------------------------------------- + +vision +---------------------------------------- + +- (Basis) Projekte und ihre Features manuell verwalten +- Mit Hilfe von KI-Chat Live Projekte entwickeln und Features erweitern + - Ich schreibe mit der KI und definiere meine Idee + - Die KI zeigt mir Live wie sich die Features ändern + - Ich verbessere und die KI passt Live an + - Wenn ich zufrieden bin, dann lasse ich die Features von der KI implementieren +- (später) Zu einem ausgewählten Projekt analysiert die KI alle kompakten Informationen dazu + - Ich wähle ein Verzeichnis das als Quelle dient + - Die Quelle wird durch ein System geschickt, dass kompakte Informationen extrahiert + - Die kompakten Informationen enthalten das Wissen zu dem WIE vom Projekt + - Also ich brauche die Funktionen und Regeln zum Projekt, nicht wie es Implementiert wird + - Es werden Features zum Projekt generiert, die es komplett abbilden diff --git a/daten/Planer/.pruefung.json b/daten/Planer/.pruefung.json index 467e210..59af213 100644 --- a/daten/Planer/.pruefung.json +++ b/daten/Planer/.pruefung.json @@ -1,172 +1,319 @@ { "abdeckung": { "bedienen:ablehnen": { - "abdruck": "61a0e2e5f8a4c439", - "funktion": "Vorschlag annehmen" + "abdruck": "e9cce25d92b81ff6", + "funktion": "Vorschlag annehmen", + "trug": "089e774256dcce89" }, "bedienen:alleAblehnen": { - "abdruck": "9d613f6b111b9b67", - "funktion": "Alle Vorschläge verwerfen" + "abdruck": "ac9262c7cafe9537", + "funktion": "Alle Vorschläge verwerfen", + "trug": "6869d68fdbd6d0a7" }, "bedienen:alleAnnehmen": { - "abdruck": "9456d726b83144c9", - "funktion": "Alle Vorschläge annehmen" + "abdruck": "94f23cae75fdc531", + "funktion": "Alle Vorschläge annehmen", + "trug": "94ebeec7b03abb70" }, "bedienen:annehmen": { - "abdruck": "97dc5220725e77ee", - "funktion": "Vorschlag annehmen" + "abdruck": "2742ad031b3d3cca", + "funktion": "Vorschlag annehmen", + "trug": "089e774256dcce89" }, "bedienen:auswaehlen": { - "abdruck": "31f34c41cbd1bd93", - "funktion": "Projekt aufrufen" + "abdruck": "d061bf62466085ce", + "funktion": "Projekt aufrufen", + "trug": "e24c2ab0a27ace24" }, "bedienen:bereichsMenue": { - "abdruck": "421627feeb92867c", - "funktion": "Projekt aufrufen" + "abdruck": "4277536d43c7bcd5", + "funktion": "Projekt aufrufen", + "trug": "e24c2ab0a27ace24" }, "bedienen:bestaetigen": { - "abdruck": "b1ce0152c68722c9", - "funktion": "Feature anlegen" + "abdruck": "db1f954b9ad01749", + "funktion": "Eingabe mit Enter bestätigen", + "trug": "43fca3b0e83b3701" + }, + "bedienen:erledige": { + "abdruck": "1b80ae13958bb11a", + "funktion": "Vorgeschlagene Karte anlegen", + "trug": "de2b733c447db595" }, "bedienen:funktionsMenue": { - "abdruck": "67bf62e64b2af11f", - "funktion": "Funktion entfernen" + "abdruck": "bacdd0a7cc9d0f92", + "funktion": "Funktion verschieben", + "trug": "6a33d1b7b5a7f28c" + }, + "bedienen:karteAnnehmen": { + "abdruck": "bf348251763e402a", + "funktion": "Vorgeschlagene Karte anlegen", + "trug": "de2b733c447db595" }, "bedienen:kartenMenue": { - "abdruck": "bc47fd3a97b2027c", - "funktion": "Feature entfernen" + "abdruck": "d3ba136a562eb1e9", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" + }, + "bedienen:leeren": { + "abdruck": "f2af432a5ae3b255", + "funktion": "Gespräch verwerfen", + "trug": "1f848fba8b2a5e56" }, "bedienen:leistenMenue": { - "abdruck": "90a66ccbe71ddc74", - "funktion": "Projekt anlegen" + "abdruck": "ed951fbeaaa9bc70", + "funktion": "Projekt anlegen", + "trug": "44b8a59e1dcb20d4" + }, + "bedienen:oeffneChat": { + "abdruck": "9bf171761edca141", + "funktion": "Gespräch öffnen", + "trug": "c71610a339bb298e" }, "bedienen:projektMenue": { - "abdruck": "58ca0dac4286c61d", - "funktion": "Projekt umbenennen" + "abdruck": "ea73f8c2597c0443", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" }, "bedienen:schliesse": { - "abdruck": "f78739ce74d876f5", - "funktion": "" + "abdruck": "919b104c012c034d", + "funktion": "", + "trug": "" + }, + "bedienen:schliessen": { + "abdruck": "1e12f9ae001e93e1", + "funktion": "Gespräch verwerfen", + "trug": "1f848fba8b2a5e56" + }, + "bedienen:senden": { + "abdruck": "8df3402ed3373acc", + "funktion": "Nachricht senden", + "trug": "e61022551a98250f" }, "bedienen:springe": { - "abdruck": "67b827c9bba0c05a", - "funktion": "Problemstelle anspringen" + "abdruck": "0b134efa50c03bff", + "funktion": "Problemstelle anspringen", + "trug": "7486526f6867c436" }, "bedienen:starte": { - "abdruck": "06e7ff1e70efc603", - "funktion": "Titel anpassen" + "abdruck": "761c2f62c917a3db", + "funktion": "Titel anpassen", + "trug": "d0b7a430e96e2599" }, "bedienen:startePruefung": { - "abdruck": "1f9ac6d1bb70cda8", - "funktion": "Stil prüfen" + "abdruck": "31c3fef23c6319d8", + "funktion": "Gespräch öffnen", + "trug": "c71610a339bb298e" }, "bedienen:umbenennen": { - "abdruck": "af404032e5814872", - "funktion": "Projekt umbenennen" + "abdruck": "6185b6b39708bf02", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" }, "bedienen:wechsleAnsicht": { - "abdruck": "ee50f2dbfa66f779", - "funktion": "Anzeigemodus umschalten" + "abdruck": "e3193fce50eaa58e", + "funktion": "Anzeigemodus umschalten", + "trug": "fccea553715951de" }, "bedienen:wechsleArt": { - "abdruck": "3fcd27f68677ed3a", - "funktion": "Feature einstufen" + "abdruck": "67250a1e8d82e960", + "funktion": "Feature einstufen", + "trug": "90b6c77ff0c412e6" }, "bedienen:wechsleDarkMode": { - "abdruck": "51e5efb1e9196f3b", - "funktion": "Darkmode umschalten" + "abdruck": "b83524eb0e12a7d7", + "funktion": "Darkmode umschalten", + "trug": "4033fc55c753db3e" }, - "lauscher:window.click": { - "abdruck": "5dd03db00120c133", - "funktion": "Kontextmenü schließen" + "bedienen:wechsleStand": { + "abdruck": "8c2e3bf3be58ec00", + "funktion": "Stand umschalten", + "trug": "37a3835d1d2a3e6c" }, - "lauscher:window.keydown": { - "abdruck": "70b3f36549535bfc", - "funktion": "" + "bedienen:zurueck": { + "abdruck": "e378014fbce96d10", + "funktion": "Schritt zurücknehmen", + "trug": "10e46c458040a5e3" + }, + "hoeren:systemDunkel.change": { + "abdruck": "d3ef681b987557dc", + "funktion": "Darkmode umschalten", + "trug": "4033fc55c753db3e" + }, + "hoeren:window.click": { + "abdruck": "620812522ed2d900", + "funktion": "Kontextmenü schließen", + "trug": "87216235bbe42a1a" + }, + "hoeren:window.keydown": { + "abdruck": "c3e1df2d60fcc067", + "funktion": "Schritt zurücknehmen", + "trug": "10e46c458040a5e3" }, "menue:+ Feature erstellen": { - "abdruck": "a9a3fefd653555c7", - "funktion": "Feature anlegen" + "abdruck": "82c40072137d5757", + "funktion": "Feature anlegen", + "trug": "df7a1452a32da410" }, "menue:+ Funktion erstellen": { - "abdruck": "0f968068851c2f7a", - "funktion": "Feature entfernen" + "abdruck": "b44457d64a5ec9d1", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" }, "menue:+ Projekt erstellen": { - "abdruck": "dbbe1573ebe97251", - "funktion": "Projekt entfernen" + "abdruck": "2be770390433a2ce", + "funktion": "Projekt anlegen", + "trug": "44b8a59e1dcb20d4" }, "menue:+ Vision erstellen": { - "abdruck": "1d814205e510b035", - "funktion": "Feature anlegen" + "abdruck": "cb22a654070e58b4", + "funktion": "Feature anlegen", + "trug": "df7a1452a32da410" + }, + "menue:→ Feature verschieben": { + "abdruck": "38e6b244668ee164", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" + }, + "menue:▲ Nach oben": { + "abdruck": "4e6fd1617d817357", + "funktion": "Funktion verschieben", + "trug": "6a33d1b7b5a7f28c" + }, + "menue:▼ Nach unten": { + "abdruck": "183651450e546c4f", + "funktion": "Funktion entfernen", + "trug": "885e16a93460f706" + }, + "menue:◇ Quelle festlegen": { + "abdruck": "e4bb1781bc375d6d", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" }, "menue:✎ Projekt anpassen": { - "abdruck": "cd7390c2f6852257", - "funktion": "Projekt umbenennen" + "abdruck": "ad505addca45b06c", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" }, "menue:✕ Feature entfernen": { - "abdruck": "e773a996f84a8d7b", - "funktion": "Feature entfernen" + "abdruck": "bc968582260c45b9", + "funktion": "Funktion anlegen", + "trug": "78d0329cf6eacca9" }, "menue:✕ Funktion entfernen": { - "abdruck": "99495f37aa040550", - "funktion": "Funktion entfernen" + "abdruck": "d29458b150c55777", + "funktion": "Funktion verschieben", + "trug": "6a33d1b7b5a7f28c" }, "menue:✕ Projekt entfernen": { - "abdruck": "bc7b8c360ac3c403", - "funktion": "Projekt anlegen" + "abdruck": "aca25c0b5feaf752", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" }, "menue:✕ Vision entfernen": { - "abdruck": "ec65c57f36ff14d0", - "funktion": "Anzeigemodus umschalten" + "abdruck": "88520b1f105d3fb5", + "funktion": "Anzeigemodus umschalten", + "trug": "fccea553715951de" }, "route:delete /projekte/{name}": { - "abdruck": "9014a4b884cca27a", - "funktion": "Projekt entfernen" + "abdruck": "b4f871be35d10e5f", + "funktion": "Projekt entfernen", + "trug": "e91a89b8d78dbd2e" }, "route:delete /projekte/{name}/features/{id}": { - "abdruck": "ff8d0773ef483606", - "funktion": "Feature entfernen" + "abdruck": "c1db81de98835c39", + "funktion": "Feature entfernen", + "trug": "f486bf09c64ebb3a" }, "route:delete /projekte/{name}/pruefung": { - "abdruck": "79f2bdc0413ea88a", - "funktion": "Prüfung beenden" + "abdruck": "7a480f33ddf55165", + "funktion": "Prüfung beenden", + "trug": "83435eb3e1394e49" }, "route:get /health": { - "abdruck": "3214361386c64911", - "funktion": "" + "abdruck": "65257319741edf35", + "funktion": "", + "trug": "" }, "route:get /projekte": { - "abdruck": "2f6756caafbe76b8", - "funktion": "" + "abdruck": "276556054437c303", + "funktion": "", + "trug": "" + }, + "route:get /projekte/{name}/chat": { + "abdruck": "fd2a22c36ea85545", + "funktion": "Gespräch öffnen", + "trug": "c71610a339bb298e" }, "route:get /projekte/{name}/features": { - "abdruck": "509119bcecfd63e6", - "funktion": "Projekt aufrufen" + "abdruck": "122f93cbd0d07881", + "funktion": "Projekt aufrufen", + "trug": "e24c2ab0a27ace24" }, "route:get /projekte/{name}/pruefung": { - "abdruck": "f7d46d8a5be26212", - "funktion": "Stil prüfen" + "abdruck": "e651ac90b7b2c520", + "funktion": "", + "trug": "" + }, + "route:get /projekte/{name}/quelle": { + "abdruck": "834d3af3203ca3a8", + "funktion": "Quelle festlegen", + "trug": "b8b70dd0ff9817cb" + }, + "route:get /projekte/{name}/verlauf": { + "abdruck": "5a3dcc678733fad8", + "funktion": "", + "trug": "" }, "route:post /projekte": { - "abdruck": "c3e70befc5eb772b", - "funktion": "Projekt anlegen" + "abdruck": "fa1628d7e469885d", + "funktion": "Projekt anlegen", + "trug": "44b8a59e1dcb20d4" + }, + "route:post /projekte/{name}/chat": { + "abdruck": "c3edc89cec5d2f6f", + "funktion": "Nachricht senden", + "trug": "e61022551a98250f" }, "route:post /projekte/{name}/features": { - "abdruck": "df08920d8f5e5d4d", - "funktion": "Feature anlegen" + "abdruck": "00eb9c16560bac73", + "funktion": "Feature anlegen", + "trug": "df7a1452a32da410" }, "route:post /projekte/{name}/pruefung": { - "abdruck": "9fb8d6c9260477c7", - "funktion": "Stil prüfen" + "abdruck": "6d7444a9dfad7d54", + "funktion": "Stil prüfen", + "trug": "d5019cdafd70efb7" + }, + "route:post /projekte/{name}/pruefung/verworfen": { + "abdruck": "a43f7221e01c386f", + "funktion": "Alle Vorschläge verwerfen", + "trug": "6869d68fdbd6d0a7" + }, + "route:post /projekte/{name}/verlauf/zurueck": { + "abdruck": "308fec6d21b01d60", + "funktion": "Schritt zurücknehmen", + "trug": "10e46c458040a5e3" }, "route:put /projekte/{name}": { - "abdruck": "6030731add729040", - "funktion": "Projekt umbenennen" + "abdruck": "75383ac009961cad", + "funktion": "Projekt umbenennen", + "trug": "40d6954a44fa3240" }, "route:put /projekte/{name}/features/{id}": { - "abdruck": "e95aea276bf795cd", - "funktion": "" + "abdruck": "b24c7000fd2ec94c", + "funktion": "", + "trug": "" + }, + "route:put /projekte/{name}/features/{id}/projekt": { + "abdruck": "fafc7a8a1656f93b", + "funktion": "Feature verschieben", + "trug": "cd2cd705298831e0" + }, + "route:put /projekte/{name}/quelle": { + "abdruck": "d342055e3163548a", + "funktion": "Quelle festlegen", + "trug": "b8b70dd0ff9817cb" } }, "belege": { @@ -175,9 +322,14 @@ "beleg": "function wechsleDarkMode() {\n modus.value = MODI[(MODI.indexOf(modus.value) + 1) % MODI.length]\n localStorage.setItem('darkModus', modus.value)\n wendeAn()\n}", "datei": "frontend/src/App.vue" }, + "[\"design\", \"Eingabe mit Enter bestätigen\"]": { + "abdruck": "3bace3e9c9f16023", + "beleg": "@keydown.enter.exact.prevent=\"senden\"", + "datei": "frontend/src/components/ChatPanel.vue" + }, "[\"design\", \"Kontextmenü schließen\"]": { - "abdruck": "519c5a56bf4b9810", - "beleg": "schliesseMenue()", + "abdruck": "671fa86bccb2c2c6", + "beleg": "export function schliesseMenue() {\n kontextMenue.value = null\n}", "datei": "frontend/src/composables/kontextmenue.js" }, "[\"features\", \"Anzeigemodus umschalten\"]": { @@ -190,14 +342,24 @@ "beleg": "async function erstellen(titel) {", "datei": "frontend/src/components/FeatureListe.vue" }, + "[\"features\", \"Feature durchsuchen\"]": { + "abdruck": "4f249c42d46d25b5", + "beleg": "function passt(f) {\n const wort = suche.value.trim().toLowerCase()\n if (!wort) return true\n const s = f.sektionen\n const text = [s.titel, s.ziel, s.regeln,\n ...s.funktionen.map(x => `${x.text} ${x.ziel} ${x.regeln} ${x.testen}`)]\n return text.join(' ').toLowerCase().includes(wort)\n}", + "datei": "frontend/src/components/FeatureListe.vue" + }, "[\"features\", \"Feature einstufen\"]": { - "abdruck": "de473e39c7232637", + "abdruck": "a0ee6590c24456bb", "beleg": "function wechsleArt() {\n s.value.art = s.value.art === 'kern' ? 'optional' : 'kern'\n speichern()\n}", "datei": "frontend/src/components/FeatureKarte.vue" }, "[\"features\", \"Feature entfernen\"]": { "abdruck": "c6f27381a41a63d7", - "beleg": "def loeschen(projekt: str, id: str):\n _datei(projekt, id).unlink()", + "beleg": "async function entfernen() {\n const id = modal.value.feature.id\n try {\n await featureLoeschen(props.projekt, id)\n features.value = features.value.filter(f => f.id !== id)\n modal.value = null\n emit('geaendert')\n } catch (e) {\n meldung.value = e.message\n }\n}", + "datei": "frontend/src/components/FeatureListe.vue" + }, + "[\"features\", \"Feature verschieben\"]": { + "abdruck": "a82b97e3d4a1b533", + "beleg": "def verschieben(projekt: str, id: str, ziel: str) -> dict:", "datei": "backend/features.py" }, "[\"features\", \"Regeln anpassen\"]": { @@ -222,7 +384,12 @@ }, "[\"funktionen\", \"Funktion entfernen\"]": { "abdruck": "20e8d8e507ee6310", - "beleg": "{ text: '✕ Funktion entfernen', aktion: () => (modal.value = { art: 'entfernen', i }) },", + "beleg": "eintraege.push({ text: '✕ Funktion entfernen', aktion: () => (modal.value = { art: 'entfernen', i }) })", + "datei": "frontend/src/components/FeatureKarte.vue" + }, + "[\"funktionen\", \"Funktion verschieben\"]": { + "abdruck": "8435119f0dd5b891", + "beleg": "async function schiebe(i, richtung) {", "datei": "frontend/src/components/FeatureKarte.vue" }, "[\"funktionen\", \"Regeln anpassen\"]": { @@ -230,6 +397,11 @@ "beleg": "async function starte(feld, i, j) {\n if (!gross.value) return // Bearbeiten nur in der ausführlichen Ansicht\n const original = wert(feld, i, j)\n aktiv.value = { feld, i, j, original }\n entwurf.value = original\n await nextTick()\n const el = Array.isArray(feldRef.value) ? feldRef.value[0] : feldRef.value\n el?.focus()\n if (feld === 'titel') el?.select()\n}", "datei": "frontend/src/components/FeatureKarte.vue" }, + "[\"funktionen\", \"Stand umschalten\"]": { + "abdruck": "b66ea5f488899d8f", + "beleg": "@click.stop=\"wechsleStand(i)\"", + "datei": "frontend/src/components/FeatureKarte.vue" + }, "[\"funktionen\", \"Testschritte anpassen\"]": { "abdruck": "e303ebeaece423de", "beleg": "
", @@ -245,6 +417,31 @@ "beleg": "
", "datei": "frontend/src/components/FeatureKarte.vue" }, + "[\"karten-besprechen\", \"Gespräch schließen\"]": { + "abdruck": "d6de2c46300fef26", + "beleg": "", + "datei": "frontend/src/components/ChatPanel.vue" + }, + "[\"karten-besprechen\", \"Gespräch verwerfen\"]": { + "abdruck": "9e74be976a4d0e15", + "beleg": "@router.delete(\"/projekte/{name}/chat\")\nasync def chat_leeren(name: str):\n try:\n chat.leeren(name)\n except FileNotFoundError as e:\n raise HTTPException(404, str(e))\n return {\"ok\": True}", + "datei": "backend/routes.py" + }, + "[\"karten-besprechen\", \"Gespräch öffnen\"]": { + "abdruck": "c84f9a14428a019e", + "beleg": "✎", + "datei": "frontend/src/App.vue" + }, + "[\"karten-besprechen\", \"Nachricht senden\"]": { + "abdruck": "308218d682fe3dd9", + "beleg": "async def frage(projekt: str, text: str) -> dict:", + "datei": "backend/chat.py" + }, + "[\"karten-besprechen\", \"Vorgeschlagene Karte anlegen\"]": { + "abdruck": "15aa862d2e0f6f6e", + "beleg": "async function karteAnnehmen(p) {", + "datei": "frontend/src/components/FeatureListe.vue" + }, "[\"karten-pruefen\", \"Alle Vorschläge annehmen\"]": { "abdruck": "52fb2acd3d6945fa", "beleg": "async function alleAnnehmen() {\n props.probleme.forEach(p => { if (anwenden(p)) erledige(p) })\n await speichern()\n}", @@ -252,7 +449,7 @@ }, "[\"karten-pruefen\", \"Alle Vorschläge verwerfen\"]": { "abdruck": "f98fd3fc005b9e56", - "beleg": "function alleAblehnen() {\n props.probleme.forEach(erledige)\n}", + "beleg": "✕", "datei": "frontend/src/components/FeatureKarte.vue" }, "[\"karten-pruefen\", \"Code in Features prüfen\"]": { @@ -265,6 +462,11 @@ "beleg": "ANKLAGE_AB = 4", "datei": "backend/inhalt.py" }, + "[\"karten-pruefen\", \"Funktion abnehmen\"]": { + "abdruck": "21095461d6190dec", + "beleg": "if beleg:\n stand[\"belege\"][schluessel] = beleg\n if x.get(\"stand\") == parser.OFFEN:\n # Abnahme: die Karte hat es bestellt, jetzt steht es im Code\n return {\"feature\": feature[\"id\"], \"titel\": x[\"text\"], \"art\": \"gebaut\",\n \"grund\": f'{beleg[\"datei\"]}: {beleg[\"beleg\"].strip()}'}", + "datei": "backend/inhalt.py" + }, "[\"karten-pruefen\", \"Problemstelle anspringen\"]": { "abdruck": "340a32321fd23834", "beleg": "karte.classList.add('gesucht')", @@ -307,9 +509,24 @@ }, "[\"projekte\", \"Projekt umbenennen\"]": { "abdruck": "d4e71f8ef907393c", - "beleg": "function projektMenue(e, name) {\n oeffneMenue(e, [\n { text: '✎ Projekt anpassen', aktion: () => starteUmbenennen(name) },\n { text: '✕ Projekt entfernen', aktion: () => oeffneModal({ art: 'entfernen', name }) },\n ])\n}", + "beleg": "function projektMenue(e, name) {\n oeffneMenue(e, [\n { text: '✎ Projekt anpassen', aktion: () => starteUmbenennen(name) },\n { text: '◇ Quelle festlegen', aktion: () => starteQuelle(name) },\n { text: '✕ Projekt entfernen', aktion: () => oeffneModal({ art: 'entfernen', name }) },\n ])\n}", "datei": "frontend/src/components/SeitenLeiste.vue" }, + "[\"projekte\", \"Quelle festlegen\"]": { + "abdruck": "fc6c20f4e8d74fa6", + "beleg": "if ziel == Path(ziel.anchor) or ziel == Path.home():", + "datei": "backend/quelle.py" + }, + "[\"schritt-zuruecknehmen\", \"Nächsten Rückschritt anzeigen\"]": { + "abdruck": "6768d8a0b83537a2", + "beleg": "letzterSchritt.value = (await fetchVerlauf(aktivesProjekt.value)).letzter", + "datei": "frontend/src/App.vue" + }, + "[\"schritt-zuruecknehmen\", \"Schritt zurücknehmen\"]": { + "abdruck": "c49332e7a679dfda", + "beleg": "def zurueck(projekt: str) -> str:\n \"\"\"Den letzten Schritt zurücknehmen. Gibt zurück, was zurückgenommen wurde.\"\"\"\n schritte = lade(projekt)\n if not schritte:\n raise ValueError(\"Nichts zum Zurücknehmen\")\n schritt = schritte.pop()", + "datei": "backend/verlauf.py" + }, "[\"vision-festhalten\", \"Anzeigemodus umschalten\"]": { "abdruck": "b983b82c02343560", "beleg": "const gross = ref(false)", @@ -332,24 +549,69 @@ } }, "ohne_code": {}, - "ohne_karte": {}, + "ohne_karte": { + "route:delete /projekte/{name}/chat": { + "abdruck": "4ba7a240985a83b4", + "beleg": "backend/routes.py:182", + "feature": "karten-besprechen", + "karten": "41f55589fcff4959", + "stelle": "route:delete /projekte/{name}/chat", + "titel": "Chatverlauf leeren" + } + }, "paare": { "[\"[\\\"features\\\", \\\"Anzeigemodus umschalten\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Anzeigemodus umschalten\\\"]\"]": { "abdruck": "d23706be97d6369a", "gleich": false }, + "[\"[\\\"features\\\", \\\"Feature anlegen\\\"]\", \"[\\\"features\\\", \\\"Feature entfernen\\\"]\"]": { + "abdruck": "586059671bbfa75b", + "gleich": false + }, "[\"[\\\"features\\\", \\\"Feature anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\"]": { "abdruck": "3eb9956887005cc4", "gleich": false }, + "[\"[\\\"features\\\", \\\"Feature anlegen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt anlegen\\\"]\"]": { + "abdruck": "66a7175c58b703c4", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\"]": { + "abdruck": "97a9dde3e968b1eb", + "gleich": false + }, "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion entfernen\\\"]\"]": { "abdruck": "9717a5c6eab69f22", "gleich": false }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\"]": { + "abdruck": "65c43ee10d0d8b4a", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Feature entfernen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision entfernen\\\"]\"]": { + "abdruck": "60434d422bbd2ca3", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"features\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "75e90ff6d5453c2d", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"features\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "a9e849a044a7ee41", + "gleich": false + }, "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\"]": { "abdruck": "827215ea68dcbada", "gleich": false }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "ea7185c230fbdd2f", + "gleich": false + }, + "[\"[\\\"features\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "bc79858745a7d262", + "gleich": false + }, "[\"[\\\"features\\\", \\\"Titel anpassen\\\"]\", \"[\\\"features\\\", \\\"Ziel anpassen\\\"]\"]": { "abdruck": "69360dc1502aa01f", "gleich": false @@ -370,6 +632,10 @@ "abdruck": "5e97e3c6fe9df287", "gleich": false }, + "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"funktionen\\\", \\\"Funktion entfernen\\\"]\"]": { + "abdruck": "3e58148f974b6b34", + "gleich": false + }, "[\"[\\\"funktionen\\\", \\\"Funktion anlegen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt anlegen\\\"]\"]": { "abdruck": "202f51c53a73b452", "gleich": false @@ -382,9 +648,281 @@ "abdruck": "4090ee6826466fa3", "gleich": false }, + "[\"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "c8321ad2b769d77f", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "7ce003da82080259", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Regeln anpassen\\\"]\", \"[\\\"karten-pruefen\\\", \\\"Funktion abnehmen\\\"]\"]": { + "abdruck": "d2f80684e1be6287", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Testschritte anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\"]": { + "abdruck": "7a51922f327ba28b", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Testschritte anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { + "abdruck": "97a70c7ecfbb9f30", + "gleich": false + }, "[\"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\", \"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\"]": { "abdruck": "17b00db94f54b62d", "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Titel anpassen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision anpassen\\\"]\"]": { + "abdruck": "d17a7b7bad8d947a", + "gleich": false + }, + "[\"[\\\"funktionen\\\", \\\"Ziel anpassen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision anpassen\\\"]\"]": { + "abdruck": "e25b21ca4183d372", + "gleich": false + }, + "[\"[\\\"karten-pruefen\\\", \\\"Alle Vorschläge annehmen\\\"]\", \"[\\\"karten-pruefen\\\", \\\"Alle Vorschläge verwerfen\\\"]\"]": { + "abdruck": "b9c707879cffb7cd", + "gleich": false + }, + "[\"[\\\"karten-pruefen\\\", \\\"Alle Vorschläge verwerfen\\\"]\", \"[\\\"karten-pruefen\\\", \\\"Vorschlag verwerfen\\\"]\"]": { + "abdruck": "aed348a776637c4a", + "gleich": false + }, + "[\"[\\\"projekte\\\", \\\"Projekt anlegen\\\"]\", \"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\"]": { + "abdruck": "957ebec8e3096ce6", + "gleich": false + }, + "[\"[\\\"projekte\\\", \\\"Projekt entfernen\\\"]\", \"[\\\"vision-festhalten\\\", \\\"Vision entfernen\\\"]\"]": { + "abdruck": "8757fb8b0f89d5a6", + "gleich": false + } + }, + "stil": { + "[\"darkmode\", \"\"]": { + "abdruck": "a5b0fd59f25c55ae", + "probleme": [] + }, + "[\"darkmode\", \"Darkmode umschalten\"]": { + "abdruck": "0dbcca6954cc4d16", + "probleme": [] + }, + "[\"design\", \"\"]": { + "abdruck": "1ae7985ebcfe6c6a", + "probleme": [] + }, + "[\"design\", \"Eingabe mit Enter bestätigen\"]": { + "abdruck": "b961f168017fb01e", + "probleme": [] + }, + "[\"design\", \"Kontextmenü schließen\"]": { + "abdruck": "a3717ea52a012784", + "probleme": [] + }, + "[\"features\", \"\"]": { + "abdruck": "b4f6fe4cd065e9e9", + "probleme": [] + }, + "[\"features\", \"Anzeigemodus umschalten\"]": { + "abdruck": "8d468a73bcec5521", + "probleme": [] + }, + "[\"features\", \"Feature anlegen\"]": { + "abdruck": "7d4d6e36b4f03318", + "probleme": [] + }, + "[\"features\", \"Feature durchsuchen\"]": { + "abdruck": "3acde68ab76b942c", + "probleme": [] + }, + "[\"features\", \"Feature einstufen\"]": { + "abdruck": "10e74d934dafacc9", + "probleme": [] + }, + "[\"features\", \"Feature entfernen\"]": { + "abdruck": "509a1153b2e6382f", + "probleme": [] + }, + "[\"features\", \"Feature verschieben\"]": { + "abdruck": "5169bc85a796b6a9", + "probleme": [] + }, + "[\"features\", \"Regeln anpassen\"]": { + "abdruck": "6b4eeed76c631333", + "probleme": [] + }, + "[\"features\", \"Titel anpassen\"]": { + "abdruck": "de6e2788e24aa230", + "probleme": [] + }, + "[\"features\", \"Ziel anpassen\"]": { + "abdruck": "f26e4426663b8265", + "probleme": [] + }, + "[\"funktionen\", \"\"]": { + "abdruck": "adcc38efdb393cf6", + "probleme": [] + }, + "[\"funktionen\", \"Funktion anlegen\"]": { + "abdruck": "11c59974712619a0", + "probleme": [] + }, + "[\"funktionen\", \"Funktion entfernen\"]": { + "abdruck": "e55d43e078f1020e", + "probleme": [] + }, + "[\"funktionen\", \"Funktion verschieben\"]": { + "abdruck": "1bdf3be9b53fdb99", + "probleme": [] + }, + "[\"funktionen\", \"Regeln anpassen\"]": { + "abdruck": "e354caf2701ee79c", + "probleme": [] + }, + "[\"funktionen\", \"Stand umschalten\"]": { + "abdruck": "f39b25d34cc6e4c4", + "probleme": [] + }, + "[\"funktionen\", \"Testschritte anpassen\"]": { + "abdruck": "8fb282300c19c3c2", + "probleme": [] + }, + "[\"funktionen\", \"Titel anpassen\"]": { + "abdruck": "63e9a78a02d890fe", + "probleme": [] + }, + "[\"funktionen\", \"Ziel anpassen\"]": { + "abdruck": "a72ce3656c787475", + "probleme": [] + }, + "[\"karten-besprechen\", \"\"]": { + "abdruck": "8d330c5a71e25e0c", + "probleme": [] + }, + "[\"karten-besprechen\", \"Gespräch schließen\"]": { + "abdruck": "d1c043cd26a05d69", + "probleme": [] + }, + "[\"karten-besprechen\", \"Gespräch verwerfen\"]": { + "abdruck": "e6d601409eb48f7a", + "probleme": [] + }, + "[\"karten-besprechen\", \"Gespräch öffnen\"]": { + "abdruck": "b9a3f8340aa9e266", + "probleme": [] + }, + "[\"karten-besprechen\", \"Nachricht senden\"]": { + "abdruck": "c3ec1453a9aff541", + "probleme": [] + }, + "[\"karten-besprechen\", \"Vorgeschlagene Karte anlegen\"]": { + "abdruck": "ca0a5b02f10bbd1e", + "probleme": [] + }, + "[\"karten-pruefen\", \"\"]": { + "abdruck": "43f92e591142fa95", + "probleme": [] + }, + "[\"karten-pruefen\", \"Alle Vorschläge annehmen\"]": { + "abdruck": "5afe1e8ec40d8b82", + "probleme": [] + }, + "[\"karten-pruefen\", \"Alle Vorschläge verwerfen\"]": { + "abdruck": "c44bbe11908637e9", + "probleme": [] + }, + "[\"karten-pruefen\", \"Code in Features prüfen\"]": { + "abdruck": "ed5da2461b99ddf3", + "probleme": [] + }, + "[\"karten-pruefen\", \"Features im Code prüfen\"]": { + "abdruck": "c31fcfa6dbc75232", + "probleme": [] + }, + "[\"karten-pruefen\", \"Funktion abnehmen\"]": { + "abdruck": "dd3cf177204bcf25", + "probleme": [] + }, + "[\"karten-pruefen\", \"Problemstelle anspringen\"]": { + "abdruck": "0656bbf0d6554c85", + "probleme": [] + }, + "[\"karten-pruefen\", \"Prüfung beenden\"]": { + "abdruck": "af40481c06d2fd97", + "probleme": [] + }, + "[\"karten-pruefen\", \"Stil prüfen\"]": { + "abdruck": "8326e792e8383b53", + "probleme": [] + }, + "[\"karten-pruefen\", \"Vorschlag annehmen\"]": { + "abdruck": "6f8d17b80787b7aa", + "probleme": [] + }, + "[\"karten-pruefen\", \"Vorschlag verwerfen\"]": { + "abdruck": "cf5bda968428df9f", + "probleme": [] + }, + "[\"projekte\", \"\"]": { + "abdruck": "a59f6fdfa58188fa", + "probleme": [] + }, + "[\"projekte\", \"Projekt anlegen\"]": { + "abdruck": "2c3ab4452996ffaf", + "probleme": [] + }, + "[\"projekte\", \"Projekt aufrufen\"]": { + "abdruck": "2ca7a3ea9e79fc6e", + "probleme": [] + }, + "[\"projekte\", \"Projekt entfernen\"]": { + "abdruck": "a0c52ceb9605a805", + "probleme": [] + }, + "[\"projekte\", \"Projekt umbenennen\"]": { + "abdruck": "d41292ff010e7fd3", + "probleme": [] + }, + "[\"projekte\", \"Quelle festlegen\"]": { + "abdruck": "990ee354f1aa70fa", + "probleme": [] + }, + "[\"schritt-zuruecknehmen\", \"\"]": { + "abdruck": "f4ecff18e05ff058", + "probleme": [] + }, + "[\"schritt-zuruecknehmen\", \"Nächsten Rückschritt anzeigen\"]": { + "abdruck": "2d944c3424b6f851", + "probleme": [] + }, + "[\"schritt-zuruecknehmen\", \"Schritt zurücknehmen\"]": { + "abdruck": "28825333acb1e107", + "probleme": [] + }, + "[\"vision-festhalten\", \"\"]": { + "abdruck": "e83e9ad5470aa4b1", + "probleme": [] + }, + "[\"vision-festhalten\", \"Anzeigemodus umschalten\"]": { + "abdruck": "87c494e1e1b0a7b2", + "probleme": [] + }, + "[\"vision-festhalten\", \"Vision anlegen\"]": { + "abdruck": "7826b26956ba51d2", + "probleme": [] + }, + "[\"vision-festhalten\", \"Vision anpassen\"]": { + "abdruck": "378ea30c154f7994", + "probleme": [] + }, + "[\"vision-festhalten\", \"Vision entfernen\"]": { + "abdruck": "340343e51583e86a", + "probleme": [] + } + }, + "verworfen": { + "route:delete /projekte/{name}/chat": { + "abdruck": "4ba7a240985a83b4", + "titel": "Gespräch schließen\nChatverlauf leeren" } } } diff --git a/daten/Planer/darkmode.md b/daten/Planer/darkmode.md index 75fba55..11c604c 100644 --- a/daten/Planer/darkmode.md +++ b/daten/Planer/darkmode.md @@ -19,5 +19,5 @@ Darkmode umschalten - Tag-Icon: ☀ - Auto-Icon: A -- LMB auf Sidebar-Icon +- LMB auf Icon in der Kopfzeile - Modus gewechselt diff --git a/daten/Planer/design.md b/daten/Planer/design.md index 22282bb..54257c1 100644 --- a/daten/Planer/design.md +++ b/daten/Planer/design.md @@ -19,11 +19,24 @@ Hält die Oberfläche lesbar und ruhig - Escape schließt das Modal ---------------------------------------- +Eingabe mit Enter bestätigen + +Spart den Weg zum Knopf + +- Gilt in einzeiligen Feldern +- Escape verwirft stattdessen + +- Modal öffnen +- Text eingeben +- Enter drücken +- Eingabe übernommen + Kontextmenü schließen Räumt ein offenes Menü aus dem Weg - Klick daneben schließt es +- Escape schließt es - Ein neues Menü verdrängt das alte - RMB auf eine Karte diff --git a/daten/Planer/features.md b/daten/Planer/features.md index df5c133..04d00f8 100644 --- a/daten/Planer/features.md +++ b/daten/Planer/features.md @@ -50,9 +50,19 @@ Trennt tragende von verzichtbaren Features - Badge zeigt die Einstufung - Vollmodus öffnen -- LMB auf Badge klicken +- LMB auf Badge - Einstufung gewechselt +Feature durchsuchen + +Findet die Karte, ohne alle zu lesen + +- Sucht in allen Feldern +- Zählt Ausgeblendete mit + +- Suchwort eingeben +- Nur passende Karten bleiben + Feature entfernen - x-Icon @@ -62,6 +72,19 @@ Feature entfernen - Bestätigen im Modal - Feature entfernt +Feature verschieben + +Hängt ein Feature in ein anderes Projekt um + +- Datei wandert +- Datei wird nicht kopiert +- Nur bei mehreren Projekten + +- RMB auf Featurecard +- Klick auf "Feature verschieben" +- Zielprojekt wählen +- Feature verschoben + Regeln anpassen - Vollmodus öffnen diff --git a/daten/Planer/funktionen.md b/daten/Planer/funktionen.md index 9d7d0dd..c65e957 100644 --- a/daten/Planer/funktionen.md +++ b/daten/Planer/funktionen.md @@ -9,7 +9,9 @@ Zerlegt ein Feature in prüfbare Stücke ---------------------------------------- - Gehört zu genau einem Feature -- Alphabetisch sortiert +- Offen heißt bestellt, nicht gebaut +- Neue Funktionen von Hand gelten als gebaut +- Reihenfolge frei wählbar - Ziel bleibt freiwillig - Regeln bleiben freiwillig - Testen bleibt freiwillig @@ -39,6 +41,30 @@ Funktion entfernen - Bestätigen im Modal - Funktion entfernt +Stand umschalten + +Trennt Bestelltes von Gebautem + +- Marke rechts vom Titel +- Offen ist gelb +- Gebaut ist ein Haken +- Kompakt erscheint nur die offene Marke + +- Vollmodus öffnen +- LMB auf die Marke +- Stand gewechselt + +Funktion verschieben + +Bringt die Schritte in ihre natürliche Folge + +- Reihenfolge steht in der Datei + +- Vollmodus öffnen +- RMB auf Funktion +- Klick auf "Nach oben" +- Funktion verschoben + Titel anpassen - Vollmodus öffnen diff --git a/daten/Planer/k1-1024.png b/daten/Planer/k1-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..2a67485bcb179e45cac7b386d03d9851d77d6dc6 GIT binary patch literal 31445 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 YSiYuBWnqU{2m&c7s6B?uy?FaS0B_E}SO5S3 literal 0 HcmV?d00001 diff --git a/daten/Planer/k1-1600.png b/daten/Planer/k1-1600.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac7549bb99643fc6fbf677342de04aadac61ce7 GIT binary patch literal 34370 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 Fe*rD1?&AOe literal 0 HcmV?d00001 diff --git a/daten/Planer/k1-390.png b/daten/Planer/k1-390.png new file mode 100644 index 0000000000000000000000000000000000000000..2132bc6d36bdf92251b9995a791b3efc96356eb9 GIT binary patch literal 28243 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 GPyYrdu!jx+ literal 0 HcmV?d00001 diff --git a/daten/Planer/k1-640.png b/daten/Planer/k1-640.png new file mode 100644 index 0000000000000000000000000000000000000000..30419258c2818792b26309b284f093d192e21ccf GIT binary patch literal 30111 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'Wv|XmVFI;_kTo3Hnyx* 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 literal 0 HcmV?d00001 diff --git a/daten/Planer/k1-820.png b/daten/Planer/k1-820.png new file mode 100644 index 0000000000000000000000000000000000000000..485f1219504a265b59d7d7c1b4866f943d6c6c4c GIT binary patch literal 31558 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 Z0;+}ofJ~qop8}tN6l7GN7fQW&`ya1ImFoZi literal 0 HcmV?d00001 diff --git a/daten/Planer/karten-besprechen.md b/daten/Planer/karten-besprechen.md new file mode 100644 index 0000000..984d38e --- /dev/null +++ b/daten/Planer/karten-besprechen.md @@ -0,0 +1,61 @@ + +Karten besprechen +---------------------------------------- + +optional +---------------------------------------- + +Entwickelt Karten im Gespräch mit der KI +---------------------------------------- + +- Die KI schreibt nie selbst in eine Karte +- Sie beschreibt den Sollzustand +- Was sich ändert, rechnet der Code aus +- Vorschläge sehen aus wie bei der Prüfung +- Neue Funktionen gelten als offen +- Das Gespräch überlebt den Neustart +- Die letzten 30 Wortmeldungen bleiben +- Gespräch und Prüfung teilen eine Spalte +---------------------------------------- + +Gespräch öffnen + +- Stift-Icon in der Kopfzeile +- Icon leuchtet bei offenem Gespräch + +- LMB auf Stift-Icon +- Gespräch geöffnet + +Nachricht senden + +Sagt der KI, was das Projekt können soll + +- Enter sendet +- Eigene Zeile erscheint sofort +- Text bleibt bei einem Fehler stehen + +- Text eingeben +- Enter drücken +- Antwort und Vorschläge erscheinen + +Vorgeschlagene Karte anlegen + +Macht aus einem Umriss eine echte Karte + +- Gestrichelter Rand vor dem Annehmen + +- LMB auf Haken am Umriss +- Karte angelegt + +Gespräch verwerfen + +- Löscht nur das Gespräch +- Karten bleiben unberührt + +- LMB auf Papierkorb-Icon +- Gespräch geleert + +Gespräch schließen + +- LMB auf x-Icon +- Spalte wieder frei diff --git a/daten/Planer/karten-pruefen.md b/daten/Planer/karten-pruefen.md index 66e6e51..cd0ae23 100644 --- a/daten/Planer/karten-pruefen.md +++ b/daten/Planer/karten-pruefen.md @@ -35,26 +35,6 @@ Alle Vorschläge verwerfen - LMB auf x-Icon der Karte - Alle Vorschläge verworfen -Code in Features prüfen - -Findet Bedienstellen ohne Funktion auf einer Karte - -- Bedienstellen kommen aus dem Code -- Fünf von sechs Stimmen entscheiden - -- LMB auf Aufwärts-Icon -- Fehlende Funktionen gelistet - -Features im Code prüfen - -Findet Funktionen ohne Entsprechung im Code - -- Sechs Stimmen suchen den Beleg -- Ein Fund genügt zum Freispruch - -- LMB auf Abwärts-Icon -- Funktionen ohne Code gelistet - Problemstelle anspringen Führt vom Panel-Eintrag zur betroffenen Karte @@ -77,7 +57,7 @@ Stil prüfen Prüft die Form gegen den Katalog -- Prüf-Icon in der Sidebar +- Prüf-Icon in der Kopfzeile - Wortzahl und Satzzeichen misst der Code - LMB auf Prüf-Icon diff --git a/daten/Planer/komfort.png b/daten/Planer/komfort.png new file mode 100644 index 0000000000000000000000000000000000000000..84ed8477d20c714b876b2f6beab7a4c62d9c53d0 GIT binary patch literal 21904 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 X+Rp#8I{n}pkbt3{>Fv_rou2;>7-K^% literal 0 HcmV?d00001 diff --git a/daten/Planer/offen.png b/daten/Planer/offen.png new file mode 100644 index 0000000000000000000000000000000000000000..382a2d5f9a801963fe0b582a1fb753ef32c50ae7 GIT binary patch literal 25795 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 literal 0 HcmV?d00001 diff --git a/daten/Planer/vision.md b/daten/Planer/vision.md index dc70237..3f87d66 100644 --- a/daten/Planer/vision.md +++ b/daten/Planer/vision.md @@ -11,7 +11,7 @@ vision - Die KI zeigt mir Live wie sich die Features ändern - Ich verbessere und die KI passt Live an - Wenn ich zufrieden bin, dann lasse ich die Features von der KI implementieren -- Zu einem ausgewählten Projekt analysiert die KI alle kompakten Informationen dazu +- (später) Zu einem ausgewählten Projekt analysiert die KI alle kompakten Informationen dazu - Ich wähle ein Verzeichnis das als Quelle dient - Die Quelle wird durch ein System geschickt, dass kompakte Informationen extrahiert - Die kompakten Informationen enthalten das Wissen zu dem WIE vom Projekt diff --git a/daten/RAG/.pruefung.json b/daten/RAG/.pruefung.json new file mode 100644 index 0000000..13292ac --- /dev/null +++ b/daten/RAG/.pruefung.json @@ -0,0 +1,2735 @@ +{ + "abdeckung": { + "befehl:mto:agent:architecture:flow-boundary-lock-self-test": { + "abdruck": "c925f9ebbfd2ac93", + "funktion": "Flow-Grenze sperren", + "trug": "ea1cbd831236ff9b" + }, + "befehl:mto:agent:architecture:product-label-formatter-self-test": { + "abdruck": "0d4a6b2e979afd6b", + "funktion": "Produktlabel-Formatierer testen", + "trug": "74392b10f4a0556c" + }, + "befehl:mto:agent:architecture:product-role-code-assignment-guard-self-test": { + "abdruck": "60e19a0ea2d093fe", + "funktion": "Rollencode-Zuweisung prüfen", + "trug": "f2997c6adf648e7d" + }, + "befehl:mto:agent:architecture:retrieval-boundary-plan-self-test": { + "abdruck": "7f8215ff3dff4b5c", + "funktion": "Abrufgrenzen prüfen", + "trug": "f28e16b270157b1c" + }, + "befehl:mto:agent:chat": { + "abdruck": "097710e520fe8631", + "funktion": "Mit Agent chatten", + "trug": "1229550e6c0369a3" + }, + "befehl:mto:agent:config:audit-patterns": { + "abdruck": "0b1c8dad920a1d05", + "funktion": "Konfigurationsmuster prüfen", + "trug": "1b7dd0cb5cba69f8" + }, + "befehl:mto:agent:config:dump-effective": { + "abdruck": "0ba647f167567c2b", + "funktion": "Konfiguration anzeigen", + "trug": "2511a19eea51ca10" + }, + "befehl:mto:agent:config:validate": { + "abdruck": "cb09c2dfeb607be8", + "funktion": "Konfiguration prüfen", + "trug": "108abbfa38def03f" + }, + "befehl:mto:agent:enterprise:backup-restore-readiness": { + "abdruck": "ad2992db1999b947", + "funktion": "Backup-Tauglichkeit prüfen", + "trug": "990d7d1975e35860" + }, + "befehl:mto:agent:enterprise:backup-run": { + "abdruck": "e5e1870cc5f2a2c7", + "funktion": "Daten sichern", + "trug": "6391c6a03fff9ba3" + }, + "befehl:mto:agent:enterprise:deployment-scheduler-readiness": { + "abdruck": "b7f9a71b8bce1733", + "funktion": "Bereitschaftsbericht ausgeben", + "trug": "1961781c00c38587" + }, + "befehl:mto:agent:enterprise:operations-overview": { + "abdruck": "941982a7c7e9d9df", + "funktion": "Übersicht rendern", + "trug": "d6b379dbcf57c5dc" + }, + "befehl:mto:agent:enterprise:operator-report": { + "abdruck": "3305eaab802a8180", + "funktion": "Akzeptanzbericht generieren", + "trug": "1e122f300e60146f" + }, + "befehl:mto:agent:enterprise:readiness-check": { + "abdruck": "c5898cf586f10094", + "funktion": "Betriebsbereitschaft prüfen", + "trug": "dd4dda8395a78a97" + }, + "befehl:mto:agent:enterprise:restore-dry-run": { + "abdruck": "f471bab3a3187f13", + "funktion": "Backup-Trockenlauf prüfen", + "trug": "38cceaaa7e618c63" + }, + "befehl:mto:agent:enterprise:security-data-protection-readiness": { + "abdruck": "0a15e861d54def48", + "funktion": "Sicherheitsstatus prüfen", + "trug": "95276315f7c29265" + }, + "befehl:mto:agent:eval:parallel": { + "abdruck": "440dabce16816af3", + "funktion": "Eval-Fälle parallelisieren", + "trug": "8de24027a3e2c83c" + }, + "befehl:mto:agent:eval:run": { + "abdruck": "85ce4fdd99e94c23", + "funktion": "Eval-Fälle ausführen", + "trug": "73538935d4ddd959" + }, + "befehl:mto:agent:feedback:classify": { + "abdruck": "5428da2879624973", + "funktion": "Feedback klassifizieren", + "trug": "00b9152d4536b7ac" + }, + "befehl:mto:agent:genre:audit-core-neutrality": { + "abdruck": "f97cab11f1213a75", + "funktion": "Genre-Hotspots prüfen", + "trug": "91bc58442eee2f36" + }, + "befehl:mto:agent:history:anchors": { + "abdruck": "69a43649a218b596", + "funktion": "Verankerungen extrahieren", + "trug": "4b9bd02538873b0f" + }, + "befehl:mto:agent:history:followup-dry-run": { + "abdruck": "2af2830fff693f92", + "funktion": "Verankerung testen", + "trug": "9803f7bc34ffb84d" + }, + "befehl:mto:agent:ingest:chunk-quality": { + "abdruck": "179b20588e0c26d7", + "funktion": "Datenqualität prüfen", + "trug": "a162e9d2ed54a9e5" + }, + "befehl:mto:agent:ingest:chunk-quality-self-test": { + "abdruck": "7f431dab24f49f21", + "funktion": "Vergleichsgrenzen validieren", + "trug": "a9bb27f89b92b3a2" + }, + "befehl:mto:agent:ingest:deferred-reindex-state-self-test": { + "abdruck": "4decd99e80b91dd7", + "funktion": "Indizierungszustand prüfen", + "trug": "3ff8ed7e97021ae8" + }, + "befehl:mto:agent:ingest:markdown-derived-chunk-diagnostics-self-test": { + "abdruck": "ab9c4c968bef5c19", + "funktion": "Provenienz prüfen", + "trug": "7c406a0b8ca3453d" + }, + "befehl:mto:agent:ingest:markdown-normalization-foundation-self-test": { + "abdruck": "3f7feb1c5b040048", + "funktion": "Normalisierung prüfen", + "trug": "109ef8545f52ea37" + }, + "befehl:mto:agent:ingest:markdown-normalization-preview-self-test": { + "abdruck": "0f88411e0d7407b2", + "funktion": "Preview prüfen", + "trug": "fc8906b1cdfef658" + }, + "befehl:mto:agent:ingest:run": { + "abdruck": "aef780b3982b6bed", + "funktion": "Ingest-Job starten", + "trug": "f887e188d6183e35" + }, + "befehl:mto:agent:ingest:segmented-markdown-normalization-self-test": { + "abdruck": "21912db371ab9e77", + "funktion": "Segmentierung prüfen", + "trug": "34003cb287e4f9d7" + }, + "befehl:mto:agent:knowledge-space:chat-selection-guard-self-test": { + "abdruck": "601aa7233164d6b5", + "funktion": "Chat-Auswahl-Guard testen", + "trug": "ac7be281304f5f16" + }, + "befehl:mto:agent:knowledge:batch-admin-upload-self-test": { + "abdruck": "21121f956adc3ca0", + "funktion": "Stapel-Upload verifizieren", + "trug": "df545dae80c027af" + }, + "befehl:mto:agent:knowledge:batch-finalize-self-test": { + "abdruck": "4d4c21b129b2a50c", + "funktion": "Wissensbatch finalisieren testen", + "trug": "e9d61c0127ac4796" + }, + "befehl:mto:agent:knowledge:batch-hygiene-self-test": { + "abdruck": "6e777c8e17e244c3", + "funktion": "Hygieneregeln prüfen", + "trug": "761903cb0a2d2033" + }, + "befehl:mto:agent:knowledge:batch-import": { + "abdruck": "47be9b2b1135f1f4", + "funktion": "Batch-Import durchführen", + "trug": "baeac712078f4a8f" + }, + "befehl:mto:agent:knowledge:batch-inbox-disposition-self-test": { + "abdruck": "3e2e59ae7e444730", + "funktion": "Hygieneregeln prüfen", + "trug": "761903cb0a2d2033" + }, + "befehl:mto:agent:mcp:admin-source-check": { + "abdruck": "414f4d925dd1dd7b", + "funktion": "MCP-Quelle prüfen", + "trug": "0917ca989dcd1b58" + }, + "befehl:mto:agent:mcp:admin-source-discover": { + "abdruck": "333c1e221f30b3b8", + "funktion": "Fähigkeiten ermitteln", + "trug": "1e53c164947ea291" + }, + "befehl:mto:agent:mcp:evidence-dry-run": { + "abdruck": "695d5fa49f9a7743", + "funktion": "Simulation ausführen", + "trug": "0f010df62c3d5412" + }, + "befehl:mto:agent:mcp:gateway-dry-run": { + "abdruck": "bf9c879d67aac387", + "funktion": "MCP-Gateway trocken ausführen", + "trug": "59f4089864406319" + }, + "befehl:mto:agent:mcp:hybrid-tool-selection-planner-self-test": { + "abdruck": "d082f417503050bd", + "funktion": "Hybrid-Tool-Auswahl testen", + "trug": "9c05f0bc361a0308" + }, + "befehl:mto:agent:mcp:read-only-tool-execution-self-test": { + "abdruck": "99468d4b3ccde91e", + "funktion": "MCP-Laufzeit-Gate prüfen", + "karten": "69d65c7a24056348", + "trug": "c67fbeaf071e4f1d" + }, + "befehl:mto:agent:mcp:resource-check": { + "abdruck": "e2bec83222815992", + "funktion": "Ressource validieren", + "trug": "3e0c5e7c05c447b1" + }, + "befehl:mto:agent:mcp:resource-read": { + "abdruck": "3bbcf40c19dfb416", + "funktion": "Ressource abrufen", + "trug": "c56c2251c777e9cd" + }, + "befehl:mto:agent:mcp:runtime-boundary-self-test": { + "abdruck": "d736aecb78b903c0", + "funktion": "MCP-Laufzeitgrenze testen", + "trug": "228e1329bb95848b" + }, + "befehl:mto:agent:mcp:runtime-gate-check": { + "abdruck": "157fd59080f4b577", + "funktion": "MCP-Laufzeit-Gate prüfen", + "trug": "c67fbeaf071e4f1d" + }, + "befehl:mto:agent:performance:cache:clear": { + "abdruck": "763defd74a61b330", + "funktion": "Performance-Cache leeren", + "trug": "46d7cac0b9f2f79c" + }, + "befehl:mto:agent:proofing:unsupported-tool-term-guard-self-test": { + "abdruck": "1be9660daebca409", + "funktion": "Guard-Mechanismus prüfen", + "trug": "464037018968440b" + }, + "befehl:mto:agent:release:v1-10-8-lock-self-test": { + "abdruck": "28db5aea7efa396a", + "funktion": "Release-Selbsttest bereitstellen", + "trug": "51c4e03a2afc8beb" + }, + "befehl:mto:agent:retrieval:test": { + "abdruck": "66a9907312e411fc", + "funktion": "Retrieval-Pipeline testen", + "trug": "7dfd51b13de31ffe" + }, + "befehl:mto:agent:shop-followup-anchor-stability-self-test": { + "abdruck": "3fbc5cbbb9918cd2", + "funktion": "Stabilitäts-Selbsttest bereitstellen", + "trug": "307662914163e231" + }, + "befehl:mto:agent:tag:health": { + "abdruck": "34aaf86ed8aa379c", + "funktion": "Tag-Index-Gesundheit prüfen", + "trug": "478f95e9cc14f7d3" + }, + "befehl:mto:agent:tags:job:run": { + "abdruck": "5bb98e3f933da917", + "funktion": "Tag-Rebuild-Auftrag ausführen", + "trug": "1b02b00a7521be25" + }, + "befehl:mto:agent:test:shop-search": { + "abdruck": "5f78005e426d4c4f", + "funktion": "Shop-Suche testen", + "trug": "e4f9db3bd08ba93c" + }, + "befehl:mto:agent:user:create": { + "abdruck": "68921f1ed8e70531", + "funktion": "Benutzer anlegen", + "trug": "d3905c51b162b0ce" + }, + "befehl:mto:agent:vector:control": { + "abdruck": "1c3e9261c8b0c2c5", + "funktion": "Vektordienst steuern", + "trug": "be8c0401addb4adc" + }, + "befehl:mto:agent:vector:health": { + "abdruck": "ab957428c904d078", + "funktion": "Systemzustand prüfen", + "trug": "340f9bb7cc48ab64" + }, + "befehl:mto:ingest:facts:coverage": { + "abdruck": "dcf005cfc8d9b45f", + "funktion": "Abdeckung prüfen", + "trug": "d90435a4cc615013" + }, + "befehl:mto:ingest:facts:inspect": { + "abdruck": "5463537ee443fe78", + "funktion": "Facts prüfen", + "trug": "76dd7c085b763488" + }, + "einbinden:erweitert admin/base.html.twig": { + "abdruck": "dfcfeacbc81295ab", + "funktion": "Chat-Feedback anzeigen", + "trug": "0fb753e62f2eb09b" + }, + "einbinden:erweitert error/access_denied.html.twig": { + "abdruck": "30769f2d88587d3d", + "funktion": "Access-Denied-Fehler bereitstellen", + "trug": "c664c4eb298dd322" + }, + "route:delete /chat-uploads/{uploadId}": { + "abdruck": "a0153beebed60be4", + "funktion": "Upload entfernen", + "trug": "eeec4fdfa3e38511" + }, + "route:get /": { + "abdruck": "de9b287ba64070d2", + "funktion": "Eval-Berichte anzeigen", + "trug": "2f9bb8b3d22f8dbe" + }, + "route:get /admin": { + "abdruck": "8c0cdf9bd2b315ea", + "funktion": "Zum Dashboard weiterleiten", + "trug": "709c61628f0f66ea" + }, + "route:get /admin/": { + "abdruck": "244b9c6384096f5d", + "funktion": "Zum Dashboard weiterleiten", + "trug": "709c61628f0f66ea" + }, + "route:get /admin/chat-feedback": { + "abdruck": "e639b1e43a886a35", + "funktion": "Chat-Feedback anzeigen", + "trug": "0fb753e62f2eb09b" + }, + "route:get /admin/chat-feedback/export": { + "abdruck": "89b2621e72d8b40e", + "funktion": "Feedback exportieren", + "trug": "37a8b8e0632ad60e" + }, + "route:get /admin/chat-feedback/{id}": { + "abdruck": "edae161a247e6bfb", + "funktion": "Feedback-Details anzeigen", + "trug": "a727999800a26db6" + }, + "route:get /admin/dashboard": { + "abdruck": "2acfe2685cf601e1", + "funktion": "Dashboard anzeigen", + "trug": "4d52ebf21e33b65d" + }, + "route:get /admin/documents": { + "abdruck": "254afcc7302b5bb0", + "funktion": "Dokumente auflisten", + "trug": "0f9da42877f59cbe" + }, + "route:get /admin/enterprise": { + "abdruck": "b9d858b5471e2275", + "funktion": "Betrieb einsehen", + "trug": "0b34c0dd4f914b6b" + }, + "route:get /admin/enterprise/backup/download/latest": { + "abdruck": "ed97e58d3ce006f5", + "funktion": "Backup herunterladen", + "trug": "98261892ea9d3263" + }, + "route:get /admin/enterprise/backup/download/{backupId}": { + "abdruck": "284a03d7c9c86a3d", + "funktion": "Backup herunterladen", + "trug": "98261892ea9d3263" + }, + "route:get /admin/evals": { + "abdruck": "894a59095781a388", + "funktion": "Eval-Berichte anzeigen", + "trug": "2f9bb8b3d22f8dbe" + }, + "route:get /admin/guides": { + "abdruck": "a6767af48c103041", + "funktion": "Anleitungsübersicht öffnen", + "trug": "98c240aa62e2af02" + }, + "route:get /admin/ingest-profiles": { + "abdruck": "bd4481affd92aaf9", + "funktion": "Ingest-Profile anzeigen", + "trug": "2a45a43dfa6f7271" + }, + "route:get /admin/knowledge-batches": { + "abdruck": "6d68dc146b79f1b1", + "funktion": "Berichte auflisten", + "trug": "1e1adebd6a533d9b" + }, + "route:get /admin/knowledge-spaces": { + "abdruck": "1f5bfdfaca51004d", + "funktion": "Knowledge-Räume anzeigen", + "trug": "e04105aad7265aec" + }, + "route:get /admin/logout": { + "abdruck": "cebcf3109c609638", + "funktion": "Logout einleiten", + "trug": "9326b36641217583" + }, + "route:get /admin/mcp": { + "abdruck": "3174b0ae81ed2d20", + "funktion": "Diagnose anzeigen", + "trug": "653ae3c6bc6a5ac7" + }, + "route:get /admin/model-config": { + "abdruck": "182f6a72c678582a", + "funktion": "Konfigurationen anzeigen", + "trug": "a4cd0821c5ab3b91" + }, + "route:get /admin/system-logs": { + "abdruck": "6c4c049808bfb725", + "funktion": "Logdateien auflisten", + "trug": "e23662d3a0a4fc26" + }, + "route:get /admin/system/agent": { + "abdruck": "1ff3e3c48256b456", + "funktion": "Agentenaktivität anzeigen", + "trug": "512d3700573a9356" + }, + "route:get /admin/system/prompt": { + "abdruck": "0f2a1947d023e2b0", + "funktion": "Promptversionen verwalten", + "trug": "3ec1e92103f00c9a" + }, + "route:get /admin/tags": { + "abdruck": "dadb6db0fce78a59", + "funktion": "Tags auflisten", + "trug": "a6bcaa4a541749b0" + }, + "route:get /admin/tags/rebuild/stream": { + "abdruck": "da90a04cfab9e7bc", + "funktion": "Tags neu indizieren", + "trug": "aad224c33efd3415" + }, + "route:get /admin/users": { + "abdruck": "451ceac42e573fda", + "funktion": "Benutzer auflisten", + "trug": "200ddcbf1533c973" + }, + "route:get /admin/vector": { + "abdruck": "3762d40b703820f7", + "funktion": "Logdatei anzeigen", + "karten": "69d65c7a24056348", + "trug": "a9d4ceb635037c40" + }, + "route:get /ask-jobs/{jobId}": { + "abdruck": "0477abfc17efcd4b", + "funktion": "Auftragsstatus prüfen", + "trug": "bf711e7620e0bc96" + }, + "route:get /ask-jobs/{jobId}/events": { + "abdruck": "b035aad4da5a9b84", + "funktion": "Auftragsereignisse abrufen", + "trug": "5ec31a2942302b5d" + }, + "route:get /ask-sse/{jobId}": { + "abdruck": "2ae6d3b6ab22ee94", + "funktion": "Chat streamen", + "trug": "3af6f0591b337739" + }, + "route:get /cases/new": { + "abdruck": "d73c3f7105356e98", + "funktion": "Fall anlegen", + "trug": "d302a36967935d71" + }, + "route:get /cases/wizard": { + "abdruck": "55b87c4c5f6edabb", + "funktion": "Assistent anzeigen", + "trug": "804b6b42634c7a25" + }, + "route:get /chat": { + "abdruck": "8af834421de8e8ef", + "funktion": "Chatseite anzeigen", + "trug": "7ef27e2f05c8c346" + }, + "route:get /chat-messages/frontend": { + "abdruck": "ac5ca7be22f54fb2", + "funktion": "Konfiguration bereitstellen", + "trug": "df981d6e3375bcdc" + }, + "route:get /chat-uploads": { + "abdruck": "ccfaa51e5a843676", + "funktion": "Uploads auflisten", + "trug": "09d17a795ce6d016" + }, + "route:get /chat/login": { + "abdruck": "dbc0f1ab46c63065", + "funktion": "", + "karten": "69d65c7a24056348", + "trug": "" + }, + "route:get /chat/logout": { + "abdruck": "8c143d7ed8bb19f1", + "funktion": "Abmelden ermöglichen", + "trug": "b10bdd01f2407daf" + }, + "route:get /create": { + "abdruck": "fb24a0a1b5de52ef", + "funktion": "Ingest-Profil anlegen", + "trug": "ea489ce2cac0eaf7" + }, + "route:get /health": { + "abdruck": "f027e5524a192d02", + "funktion": "Dienststatus melden", + "trug": "161408c208cf7559" + }, + "route:get /history": { + "abdruck": "1a45e95056f2e9ec", + "funktion": "Verlauf abrufen", + "trug": "9867e39b79854b64" + }, + "route:get /log": { + "abdruck": "d174343fa1d615b0", + "funktion": "Logdatei anzeigen", + "karten": "69d65c7a24056348", + "trug": "a9d4ceb635037c40" + }, + "route:get /new": { + "abdruck": "fb14d5f8ec1a4eaa", + "funktion": "Dokument erstellen", + "trug": "22f98a663b531e62" + }, + "route:get /version/{versionId}/chunk-quality": { + "abdruck": "3d9010c730e6ec8d", + "funktion": "Abschnittsqualität laden", + "trug": "3cb1468222207d3a" + }, + "route:get /version/{versionId}/derive": { + "abdruck": "cdf85b729cf231dd", + "funktion": "Version ableiten", + "trug": "0dd44cc05ad88501" + }, + "route:get /version/{versionId}/preview": { + "abdruck": "058dec3bb1d45c3d", + "funktion": "Versionvorschau anzeigen", + "trug": "a0bf7fb5ea225b8c" + }, + "route:get /view/{date}": { + "abdruck": "9e6084cb57091b03", + "funktion": "Logdatei anzeigen", + "trug": "a9d4ceb635037c40" + }, + "route:get /{batchId}/download/{format}": { + "abdruck": "a6452842849c08bf", + "funktion": "Bericht als JSON herunterladen", + "trug": "22375d7e87b48c7a" + }, + "route:get /{id}": { + "abdruck": "ee95293ff6fa8c1e", + "funktion": "Dokument anzeigen", + "trug": "f8dbff8484664fa3" + }, + "route:get /{id}/assign": { + "abdruck": "104594e54aef3de9", + "funktion": "", + "karten": "69d65c7a24056348", + "trug": "" + }, + "route:get /{id}/edit": { + "abdruck": "8884a169ccea6f64", + "funktion": "Benutzer bearbeiten", + "trug": "8915fc3934e98aeb" + }, + "route:get /{id}/status": { + "abdruck": "8ea057327ee0827e", + "funktion": "Auftragsstatus anzeigen", + "trug": "28f625fb14170c58" + }, + "route:get /{id}/test-retrieval": { + "abdruck": "2ba055d91fdcc948", + "funktion": "Retrieval-Qualität testen", + "trug": "ebe624f4ef848daa" + }, + "route:get /{id}/version/new": { + "abdruck": "c690365b95e860d1", + "funktion": "Version erstellen", + "trug": "99e905871d2af5b8" + }, + "route:get /{slug}": { + "abdruck": "44a679fcb574ce62", + "funktion": "Anleitung anzeigen", + "trug": "1abf113dd0ca51b5" + }, + "route:patch /chat-uploads/{uploadId}/authority-mode": { + "abdruck": "9887f2123af2c793", + "funktion": "Berechtigungsmodus ändern", + "trug": "1b7c2db95a58e7b4" + }, + "route:post /activate/{id}": { + "abdruck": "c9636625aae80c95", + "funktion": "post activate {id} bereitstellen", + "trug": "8cea29a4826cdd6a" + }, + "route:post /admin/chat-feedback/batch/review-status": { + "abdruck": "be6a181dc679b11f", + "funktion": "Feedback-Status aktualisieren", + "trug": "4422d06808d2e980" + }, + "route:post /admin/chat-feedback/{id}/delete": { + "abdruck": "6893b0aa4d8eab87", + "funktion": "Feedback löschen", + "trug": "394b01bbb9e78c64" + }, + "route:post /admin/chat-feedback/{id}/review-status": { + "abdruck": "e25459719748b78c", + "funktion": "Feedback-Status aktualisieren", + "trug": "4422d06808d2e980" + }, + "route:post /admin/enterprise/backup/dry-run": { + "abdruck": "cc7a6cb84b283232", + "funktion": "", + "karten": "69d65c7a24056348", + "trug": "" + }, + "route:post /admin/enterprise/backup/start": { + "abdruck": "c26f0e1b8ec48387", + "funktion": "Backup starten", + "trug": "a80ee1ac8d09feef" + }, + "route:post /admin/enterprise/check/backup-restore": { + "abdruck": "60189cb65f15f7c4", + "funktion": "Backup-Wiederherstellung prüfen", + "trug": "2f43d33d76a1b5fd" + }, + "route:post /admin/enterprise/check/deployment-scheduler": { + "abdruck": "5a0199bcefb3aafe", + "funktion": "Deployment prüfen", + "trug": "72e96ff15688afb5" + }, + "route:post /admin/enterprise/check/security": { + "abdruck": "b626d367ee88e80d", + "funktion": "post admin enterprise check security bereitstellen", + "trug": "ae4ec899a0ed87f9" + }, + "route:post /admin/enterprise/restore/dry-run/latest": { + "abdruck": "4233f9927778bb02", + "funktion": "Backup-Trockenlauf prüfen", + "trug": "38cceaaa7e618c63" + }, + "route:post /admin/enterprise/restore/dry-run/{backupId}": { + "abdruck": "9a80fdd8dd1ce713", + "funktion": "Wiederherstellung testen", + "trug": "bffab37148aca377" + }, + "route:post /admin/knowledge-spaces/chat-availability": { + "abdruck": "5846f32d223c395c", + "funktion": "Chat-Verfügbarkeit prüfen", + "trug": "5bfe9a138fa7a344" + }, + "route:post /admin/knowledge-spaces/diagnostics/run": { + "abdruck": "d36a6a72518706c9", + "funktion": "Wissensräume prüfen", + "trug": "00428abe5d12a1a6" + }, + "route:post /admin/knowledge-spaces/provider-candidate-select": { + "abdruck": "70273cbf7942e934", + "funktion": "Kandidaten wählen", + "trug": "1b400e58e9b9ffa1" + }, + "route:post /admin/knowledge-spaces/provider-resource-chat": { + "abdruck": "94af13df841dd297", + "funktion": "Chat-Freigabe umschalten", + "trug": "ba7f9fdd0f377d82" + }, + "route:post /admin/knowledge-spaces/provider-resource-live-preview": { + "abdruck": "59ce57e712f49f67", + "funktion": "Live-Vorschau laden", + "trug": "60f5dcce03a7be18" + }, + "route:post /admin/knowledge-spaces/provider-resource-review": { + "abdruck": "3d9e1c18d8d90b91", + "funktion": "Kandidaten wählen", + "trug": "1b400e58e9b9ffa1" + }, + "route:post /admin/knowledge-spaces/provider-tool-allowlist": { + "abdruck": "bfb807bb4464c1fc", + "funktion": "Tool-Freigaben aktualisieren", + "trug": "71c29c88725cc001" + }, + "route:post /admin/runtime-cache/clear": { + "abdruck": "b70129f6aca03fad", + "funktion": "Cache leeren", + "trug": "5117399da510e8d0" + }, + "route:post /admin/system/prompt/{id}/activate": { + "abdruck": "dd98f9404f17be0a", + "funktion": "Promptversion aktivieren", + "trug": "7f1b7c10cfc78ea1" + }, + "route:post /admin/system/prompt/{id}/delete": { + "abdruck": "47cc4c8359701df5", + "funktion": "Promptversion löschen", + "trug": "69954cb2aa7826c8" + }, + "route:post /ask-jobs": { + "abdruck": "86dc2f6802845aad", + "funktion": "Auftrag starten", + "trug": "82c4f207a44eed63" + }, + "route:post /ask-sse": { + "abdruck": "87998efb193f5a13", + "funktion": "Chat streamen", + "trug": "3af6f0591b337739" + }, + "route:post /cases": { + "abdruck": "891fb74ed011cee0", + "funktion": "Fall erstellen", + "trug": "b2eeeb327760069a" + }, + "route:post /cases/delete": { + "abdruck": "f7d1df8c1239a344", + "funktion": "Fälle löschen bereitstellen", + "trug": "1644004910ad89e4" + }, + "route:post /cases/wizard": { + "abdruck": "f30980daf2c898a1", + "funktion": "Fall erstellen", + "trug": "b2eeeb327760069a" + }, + "route:post /chat-feedback/status": { + "abdruck": "58df216dabd44e95", + "funktion": "Feedback-Status prüfen", + "trug": "f633724f8d81bf1d" + }, + "route:post /chat-uploads": { + "abdruck": "29d717ceaaf86caa", + "funktion": "Datei hochladen", + "trug": "cf32f652744b3bce" + }, + "route:post /chat-uploads/clear": { + "abdruck": "62df3634844e6b6c", + "funktion": "Upload entfernen", + "trug": "eeec4fdfa3e38511" + }, + "route:post /cleanup": { + "abdruck": "e63b808d97ff109c", + "funktion": "Verzeichnis bereinigen", + "trug": "e4bdd1b6abc28e16" + }, + "route:post /clear-cache": { + "abdruck": "ee57c19a44d92c93", + "funktion": "Performance-Cache leeren", + "trug": "46d7cac0b9f2f79c" + }, + "route:post /create": { + "abdruck": "1c4155cf5a5a761e", + "funktion": "Tags bearbeiten", + "trug": "3a6a4c0fb9c8c0e2" + }, + "route:post /global-reindex": { + "abdruck": "0fbbf88bea2405f9", + "funktion": "Neuindizierung starten", + "trug": "ecd57c4d2d8030b3" + }, + "route:post /history/delete": { + "abdruck": "6e0556a3d3ba517a", + "funktion": "Verlauf löschen", + "trug": "9e769103ea5134a6" + }, + "route:post /reload": { + "abdruck": "79600beee79f0e3f", + "funktion": "Daten neu laden", + "trug": "148a6c4d4edb318d" + }, + "route:post /reports/cleanup": { + "abdruck": "8562351bb6f08c43", + "funktion": "Berichte bereinigen", + "trug": "0f19d3d7b9b076c8" + }, + "route:post /reset": { + "abdruck": "fb1f8b79658c653b", + "funktion": "Systemzustand zurücksetzen", + "trug": "bdfc7ede2fdab0cc" + }, + "route:post /run": { + "abdruck": "cf1ec8908428c705", + "funktion": "Evaluation ausführen", + "trug": "ad158b97138fdfd5" + }, + "route:post /search-chunks": { + "abdruck": "76d40589251fcbcd", + "funktion": "Textteile suchen", + "trug": "f12b4b68064135a4" + }, + "route:post /search-tags": { + "abdruck": "3b82c9af379b43c2", + "funktion": "Tags suchen", + "trug": "c28826e98ccf4488" + }, + "route:post /version/{versionId}/ingest": { + "abdruck": "d219584b34c5cf59", + "funktion": "Abschnitte laden", + "trug": "1fdbb25d131c9241" + }, + "route:post /version/{versionId}/markdown-normalize": { + "abdruck": "84b4594ebade4f10", + "funktion": "Markdown bereinigen", + "trug": "3b52c219a579635d" + }, + "route:post /{batchId}/delete": { + "abdruck": "5cc03440260bd2c2", + "funktion": "Bericht löschen", + "trug": "da18d390ddee9f9e" + }, + "route:post /{id}/activate": { + "abdruck": "f57b82e8c822e3a9", + "funktion": "Konfiguration aktivieren", + "trug": "1de4ccbe029cd746" + }, + "route:post /{id}/delete": { + "abdruck": "b39fd9ea4063eef6", + "funktion": "Dokument entfernen", + "trug": "9cfe41d491014a02" + }, + "route:post /{id}/tags/save": { + "abdruck": "daf6d63a0d9dac6f", + "funktion": "post {id} tags save bereitstellen", + "trug": "bfe4c204d790784c" + }, + "route:post /{id}/title": { + "abdruck": "5f4a8a89a24220e5", + "funktion": "Titel aktualisieren", + "trug": "43eca51f9fdc858b" + }, + "route:post /{id}/title-suggestions": { + "abdruck": "fc54786daea4cb86", + "funktion": "Titelvorschläge laden", + "trug": "bdd02c15d128d3e7" + }, + "route:post /{id}/toggle-active": { + "abdruck": "9317d97fb76431ce", + "funktion": "Benutzer aktivieren", + "trug": "ef44f89122814a30" + } + }, + "belege": { + "[\"admin\", \"Dashboard anzeigen\"]": { + "abdruck": "88c7b9f422dc8eb8", + "beleg": "#[Route('/admin/dashboard', name: 'admin_dashboard', methods: ['GET'])]", + "datei": "src/Controller/Admin/DashboardController.php" + }, + "[\"admin\", \"Logout einleiten\"]": { + "abdruck": "22b7a2529dbafa62", + "beleg": "throw new \\LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');", + "datei": "src/Controller/Admin/SecurityController.php" + }, + "[\"admin\", \"Wiederherstellung testen\"]": { + "abdruck": "50b702083d4b3b49", + "beleg": "#[Route('/admin/enterprise/restore/dry-run/{backupId}', name: 'admin_enterprise_restore_dry_run', requirements: ['backupId' => 'retriex-backup-[0-9]{8}-[0-9]{6}(?:-[a-f0-9]{6})?'], methods: ['POST'])]", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"admin\", \"Zum Dashboard weiterleiten\"]": { + "abdruck": "868c59b96819addc", + "beleg": "return $this->redirectToRoute('admin_dashboard');", + "datei": "src/Controller/Admin/DashboardController.php" + }, + "[\"agenten\", \"Agentenaktivität anzeigen\"]": { + "abdruck": "2e27daae10412580", + "beleg": "$limit = max(1, min(200, (int) $request->query->get('limit', 50)));", + "datei": "src/Controller/Admin/SystemAgentController.php" + }, + "[\"agenten\", \"Chat-Auswahl-Guard testen\"]": { + "abdruck": "3f5ad7d5b139a81c", + "beleg": "return ($report['status'] ?? '') === 'OK' ? Command::SUCCESS : Command::FAILURE;", + "datei": "src/Command/KnowledgeSpaceChatSelectionGuardSelfTestCommand.php" + }, + "[\"agenten\", \"Fähigkeiten ermitteln\"]": { + "abdruck": "82e0eb0d75ca0c79", + "beleg": "/** @return array */\n public function discover(string $serverKey, ?int $resourceIndex = null, bool $includeResourceRead = false): array", + "datei": "src/Mcp/McpAdminSourceRegistryBridge.php" + }, + "[\"agenten\", \"Hybrid-Tool-Auswahl testen\"]": { + "abdruck": "05bb4dd7e9a30b1a", + "beleg": "$cases = [\n $this->case('planner_self_test_is_green', [($plannerReport['status'] ?? '') === 'OK'], $plannerReport),\n $this->case('agent_runner_uses_llm_only_as_planner_before_retriex_validation', [\n str_contains($agentRunner, 'buildLlmSelectionPrompt($prompt, $spaceId, $serverKey, $allowlistedTools)'),\n str_contains($agentRunner, 'parseLlmSelectionResponse($rawToolSelection)'),\n str_contains($agentRunner, 'planFromLlmSuggestion($prompt, $spaceId, $serverKey, $allowlistedTools, $toolSuggestion)'),\n str_contains($agentRunner, \"llmCallModel('mcp_tool_selection')\"),\n str_contains($agentRunner, 'deterministic_fallback_allowed'),\n ], ['agent_runner_contains_hybrid_selection' => true]),\n $this->case('loader_exposes_tool_selection_latency', [\n str_contains($agentRunner, 'Passendes Tool wird ausgewählt'),\n str_contains($chatMessages, 'loader_mcp_selecting_tool'),\n str_contains($chatJs, 'loader_mcp_selecting_tool'),\n ], ['loader_status' => 'selecting_tool']),\n $this->case('model_config_has_dedicated_optional_call_model', [\n str_contains($modelConfig, 'mcp_tool_selection:'),\n ], ['model_config' => 'mcp_tool_selection']),\n ];", + "datei": "src/Command/McpHybridToolSelectionPlannerSelfTestCommand.php" + }, + "[\"agenten\", \"MCP-Gateway trocken ausführen\"]": { + "abdruck": "ab8dcf1eaaeba5a5", + "beleg": "return $result['status'] === 'ready' ? Command::SUCCESS : Command::FAILURE;", + "datei": "src/Command/McpGatewayDryRunCommand.php" + }, + "[\"agenten\", \"MCP-Laufzeit-Gate prüfen\"]": { + "abdruck": "a610bdc0e1f1b6e2", + "beleg": "$result = (bool) $input->getOption('fixture')\n ? $this->gate->checkResourceForServers(\n $this->fixtureServers(),\n $request,\n (bool) $input->getOption('assume-enabled'),\n )->toArray()\n : $this->gate->checkResource($request)->toArray();", + "datei": "src/Command/McpRuntimeGateCheckCommand.php" + }, + "[\"agenten\", \"MCP-Laufzeitgrenze testen\"]": { + "abdruck": "a644cd0877293b21", + "beleg": "#[AsCommand(\n name: 'mto:agent:mcp:runtime-boundary-self-test',\n description: 'Validate that MCP stays admin-controlled and bounded for answer runtime'\n)]", + "datei": "src/Command/McpRuntimeBoundarySelfTestCommand.php" + }, + "[\"agenten\", \"MCP-Quelle prüfen\"]": { + "abdruck": "af9e24b774af1592", + "beleg": "#[AsCommand(\n name: 'mto:agent:mcp:admin-source-check',\n description: 'Check one stored Admin MCP source as a registry-compatible read-only test policy'\n)]", + "datei": "src/Command/McpAdminSourceCheckCommand.php" + }, + "[\"agenten\", \"Mit Agent chatten\"]": { + "abdruck": "e74a0245ad75018b", + "beleg": "foreach ($this->agentRunner->run($prompt, $userId) as $token) {\n $output->write($token);\n }", + "datei": "src/Command/AgentCliCommand.php" + }, + "[\"agenten\", \"Performance-Cache leeren\"]": { + "abdruck": "42a53bc0d0dd9e2f", + "beleg": "$result = $this->runtimeCacheClearService->clearAll(!((bool) $input->getOption('skip-vector-service')));", + "datei": "src/Command/RuntimeCacheClearCommand.php" + }, + "[\"agenten\", \"Produktlabel-Formatierer testen\"]": { + "abdruck": "e8e2412ddcf623eb", + "beleg": "private function containsRuntimeSideEffectMarker(string $source): bool\n {\n return false;\n }", + "datei": "src/Command/ProductLabelFormatterExtractionSelfTestCommand.php" + }, + "[\"agenten\", \"Release-Selbsttest bereitstellen\"]": { + "abdruck": "7f9423f2d5b36480", + "beleg": "private const REQUIRED_RELEASE_FILES = [", + "datei": "src/Command/RetriexV1108ReleaseLockSelfTestCommand.php" + }, + "[\"agenten\", \"Ressource abrufen\"]": { + "abdruck": "fe6f6babdb73587a", + "beleg": "$result = (bool) $input->getOption('fixture')\n ? $this->client->readForServers($this->fixtureServers(), $request, (bool) $input->getOption('assume-enabled'))\n : $this->client->read($request, (bool) $input->getOption('assume-enabled'));", + "datei": "src/Command/McpResourceReadCommand.php" + }, + "[\"agenten\", \"Ressource validieren\"]": { + "abdruck": "5fd85436d1302f70", + "beleg": "return $decision->allowed ? Command::SUCCESS : Command::FAILURE;", + "datei": "src/Command/McpResourceCheckCommand.php" + }, + "[\"agenten\", \"Rollencode-Zuweisung prüfen\"]": { + "abdruck": "3ccada3f8950af23", + "beleg": "private function buildReport(): array", + "datei": "src/Command/ProductRoleCodeAssignmentRegressionGuardSelfTestCommand.php" + }, + "[\"agenten\", \"Stabilitäts-Selbsttest bereitstellen\"]": { + "abdruck": "e100bf5436bb7888", + "beleg": "final class ShopFollowupAnchorStabilitySelfTestCommand extends Command", + "datei": "src/Command/ShopFollowupAnchorStabilitySelfTestCommand.php" + }, + "[\"agenten\", \"System rebuild bereitstellen\"]": { + "abdruck": "4a94da2e8f5631d7", + "beleg": "#[AsCommand(\n name: 'mto:agent:system:rebuild',\n description: 'Hard rebuild: global reindex (chunks+vector), rebuild tag index, then reload vector service'\n)]", + "datei": "src/Command/SystemRebuildCommand.php" + }, + "[\"agenten\", \"Vektordienst steuern\"]": { + "abdruck": "81ff7d5a3425664b", + "beleg": "private readonly int $timeoutSeconds = 300,", + "datei": "src/Command/VectorControlCommand.php" + }, + "[\"agenten\", \"Wissensbatch finalisieren testen\"]": { + "abdruck": "fc30904681203405", + "beleg": "protected function execute(InputInterface $input, OutputInterface $output): int", + "datei": "src/Command/KnowledgeBatchFinalizeSelfTestCommand.php" + }, + "[\"anleitungen\", \"Anleitung anzeigen\"]": { + "abdruck": "7638a294a35eaedb", + "beleg": "'html' => $renderer->render($content),", + "datei": "src/Controller/Admin/GuideController.php" + }, + "[\"anleitungen\", \"Anleitungsübersicht öffnen\"]": { + "abdruck": "2335ab051c43a64d", + "beleg": "usort($guides, fn ($a, $b) => strcasecmp($a['title'], $b['title']));", + "datei": "src/Controller/Admin/GuideController.php" + }, + "[\"auftraege\", \"Auftrag starten\"]": { + "abdruck": "b2dc7effa8028795", + "beleg": "#[Route('/ask-jobs', name: 'ask_job_start', methods: ['POST'])]", + "datei": "src/Controller/AskSseController.php" + }, + "[\"auftraege\", \"Auftragsereignisse abrufen\"]": { + "abdruck": "eccbb5871ebf164c", + "beleg": "return new JsonResponse([\n 'status' => (string) ($job['status'] ?? ''),\n 'message' => is_string($job['message'] ?? null) ? (string) $job['message'] : '',\n 'lastEventId' => max(0, (int) ($job['lastEventId'] ?? 0)),\n 'updatedAt' => max(0, (int) ($job['updatedAt'] ?? 0)),\n 'completedAt' => max(0, (int) ($job['completedAt'] ?? 0)),\n 'events' => $this->readJobOutputAfter($jobId, $afterEventId),\n ]);", + "datei": "src/Controller/AskSseController.php" + }, + "[\"auftraege\", \"Auftragsstatus anzeigen\"]": { + "abdruck": "96e47a6fc65c461f", + "beleg": "return $this->json([\n 'id' => (string) $job->getId(),\n 'type' => $job->getType(),\n 'status' => $job->getStatus(),\n 'startedAt' => $job->getStartedAt()->format(DATE_ATOM),\n 'finishedAt' => $job->getFinishedAt()?->format(DATE_ATOM),\n 'errorMessage' => $job->getErrorMessage(),\n 'logPath' => $job->getLogPath(),\n ]);", + "datei": "src/Controller/Admin/IngestJobController.php" + }, + "[\"auftraege\", \"Auftragsstatus prüfen\"]": { + "abdruck": "d8926247da5b90fa", + "beleg": "public function jobStatus(string $jobId): JsonResponse", + "datei": "src/Controller/AskSseController.php" + }, + "[\"auftraege\", \"Ingest-Job starten\"]": { + "abdruck": "e52af5fba6df161f", + "beleg": "protected function execute(InputInterface $input, OutputInterface $output): int", + "datei": "src/Command/IngestRunJobCommand.php" + }, + "[\"backup\", \"Backup herunterladen\"]": { + "abdruck": "8c2bbb210875e413", + "beleg": "#[Route('/admin/enterprise/backup/download/{backupId}', name: 'admin_enterprise_backup_download', requirements: ['backupId' => 'retriex-backup-[0-9]{8}-[0-9]{6}(?:-[a-f0-9]{6})?'], methods: ['GET'])]", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"backup\", \"Backup starten\"]": { + "abdruck": "863cdc2fa384bd3b", + "beleg": "$report = $rollingBackup->createBackup(false, null, false, $includeDatabaseDump);", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"backup\", \"Backup-Tauglichkeit prüfen\"]": { + "abdruck": "7f32db860c7e3cf4", + "beleg": "return ($report['status'] ?? '') === 'OK' ? Command::SUCCESS : Command::FAILURE;", + "datei": "src/Command/EnterpriseBackupRestoreReadinessCheckCommand.php" + }, + "[\"backup\", \"Backup-Trockenlauf prüfen\"]": { + "abdruck": "1a3a2e4963e023bc", + "beleg": "$report = $restoreDryRun->buildDryRunReport();\n $operatorCheckProtocol->recordCheck('restore_dry_run', 'Restore pruefen', $report, ['backup_id' => (string) ($report['backup_id'] ?? ''), 'dry_run' => true]);\n $this->addRestoreDryRunFlash($report);", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"backup\", \"Backup-Wiederherstellung prüfen\"]": { + "abdruck": "b06b798f0cdc03dc", + "beleg": "#[Route('/admin/enterprise/check/backup-restore', name: 'admin_enterprise_check_backup_restore', methods: ['POST'])]", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"benutzer\", \"Benutzer aktivieren\"]": { + "abdruck": "7bc70cb331b3a2ac", + "beleg": "#[Route('/{id}/toggle-active', name: 'admin_users_toggle_active', requirements: ['id' => '[0-9a-fA-F\\-]{36}'], methods: ['POST'])]", + "datei": "src/Controller/Admin/UserController.php" + }, + "[\"benutzer\", \"Benutzer anlegen\"]": { + "abdruck": "93125c82911d2de0", + "beleg": "if (strlen(trim($plainPassword)) < 8) {", + "datei": "src/Command/CreateUserCommand.php" + }, + "[\"benutzer\", \"Benutzer auflisten\"]": { + "abdruck": "d527fa14409a6978", + "beleg": "public function listUsers(string $query = '', string $status = 'all', string $role = 'all'): array", + "datei": "src/Service/Admin/UserAdminService.php" + }, + "[\"benutzer\", \"Benutzer bearbeiten\"]": { + "abdruck": "63f9b60fe54af1c2", + "beleg": "#[Route('/{id}/edit', name: 'admin_users_edit', requirements: ['id' => '[0-9a-fA-F\\-]{36}'], methods: ['GET', 'POST'])]\n public function edit(string $id, Request $request, UserAdminService $users): Response", + "datei": "src/Controller/Admin/UserController.php" + }, + "[\"berichte\", \"Akzeptanzbericht generieren\"]": { + "abdruck": "202ceb031a05333e", + "beleg": "$io->table(['Zeitpunkt', 'Pruefung', 'Status', 'Ergebnis'], array_map(", + "datei": "src/Command/EnterpriseOperatorAcceptanceReportCommand.php" + }, + "[\"berichte\", \"Bericht als JSON herunterladen\"]": { + "abdruck": "cca47a8c490854b4", + "beleg": "public function download(string $batchId, string $format, KnowledgeBatchReportReadService $reports): BinaryFileResponse", + "datei": "src/Controller/Admin/KnowledgeBatchReportController.php" + }, + "[\"berichte\", \"Bericht löschen\"]": { + "abdruck": "94555049b4fa8aa5", + "beleg": "public function deleteReport(string $batchId, Request $request, KnowledgeBatchReportReadService $reports): Response", + "datei": "src/Controller/Admin/KnowledgeBatchReportController.php" + }, + "[\"berichte\", \"Übersicht rendern\"]": { + "abdruck": "17f97a67c55bc85f", + "beleg": "$overview = $this->operationsOverview->buildOverview($backupRestoreReport, $securityReport, $deploymentReport, $acceptanceReport, $backupOverview);", + "datei": "src/Command/EnterpriseOperationsOverviewCommand.php" + }, + "[\"chat\", \"Abmelden ermöglichen\"]": { + "abdruck": "8178f115f5e6d301", + "beleg": "#[Route('/chat/logout', name: 'chat_logout', methods: ['GET'])]", + "datei": "src/Controller/Chat/SecurityController.php" + }, + "[\"chat\", \"Chat streamen\"]": { + "abdruck": "8973369a0ffbb6c6", + "beleg": "return new StreamedResponse(\n function () use ($prompt, $clientId, $cookieResponse, $includeFullContext, $requestContextHint, $dataSourceMode, $finalAnswerModelMode, $temporaryUploadIds, $knowledgeSpaceEffectiveSpaceId): void {\n $this->streamAgentResponse(\n prompt: $prompt,\n clientId: $clientId,\n includeFullContext: $includeFullContext,\n cookieResponse: $cookieResponse,\n jobId: null,\n requestContextHint: $requestContextHint,\n dataSourceMode: $dataSourceMode,\n finalAnswerModelOverride: $this->finalAnswerModelOverride($finalAnswerModelMode),\n temporaryUploadIds: $temporaryUploadIds,\n knowledgeSpaceEffectiveSpaceId: $knowledgeSpaceEffectiveSpaceId\n );\n },\n Response::HTTP_OK,\n $this->streamHeaders()\n );", + "datei": "src/Controller/AskSseController.php" + }, + "[\"chat\", \"Chatseite anzeigen\"]": { + "abdruck": "32f2c858efb14e67", + "beleg": "return $this->render('chat/index.html.twig', [\n 'chat_prompt_user_name' => $this->resolvePromptUserName(),\n 'chat_knowledge_space_selector' => $knowledgeSpaceSelector->build(),\n 'chat_handbook_available' => $chatHandbookMarkdown !== null,\n 'chat_handbook_markdown' => $chatHandbookMarkdown ?? '',\n ]);", + "datei": "src/Controller/Chat/ChatController.php" + }, + "[\"diagnose\", \"Abdeckung prüfen\"]": { + "abdruck": "48d3b0d8a7011a70", + "beleg": "usort($rows, function (array $a, array $b): int {", + "datei": "src/Command/IngestFactsCoverageCommand.php" + }, + "[\"diagnose\", \"Abrufgrenzen prüfen\"]": { + "abdruck": "a37984380c253a68", + "beleg": "final class AgentRetrievalBoundaryPlanSelfTestCommand extends Command", + "datei": "src/Command/AgentRetrievalBoundaryPlanSelfTestCommand.php" + }, + "[\"diagnose\", \"Bereitschaftsbericht ausgeben\"]": { + "abdruck": "a09f986af89eaacd", + "beleg": "return ($report['status'] ?? '') === 'OK' ? Command::SUCCESS : Command::FAILURE;", + "datei": "src/Command/EnterpriseDeploymentSchedulerReadinessCheckCommand.php" + }, + "[\"diagnose\", \"Datenqualität prüfen\"]": { + "abdruck": "ca2c74c205e880ff", + "beleg": "#[AsCommand(\n name: 'mto:agent:ingest:chunk-quality',\n description: 'Compare original and derived Markdown ingest chunk quality in dry-run diagnostics'\n)]", + "datei": "src/Command/IngestChunkQualityCommand.php" + }, + "[\"diagnose\", \"Diagnose anzeigen\"]": { + "abdruck": "a44b68c6167f4548", + "beleg": "#[Route('/admin/mcp', name: 'admin_mcp_diagnostics', methods: ['GET', 'POST'])]", + "datei": "src/Controller/Admin/McpDiagnosticsController.php" + }, + "[\"diagnose\", \"Genre-Hotspots prüfen\"]": { + "abdruck": "83a0e5f5a3d81804", + "beleg": "public function audit(?callable $progress = null): array", + "datei": "src/Genre/CoreNeutralityAuditProvider.php" + }, + "[\"diagnose\", \"Guard-Mechanismus prüfen\"]": { + "abdruck": "428aec0b4471fc87", + "beleg": "private function buildReport(): array", + "datei": "src/Command/UnsupportedToolTermGuardSelfTestCommand.php" + }, + "[\"diagnose\", \"Hygieneregeln prüfen\"]": { + "abdruck": "d0a1488af78eb9a4", + "beleg": "private function buildReport(): array", + "datei": "src/Command/KnowledgeBatchHygieneSelfTestCommand.php" + }, + "[\"diagnose\", \"Indizierungszustand prüfen\"]": { + "abdruck": "5c404523842d6af0", + "beleg": "final class IngestDeferredReindexStateSelfTestCommand extends Command", + "datei": "src/Command/IngestDeferredReindexStateSelfTestCommand.php" + }, + "[\"diagnose\", \"Konfiguration prüfen\"]": { + "abdruck": "0258b188bf0a71d8", + "beleg": "#[AsCommand(\n name: 'mto:agent:config:validate',\n description: 'Validate the effective RetrieX configuration'\n)]", + "datei": "src/Command/ConfigValidateCommand.php" + }, + "[\"diagnose\", \"Provenienz prüfen\"]": { + "abdruck": "3ef13c4717f68df6", + "beleg": "$cases[] = $this->case(\n 'chunk_records_receive_provenance_metadata',\n str_contains($ingestService, 'source_file_extension')\n && str_contains($ingestService, 'source_version_id')\n && str_contains($ingestService, 'derived_from_version_id')\n && str_contains($ingestService, 'derived_format')\n && str_contains($ingestService, 'normalization_prompt_version')\n && str_contains($ingestService, 'normalization_model')\n && str_contains($ingestService, 'normalization_status'),\n 'NDJSON metadata includes source and derived Markdown provenance keys'\n );", + "datei": "src/Command/IngestMarkdownDerivedChunkDiagnosticsSelfTestCommand.php" + }, + "[\"diagnose\", \"Retrieval-Pipeline testen\"]": { + "abdruck": "a2bda82b3cf0c287", + "beleg": "final class TestHybridRetrievalCommand extends Command", + "datei": "src/Command/TestHybridRetrievalCommand.php" + }, + "[\"diagnose\", \"Segmentierung prüfen\"]": { + "abdruck": "2ddb19d3004bb42b", + "beleg": "$service = $this->read($root . '/src/Ingest/MarkdownNormalization/DocumentMarkdownNormalizationService.php');", + "datei": "src/Command/IngestSegmentedMarkdownNormalizationExecutionSelfTestCommand.php" + }, + "[\"diagnose\", \"Shop-Suche testen\"]": { + "abdruck": "ed98c9737930f464", + "beleg": "'zeige mir produkte unter 5000 euro'", + "datei": "src/Command/TestShopSearchCommand.php" + }, + "[\"diagnose\", \"Sicherheitsstatus prüfen\"]": { + "abdruck": "003f893fb9cea617", + "beleg": "return ($report['status'] ?? '') === 'OK' ? Command::SUCCESS : Command::FAILURE;", + "datei": "src/Command/EnterpriseSecurityDataProtectionReadinessCheckCommand.php" + }, + "[\"diagnose\", \"Stapel-Upload verifizieren\"]": { + "abdruck": "fff1582bd8e5bf3f", + "beleg": "final class KnowledgeBatchAdminUploadSelfTestCommand extends Command", + "datei": "src/Command/KnowledgeBatchAdminUploadSelfTestCommand.php" + }, + "[\"diagnose\", \"Systemzustand prüfen\"]": { + "abdruck": "7045932ec8f4d9ce", + "beleg": "return str_starts_with($result['status'], 'OK')\n ? Command::SUCCESS\n : Command::FAILURE;", + "datei": "src/Command/VectorHealthCheckCommand.php" + }, + "[\"diagnose\", \"Tag-Index-Gesundheit prüfen\"]": { + "abdruck": "79248caf983173f9", + "beleg": "private function isHealthy(string $status): bool\n {\n return in_array($status, ['OK', 'OK_EMPTY'], true);\n }", + "datei": "src/Command/TagHealthCheckCommand.php" + }, + "[\"diagnose\", \"Tags neu indizieren\"]": { + "abdruck": "411663e63cc97ed3", + "beleg": "while (!connection_aborted()) {", + "datei": "src/Controller/Admin/TagRebuildStreamController.php" + }, + "[\"diagnose\", \"Verankerung testen\"]": { + "abdruck": "73de227779d46c5f", + "beleg": "if ((bool) $input->getOption('sample')) {\n [$prompt, $history] = $this->samplePromptAndHistory();\n } elseif ($historyFile !== '') {", + "datei": "src/Command/TestFollowUpAnchorResolverDryRunCommand.php" + }, + "[\"diagnose\", \"Vergleichsgrenzen validieren\"]": { + "abdruck": "669f27f21e0c7cbc", + "beleg": "private function buildReport(): array\n {\n $root = rtrim($this->kernel->getProjectDir(), '/\\\\');\n $service = $this->read($root . '/src/Service/Admin/DocumentChunkQualityComparisonService.php');\n $command = $this->read($root . '/src/Command/IngestChunkQualityCommand.php');\n $controller = $this->read($root . '/src/Controller/Admin/DocumentController.php');\n $template = $this->read($root . '/templates/admin/document/show.html.twig');\n $styles = $this->read($root . '/public/assets/styles/base.css');\n $segmentationPlanService = $this->read($root . '/src/Ingest/MarkdownNormalization/DocumentMarkdownSegmentationPlanService.php');\n $agentRunner = $this->read($root . '/src/Agent/AgentRunner.php');\n $ingestService = $this->read($root . '/src/Knowledge/Ingest/KnowledgeIngestService.php');", + "datei": "src/Command/IngestChunkQualityComparisonSelfTestCommand.php" + }, + "[\"dokumente\", \"Abschnitte laden\"]": { + "abdruck": "6be09cd85989675b", + "beleg": "$version->setIngestStatus(DocumentVersion::INGEST_PENDING);", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"dokumente\", \"Abschnittsqualität laden\"]": { + "abdruck": "ff648f1bf4dd8875", + "beleg": "public function versionChunkQuality(", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"dokumente\", \"Dokument entfernen\"]": { + "abdruck": "b30e86c7c0afc914", + "beleg": "public function deleteDocument(", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"dokumente\", \"Dokument erstellen\"]": { + "abdruck": "216bdc467154f33a", + "beleg": "#[Route('/new', name: 'admin_document_new', methods: ['GET', 'POST'])]", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"dokumente\", \"Dokumente auflisten\"]": { + "abdruck": "d0fc65218aa9ccd3", + "beleg": "#[Route('', name: 'admin_documents', methods: ['GET'])]", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"dokumente\", \"Markdown bereinigen\"]": { + "abdruck": "9e0e8ea0de452f7f", + "beleg": "$newVersion = $documentService->addVersion($document, $result['file_path'], $this->requireUser());", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"evaluation\", \"Berichte bereinigen\"]": { + "abdruck": "ab28043e52bdafa3", + "beleg": "public function cleanupReportHistory(string $scope, string $mode = 'trim'): array", + "datei": "src/Service/Admin/EvalAdminService.php" + }, + "[\"evaluation\", \"Eval-Berichte anzeigen\"]": { + "abdruck": "7c5a683645081b79", + "beleg": "#[Route('/', name: 'admin_evals_index', methods: ['GET'])]", + "datei": "src/Controller/Admin/AdminEvalController.php" + }, + "[\"evaluation\", \"Eval-Fälle ausführen\"]": { + "abdruck": "130685562e3eff09", + "beleg": "return $failed > 0 ? Command::FAILURE : Command::SUCCESS;", + "datei": "src/Command/AgentEvalRunCommand.php" + }, + "[\"evaluation\", \"Eval-Fälle parallelisieren\"]": { + "abdruck": "2d6d1b790ca8f991", + "beleg": "while (!$stopScheduling && $nextIndex < $caseCount && count($running) < $jobs) {", + "datei": "src/Command/AgentEvalParallelCommand.php" + }, + "[\"evaluation\", \"Evaluation ausführen\"]": { + "abdruck": "5b2305d1f3727b25", + "beleg": "#[Route('/run', name: 'admin_evals_run', methods: ['POST'])]", + "datei": "src/Controller/Admin/AdminEvalController.php" + }, + "[\"faelle\", \"Assistent anzeigen\"]": { + "abdruck": "d34e5813e73074d3", + "beleg": "public function caseWizard(Request $request, EvalAdminService $evals): Response", + "datei": "src/Controller/Admin/AdminEvalController.php" + }, + "[\"faelle\", \"Fall anlegen\"]": { + "abdruck": "c29d7fd91f3232df", + "beleg": "#[Route('/cases/new', name: 'admin_evals_case_new', methods: ['GET'])]", + "datei": "src/Controller/Admin/AdminEvalController.php" + }, + "[\"faelle\", \"Fall erstellen\"]": { + "abdruck": "52edb0d34124f34b", + "beleg": "#[Route('/cases', name: 'admin_evals_case_create', methods: ['POST'])]", + "datei": "src/Controller/Admin/AdminEvalController.php" + }, + "[\"faelle\", \"Fälle löschen bereitstellen\"]": { + "abdruck": "d3a7338ca875abcd", + "beleg": "#[Route('/cases/delete', name: 'admin_evals_case_delete', methods: ['POST'])]\n public function deleteCase(Request $request, EvalAdminService $evals): Response\n {\n $this->denyAccessUnlessGranted(ApplicationRoles::ROLE_KNOWLEDGE_ADMIN);", + "datei": "src/Controller/Admin/AdminEvalController.php" + }, + "[\"feedback\", \"Chat-Feedback anzeigen\"]": { + "abdruck": "380650cd110c8613", + "beleg": "#[Route('/admin/chat-feedback', name: 'admin_chat_feedback_index', methods: ['GET'])]", + "datei": "src/Controller/Admin/AdminChatFeedbackController.php" + }, + "[\"feedback\", \"Feedback exportieren\"]": { + "abdruck": "f4168bfa7d6e819a", + "beleg": "#[Route('/admin/chat-feedback/export', name: 'admin_chat_feedback_export', methods: ['GET'])]\n public function export(Request $request, ChatAnswerFeedbackRepository $repository): StreamedResponse\n {\n $this->denyAccessUnlessGranted(ApplicationRoles::ROLE_KNOWLEDGE_ADMIN);", + "datei": "src/Controller/Admin/AdminChatFeedbackController.php" + }, + "[\"feedback\", \"Feedback klassifizieren\"]": { + "abdruck": "722b8e9be1eda83d", + "beleg": "if ($processed % 100 === 0) {", + "datei": "src/Command/ChatFeedbackClassifyCommand.php" + }, + "[\"feedback\", \"Feedback löschen\"]": { + "abdruck": "774f9c113b07b54c", + "beleg": "public function delete(string $id, Request $request, ChatAnswerFeedbackRepository $repository, EntityManagerInterface $entityManager): Response", + "datei": "src/Controller/Admin/AdminChatFeedbackController.php" + }, + "[\"feedback\", \"Feedback-Details anzeigen\"]": { + "abdruck": "5ccfb944dd8353de", + "beleg": "#[Route('/admin/chat-feedback/{id}', name: 'admin_chat_feedback_show', requirements: ['id' => '[0-9a-fA-F-]{36}'], methods: ['GET'])]", + "datei": "src/Controller/Admin/AdminChatFeedbackController.php" + }, + "[\"feedback\", \"Feedback-Status aktualisieren\"]": { + "abdruck": "107aa5d09bbfd64c", + "beleg": "$status = trim((string) $request->request->get('status', ChatAnswerFeedback::REVIEW_STATUS_DONE));\n if ($status === ChatAnswerFeedback::REVIEW_STATUS_DONE) {\n $feedback->markReviewDone(trim((string) $request->request->get('reviewNote', '')) ?: null);\n $this->addFlash('success', 'Feedback wurde als erledigt markiert.');\n } else {\n $feedback->reopenReview();\n $this->addFlash('success', 'Feedback wurde wieder geöffnet.');\n }", + "datei": "src/Controller/Admin/AdminChatFeedbackController.php" + }, + "[\"feedback\", \"Feedback-Status prüfen\"]": { + "abdruck": "e08595a775786488", + "beleg": "$response = new JsonResponse([\n 'status' => 'ok',\n 'stored' => $feedback !== null,\n 'feedbackId' => $feedback !== null ? (string) $feedback->getId() : null,\n 'rating' => $feedback !== null ? $feedback->getRating() : null,\n ]);", + "datei": "src/Controller/ChatFeedbackController.php" + }, + "[\"knowledge-raeume\", \"Batch-Import durchführen\"]": { + "abdruck": "ed8e53ee87a33ecd", + "beleg": "final class KnowledgeBatchImportCommand extends Command", + "datei": "src/Command/KnowledgeBatchImportCommand.php" + }, + "[\"knowledge-raeume\", \"Chat-Freigabe umschalten\"]": { + "abdruck": "b0459d69691cd838", + "beleg": "#[Route('/admin/knowledge-spaces/provider-resource-chat', name: 'admin_knowledge_spaces_provider_resource_chat_update', methods: ['POST'])]", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"knowledge-raeume\", \"Chat-Verfügbarkeit prüfen\"]": { + "abdruck": "07ac7926675dc356", + "beleg": "#[Route('/admin/knowledge-spaces/chat-availability', name: 'admin_knowledge_spaces_chat_availability_update', methods: ['POST'])]", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"knowledge-raeume\", \"Facts prüfen\"]": { + "abdruck": "0150181090352e46", + "beleg": "$io->warning('No chunks with diagnostic ingest facts matched the current filter. Run a global reindex after extractor changes so index.ndjson contains the current fact schema.');", + "datei": "src/Command/IngestFactsInspectCommand.php" + }, + "[\"knowledge-raeume\", \"Kandidaten wählen\"]": { + "abdruck": "f3cfe523ec5c3401", + "beleg": "#[Route('/admin/knowledge-spaces/provider-candidate-select', name: 'admin_knowledge_spaces_provider_candidate_select', methods: ['POST'])]", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"knowledge-raeume\", \"Knowledge-Räume anzeigen\"]": { + "abdruck": "651989a1820b87cf", + "beleg": "#[Route('/admin/knowledge-spaces', name: 'admin_knowledge_spaces_overview', methods: ['GET'])]\n public function index(McpKnowledgeSpaceReadModel $readModel, KnowledgeSpaceAdminOverviewReadModel $adminOverviewReadModel, KnowledgeSpaceAvailabilityReadModel $availabilityReadModel, KnowledgeSpaceChatSelectorReadModel $chatSelectorReadModel, KnowledgeSpaceProviderResourceCandidateReadModel $providerResourceCandidateReadModel): Response\n {\n return $this->render('admin/knowledge_spaces/index.html.twig', [\n 'knowledgeSpaceReadModel' => $readModel->build(),\n 'knowledgeSpaceAdminOverview' => $adminOverviewReadModel->build(),\n 'knowledgeSpaceAvailability' => $availabilityReadModel->build(),\n 'chatKnowledgeSpaceSelector' => $chatSelectorReadModel->build(),\n 'knowledgeSpaceProviderResourceCandidates' => $providerResourceCandidateReadModel->build(),\n ]);\n }", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"knowledge-raeume\", \"Live-Vorschau laden\"]": { + "abdruck": "581e01a64ada02e6", + "beleg": "#[Route('/admin/knowledge-spaces/provider-resource-live-preview', name: 'admin_knowledge_spaces_provider_resource_live_preview', methods: ['POST'])]", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"knowledge-raeume\", \"Ressourcenprüfung durchführen\"]": { + "abdruck": "1d6a2b8d376cce22", + "beleg": "public function check(string $serverKey, string $resourceUri, string $mimeType = ''): McpResourcePolicyDecision", + "datei": "src/Mcp/McpResourcePolicyChecker.php" + }, + "[\"knowledge-raeume\", \"Textteile suchen\"]": { + "abdruck": "cb366acdc584d3cd", + "beleg": "@app.post(\"/search-chunks\")\ndef search_chunks(req: SearchRequest) -> List[Dict[str, Any]]:", + "datei": "python/vector/vector_service.py" + }, + "[\"knowledge-raeume\", \"Wissensräume prüfen\"]": { + "abdruck": "f329f8b7d149443c", + "beleg": "#[Route('/admin/knowledge-spaces/diagnostics/run', name: 'admin_knowledge_spaces_diagnostics_run', methods: ['POST'])]\n public function runDiagnostics(", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"konfiguration\", \"Ingest-Profil anlegen\"]": { + "abdruck": "88d9ebf11cc65de1", + "beleg": "#[Route('/create', name: 'admin_ingest_profile_create', methods: ['GET', 'POST'])]", + "datei": "src/Controller/Admin/IngestProfileController.php" + }, + "[\"konfiguration\", \"Ingest-Profile anzeigen\"]": { + "abdruck": "3bcd4f2eecf9e04d", + "beleg": "{% if p.active %}\n Aktiv\n {% else %}\n \n Inaktiv\n \n {% endif %}", + "datei": "templates/admin/ingest_profile/list.html.twig" + }, + "[\"konfiguration\", \"Konfiguration aktivieren\"]": { + "abdruck": "3cdcaacb5c30935e", + "beleg": "#[Route('/{id}/activate', name: 'admin_model_config_activate', methods: ['POST'])]", + "datei": "src/Controller/Admin/ModelGenerationConfigController.php" + }, + "[\"konfiguration\", \"Konfiguration anzeigen\"]": { + "abdruck": "be665b176d285ec7", + "beleg": "$json = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);", + "datei": "src/Command/ConfigDumpEffectiveCommand.php" + }, + "[\"konfiguration\", \"Konfiguration bereitstellen\"]": { + "abdruck": "d726bc00b770d39d", + "beleg": "#[Route('/chat-messages/frontend', name: 'chat_messages_frontend', methods: ['GET'])]", + "datei": "src/Controller/ChatMessagesController.php" + }, + "[\"konfiguration\", \"Konfigurationen anzeigen\"]": { + "abdruck": "4d0677e36928af2f", + "beleg": "#[Route('/', name: 'admin_model_config_list')]\n public function list(ModelGenerationConfigAdminService $svc): Response\n {\n $this->denyAccessUnlessGranted(ApplicationRoles::ROLE_KNOWLEDGE_ADMIN);", + "datei": "src/Controller/Admin/ModelGenerationConfigController.php" + }, + "[\"konfiguration\", \"Konfigurationsmuster prüfen\"]": { + "abdruck": "0e0bc4972945d622", + "beleg": "$calls = $this->matchingCalls((string) $line, $suspiciousCalls);", + "datei": "src/Config/CorePatternAuditProvider.php" + }, + "[\"konfiguration\", \"Tool-Freigaben aktualisieren\"]": { + "abdruck": "564123f595ea652e", + "beleg": "#[Route('/admin/knowledge-spaces/provider-tool-allowlist', name: 'admin_knowledge_spaces_provider_tool_allowlist_update', methods: ['POST'])]\n public function updateProviderToolAllowlist(Request $request, McpAdminSourceStore $sourceStore): RedirectResponse", + "datei": "src/Controller/Admin/KnowledgeSpaceOverviewController.php" + }, + "[\"logs\", \"Logdatei anzeigen\"]": { + "abdruck": "e5823ed4e9f28bf2", + "beleg": "$content = $this->readLastLines($path, 1000);", + "datei": "src/Controller/Admin/AdminSystemLogController.php" + }, + "[\"logs\", \"Logdateien auflisten\"]": { + "abdruck": "65b9c55ff9cc0246", + "beleg": "foreach (\\glob($this->logDir . '/system*.log') ?: [] as $file) {", + "datei": "src/Controller/Admin/AdminSystemLogController.php" + }, + "[\"sonstiges\", \"post activate {id} bereitstellen\"]": { + "abdruck": "77751e07c0ac66e6", + "beleg": "if (!$this->isCsrfTokenValid('activate_ingest_profile_' . $profile->getId(), (string) $request->request->get('_token'))) {", + "datei": "src/Controller/Admin/IngestProfileController.php" + }, + "[\"sonstiges\", \"post admin enterprise check security bereitstellen\"]": { + "abdruck": "6fde0d762ab1f63a", + "beleg": "#[Route('/admin/enterprise/check/security', name: 'admin_enterprise_check_security', methods: ['POST'])]", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"sonstiges\", \"post {id} tags save bereitstellen\"]": { + "abdruck": "4b25cdb131288705", + "beleg": "#[Route('/{id}/tags/save', name: 'admin_document_tags_save', methods: ['POST'])]", + "datei": "src/Controller/Admin/DocumentTagController.php" + }, + "[\"system\", \"Access-Denied-Fehler bereitstellen\"]": { + "abdruck": "82cd2269b409655e", + "beleg": "if ($targetHomeRoute === 'admin_dashboard' && $this->security->isGranted(ApplicationRoles::ROLE_ADMIN_AREA)) {", + "datei": "src/Security/AccessDeniedPageRenderer.php" + }, + "[\"system\", \"Betriebsbereitschaft prüfen\"]": { + "abdruck": "447f0da9c71ca14d", + "beleg": "$report = $this->buildReport();", + "datei": "src/Command/EnterpriseOperationsReadinessCheckCommand.php" + }, + "[\"system\", \"Cache leeren\"]": { + "abdruck": "5fa28d5145b77c72", + "beleg": "if (!$this->isCsrfTokenValid('runtime_cache_clear', (string) $request->request->get('_token'))) {", + "datei": "src/Controller/Admin/DashboardController.php" + }, + "[\"system\", \"Daten neu laden\"]": { + "abdruck": "37040fd380c7eb93", + "beleg": "@app.post(\"/reload\")\ndef reload() -> Dict[str, str]:\n try:\n load_all()\n return {\"status\": \"reloaded\", \"stamp\": SERVICE_STAMP}\n except Exception as exc:\n logger.exception(\"reload failed\")\n raise HTTPException(status_code=500, detail=str(exc))", + "datei": "python/vector/vector_service.py" + }, + "[\"system\", \"Daten sichern\"]": { + "abdruck": "7ccd1004eac1418a", + "beleg": "protected function execute(InputInterface $input, OutputInterface $output): int", + "datei": "src/Command/EnterpriseRollingBackupCommand.php" + }, + "[\"system\", \"Deployment prüfen\"]": { + "abdruck": "2e5833bfbb397dfc", + "beleg": "if (!$this->isCsrfTokenValid('enterprise_check_deployment_scheduler', (string) $request->request->get('_token', ''))) {", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"system\", \"Dienststatus melden\"]": { + "abdruck": "f03c81a271cb0eb9", + "beleg": "@app.get(\"/health\")", + "datei": "python/vector/vector_service.py" + }, + "[\"system\", \"Flow-Grenze sperren\"]": { + "abdruck": "4e90cc73b0837ac4", + "beleg": "private function buildReport(): array\n {\n $root = rtrim($this->kernel->getProjectDir(), '/\\\\');\n $boundaries = AgentRunFlowBoundaryContract::boundaries();\n $actualSections = array_keys($boundaries);\n $missingFiles = $this->missingFiles($root, self::REQUIRED_FILES);\n $flowFiles = glob($root . '/src/Agent/Run/*Flow.php') ?: [];\n $flowSources = $this->combinedReadableSource($flowFiles);\n $agentRunner = $this->read($root . '/src/Agent/AgentRunner.php');\n $sourceLeakTrace = $this->buildSensitiveTraceLeakReport();\n $missingOwnerTokens = $this->missingTokens($agentRunner, self::AGENTRUNNER_CRITICAL_OWNER_TOKENS);\n $forbiddenFlowTokens = $this->presentTokens($flowSources, self::FORBIDDEN_FLOW_TOKENS);\n $badBoundaryContracts = $this->badBoundaryContracts($boundaries);\n $badSectionFlows = $this->badSectionFlows($boundaries);\n $debugTraceBuilderFindings = $this->debugTraceBuilderFindings($agentRunner, $this->read($root . '/src/Agent/Run/AgentRunDebugTracePayloadBuilder.php'));\n $capabilityBoundaryFindings = $this->capabilityBoundaryFindings(\n $this->read($root . '/src/Agent/Run/CapabilityContextFlow.php'),\n $this->read($root . '/src/Agent/Run/CapabilityContextResult.php')\n );\n $followUpActionBuilderFindings = $this->followUpActionBuilderFindings(\n $agentRunner,\n $this->read($root . '/src/Agent/Support/FollowUpActionBuilder.php')\n );\n $evidenceDiagnosticMetaBuilderFindings = $this->evidenceDiagnosticMetaBuilderFindings(\n $agentRunner,\n $this->read($root . '/src/Agent/Support/EvidenceDiagnosticMetaMessageBuilder.php')\n );\n $claimEvidencePresentationBuilderFindings = $this->claimEvidencePresentationBuilderFindings(\n $agentRunner,\n $this->read($root . '/src/Agent/Support/ClaimEvidencePresentationMessageBuilder.php')\n );", + "datei": "src/Command/AgentRunFlowBoundaryLockSelfTestCommand.php" + }, + "[\"system\", \"Neuindizierung starten\"]": { + "abdruck": "b4519b8d45b5d080", + "beleg": "#[Route('/global-reindex', name: 'admin_global_reindex', methods: ['POST'])]", + "datei": "src/Controller/Admin/IngestJobController.php" + }, + "[\"system\", \"Normalisierung prüfen\"]": { + "abdruck": "36bcb0a013c43f30", + "beleg": "/** @var list */\n private const REQUIRED_FILES = [\n 'src/Ingest/MarkdownNormalization/DocumentMarkdownNormalizationService.php',\n 'src/Ingest/MarkdownNormalization/DocumentMarkdownNormalizationPromptBuilder.php',\n 'src/Ingest/MarkdownNormalization/DocumentMarkdownNormalizationValidator.php',\n 'src/Ingest/MarkdownNormalization/DocumentMarkdownSourceTextCleaner.php',\n 'src/Ingest/MarkdownNormalization/DocumentDerivedMarkdownVersionWriter.php',\n 'src/Ingest/MarkdownNormalization/DocumentMarkdownSegmentationPlanService.php',\n 'src/Command/IngestMarkdownNormalizationFoundationSelfTestCommand.php',\n 'docs/retriex/ingest-markdown-normalization-foundation.md',\n 'README.md',\n 'PATCH_MANIFEST.md',\n 'GENRE_NEUTRAL_CORE_PATCHLINE.md',\n ];", + "datei": "src/Command/IngestMarkdownNormalizationFoundationSelfTestCommand.php" + }, + "[\"system\", \"Preview prüfen\"]": { + "abdruck": "175111522fc5db0e", + "beleg": "#[AsCommand(\n name: 'mto:agent:ingest:markdown-normalization-preview-self-test',\n description: 'Validate the admin Markdown normalization preview wiring without LLM, DB, ingest or answer side effects'\n)]", + "datei": "src/Command/IngestMarkdownNormalizationPreviewSelfTestCommand.php" + }, + "[\"system\", \"Promptversion aktivieren\"]": { + "abdruck": "2bd24ab6b032d071", + "beleg": "$svc->activate($prompt);", + "datei": "src/Controller/Admin/SystemPromptController.php" + }, + "[\"system\", \"Promptversion löschen\"]": { + "abdruck": "5dd7729167e2c812", + "beleg": "#[Route('/admin/system/prompt/{id}/delete', name: 'admin_system_prompt_delete', methods: ['POST'])]", + "datei": "src/Controller/Admin/SystemPromptController.php" + }, + "[\"system\", \"Promptversionen verwalten\"]": { + "abdruck": "35608f50dcb84951", + "beleg": "'all' => $this->repo->findBy([], ['version' => 'DESC']),", + "datei": "src/Service/Admin/SystemPromptAdminService.php" + }, + "[\"system\", \"Restore-Vorschau prüfen\"]": { + "abdruck": "1e0c758c14cafbd5", + "beleg": "private function addRestoreDryRunFlash(array $report): void", + "datei": "src/Controller/Admin/EnterpriseOperationsController.php" + }, + "[\"system\", \"Simulation ausführen\"]": { + "abdruck": "c50566f7d0f432ba", + "beleg": "if ($payloadJson !== '' && $payloadFile !== '') {\n throw new \\InvalidArgumentException('Use either --payload-json or --payload-file, not both.');\n }", + "datei": "src/Command/McpEvidenceDryRunCommand.php" + }, + "[\"system\", \"Systemzustand zurücksetzen\"]": { + "abdruck": "ec8e8511801fc5ca", + "beleg": "#[Route('/reset', name: 'admin_document_reset', methods: ['POST'])]", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"system\", \"Verzeichnis bereinigen\"]": { + "abdruck": "cacd399eaef94143", + "beleg": "#[Route('/cleanup', name: 'admin_knowledge_batch_cleanup', methods: ['POST'])]", + "datei": "src/Controller/Admin/KnowledgeBatchReportController.php" + }, + "[\"tags\", \"Tag-Rebuild-Auftrag ausführen\"]": { + "abdruck": "08bdc2dfadebb29a", + "beleg": "$job->markCompleted();", + "datei": "src/Command/TagRebuildRunJobCommand.php" + }, + "[\"tags\", \"Tags auflisten\"]": { + "abdruck": "f35e569340543788", + "beleg": "#[Route('', name: 'admin_tags_index', methods: ['GET'])]", + "datei": "src/Controller/Admin/TagController.php" + }, + "[\"tags\", \"Tags bearbeiten\"]": { + "abdruck": "a75df6fbceed8e9d", + "beleg": "#[Route('/{id}/tags', name: 'admin_document_tags_edit', methods: ['GET'])]", + "datei": "src/Controller/Admin/DocumentTagController.php" + }, + "[\"tags\", \"Tags suchen\"]": { + "abdruck": "d507a2144565b9a9", + "beleg": "@app.post(\"/search-tags\")\ndef search_tags(req: SearchRequest) -> List[Dict[str, Any]]:", + "datei": "python/vector/vector_service.py" + }, + "[\"titel\", \"Titel aktualisieren\"]": { + "abdruck": "f4226daad62eb2a6", + "beleg": "$document->updateTitle($title, Document::TITLE_SOURCE_MANUAL, false);", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"titel\", \"Titelvorschläge laden\"]": { + "abdruck": "09506400afa4f506", + "beleg": "$result = $titleSuggestionService->suggest($document);", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"uploads\", \"Berechtigungsmodus ändern\"]": { + "abdruck": "ec7ba210bc22e0ee", + "beleg": "#[Route('/chat-uploads/{uploadId}/authority-mode', name: 'chat_upload_authority_mode', requirements: ['uploadId' => '[a-f0-9]{32}'], methods: ['PATCH', 'POST'])]\n public function setAuthorityMode(Request $request, string $uploadId): JsonResponse", + "datei": "src/Controller/ChatUploadController.php" + }, + "[\"uploads\", \"Datei hochladen\"]": { + "abdruck": "abda7a007e492357", + "beleg": "$status = $this->isSizeError($e->getMessage())\n ? Response::HTTP_REQUEST_ENTITY_TOO_LARGE\n : Response::HTTP_BAD_REQUEST;", + "datei": "src/Controller/ChatUploadController.php" + }, + "[\"uploads\", \"Upload entfernen\"]": { + "abdruck": "c12063ad4ea6504a", + "beleg": "public function delete(Request $request, string $uploadId): JsonResponse", + "datei": "src/Controller/ChatUploadController.php" + }, + "[\"uploads\", \"Uploads auflisten\"]": { + "abdruck": "f715c27aaa2efe0b", + "beleg": "#[Route('/chat-uploads', name: 'chat_upload_list', methods: ['GET'])]", + "datei": "src/Controller/ChatUploadController.php" + }, + "[\"verlauf\", \"Verankerungen extrahieren\"]": { + "abdruck": "07982f2a65cfc9a3", + "beleg": "$anchors = $this->extractor->extractRecentAnchors($history, $maxTurns);", + "datei": "src/Command/TestStructuredHistoryAnchorsCommand.php" + }, + "[\"verlauf\", \"Verlauf abrufen\"]": { + "abdruck": "5245760a2672d725", + "beleg": "#[Route('/history', name: 'chat_history', methods: ['GET'])]", + "datei": "src/Controller/HistoryController.php" + }, + "[\"verlauf\", \"Verlauf löschen\"]": { + "abdruck": "a1e4bd366e494634", + "beleg": "$this->contextService->deleteHistory($clientId);", + "datei": "src/Controller/HistoryController.php" + }, + "[\"versionen\", \"Version ableiten\"]": { + "abdruck": "9d7b531eafa6b4db", + "beleg": "public function deriveVersion(\n string $versionId,\n Request $request,\n EntityManagerInterface $em,\n DocumentService $documentService,\n ParameterBagInterface $params,\n FormatText $formatText,\n DocumentVersionPreviewService $previewService,\n ): Response {", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"versionen\", \"Version einlesen\"]": { + "abdruck": "e104d93b6d3ca473", + "beleg": "#[Route(\n '/version/{versionId}/preview',\n name: 'admin_document_version_preview',\n requirements: ['versionId' => '[0-9a-fA-F\\-]{36}'],\n methods: ['GET']\n )]\n public function previewVersion(", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"versionen\", \"Version erstellen\"]": { + "abdruck": "e91ce1c1c6094cf1", + "beleg": "$documentService->addVersion($document, $filePath, $user);", + "datei": "src/Controller/Admin/DocumentController.php" + }, + "[\"versionen\", \"Versionvorschau anzeigen\"]": { + "abdruck": "a974b2f0fc1570d9", + "beleg": "return $this->json([\n 'ok' => true,\n 'preview' => $previewService->buildPreview(\n $version,\n max(0, (int) $request->query->get('offset', 0)),\n (int) $request->query->get('limit', 0) ?: null,\n ),\n ]);", + "datei": "src/Controller/Admin/DocumentController.php" + } + }, + "ohne_code": {}, + "ohne_karte": { + "befehl:mto:agent:admin:title-suggestions-batch-ux-self-test": { + "abdruck": "843d5ca642b321bb", + "beleg": "src/Command/AdminTitleSuggestionsBatchUxSelfTestCommand.php:13", + "feature": "diagnose", + "karten": "69d65c7a24056348", + "stelle": "befehl:mto:agent:admin:title-suggestions-batch-ux-self-test", + "titel": "Titelvorschläge-Selbsttest bereitstellen" + }, + "befehl:mto:agent:config:audit-source": { + "abdruck": "6230151689bef31c", + "beleg": "src/Command/ConfigSourceAuditCommand.php:16", + "feature": "diagnose", + "karten": "69d65c7a24056348", + "stelle": "befehl:mto:agent:config:audit-source", + "titel": "Konfigurationsquellen prüfen" + }, + "befehl:mto:agent:knowledge:batch-markdown-normalization-self-test": { + "abdruck": "3e48335eb38ac843", + "beleg": "src/Command/KnowledgeBatchMarkdownNormalizationSelfTestCommand.php:15", + "feature": "diagnose", + "karten": "69d65c7a24056348", + "stelle": "befehl:mto:agent:knowledge:batch-markdown-normalization-self-test", + "titel": "Batch-Markdown-Normalisierung testen" + }, + "befehl:mto:agent:mcp:policy-check": { + "abdruck": "8110a377aeb90a72", + "beleg": "src/Command/McpPolicyCheckCommand.php:15", + "feature": "agenten", + "karten": "69d65c7a24056348", + "stelle": "befehl:mto:agent:mcp:policy-check", + "titel": "MCP-Allowlist prüfen" + }, + "befehl:mto:agent:system:rebuild": { + "abdruck": "338b6ba198206984", + "beleg": "src/Command/SystemRebuildCommand.php:23", + "feature": "agenten", + "karten": "69d65c7a24056348", + "stelle": "befehl:mto:agent:system:rebuild", + "titel": "System rebuild bereitstellen" + }, + "einbinden:erweitert error/layout.html.twig": { + "abdruck": "7e0ec1ba9d60dfc2", + "beleg": "templates/bundles/TwigBundle/Exception/error.html.twig:1", + "feature": "system", + "karten": "69d65c7a24056348", + "stelle": "einbinden:erweitert error/layout.html.twig", + "titel": "Fehlerseite anzeigen" + }, + "route:get /admin/enterprise/operator-report.json": { + "abdruck": "f80c52683806f557", + "beleg": "src/Controller/Admin/EnterpriseOperationsController.php:222", + "feature": "backup", + "karten": "69d65c7a24056348", + "stelle": "route:get /admin/enterprise/operator-report.json", + "titel": "Operatorbericht als JSON exportieren" + }, + "route:get /admin/enterprise/operator-report.md": { + "abdruck": "013cf5bf01f75995", + "beleg": "src/Controller/Admin/EnterpriseOperationsController.php:233", + "feature": "berichte", + "karten": "69d65c7a24056348", + "stelle": "route:get /admin/enterprise/operator-report.md", + "titel": "Operatorbericht als Markdown herunterladen" + }, + "route:get /admin/jobs": { + "abdruck": "bb7ffeb8ab6206d7", + "beleg": "src/Controller/Admin/IngestJobController.php:19", + "feature": "auftraege", + "karten": "69d65c7a24056348", + "stelle": "route:get /admin/jobs", + "titel": "Ingest-Jobs auflisten" + }, + "route:get /admin/login": { + "abdruck": "26892f59f58a1343", + "beleg": "src/Controller/Admin/SecurityController.php:17", + "feature": "system", + "karten": "69d65c7a24056348", + "stelle": "route:get /admin/login", + "titel": "Admin-Login bereitstellen" + }, + "route:get /tags/status": { + "abdruck": "563ca03e6e7d0168", + "beleg": "src/Controller/Admin/DocumentTagController.php:64", + "feature": "tags", + "karten": "69d65c7a24056348", + "stelle": "route:get /tags/status", + "titel": "Tag-Rebuild-Status abfragen" + }, + "route:get /version/{versionId}/chunks": { + "abdruck": "5912e8ad04dff0b9", + "beleg": "src/Controller/Admin/DocumentController.php:362", + "feature": "dokumente", + "karten": "69d65c7a24056348", + "stelle": "route:get /version/{versionId}/chunks", + "titel": "Version-Chunks abrufen" + }, + "route:get /{batchId}": { + "abdruck": "aff9a8b22d9a3898", + "beleg": "src/Controller/Admin/KnowledgeBatchReportController.php:120", + "feature": "berichte", + "karten": "69d65c7a24056348", + "stelle": "route:get /{batchId}", + "titel": "Batch-Bericht anzeigen" + }, + "route:get /{id}/tags": { + "abdruck": "647012ad65e4e903", + "beleg": "src/Controller/Admin/DocumentTagController.php:20", + "feature": "tags", + "karten": "69d65c7a24056348", + "stelle": "route:get /{id}/tags", + "titel": "Tag-Zuordnung bearbeiten" + }, + "route:post /chat-feedback": { + "abdruck": "3580073b0c13af05", + "beleg": "src/Controller/ChatFeedbackController.php:58", + "feature": "feedback", + "karten": "69d65c7a24056348", + "stelle": "route:post /chat-feedback", + "titel": "Feedback speichern" + }, + "route:post /remove/{id}": { + "abdruck": "a1713c7060f2b0aa", + "beleg": "src/Controller/Admin/IngestProfileController.php:76", + "feature": "konfiguration", + "karten": "69d65c7a24056348", + "stelle": "route:post /remove/{id}", + "titel": "Ingest-Profil entfernen" + }, + "route:post /upload": { + "abdruck": "4dc0d28cbc695b67", + "beleg": "src/Controller/Admin/KnowledgeBatchReportController.php:65", + "feature": "berichte", + "karten": "69d65c7a24056348", + "stelle": "route:post /upload", + "titel": "Batch-Bericht hochladen" + }, + "route:post /version/{versionId}/activate": { + "abdruck": "19e7d9844ad77ac3", + "beleg": "src/Controller/Admin/DocumentController.php:549", + "feature": "versionen", + "karten": "69d65c7a24056348", + "stelle": "route:post /version/{versionId}/activate", + "titel": "Version aktivieren" + } + }, + "paare": { + "[\"[\\\"diagnose\\\", \\\"Konfiguration prüfen\\\"]\", \"[\\\"konfiguration\\\", \\\"Konfigurationsmuster prüfen\\\"]\"]": { + "abdruck": "15337f18a6737c8c", + "gleich": false + }, + "[\"[\\\"knowledge-raeume\\\", \\\"Batch-Import durchführen\\\"]\", \"[\\\"knowledge-raeume\\\", \\\"Ressourcenprüfung durchführen\\\"]\"]": { + "abdruck": "2986858d481560bc", + "gleich": false + }, + "[\"[\\\"knowledge-raeume\\\", \\\"Chat-Verfügbarkeit prüfen\\\"]\", \"[\\\"knowledge-raeume\\\", \\\"Ressourcenprüfung durchführen\\\"]\"]": { + "abdruck": "152316f10336728c", + "gleich": false + }, + "[\"[\\\"knowledge-raeume\\\", \\\"Facts prüfen\\\"]\", \"[\\\"knowledge-raeume\\\", \\\"Ressourcenprüfung durchführen\\\"]\"]": { + "abdruck": "b4dbd1bd2cdfad59", + "gleich": false + }, + "[\"[\\\"knowledge-raeume\\\", \\\"Live-Vorschau laden\\\"]\", \"[\\\"knowledge-raeume\\\", \\\"Ressourcenprüfung durchführen\\\"]\"]": { + "abdruck": "6bd6037f86a8638b", + "gleich": false + }, + "[\"[\\\"konfiguration\\\", \\\"Ingest-Profil anlegen\\\"]\", \"[\\\"konfiguration\\\", \\\"Ingest-Profile anzeigen\\\"]\"]": { + "abdruck": "54fa5dc37e4bce7b", + "gleich": false + }, + "[\"[\\\"konfiguration\\\", \\\"Konfiguration anzeigen\\\"]\", \"[\\\"konfiguration\\\", \\\"Konfigurationen anzeigen\\\"]\"]": { + "abdruck": "1a2b3ae854024ca6", + "gleich": false + } + }, + "stil": { + "[\"admin\", \"\"]": { + "abdruck": "a203875bd41900c1", + "probleme": [] + }, + "[\"admin\", \"Betrieb einsehen\"]": { + "abdruck": "92a486ddfff5158e", + "probleme": [] + }, + "[\"admin\", \"Dashboard anzeigen\"]": { + "abdruck": "54e5d6299d132ede", + "probleme": [ + { + "feature": "admin", + "feld": "regeln", + "funktion": "Dashboard anzeigen", + "ganzes_feld": true, + "original": "Rendered admin dashboard index html twig\nEnthält Chunk-Zähler und Chunk-Limit\nEnthält Vektor- und Tag-Gesundheitsdaten\nEnthält Reset-Konfiguration", + "problem": "Template-Pfad kein Feature-Inhalt. Chunk-Zähler und Limit sowie Vektor- und Tag-Daten sind je zwei Inhalte in einer Zeile", + "regel": "Genau eine Aussage je Zeile; zwei Aussagen werden zu zwei Regeln", + "vorschlag": "Chunk-Zähler und Chunk-Limit anzeigen\nVektor- und Tag-Gesundheitsdaten anzeigen\nReset-Konfiguration anzeigen" + } + ] + }, + "[\"admin\", \"Logout einleiten\"]": { + "abdruck": "42dcd7e9064bcbbf", + "probleme": [] + }, + "[\"admin\", \"Wiederherstellung testen\"]": { + "abdruck": "0a40315eeece5b67", + "probleme": [] + }, + "[\"admin\", \"Zum Dashboard weiterleiten\"]": { + "abdruck": "7b834b643e67b940", + "probleme": [] + }, + "[\"agenten\", \"\"]": { + "abdruck": "901c385fec70b938", + "probleme": [] + }, + "[\"agenten\", \"Agentenaktivität anzeigen\"]": { + "abdruck": "cd9f8ffc4b1305b9", + "probleme": [] + }, + "[\"agenten\", \"Chat-Auswahl-Guard testen\"]": { + "abdruck": "64ce9ac9cfcff1dc", + "probleme": [] + }, + "[\"agenten\", \"Fähigkeiten ermitteln\"]": { + "abdruck": "785628cbe59d669a", + "probleme": [] + }, + "[\"agenten\", \"Hybrid-Tool-Auswahl testen\"]": { + "abdruck": "ee09ee5102072416", + "probleme": [] + }, + "[\"agenten\", \"MCP-Allowlist prüfen\"]": { + "abdruck": "853ccb3f4e4aa8d4", + "probleme": [] + }, + "[\"agenten\", \"MCP-Gateway trocken ausführen\"]": { + "abdruck": "1439df287c8150b2", + "probleme": [] + }, + "[\"agenten\", \"MCP-Laufzeit-Gate prüfen\"]": { + "abdruck": "b3293656f686ae09", + "probleme": [ + { + "feature": "agenten", + "feld": "regeln", + "funktion": "MCP-Laufzeit-Gate prüfen", + "ganzes_feld": false, + "original": "Gate ohne Transport öffnen", + "problem": "Erste Regel ist Ablaufschritt statt Eigenschaft", + "regel": "Beschreibt eine Eigenschaft oder Bedingung, keinen Ablaufschritt", + "vorschlag": "Gate ohne Transport verfügbar" + }, + { + "feature": "agenten", + "feld": "testen", + "funktion": "MCP-Laufzeit-Gate prüfen", + "ganzes_feld": false, + "original": "JSON auf Status ready und Fehler prüfen", + "problem": "Letzte Zeile enthält Handlung statt Endzustand", + "regel": "Letzte Zeile beschreibt den Endzustand, keine Handlung", + "vorschlag": "JSON zeigt Status ready ohne Fehler" + } + ] + }, + "[\"agenten\", \"MCP-Laufzeitgrenze testen\"]": { + "abdruck": "080b368f6b310470", + "probleme": [] + }, + "[\"agenten\", \"MCP-Quelle prüfen\"]": { + "abdruck": "c1558584859c0dec", + "probleme": [] + }, + "[\"agenten\", \"Mit Agent chatten\"]": { + "abdruck": "00eafdf90dab665a", + "probleme": [] + }, + "[\"agenten\", \"Performance-Cache leeren\"]": { + "abdruck": "97e48547004e559b", + "probleme": [] + }, + "[\"agenten\", \"Produktlabel-Formatierer testen\"]": { + "abdruck": "c5831a681dbce9d2", + "probleme": [] + }, + "[\"agenten\", \"Release-Selbsttest bereitstellen\"]": { + "abdruck": "4d0951f85d841836", + "probleme": [] + }, + "[\"agenten\", \"Ressource abrufen\"]": { + "abdruck": "f41b71225f818920", + "probleme": [] + }, + "[\"agenten\", \"Ressource validieren\"]": { + "abdruck": "3d7999723f74822d", + "probleme": [] + }, + "[\"agenten\", \"Rollencode-Zuweisung prüfen\"]": { + "abdruck": "287ee050cc63c85a", + "probleme": [ + { + "feature": "agenten", + "feld": "testen", + "funktion": "Rollencode-Zuweisung prüfen", + "ganzes_feld": false, + "original": "Ausgabe auf Status OK prüfen", + "problem": "Zweiter Ablauf in einer Funktion", + "regel": "Genau ein Ablauf: handeln, handeln, Ergebnis", + "vorschlag": "" + } + ] + }, + "[\"agenten\", \"Stabilitäts-Selbsttest bereitstellen\"]": { + "abdruck": "3db549d48f744d79", + "probleme": [ + { + "feature": "agenten", + "feld": "testen", + "funktion": "Stabilitäts-Selbsttest bereitstellen", + "ganzes_feld": true, + "original": "Binconsole mto:agent:shop-followup-anchor-stability-self-test\nStatus OK prüfen\npassed größer 0 prüfen\nfailed gleich 0 prüfen\nBinconsole mit --json\nJSON-Status OK prüfen", + "problem": "Zweiter Ablauf für menschenlesbare Ausgabe", + "regel": "Zwei Abläufe in einer Funktion", + "vorschlag": "Binconsole mto:agent:shop-followup-anchor-stability-self-test --json ausführen\nExit-Code 0 prüfen\nJSON-Status OK prüfen\nJSON failed gleich 0 prüfen\nJSON passed größer 0 prüfen" + } + ] + }, + "[\"agenten\", \"System rebuild bereitstellen\"]": { + "abdruck": "5bfdef4e50e34918", + "probleme": [ + { + "feature": "agenten", + "feld": "testen", + "funktion": "System rebuild bereitstellen", + "ganzes_feld": true, + "original": "", + "problem": "Funktion benötigt Testschritte, Feld fehlt", + "regel": "Feld testen. Gibt es nur bei Funktionen, nie auf Kartenebene.", + "vorschlag": "System rebuild Befehl ausführen\nRebuild abgeschlossen" + } + ] + }, + "[\"agenten\", \"Vektordienst steuern\"]": { + "abdruck": "ac9028407142447d", + "probleme": [] + }, + "[\"agenten\", \"Wissensbatch finalisieren testen\"]": { + "abdruck": "ff209274e8194d00", + "probleme": [] + }, + "[\"anleitungen\", \"\"]": { + "abdruck": "cd6d903356c7e46e", + "probleme": [] + }, + "[\"anleitungen\", \"Anleitung anzeigen\"]": { + "abdruck": "899edf023676bec8", + "probleme": [] + }, + "[\"anleitungen\", \"Anleitungsübersicht öffnen\"]": { + "abdruck": "806b26a376c96a30", + "probleme": [] + }, + "[\"auftraege\", \"\"]": { + "abdruck": "af6f7983d90efdc8", + "probleme": [] + }, + "[\"auftraege\", \"Auftrag starten\"]": { + "abdruck": "b6eab1ba718ae1a4", + "probleme": [] + }, + "[\"auftraege\", \"Auftragsereignisse abrufen\"]": { + "abdruck": "c4b50cdc890f64a5", + "probleme": [] + }, + "[\"auftraege\", \"Auftragsstatus anzeigen\"]": { + "abdruck": "3b24cdd657d277e3", + "probleme": [] + }, + "[\"auftraege\", \"Auftragsstatus prüfen\"]": { + "abdruck": "00a4cdd2990b0add", + "probleme": [] + }, + "[\"auftraege\", \"Ingest-Job starten\"]": { + "abdruck": "72aec88bb6eff241", + "probleme": [] + }, + "[\"auftraege\", \"Ingest-Jobs auflisten\"]": { + "abdruck": "f7d0895bcadf912d", + "probleme": [] + }, + "[\"backup\", \"\"]": { + "abdruck": "45e98250435d775b", + "probleme": [] + }, + "[\"backup\", \"Backup herunterladen\"]": { + "abdruck": "e2f3abc461d9c194", + "probleme": [] + }, + "[\"backup\", \"Backup starten\"]": { + "abdruck": "566508ee6bfb61bc", + "probleme": [] + }, + "[\"backup\", \"Backup-Tauglichkeit prüfen\"]": { + "abdruck": "6eb57d4ef14f886c", + "probleme": [] + }, + "[\"backup\", \"Backup-Trockenlauf prüfen\"]": { + "abdruck": "0690893ed788267b", + "probleme": [] + }, + "[\"backup\", \"Backup-Wiederherstellung prüfen\"]": { + "abdruck": "dbc11a271214f791", + "probleme": [] + }, + "[\"backup\", \"Operatorbericht als JSON exportieren\"]": { + "abdruck": "14bef84729eaadf1", + "probleme": [] + }, + "[\"benutzer\", \"\"]": { + "abdruck": "32420f60cbf635b1", + "probleme": [] + }, + "[\"benutzer\", \"Benutzer aktivieren\"]": { + "abdruck": "96f95d98b60ce655", + "probleme": [] + }, + "[\"benutzer\", \"Benutzer anlegen\"]": { + "abdruck": "f05fc2e1c4187019", + "probleme": [] + }, + "[\"benutzer\", \"Benutzer auflisten\"]": { + "abdruck": "8321758658996847", + "probleme": [ + { + "feature": "benutzer", + "feld": "testen", + "funktion": "Benutzer auflisten", + "ganzes_feld": true, + "original": "Seite /admin/users aufrufen\nSeite zeigt Benutzerliste mit Rollen und Status\nFilter auf Status \"aktiv\" setzen\nListe zeigt nur aktive Benutzer", + "problem": "Schrägstrich in Pfad entfernt", + "regel": "Keine Klammern und keine Schrägstriche", + "vorschlag": "Seite admin Benutzer aufrufen\nFilter auf Status \"aktiv\" setzen\nListe zeigt nur aktive Benutzer" + } + ] + }, + "[\"benutzer\", \"Benutzer bearbeiten\"]": { + "abdruck": "f127b29c9c5bc74e", + "probleme": [] + }, + "[\"berichte\", \"\"]": { + "abdruck": "0f4156c5fc44424d", + "probleme": [] + }, + "[\"berichte\", \"Akzeptanzbericht generieren\"]": { + "abdruck": "f04707b53e234402", + "probleme": [] + }, + "[\"berichte\", \"Batch-Bericht anzeigen\"]": { + "abdruck": "f38e641b3339b8ab", + "probleme": [] + }, + "[\"berichte\", \"Batch-Bericht hochladen\"]": { + "abdruck": "9030b692a0e36c2a", + "probleme": [] + }, + "[\"berichte\", \"Bericht als JSON herunterladen\"]": { + "abdruck": "ddc360bbfd90df78", + "probleme": [] + }, + "[\"berichte\", \"Bericht löschen\"]": { + "abdruck": "469932b04c26e284", + "probleme": [] + }, + "[\"berichte\", \"Berichte auflisten\"]": { + "abdruck": "9080b473520828ed", + "probleme": [] + }, + "[\"berichte\", \"Operatorbericht als Markdown herunterladen\"]": { + "abdruck": "7c7899d0d1d192c9", + "probleme": [ + { + "feature": "berichte", + "feld": "testen", + "funktion": "Operatorbericht als Markdown herunterladen", + "ganzes_feld": true, + "original": "", + "problem": "Funktion ohne Ziel, Regeln und Testen", + "regel": "Jede Funktion hat Ziel, Regeln oder Testschritte — nie nur einen Titel", + "vorschlag": "Operatorbericht herunterladen\nDownload der Markdown-Datei" + } + ] + }, + "[\"berichte\", \"Übersicht rendern\"]": { + "abdruck": "6dc46bd6fede91df", + "probleme": [] + }, + "[\"chat\", \"\"]": { + "abdruck": "a1447aea8aded8a8", + "probleme": [] + }, + "[\"chat\", \"Abmelden ermöglichen\"]": { + "abdruck": "c0f05ddcafaea075", + "probleme": [] + }, + "[\"chat\", \"Chat streamen\"]": { + "abdruck": "e1e9cb8c9053e37b", + "probleme": [] + }, + "[\"chat\", \"Chatseite anzeigen\"]": { + "abdruck": "11e80969e49bdcba", + "probleme": [] + }, + "[\"diagnose\", \"\"]": { + "abdruck": "dabf1d8c23deb380", + "probleme": [] + }, + "[\"diagnose\", \"Abdeckung prüfen\"]": { + "abdruck": "329d2b8accf37a8c", + "probleme": [] + }, + "[\"diagnose\", \"Abrufgrenzen prüfen\"]": { + "abdruck": "2e96c8c9e81d5c08", + "probleme": [] + }, + "[\"diagnose\", \"Batch-Markdown-Normalisierung testen\"]": { + "abdruck": "e2381c7b61403312", + "probleme": [ + { + "feature": "diagnose", + "feld": "testen", + "funktion": "Batch-Markdown-Normalisierung testen", + "ganzes_feld": true, + "original": "", + "problem": "Testen fehlt, Funktion benötigt Testschritte", + "regel": "Jede Funktion hat Ziel, Regeln oder Testschritte — nie nur einen Titel", + "vorschlag": "Batch-Markdown-Dateien auswählen\nNormalisierung starten\nMarkdown-Dateien nach Regeln formatiert" + } + ] + }, + "[\"diagnose\", \"Bereitschaftsbericht ausgeben\"]": { + "abdruck": "08760e3d3d8b51db", + "probleme": [] + }, + "[\"diagnose\", \"Datenqualität prüfen\"]": { + "abdruck": "c511b22c8c39db86", + "probleme": [] + }, + "[\"diagnose\", \"Diagnose anzeigen\"]": { + "abdruck": "5c04af7f55f567b2", + "probleme": [] + }, + "[\"diagnose\", \"Genre-Hotspots prüfen\"]": { + "abdruck": "e030f3ee1c29b26b", + "probleme": [] + }, + "[\"diagnose\", \"Guard-Mechanismus prüfen\"]": { + "abdruck": "3b18f616a3db9276", + "probleme": [ + { + "feature": "diagnose", + "feld": "testen", + "funktion": "Guard-Mechanismus prüfen", + "ganzes_feld": true, + "original": "Befehl ausführen: mto:agent:proofing:unsupported-tool-term-guard-self-test\nStatus OK in JSON-Ausgabe prüfen\nAlle 8 Testfälle bestanden", + "problem": "Zwei getrennte Ergebnisse statt einem Ablauf", + "regel": "Genau ein Ablauf: handeln, handeln, Ergebnis", + "vorschlag": "Befehl ausführen: mto:agent:proofing:unsupported-tool-term-guard-self-test\nJSON-Ausgabe enthält Status OK und 8 bestandene Testfälle" + } + ] + }, + "[\"diagnose\", \"Hygieneregeln prüfen\"]": { + "abdruck": "ddfb86db54bf0bef", + "probleme": [] + }, + "[\"diagnose\", \"Indizierungszustand prüfen\"]": { + "abdruck": "208a457fe1c0d0b7", + "probleme": [] + }, + "[\"diagnose\", \"Konfiguration prüfen\"]": { + "abdruck": "8a8ce42e5d2051e8", + "probleme": [ + { + "feature": "diagnose", + "feld": "testen", + "funktion": "Konfiguration prüfen", + "ganzes_feld": true, + "original": "php bin/console mto:agent:config:validate ausführen\nErgebnis auf Fehler und Warnungen prüfen\nExitcode prüfen\nKonfiguration gültig: Exitcode 0\nphp bin/console mto:agent:config:validate --json ausführen\nJSON-Ausgabe enthält status, errors, warnings", + "problem": "Schrägstrich im Konsolenbefehl entfernt", + "regel": "Keine Klammern und keine Schrägstriche", + "vorschlag": "Konsolenbefehl mto:agent:config:validate ausführen\nErgebnis auf Fehler und Warnungen prüfen\nExitcode prüfen\nKonfiguration gültig: Exitcode 0" + } + ] + }, + "[\"diagnose\", \"Konfigurationsquellen prüfen\"]": { + "abdruck": "53ba45d064f6433a", + "probleme": [ + { + "feature": "diagnose", + "feld": "testen", + "funktion": "Konfigurationsquellen prüfen", + "ganzes_feld": true, + "original": "", + "problem": "Pflichtfelder bei Funktion fehlen", + "regel": "Jede Funktion hat Ziel, Regeln oder Testschritte — nie nur einen Titel", + "vorschlag": "Testschritte erforderlich" + } + ] + }, + "[\"diagnose\", \"Provenienz prüfen\"]": { + "abdruck": "82bbe9fc8808a6a8", + "probleme": [] + }, + "[\"diagnose\", \"Retrieval-Pipeline testen\"]": { + "abdruck": "c7469a1ab52e339a", + "probleme": [] + }, + "[\"diagnose\", \"Retrieval-Qualität testen\"]": { + "abdruck": "7b133381f3194f4f", + "probleme": [] + }, + "[\"diagnose\", \"Segmentierung prüfen\"]": { + "abdruck": "9c80d823344ee85b", + "probleme": [] + }, + "[\"diagnose\", \"Shop-Suche testen\"]": { + "abdruck": "86201015e42388f0", + "probleme": [] + }, + "[\"diagnose\", \"Sicherheitsstatus prüfen\"]": { + "abdruck": "763e7ad0e8d96136", + "probleme": [ + { + "feature": "diagnose", + "feld": "testen", + "funktion": "Sicherheitsstatus prüfen", + "ganzes_feld": true, + "original": "php bin/console mto:agent:enterprise:security-data-protection-readiness\nTabelle mit Cases wird ausgegeben\nphp bin/console mto:agent:enterprise:security-data-protection-readiness --json\nJSON-Objekt wird ausgegeben", + "problem": "Schrägstrich im Befehlspfad verboten", + "regel": "Keine Klammern und keine Schrägstriche", + "vorschlag": "mto:agent:enterprise:security-data-protection-readiness im Terminal ausführen\nTabelle mit Cases wird ausgegeben\nmto:agent:enterprise:security-data-protection-readiness mit JSON-Option im Terminal ausführen\nJSON-Objekt wird ausgegeben" + } + ] + }, + "[\"diagnose\", \"Stapel-Upload verifizieren\"]": { + "abdruck": "1d26cafba701a598", + "probleme": [ + { + "feature": "diagnose", + "feld": "regeln", + "funktion": "Stapel-Upload verifizieren", + "ganzes_feld": true, + "original": "Trockenlauf ohne Dokumentenimport\nRuft kein LLM auf\nÄndert keine Daten im Wissensspeicher\nGibt maschinenlesbares JSON aus\nPrüft CSRF-Schutz, Dienstintegration und Fortschrittsanzeige\nPrüft PDF-Schutz, Speichergrenzen und Leerraum-Bereinigung\nPrüft CLI-Progress und keine Agent-Verschaltung", + "problem": "Zeilen 5 6 7 enthalten jeweils mehrere Aussagen", + "regel": "Genau eine Aussage je Zeile; zwei Aussagen werden zu zwei Regeln", + "vorschlag": "Trockenlauf ohne Dokumentenimport\nRuft kein LLM auf\nÄndert keine Daten im Wissensspeicher\nGibt maschinenlesbares JSON aus\nPrüft CSRF-Schutz\nPrüft Dienstintegration\nPrüft Fortschrittsanzeige\nPrüft PDF-Schutz\nPrüft Speichergrenzen\nPrüft Leerraum-Bereinigung\nPrüft CLI-Progress\nPrüft keine Agent-Verschaltung" + } + ] + }, + "[\"diagnose\", \"Systemzustand prüfen\"]": { + "abdruck": "d28aa2acfe9cfac4", + "probleme": [] + }, + "[\"diagnose\", \"Tag-Index-Gesundheit prüfen\"]": { + "abdruck": "a48e532486b4c2b5", + "probleme": [] + }, + "[\"diagnose\", \"Tags neu indizieren\"]": { + "abdruck": "a037e610d8d69c42", + "probleme": [] + }, + "[\"diagnose\", \"Titelvorschläge-Selbsttest bereitstellen\"]": { + "abdruck": "86b944b2266d2b37", + "probleme": [] + }, + "[\"diagnose\", \"Verankerung testen\"]": { + "abdruck": "8ca4a84d17efdfa2", + "probleme": [] + }, + "[\"diagnose\", \"Vergleichsgrenzen validieren\"]": { + "abdruck": "bc540e615d0d5bd7", + "probleme": [] + }, + "[\"dokumente\", \"\"]": { + "abdruck": "4becdb2142c5bd23", + "probleme": [] + }, + "[\"dokumente\", \"Abschnitte laden\"]": { + "abdruck": "63a90ebf0595d865", + "probleme": [] + }, + "[\"dokumente\", \"Abschnittsqualität laden\"]": { + "abdruck": "c62844c88eabc50e", + "probleme": [] + }, + "[\"dokumente\", \"Dokument anzeigen\"]": { + "abdruck": "d6b054833ea79af3", + "probleme": [] + }, + "[\"dokumente\", \"Dokument entfernen\"]": { + "abdruck": "e64c95dd87a82000", + "probleme": [] + }, + "[\"dokumente\", \"Dokument erstellen\"]": { + "abdruck": "8e01d7cbd5a0a8a4", + "probleme": [] + }, + "[\"dokumente\", \"Dokumente auflisten\"]": { + "abdruck": "b7c2416d7d4cbbae", + "probleme": [ + { + "feature": "dokumente", + "feld": "testen", + "funktion": "Dokumente auflisten", + "ganzes_feld": true, + "original": "admin/documents öffnet die Übersicht\nDokumente werden mit Titeln angezeigt\nLMB auf Filterfeld\nFilterkriterium auswählen\nErgebnis zeigt gefilterte Dokumente", + "problem": "Schrägstrich in admin/documents und vermischte Abläufe", + "regel": "Keine Klammern und keine Schrägstriche", + "vorschlag": "admin Dokumente Übersicht öffnen\nDokumentenübersicht zeigt Dokumente mit Titeln\nLMB auf Filterfeld\nFilterkriterium auswählen\nGefilterte Dokumente anzeigen" + } + ] + }, + "[\"dokumente\", \"Markdown bereinigen\"]": { + "abdruck": "06b80c5a0e87b0a2", + "probleme": [] + }, + "[\"dokumente\", \"Version-Chunks abrufen\"]": { + "abdruck": "121d643dfeaa9d06", + "probleme": [] + }, + "[\"evaluation\", \"\"]": { + "abdruck": "594221238c11b947", + "probleme": [] + }, + "[\"evaluation\", \"Berichte bereinigen\"]": { + "abdruck": "a7042dc676807598", + "probleme": [] + }, + "[\"evaluation\", \"Eval-Berichte anzeigen\"]": { + "abdruck": "e5bef4df8f06ec4c", + "probleme": [] + }, + "[\"evaluation\", \"Eval-Fälle ausführen\"]": { + "abdruck": "d6df9edb6f759315", + "probleme": [] + }, + "[\"evaluation\", \"Eval-Fälle parallelisieren\"]": { + "abdruck": "27acbff82a31da6a", + "probleme": [] + }, + "[\"evaluation\", \"Evaluation ausführen\"]": { + "abdruck": "2b308fa2f538a538", + "probleme": [] + }, + "[\"faelle\", \"\"]": { + "abdruck": "e38157c616482b1c", + "probleme": [] + }, + "[\"faelle\", \"Assistent anzeigen\"]": { + "abdruck": "4e8e66ff7acfb7c0", + "probleme": [] + }, + "[\"faelle\", \"Fall anlegen\"]": { + "abdruck": "bce7e877c144ea9d", + "probleme": [] + }, + "[\"faelle\", \"Fall erstellen\"]": { + "abdruck": "ec52ed76fbd9d12b", + "probleme": [] + }, + "[\"faelle\", \"Fälle löschen bereitstellen\"]": { + "abdruck": "69713f6beacefbcc", + "probleme": [] + }, + "[\"feedback\", \"\"]": { + "abdruck": "4b64525f442c4972", + "probleme": [] + }, + "[\"feedback\", \"Chat-Feedback anzeigen\"]": { + "abdruck": "69466ab1f54c2cb9", + "probleme": [] + }, + "[\"feedback\", \"Feedback exportieren\"]": { + "abdruck": "ddb61be881c2bbff", + "probleme": [] + }, + "[\"feedback\", \"Feedback klassifizieren\"]": { + "abdruck": "9d766ebb18ca02c5", + "probleme": [] + }, + "[\"feedback\", \"Feedback löschen\"]": { + "abdruck": "d60ec5bc507ba562", + "probleme": [] + }, + "[\"feedback\", \"Feedback speichern\"]": { + "abdruck": "d48bb573cdb9705d", + "probleme": [] + }, + "[\"feedback\", \"Feedback-Details anzeigen\"]": { + "abdruck": "d6b5bce8fb06d510", + "probleme": [] + }, + "[\"feedback\", \"Feedback-Status aktualisieren\"]": { + "abdruck": "b403e18917069070", + "probleme": [] + }, + "[\"feedback\", \"Feedback-Status prüfen\"]": { + "abdruck": "b26f6d469ab858d2", + "probleme": [] + }, + "[\"knowledge-raeume\", \"\"]": { + "abdruck": "25228e3324851fe7", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Batch-Import durchführen\"]": { + "abdruck": "31019ec87c246d93", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Chat-Freigabe umschalten\"]": { + "abdruck": "080f4432ef5b203c", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Chat-Verfügbarkeit prüfen\"]": { + "abdruck": "603b7775de757a04", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Facts prüfen\"]": { + "abdruck": "3896b29ce690ad30", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Kandidaten wählen\"]": { + "abdruck": "d964a18b84dad74d", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Knowledge-Räume anzeigen\"]": { + "abdruck": "562a038e69aa6f0e", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Live-Vorschau laden\"]": { + "abdruck": "f728e6193791be38", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Ressourcenprüfung durchführen\"]": { + "abdruck": "b1a1ebfc2a7a3ee9", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Textteile suchen\"]": { + "abdruck": "e17ffa8ad1243dc9", + "probleme": [] + }, + "[\"knowledge-raeume\", \"Wissensräume prüfen\"]": { + "abdruck": "3a41f11618fa60df", + "probleme": [] + }, + "[\"konfiguration\", \"\"]": { + "abdruck": "92cf0d92545eb7ff", + "probleme": [ + { + "feature": "konfiguration", + "feld": "regeln", + "funktion": "", + "ganzes_feld": true, + "original": "ROLE_SUPER_ADMIN darf alle Funktionen aufrufen\nROLE_KNOWLEDGE_ADMIN darf Konfigurationen lesen\nPOST erfordert gültiges CSRF-Token\nFlash-Nachrichten zeigen Erfolg und Fehler\nJsonResponse ohne Browser-Cache-Header\nDefault-Ausgabe ist JSON\nIngest-Profil entfernen fehlt\nModel-Konfiguration löschen fehlt\nModel-Konfiguration Retrieval testen fehlt", + "problem": "Drei Zeilen beschreiben fehlende Features", + "regel": "Beschreibt eine Eigenschaft oder Bedingung, keinen Ablaufschritt", + "vorschlag": "ROLE_SUPER_ADMIN darf alle Funktionen aufrufen\nROLE_KNOWLEDGE_ADMIN darf Konfigurationen lesen\nPOST erfordert gültiges CSRF-Token\nFlash-Nachrichten zeigen Erfolg und Fehler\nJsonResponse ohne Browser-Cache-Header\nDefault-Ausgabe ist JSON" + } + ] + }, + "[\"konfiguration\", \"Ingest-Profil anlegen\"]": { + "abdruck": "9e5b29256daf2c06", + "probleme": [] + }, + "[\"konfiguration\", \"Ingest-Profil entfernen\"]": { + "abdruck": "0c1b8c259154ef6c", + "probleme": [ + { + "feature": "konfiguration", + "feld": "testen", + "funktion": "Ingest-Profil entfernen", + "ganzes_feld": true, + "original": "", + "problem": "Leer, widerspricht Regel Jede Funktion hat Ziel, Regeln oder Testschritte", + "regel": "Kein Satzzeichen am Zeilenende, kein Punkt und kein Semikolon", + "vorschlag": "Ingest-Profil auswählen\nLöschen betätigen\nIngest-Profil nicht mehr vorhanden" + } + ] + }, + "[\"konfiguration\", \"Ingest-Profile anzeigen\"]": { + "abdruck": "caf3406830504a3d", + "probleme": [] + }, + "[\"konfiguration\", \"Konfiguration aktivieren\"]": { + "abdruck": "d0348c558413f373", + "probleme": [] + }, + "[\"konfiguration\", \"Konfiguration anzeigen\"]": { + "abdruck": "c5e60cea343fde20", + "probleme": [] + }, + "[\"konfiguration\", \"Konfiguration bereitstellen\"]": { + "abdruck": "26a2e49c0ad08c5d", + "probleme": [] + }, + "[\"konfiguration\", \"Konfigurationen anzeigen\"]": { + "abdruck": "b99bbc6dc1dbb85b", + "probleme": [] + }, + "[\"konfiguration\", \"Konfigurationsmuster prüfen\"]": { + "abdruck": "548417111961dff3", + "probleme": [] + }, + "[\"konfiguration\", \"Tool-Freigaben aktualisieren\"]": { + "abdruck": "6a817eb0259e5a15", + "probleme": [] + }, + "[\"logs\", \"\"]": { + "abdruck": "8973dbd63027cc8d", + "probleme": [] + }, + "[\"logs\", \"Logdatei anzeigen\"]": { + "abdruck": "5cb3a44df5954a83", + "probleme": [] + }, + "[\"logs\", \"Logdateien auflisten\"]": { + "abdruck": "a99c8ae34ebbf477", + "probleme": [] + }, + "[\"sonstiges\", \"\"]": { + "abdruck": "1b9e9b354b4e4eb6", + "probleme": [] + }, + "[\"sonstiges\", \"Sicherheitsnachweis bereitstellen\"]": { + "abdruck": "4f9581ea69437237", + "probleme": [] + }, + "[\"sonstiges\", \"post activate {id} bereitstellen\"]": { + "abdruck": "97cd9a4ee22b4c8e", + "probleme": [] + }, + "[\"sonstiges\", \"post {id} tags save bereitstellen\"]": { + "abdruck": "c70846fc95f332de", + "probleme": [] + }, + "[\"system\", \"\"]": { + "abdruck": "cd76c21c32180982", + "probleme": [] + }, + "[\"system\", \"Access-Denied-Fehler bereitstellen\"]": { + "abdruck": "0c4867fdd18e405f", + "probleme": [] + }, + "[\"system\", \"Admin-Login bereitstellen\"]": { + "abdruck": "90977c98a07c9372", + "probleme": [] + }, + "[\"system\", \"Betriebsbereitschaft prüfen\"]": { + "abdruck": "875a43396ab59856", + "probleme": [ + { + "feature": "system", + "feld": "testen", + "funktion": "Betriebsbereitschaft prüfen", + "ganzes_feld": true, + "original": "Command ausführen ohne Option\nTabelle zeigt Status, Case und Details\nAlle Cases mit PASS erscheinen\nCommand mit --json ausführen\nJSON-Objekt mit status, summary und cases erscheint", + "problem": "Zweiter Ablauf entfernt, nur ein Ablauf erlaubt", + "regel": "Genau ein Ablauf: handeln, handeln, Ergebnis", + "vorschlag": "Command ausführen ohne Option\nTabelle zeigt Status, Case und Details" + } + ] + }, + "[\"system\", \"Cache leeren\"]": { + "abdruck": "fb93b62747244c97", + "probleme": [] + }, + "[\"system\", \"Daten neu laden\"]": { + "abdruck": "7b1bde58f2c6be89", + "probleme": [] + }, + "[\"system\", \"Daten sichern\"]": { + "abdruck": "a346f050ca9ca3dd", + "probleme": [] + }, + "[\"system\", \"Deployment prüfen\"]": { + "abdruck": "58f45050c3d6ddf2", + "probleme": [] + }, + "[\"system\", \"Dienststatus melden\"]": { + "abdruck": "53692da8a39ee4ee", + "probleme": [] + }, + "[\"system\", \"Fehlerseite anzeigen\"]": { + "abdruck": "ac91cfa7c4443a2c", + "probleme": [ + { + "feature": "system", + "feld": "testen", + "funktion": "Fehlerseite anzeigen", + "ganzes_feld": true, + "original": "", + "problem": "Funktion ohne Ziel, Regeln und Testen", + "regel": "Jede Funktion hat Ziel, Regeln oder Testschritte — nie nur einen Titel", + "vorschlag": "Fehlerseite auslösen\nFehlerseite prüft Inhalt\nFehlerseite angezeigt" + } + ] + }, + "[\"system\", \"Flow-Grenze sperren\"]": { + "abdruck": "7f8f2ff111578aee", + "probleme": [] + }, + "[\"system\", \"Neuindizierung starten\"]": { + "abdruck": "baab3281c00716ea", + "probleme": [] + }, + "[\"system\", \"Normalisierung prüfen\"]": { + "abdruck": "1d078a8c8739dce7", + "probleme": [] + }, + "[\"system\", \"Preview prüfen\"]": { + "abdruck": "36bfb9af2c395881", + "probleme": [] + }, + "[\"system\", \"Promptversion aktivieren\"]": { + "abdruck": "cf621d5db06669cd", + "probleme": [] + }, + "[\"system\", \"Promptversion löschen\"]": { + "abdruck": "4831087ddffa3a02", + "probleme": [] + }, + "[\"system\", \"Promptversionen verwalten\"]": { + "abdruck": "271419aa16b295c1", + "probleme": [] + }, + "[\"system\", \"Restore-Vorschau prüfen\"]": { + "abdruck": "79007d6f20f9f259", + "probleme": [] + }, + "[\"system\", \"Simulation ausführen\"]": { + "abdruck": "872c7daa285566a6", + "probleme": [] + }, + "[\"system\", \"Systemzustand zurücksetzen\"]": { + "abdruck": "aad55d89505af36e", + "probleme": [] + }, + "[\"system\", \"Verzeichnis bereinigen\"]": { + "abdruck": "c3a169bd14fc72ff", + "probleme": [] + }, + "[\"tags\", \"\"]": { + "abdruck": "0137270973dfabae", + "probleme": [] + }, + "[\"tags\", \"Tag-Rebuild-Auftrag ausführen\"]": { + "abdruck": "84922f94b261c3aa", + "probleme": [] + }, + "[\"tags\", \"Tag-Rebuild-Status abfragen\"]": { + "abdruck": "3b7cd1dfa6cce19b", + "probleme": [] + }, + "[\"tags\", \"Tag-Zuordnung bearbeiten\"]": { + "abdruck": "2c07ad450bffd805", + "probleme": [ + { + "feature": "tags", + "feld": "testen", + "funktion": "Tag-Zuordnung bearbeiten", + "ganzes_feld": true, + "original": "", + "problem": "Testen leer stattTestschritte zu enthalten", + "regel": "Jede Funktion hat Ziel, Regeln oder Testschritte — nie nur einen Titel", + "vorschlag": "[Tag auswählen]\n[Zuweisung ändern]\n[Änderung bestätigen]" + } + ] + }, + "[\"tags\", \"Tags auflisten\"]": { + "abdruck": "b9eeaa47d21451b3", + "probleme": [] + }, + "[\"tags\", \"Tags bearbeiten\"]": { + "abdruck": "b499aeba37fc4762", + "probleme": [] + }, + "[\"tags\", \"Tags suchen\"]": { + "abdruck": "bc800e0107e9e99e", + "probleme": [] + }, + "[\"titel\", \"\"]": { + "abdruck": "b771a18e13aba81c", + "probleme": [] + }, + "[\"titel\", \"Titel aktualisieren\"]": { + "abdruck": "5fd71fcaa6cf86b1", + "probleme": [] + }, + "[\"titel\", \"Titelvorschläge laden\"]": { + "abdruck": "7c5913d783929e93", + "probleme": [] + }, + "[\"uploads\", \"\"]": { + "abdruck": "bfee1441da40c5ca", + "probleme": [] + }, + "[\"uploads\", \"Berechtigungsmodus ändern\"]": { + "abdruck": "fe6824d5e74aa716", + "probleme": [] + }, + "[\"uploads\", \"Datei hochladen\"]": { + "abdruck": "097eed6431a3436c", + "probleme": [] + }, + "[\"uploads\", \"Upload entfernen\"]": { + "abdruck": "9743e4d26d8c92e4", + "probleme": [] + }, + "[\"uploads\", \"Uploads auflisten\"]": { + "abdruck": "5b8d1649c1128f87", + "probleme": [] + }, + "[\"verlauf\", \"\"]": { + "abdruck": "1ad061f8898591f2", + "probleme": [] + }, + "[\"verlauf\", \"Verankerungen extrahieren\"]": { + "abdruck": "c8b5823dc343a021", + "probleme": [] + }, + "[\"verlauf\", \"Verlauf abrufen\"]": { + "abdruck": "512f74a4d7093956", + "probleme": [] + }, + "[\"verlauf\", \"Verlauf löschen\"]": { + "abdruck": "3cd576b5811fc821", + "probleme": [] + }, + "[\"versionen\", \"\"]": { + "abdruck": "a2ff5a390898eadf", + "probleme": [] + }, + "[\"versionen\", \"Version ableiten\"]": { + "abdruck": "23c5eaf21b66893b", + "probleme": [] + }, + "[\"versionen\", \"Version aktivieren\"]": { + "abdruck": "f8c322e31e37620c", + "probleme": [] + }, + "[\"versionen\", \"Version einlesen\"]": { + "abdruck": "7a8b97e289a62d9e", + "probleme": [] + }, + "[\"versionen\", \"Version erstellen\"]": { + "abdruck": "0c0a4c71ade40480", + "probleme": [] + }, + "[\"versionen\", \"Versionvorschau anzeigen\"]": { + "abdruck": "eab759a8abfc20e7", + "probleme": [] + } + }, + "verworfen": {} +} diff --git a/daten/RAG/admin.md b/daten/RAG/admin.md new file mode 100644 index 0000000..09b173d --- /dev/null +++ b/daten/RAG/admin.md @@ -0,0 +1,93 @@ + +Admin +---------------------------------------- + +kern +---------------------------------------- + +Bietet Zugriff auf Enterprise-Betriebsdaten und Systemüberwachung für Administratoren +---------------------------------------- + +- POST-Operationen erfordern gültiges CSRF-Token +- Wiederherstellung erfordert ROLE_SUPER_ADMIN +- Ergebnis jeder Operation als Flash-Meldung +- Backup-Download erfordert ROLE_SUPER_ADMIN +---------------------------------------- + +Betrieb einsehen + +Verschafft Admins einen Überblick über den Betriebszustand aller Systeme + +- Backup- und Restore-Bereitschaft zeigt Status +- Sicherheit und Datenschutz zeigt Bereitschaft +- Deployment-Scheduler zeigt Bereitschaft +- Backup-Übersicht zeigt vorhandene Sicherungen +- Operator-Prüfprotokoll zeigt letzte 8 Prüfungen +- Übersicht kombiniert alle Berichte + +- Admin-Dashboard öffnen +- Backup- und Restore-Bereitschaft anzeigen +- Sicherheit und Datenschutz anzeigen +- Deployment-Scheduler anzeigen +- Backup-Übersicht mit vorhandenen Sicherungen +- Operator-Prüfprotokoll mit letzten 8 Einträgen +- Kombinierte Übersicht aller Berichte +---------------------------------------- + +Dashboard anzeigen + +Zeigt Systemzustand und Konfiguration im Admin-Bereich + +- Rendered admin dashboard index html twig +- Enthält Chunk-Zähler und Chunk-Limit +- Enthält Vektor- und Tag-Gesundheitsdaten +- Enthält Reset-Konfiguration + +- Admin-Dashboard aufrufen +- HTTP 200 zurückerhalten +- admin-dashboard-index-html-twigt Template prüfen +- Chunk-Zähler im Response vorhanden +- Vektor-Gesundheitsdaten im Response vorhanden +---------------------------------------- + +Logout einleiten + +Beendet die aktive Adminsession sicher + +- GET oder POST an Admin-Logout startet Logout +- Wird vom Framework-Sicherheitssystem abgefangen +- Leere Methoden-Signatur +- Löscht Session und Authentifizierungsdaten + +- Klick auf Logout-Button im Admin +- Weiterleitung zur Login-Seite +- Session beendet +---------------------------------------- + +Wiederherstellung testen + +Prueft ob ein Backup sich vollständig wiederherstellen laesst + +- Benoetigt ROLE_SUPER_ADMIN +- POST-Request mit CSRF-Token +- Prueft angegebene Backup-ID gegen Muster retriex-backup-YYYYMMDD-HHMMSS +- Trockenlauf ohne tatsaechliche Wiederherstellung +- Ergebnis als Flash-Meldung nach Startseite + +- Admin-Enterprise-Seite aufrufen +- Dry-Run-Wiederherstellung mit gueltigem CSRF-Token absenden +- Rueckleitung auf Admin-Enterprise mit Flash-Meldung pruefen +- Flash-Meldung zeigt Warnungen und Fehler oder Erfolg +---------------------------------------- + +Zum Dashboard weiterleiten + +Leitet admin und admin- auf das Dashboard um + +- Admin leitet zum Dashboard um +- Verhindert doppelten Inhalt + +- admin aufrufen +- Weiterleitung zu dashboard prüfen +- admin-Abschluss aufrufen +- Weiterleitung zu dashboard prüfen diff --git a/daten/RAG/agenten.md b/daten/RAG/agenten.md new file mode 100644 index 0000000..15dbf65 --- /dev/null +++ b/daten/RAG/agenten.md @@ -0,0 +1,286 @@ + +Agenten +---------------------------------------- + +kern +---------------------------------------- + +Steuert Agentenaktivitaet und prueft deren Komponenten automatisiert +---------------------------------------- + +- JSON-Ausgabe bei gesetztem --json Flag +- Self-TestsFuehrenKeineMCPTransportAufrufeAus +- AgentenaktivitaetSeiteAusQueryParameterPage +- LimitZwischen1Und200Standardmaessig50 +- StreamingGibtJedesTokenSofortAus +- Inspector liefert paths, meta und ndjson +- paths zeigen konfigurierte Agentenlogikdateien +- meta enthält Statistiken zur Agentenaktivität +- ndjson enthält paginierte Aktivitätseinträge +---------------------------------------- + +Agentenaktivität anzeigen + +Zeigt eine liste der agentenaktivitäten + +- Seite aus Query-Parameter page +- Limit zwischen 1 und 200 +- Standardlimit 50 + +- Admin-System-Agent abrufen +- Antwort ist 200 +- Debug-Count zeigt Itemanzahl +---------------------------------------- + +Chat-Auswahl-Guard testen + +Validiert dass der Chat-Auswahl-Guard korrekt funktioniert + +- Command mto:agent:knowledge-space:chat-selection-guard-self-test +- json gibt strukturierte Daten aus +- Exit-Code 0 bei Status OK, sonst 1 + +- Command mit --json Flag ausführen +- JSON mit status summary cases enthält +- Exit-Code entspricht Status +---------------------------------------- + +Fähigkeiten ermitteln + +Listet verfügbare Resources, Tools und Prompts eines Admin-MCP-Servers auf + +- Benötigt gespeicherten Admin-MCP-Server +- read liest Resource-URIs metadaten +- json maschinelles Format +- Status ready bei erfolgreicher Erkennung +- Runtime-Calls gezählt + +- Befehl mit gespeichertem Servernamen ausführen +- Ausgabe auf Status ready prüfen +- Resources, Tools und Prompts in Ausgabe +---------------------------------------- + +Hybrid-Tool-Auswahl testen + +Stellt sicher, dass LLM-Vorschlag und RetrieX-Validierung bei der Tool-Auswahl zusammenarbeiten + +- Planner besteht eigenen Self-Test +- AgentRunner nutzt LLM für Vorschlag vor RetrieX-Validierung +- Loader zeigt Status beim Tool-Auswählen +- Model-Config enthält dediziertes mcp_tool_selection-Modell + +- mto:agent:mcp:hybrid-tool-selection-planner-self-test --json ausführen +- JSON-Ausgabe auf status OK prüfen +- Alle vier Cases mit Status PASS vorhanden +---------------------------------------- + +MCP-Gateway trocken ausführen + +Prüft ob eine Resource die Gateway-Policy erfüllt und welches Evidence erzeugt wird + +- Kein MCP-Transport wird geöffnet +- fixture nutzt eingebaute Testdaten +- Exit-Code 0 bei Status ready +- json gibt Ergebnis als JSON aus + +- bin console mto agent mcp gateway-dry-run --fixture ausführen +- Ausgabe zeigt status ready +---------------------------------------- + +MCP-Laufzeit-Gate prüfen + +Prüft ob ein MCP-Read-Only-Zugriff erlaubt ist, ohne Transport zu öffnen + +- Gate ohne Transport öffnen +- fixture nutzt eingebaute Testdaten +- assume-enabled simuliert aktivierte MCP-Konfiguration +- JSON-Ausgabe verfügbar + +- Console-Befehl mit --json ausführen +- Exit-Code auf SUCCESS prüfen +- JSON auf Status ready und Fehler prüfen +---------------------------------------- + +MCP-Laufzeitgrenze testen + +Validiert, dass MCP-Server nur Admin-gesteuert und begrenzt in der Antwort-Runtime verwendet werden + +- McpDataRoomStore nur in Admin, CLI, ReadModels referenziert +- Keine externen MCP-Abrufe in Runtime-Boundary +- Keine Chat-, Retrieval- oder Evidence-Beruehrung +- Tool-Nachweise unterscheiden sichtbare Tool-Ausfuehrung +- Tool-first-Inhalts-Fallback bleibt im Statusprotokoll sichtbar +- Live-Inhalts-Fallback buendelt MCP-JSON-RPC-Resource-Reads + +- Rueckgabewert pruefen: Exitcode 0 bestaetigt OK +- Rueckgabewert pruefen: Exitcode 1 bestaetigt FAIL +---------------------------------------- + +MCP-Quelle prüfen + +Prüft eine gespeicherte Admin-MCP-Quelle als registrierungskompatible Richtlinie + +- Lokale Prüfung ohne MCP-Transport +- server wählt die gespeicherte Quelle +- audit-all prüft alle Quellen +- online führt einen Nur-Lese-Netzwerktest durch +- json gibt nur Metadaten aus + +- mto:agent:mcp:admin-source-check --server=my_source +- Ergebnis zeigt Status, Label und Fehler +---------------------------------------- + +Mit Agent chatten + +Stellt Fragen an den KI-Agenten und empfängt Antworten in Echtzeit + +- Streaming-Ausgabe jedes Tokens sofort +- Beendet auf Eingabe von exit +- Beendet auf Strg+C +- Leerer Prompt beendet +- user-id Standardwert ist cli + +- mto:agent:chat ausführen +- Frage eingeben +- Antwort tokenweise empfangen +- exit eingeben +- CLI beendet +---------------------------------------- + +Performance-Cache leeren + +Leert alle RetrieX Runtime-Caches und den Python Vector-Service-Query-Cache + +- Löscht den PHP Runtime-Cache +- Löscht optional den Vector-Service-Query-Cache +- skip-vector-service überspringt den Vector-Service-Cache +- json gibt maschinenlesbare Ausgabe aus + +- php bin console mto:agent:performance:cache:clear json +---------------------------------------- + +Produktlabel-Formatierer testen + +Validiert die p465-Formatter-Extraktion ohne Laufzeiteffekte + +- Liest nur lokale Quelldateien +- Ruft keine Chat-, Retrieval-, Shop-, MCP- oder LLM-Dienste auf +- Prüft AgentRunner-Delegation an ProductLabelFormatter +- Prüft Formatter-Besitz reiner Anzeige-Methoden +- Prüft Formatter-Besitz reiner Label-Methoden +- Prüft Abwesenheit von Runtime-Dependencies im Formatter +- Prüft Abwesenheit von p465-Methoden im AgentRunner +- Prüft Dokumentationsabdeckung in allen Referenzdateien + +- Produktlabel-Formatter-Selbsttest mit --json ausführen +- JSON zeigt status OK und 11 PASS +---------------------------------------- + +Release-Selbsttest bereitstellen + +Validiert den v1.10.8 Release-Lock ohne Seiteneffekte im Chat-Pipeline, Agent-Runtime, Retrieval, Ranking, Shop, Followup, Evidence oder Truth Layer. + +- Prüft 22 Release-Artefakte +- Prüft 8 zentrale Produktdokumente auf v1.10.8 +- Prüft 16 Required-Release-Phrasen +- Liest nur lokale Dateien +- Führt keine Chat-, LLM- oder MCP-Live-Aufrufe aus +- Führt keine Retrieval-, Shop- oder Netzaufrufe aus + +- Ausgabe zeigt Status PASS +- JSON zeigt status OK und runtime_calls 0 +---------------------------------------- + +Ressource abrufen + +Liest eine erlaubte MCP-Ressource über die CLI ab + +- Nur allowlisted Ressourcen abrufbar +- MIME-Typ geprüft +- Ergebnis enthält Status, Metadaten und Fehler + +- Befehl mit Optionen ausführen +- Kurzformat prüfen +- json Flag verwenden +- Status ready und Ressource vorhanden +---------------------------------------- + +Ressource validieren + +Ermöglicht das Prüfen, ob eine MCP-Ressource_URI auf der Allowlist steht + +- Prüft URI gegen konfigurierten Allowlist-Eintrag +- Prüft MIME-Type gegen erlaubte Typen des Eintrags +- Gibt Fehler und Warnungen aus +- CLI-Exit-Code spiegelt Entscheidung wider + +- CLI-Befehl mit --server und --resource-uri ausführen +- Option --mime-type ergänzen +- Exit-Code zeigt Ergebnis an +---------------------------------------- + +Rollencode-Zuweisung prüfen + +Validiert die p465b-Rollencode-Zuweisungs-Grenzen ohne Laufzeiteffekte + +- Prüft statische Artefakte nur +- Keine Chat-, Retrieval- oder LLM-Laufzeit +- Keine Shop-Suche +- Keine MCP-Aufrufe +- ProductLabelFormatter bleibt frei von Shop, Retrieval, Evidence und LLM +- AgentRunner bleibt Orchestrator + +- Befehl ausführen: mto:agent:architecture:product-role-code-assignment-guard-self-test +- Ausgabe auf Status OK prüfen +- Ergebnis: status = OK oder FAIL mit Details +---------------------------------------- + +Stabilitäts-Selbsttest bereitstellen + +Validierung der Shop- und Follow-up-Ankerwächter vor dem Deployment + +- Prüft REQUIRED_METHODS in AgentRunner.php +- Prüft keine FORBIDDEN_GUARD_MARKERS in Ankerwächter-Methoden +- Liest PATCH_MANIFEST.md und patch_history-Dateien +- Erzeugt Report ohne Runtime-Seiteneffekte +- json gibt maschinenlesbares Format aus + +- Binconsole mto:agent:shop-followup-anchor-stability-self-test +- Status OK prüfen +- passed größer 0 prüfen +- failed gleich 0 prüfen +- Binconsole mit --json +- JSON-Status OK prüfen +---------------------------------------- + +System rebuild bereitstellen +---------------------------------------- + +Vektordienst steuern + +Steuert den Vektorsuchdienst über die Kommandozeile + +- Rufzeit 300 Sekunden +- Standard-Host 0.0.0.0 +- Standard-Port 8090 +- Ruft Vector-Kontrollskript auf + +- Status wird angezeigt +---------------------------------------- + +Wissensbatch finalisieren testen + +Prüft die Verknüpfung von Batch-Abschluss und Bericht ohne Seiteneffekte + +- Prüft ohne Import, LLM-Aufruf oder Index-Rebuild +- Neun Prüfungen für Routing, Report und Abhängigkeiten +- Gibt FAIL bei einer einzigen fehlgeschlagenen Prüfung +- JSON-Ausgabe enthält status, scope, checks und failed + +- Command ausführen: mto:agent:knowledge:batch-finalize-self-test +- Ausgabe zeigt status OK oder FAIL +- JSON-Flag setzen: --json +- JSON enthält status und failed-Liste +---------------------------------------- + +MCP-Allowlist prüfen diff --git a/daten/RAG/anleitungen.md b/daten/RAG/anleitungen.md new file mode 100644 index 0000000..6754020 --- /dev/null +++ b/daten/RAG/anleitungen.md @@ -0,0 +1,43 @@ + +Anleitungen +---------------------------------------- + +kern +---------------------------------------- + +Zeigt Anleitungen als gerendertes Markdown im Admin-Bereich +---------------------------------------- + +- Erste H1 als Titel +- Ohne H1 wird Slug als Titel verwendet +- H1 erscheint doppelt: als Titel und im gerenderten Inhalt +---------------------------------------- + +Anleitung anzeigen + +Liest eine Markdown-Datei und zeigt sie als HTML gerendert an + +- Ungültiger Slug wirft 404 +- Fehlende Datei wirft 404 +- Titel aus erster H1 oder aus Slug +- Markdown als HTML gerendert + +- admin guides beispiel-seite aufrufen +- Titel und HTML-Inhalt sehen +- admin guides ungueltig aufrufen +- 404-Fehlerseite +---------------------------------------- + +Anleitungsübersicht öffnen + +Listet alle verfügbaren Anleitungen zur schnellen Auswahl auf + +- Markdown-Dateien aus bestimmtem Ordner +- Erste Überschrift als Titel +- Ohne Ordner wird leere Liste angezeigt +- Alphabetisch nach Titel sortiert +- Ungültige Dateinamen ignoriert + +- Admin-Bereich öffnen +- Klick auf Anleitungen +- Anleitungen alphabetisch aufgelistet diff --git a/daten/RAG/auftraege.md b/daten/RAG/auftraege.md new file mode 100644 index 0000000..e00a675 --- /dev/null +++ b/daten/RAG/auftraege.md @@ -0,0 +1,94 @@ + +Aufträge +---------------------------------------- + +kern +---------------------------------------- + +Verarbeitet asynchrone Aufgaben mit Verfolgung von Status und Ereignissen +---------------------------------------- + +- ROLE_ADMIN_AREA für Admin-Statusabruf erforderlich +- Admin-Bereich für Ereignisse gilt ohne Events-Endpunkt +- Antwort enthält lastEventId, updatedAt, startedAt, completedAt, runningStaleAfterSeconds +- Vollständiger Kontext muss explizit angefordert werden, Standard ist eingeschränkter Kontext +- Abgeschlossene, fehlgeschlagene und abgebrochene Ingest-Jobs werden mit Exitcode SUCCESS beendet +- Dry-Run gibt im Output einen Hinweis zum Zwischenspeicher-Status aus +- Ingest-Job-Verarbeitung leert PHP-Laufzeit- und Vector-Service-Cache nach Abschluss +---------------------------------------- + +Auftrag starten + +Übermittelt einen Prompt zur asynchronen Verarbeitung im Hintergrund + +- Leere Prompts werden abgelehnt +- Prompts über dem Zeichenlimit werden abgelehnt +- Ungültige Upload-IDs werden abgelehnt +- Job-ID besteht aus 48 Hexadezimalzeichen +- Erstellt Job mit Status pending + +- POST ask-jobs mit gültigem Prompt +- Antwort enthält jobId +- Statuscode ist 200 +- POST ask-jobs mit leerem Prompt +- Statuscode ist 400 +- POST ask-jobs mit zu langem Prompt +- Statuscode ist 413 +---------------------------------------- + +Auftragsereignisse abrufen + +Ermöglicht dem Client, Auftragsereignisse zu pollen + +- Unbekannte Auftrags-ID gibt HTTP 404 zurück +- Veraltete laufende Aufträge werden als fehlgeschlagen markiert +- Ereignisse nach after werden zurückgegeben + +- GET ask-jobs jobId events after 0 +- Antwort enthält status, events, lastEventId +- Unbekannte jobId gibt HTTP 404 +---------------------------------------- + +Auftragsstatus anzeigen + +Ermöglicht dem Admin, den aktuellen Status eines Auftrags ohne Seitenreload zu prüfen + +- ROLE_ADMIN_AREA erforderlich +- JSON mit id, type, status, startedAt, finishedAt, errorMessage, logPath +- 404 bei unbekannter Auftrags-ID + +- Detailseite eines Auftrags öffnen +- Statusabfrage per AJAX auslösen +- JSON mit status und Zeitstempeln empfangen +---------------------------------------- + +Auftragsstatus prüfen + +Ermöglicht das Prüfen des aktuellen Zustands eines Auftrags + +- jobId ist eine 48-stellige Hexadezimalzahl +- Ungültige jobId liefert Status missing +- Abgelaufene Aufträge werden als failed markiert +- Antwort enthält status, message, timestamps und serverTime + +- ask-jobs-Endpunkt mit jobId aufrufen +- JSON-Antwort mit Status prüfen +- Status pending, running, completed, interrupted oder failed zurückgegeben +---------------------------------------- + +Ingest-Job starten + +Startet einen bereitgestellten Ingest-Job über seine UUID + +- Job-ID als Pflichtargument erforderlich +- Job-Status muss ausführbar sein +- Abgeschlossene Jobs werden nicht erneut ausgeführt +- Dry-Run vermeidet Seiteneffekte +- Fehler führen zu FAILURE-Exitcode + +- Befehl mit gültiger Job-ID ausführen +- Job wird verarbeitet +- Erfolgsmeldung erscheint +---------------------------------------- + +Ingest-Jobs auflisten diff --git a/daten/RAG/backup.md b/daten/RAG/backup.md new file mode 100644 index 0000000..7d8afa6 --- /dev/null +++ b/daten/RAG/backup.md @@ -0,0 +1,97 @@ + +Backup +---------------------------------------- + +kern +---------------------------------------- + +Erstellt, prüft und stellt Backups bereit +---------------------------------------- + +- POST-Routen erfordern CSRF-Token +- Super Admin darf Restore-Prüfungen ausführen +- Flash-Meldung zeigt Status nach jeder Aktion +- Alle Prüfungen werden protokolliert +- Backup-IDs folgen dem Muster retriex-backup-Datum-Uhrzeit +- json gibt maschinenlesbare Ausgabe zurück +- Ungueltiges CSRF-Token zeigt Flash-Meldung +- Backup herunterladen mit "Neueste" waehlt aktuelles Backup +- Operator-Report als JSON exportieren +- Deployment-Scheduler-Pruefung mit Beschreibung in Flash-Meldung +- Sicherheit-und-Datenschutz-Pruefung mit Beschreibung in Flash-Meldung +- Backup-Dry-Run erwähnt fehlende Dateischreibweise in Flash-Meldung +---------------------------------------- + +Backup herunterladen + +Ermöglicht dem Super Admin das Herunterladen einer Sicherungsdatei + +- Nur Super Admin +- Backup-ID aus Liste oder "Neueste" +- Fehlgeschlagener Download zeigt Flash-Meldung +- Erfolgreicher Download protokolliert OperatorCheckProtocol + +- admin_enterprise_operations öffnen +- Backup-ID aus Liste auswählen +- Klick auf Download-Button +- Datei im Browser heruntergeladen +---------------------------------------- + +Backup starten + +Erstellt eine Sicherungskopie mit allen konfigurierten Quellen + +- CSRF-Token erforderlich +- Ablauf im Operator-Protokoll +- Flash-Meldung je nach Status +- Database-Dump als Option + +- Backup-Endpunkt per POST aufrufen +- _token und include_database_dump senden +- Flash-Meldung zeigt Status +- Backup erstellt +---------------------------------------- + +Backup-Tauglichkeit prüfen + +Prüft ob das System alle Voraussetzungen für Backup und Restore erfüllt + +- JSON-Ausgabe mit --json +- Tabelle zeigt alle Testfälle +- Rückgabe SUCCESS bei Status OK + +- Befehl mto:agent:enterprise:backup-restore-readiness ausführen +- Tabelle mit Testfällen prüfen +- Rückgabe SUCCESS bei Status OK +---------------------------------------- + +Backup-Trockenlauf prüfen + +Prüft die Wiederherstellbarkeit eines Backups ohne tatsächlichen Restore + +- Nur Super-Admin darf Funktion ausführen +- CSRF-Token wird geprüft +- Report wird im Prüfprotokoll aufgezeichnet +- Flash-Nachricht zeigt Status, Backup-ID und Anzahl Warnungen sowie Fehler + +- POST an admin enterprise restore dry-run latest +- Erfolg: Redirect zur Übersicht mit Flash-Nachricht +- Fehler: Redirect zur Übersicht mit Fehlermeldung +---------------------------------------- + +Backup-Wiederherstellung prüfen + +Prüft ob Backup-Pfad, Restore-Nachweis und Betreiberhinweise vorhanden sind + +- CSRF-Token erforderlich +- Flash-Meldung zeigt Zusammenfassung +- Protokolliert den Check + +- POST an /admin/enterprise/check/backup-restore +- ungültiges CSRF-Token senden +- Weiterleitung mit Fehlermeldung +- gültiges CSRF-Token senden +- Weiterleitung mit Zusammenfassung +---------------------------------------- + +Operatorbericht als JSON exportieren diff --git a/daten/RAG/benutzer.md b/daten/RAG/benutzer.md new file mode 100644 index 0000000..ea18020 --- /dev/null +++ b/daten/RAG/benutzer.md @@ -0,0 +1,89 @@ + +Benutzer +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht Super-Admins die Verwaltung aller Benutzer des Systems +---------------------------------------- + +- POST-Requests erfordern gültiges CSRF-Token +- Mindestens eine Rolle erforderlich +- Statusfilter akzeptiert nur all, active, inactive +- Statusfilter default bei ungueltigem Wert ist all +- Rollefilter default bei ungueltiger Rolle ist all +- Vorname ist optional +- Abteilung ist optional +- Passwort ist erforderlich +- is_active ist standardmaessig inaktiv +- Rollen werden als Array uebergeben +- Bearbeiten erfordert aktuellen Benutzer +- Benutzer-ID muss UUID-Format haben +---------------------------------------- + +Benutzer aktivieren + +Aktiviert oder deaktiviert einen Benutzer sofort + +- Nur ROLE_SUPER_ADMIN hat Zugriff +- POST mit gültigem CSRF-Token nötig +- Umschalten zwischen Aktiv und Inaktiv +- Redirect zur Übersicht nach Umschalten + +- Admin-Übersicht öffnen +- LMB auf Toggle-Button eines aktiven Benutzers +- Benutzer ist inaktiv +---------------------------------------- + +Benutzer anlegen + +Legt einen Anwendungsbenutzer über die Konsole an + +- E-Mail gültig und einmalig +- Passwort mindestens 8 Zeichen +- Passwort zweimal identisch eingegeben +- Mindestens eine Rolle zugewiesen + +- mto-agent-user-create aufrufen +- Ungültige E-Mail eingeben +- Validierungsfehler erwarten +- Gültige E-Mail eingeben +- Zu kurzes Passwort eingeben +- Validierungsfehler erwarten +- Passwort eingeben +- Anderes Passwort wiederholen +- Validierungsfehler erwarten +- Passwort wiederholen +- Rollen auswählen +- Benutzeraktivierung bestätigen +- Ausgabe zeigt E-Mail Rolle Aktiv +---------------------------------------- + +Benutzer auflisten + +Zeigt admin-seitig alle Benutzer mit Filteroptionen an + +- Nur Super-Admin darf zugreifen +- Filterung nach Suchbegriff, Status und Rolle +- Standardfilterung ohne Parameter zeigt alle + +- Seite /admin/users aufrufen +- Seite zeigt Benutzerliste mit Rollen und Status +- Filter auf Status "aktiv" setzen +- Liste zeigt nur aktive Benutzer +---------------------------------------- + +Benutzer bearbeiten + +Änderungen an Benutzerdaten speichern + +- Super Admin erforderlich +- CSRF-Token erforderlich +- E-Mail muss gültig sein +- Neues Passwort optional + +- Bearbeitungsseite für Benutzer öffnen +- Formular mit geänderten Daten absenden +- Erfolgsmeldung anzeigen +- Zur Übersicht redirect diff --git a/daten/RAG/berichte.md b/daten/RAG/berichte.md new file mode 100644 index 0000000..c18287b --- /dev/null +++ b/daten/RAG/berichte.md @@ -0,0 +1,90 @@ + +Berichte +---------------------------------------- + +kern +---------------------------------------- + +Berichte aus Enterprise-Diensten generieren, herunterladen und löschen +---------------------------------------- + +- Rolle SUPER_ADMIN statt EDITOR für Bericht als JSON herunterladen erforderlich +- Akzeptanzbericht generieren fehlt Ausgabe als Markdown für Nachweisprotokoll +- FAIL-Status: Exitcode 1 nur im JSON-Modus +- Operatorbericht als Markdown herunterladen fehlt als Funktion +---------------------------------------- + +Akzeptanzbericht generieren + +Zeigt zusammengefasste Ergebnisse der Operator-Prüfungen im Terminal + +- markdown-Option gibt Markdown aus +- json-Option gibt JSON aus +- Standardausgabe formatiert als Tabelle + +- Kommando mit markdown-Option ausführen +- Markdown-Tabelle erscheint +---------------------------------------- + +Bericht als JSON herunterladen + +Exportiert einen Batch-Bericht als JSON-Datei zum Speichern + +- Rolle EDITOR erforderlich +- Format muss json oder md sein +- Datei muss existieren + +- Batch-Übersicht öffnen +- LMB auf JSON-Download-Link eines Batch-Berichts +- Datei wird heruntergeladen +---------------------------------------- + +Bericht löschen + +Entfernt einen nicht mehr benötigten Batch-Bericht dauerhaft + +- POST-Methode erforderlich +- CSRF-Token obligatorisch +- Nur ROLE_EDITOR hat Zugriff +- Erfolgs- oder Warnmeldung als Flash +- Zur Berichte-Übersicht weitergeleitet + +- Batch-Bericht öffnen +- Löschen-Schaltfläche klicken +- Bestätigungsdialog bestätigen +- Zur Übersicht weitergeleitet +- Flash-Meldung 'gelöscht' sichtbar +---------------------------------------- + +Berichte auflisten + +Zeigt alle Batch-Importe zur Übersicht + +- listReports liefert alle Berichte +- defaultReportDir wird übergeben + +- GET admin knowledge-batches aufrufen +- Seite mit Berichtsliste wird angezeigt +---------------------------------------- + +Übersicht rendern + +Zeigt den Betriebszustand aller Enterprise-Komponenten auf einen Blick + +- Baut Berichte aller Enterprise-Dienste +- json gibt maschinenlesbares JSON aus +- Ohne Flag formatiert SymfonyStyle-Ausgabe +- FAIL-Status gibt Exitcode 1 zurück + +- php bin console mto:agent:enterprise:operations-overview --json +- JSON-Ausgabe enthält Felder status, progress, components, primary_action +- Exitcode ist 1 bei Status FAIL +---------------------------------------- + +Operatorbericht als Markdown herunterladen +---------------------------------------- + +Batch-Bericht hochladen +---------------------------------------- + +Batch-Bericht anzeigen diff --git a/daten/RAG/chat.md b/daten/RAG/chat.md new file mode 100644 index 0000000..aaf5b5e --- /dev/null +++ b/daten/RAG/chat.md @@ -0,0 +1,53 @@ + +Chat +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht authentifizierten Nutzern, Prompts zu senden und Antworten als Event-Stream zu empfangen +---------------------------------------- + +- Eigener Login-Bereich +- Upload-IDs werden gegen Client-ID validiert +- CHAT_HANDBOOK.md wird aus Projektverzeichnis gelesen +- Fehlende oder leere CHAT_HANDBOOK.md als nicht verfügbar +- Anonym bei fehlendem Namen +- Handbook maximal 512 KB +---------------------------------------- + +Abmelden ermöglichen + +- Abmelden wählen +- Anmeldung beendet +---------------------------------------- + +Chat streamen + +Liefert eine Chat-Antwort als kontinuierlichen Datenstrom im Browser + +- POST mit Prompt im Body +- Prompt zu lang: Stream mit error-Event +- Prompt leer: Stream mit error-Event +- Upload-IDs werden validiert +- Antwort im Format text event-stream +- retry: 3000 bei Verbindungsproblemen + +- Ask-SSE-Endpunkt mit gültigem Prompt ansprechen +- Daten-Chunks aus Stream empfangen +- event: done als Abschluss +---------------------------------------- + +Chatseite anzeigen + +Zeigt die Chatseite mit Prompt-Benutzername und Wissensraum-Auswahl + +- Liest CHAT_HANDBOOK.md aus dem Projektverzeichnis +- Fehlende oder leere Datei wird als nicht verfügbar behandelt +- Eigene Vorlage: chat index.html.twig + +- GET chat aufrufen +- Seite rendert ohne Fehler +- Prompt-Benutzername ist Anonym +- Wissensraum-Auswahl wird angezeigt +- Handbuch-Verfügbarkeit wird angezeigt diff --git a/daten/RAG/diagnose.md b/daten/RAG/diagnose.md new file mode 100644 index 0000000..dd908e2 --- /dev/null +++ b/daten/RAG/diagnose.md @@ -0,0 +1,386 @@ + +Diagnose +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht Betreibern die Überprüfung von Systemzustand, Konfiguration und Datenqualität ohne produktive Änderungen +---------------------------------------- + +- Alle Diagnosekommandos bieten --json-Ausgabe +- Exit-Code 0 spiegelt Status OK wider +- Exit-Code 1 zeigt Fehler oder Befunde an +- Diagnoseoperationen verändern keine Daten +- Kein Diagnosebefehl ruft LLM während der Prüfung auf +- MAX_LINE_BYTES = 2097152 +- limit-Option: Standardwert 10 +- Diagnostic-only-Hinweis im Footer +- Patchline-Pruefung bei Architecture Release Lock +- Genau ein AgentRunner-Boundary-Call sichtbar +---------------------------------------- + +Abdeckung prüfen + +Prüft ob gespeicherte Ingest-Facts eine Anfrage abdecken + +- Query muss nicht leer sein +- index.ndjson muss existieren +- Treffer nach State-Rang und Score sortiert +- json gibt maschinenlesbare Daten zurück + +- Command mit Query ausführen +- Diagnoseausgabe mit Abdeckungsdaten prüfen +- Command mit --json ausführen +- JSON-Struktur mit rows und summary prüfen +- Command mit --min-score und --limit ausführen +- Gefilterte Treffer nach Score geordnet +---------------------------------------- + +Abrufgrenzen prüfen + +Prüft ob Retrieval-Architekturgrenzen eingehalten werden + +- Required-Dateien sind vorhanden +- AgentRunner besitzt Retrieval-Orchestrierung +- Genau ein Boundary-Call in AgentRunner +- Boundary-Service bleibt dünn +- Flow bleibt trace-only +- ReadModel bleibt beschränkt +- PostCallFocus erweitert keinen Constructor +- RetrieverInterface bleibt minimal +- HybridRetriever bleibt in Retrieval-Layer +- Dokumentation sichert Architecture Release Lock + +- Command ausführen mit --json +- Ausgabe zeigt Status OK +---------------------------------------- + +Bereitschaftsbericht ausgeben + +Prüft Bereitschaft von Deployment und Scheduler und zeigt Ergebnisse an + +- json-Option gibt maschinenlesbares JSON aus +- Standardausgabe zeigt DefinitionList und Tabelle +- Exit-Code 0 bei Status OK + +- Befehl mit --json ausführen +- JSON-Ausgabe validieren +- Befehl ohne Option ausführen +- Tabelle mit Status OK prüfen +---------------------------------------- + +Datenqualität prüfen + +Prüft die Qualität von Text-Chunks im Original und nach Markdown-Umsetzung auf Datenverluste + +- Liest ausschließlich ohne Index-Schreibzugriff +- Kein Ranking und keine Antwortlogik +- Argument document-id ist erforderlich +- Option version wählt eine bestimmte Dokumentversion +- Option json liefert maschinenlesbare Ausgabe + +- php bin/console mto:agent:ingest:chunk-quality {uuid} +- Ausgabe zeigt Titel und ausgewählte Version +- Abschnitt Original zeigt Chunk-Profil +- Abschnitt Markdown zeigt Chunk-Profil +- Abschnitt Vergleich zeigt Kennzahlen und Delta +- Abschnitt Interpretation zeigt strukturierte Hinweise +---------------------------------------- + +Diagnose anzeigen + +Ermöglicht dem Administrator die MCP-Anbindungen und Wissensraum-Inhalte zu prüfen und zu verwalten + +- Nur Super-Administratoren haben Zugriff +- Vier Ansichten: Übersicht, Anbindung, Wissensräume, System +- Vorgangsvarianten werden als Flash-Meldungen zurückgemeldet +- Formularaktionen erfordern gültiges CSRF-Token +- Transienter Zustand wird über POST-GET-Redirect erhalten + +- Admin-MCP-Seite aufrufen +- Route antwortet mit Status 200 +- Übersicht der Anbindungen sichtbar +---------------------------------------- + +Genre-Hotspots prüfen + +Entdeckt genrespezifische Begriffe im Kerncode, die das Sprachmodell beeinflussen können + +- Ergebnis ist schreibgeschützt +- json gibt maschinenlesbare Daten aus +- strict gibt Nicht-Null-Exit-Code bei Befunden aus +- details zeigt alle Ergebniszeilen + +- Terminal öffnen +- Befehl ohne Parameter ausführen +- Zusammenfassung mit Befunden erscheint +---------------------------------------- + +Guard-Mechanismus prüfen + +Prüft die Guard-Implementierung ohne Seiteneffekte + +- Liest nur lokale Dateien +- Keine Runtime-Aufrufe +- Prüft 8 Testfälle + +- Befehl ausführen: mto:agent:proofing:unsupported-tool-term-guard-self-test +- Status OK in JSON-Ausgabe prüfen +- Alle 8 Testfälle bestanden +---------------------------------------- + +Hygieneregeln prüfen + +Prüft ob Batch-Hygieneregeln korrekt implementiert und nicht in die Antwortlaufzeit verdrahtet sind + +- source_noise_cleaner_entfernt_PDF_Restzeichen +- validator_entfernt_QUELLSEGMENT_Echo +- directory_cleanup_entfernt_leere_Admin-Upload_Ordner +- directory_cleanup_verschiebt_Legacy_failed_Eintraege +- batch_reports_sind_loeschbar_mit_CSRF_Schutz +- document_delete_bereinigt_physische_Dateien +- failed_skipped_resolvt_ausserhalb_inbox +- keine_Hygiene_Dienste_in_Antwortlaufzeit_verdrahtet + +- Befehl `mto:agent:knowledge:batch-hygiene-self-test` ausfuehren +- JSON-Ausgabe pruefen +- Alle Faelle Status OK +---------------------------------------- + +Indizierungszustand prüfen + +Prüft automatisch, ob der verzögerte Indizierungsvertrag in allen Dateien korrekt umgesetzt ist + +- Liest Controller, Services, Repositories und Templates ein +- Prüft 19 Vertragsfälle zum verzögerten Indizierungsworkflow +- Gibt Zusammenfassung oder strukturiertes JSON aus +- Gibt Erfolgscode bei allen bestandenen Fällen zurück + +- Befehl mit --json ausführen +- Ausgabe auf "OK" oder "FAILED" prüfen +- FEHLGESCHLAGEN: Case entfernt ungültigen startJob-Aufruf in activateVersion +- FEHLGESCHLAGEN: Case entfernt verzögertes setCurrentVersion in documentService +- Alle Cases bestanden: Rückgabewert Command::SUCCESS +---------------------------------------- + +Konfiguration prüfen + +Prüft ob alle RetrieX-Einstellungen gültig sind und zeigt Fehler oder Warnungen an + +- mto:agent:config:validate als Konsolenbefehl verfügbar +- Gibt Fehler und Warnungen aus +- json gibt maschinenlesbares Ergebnis aus +- Rückgabewert 0 bei gültiger Konfiguration +- Rückgabewert 1 bei ungültiger Konfiguration +- Regression Guardrails werden geprüft + +- php bin/console mto:agent:config:validate ausführen +- Ergebnis auf Fehler und Warnungen prüfen +- Exitcode prüfen +- Konfiguration gültig: Exitcode 0 +- php bin/console mto:agent:config:validate --json ausführen +- JSON-Ausgabe enthält status, errors, warnings +---------------------------------------- + +Provenienz prüfen + +Prüft ob Provenienzdiagnostik ohne Ranking- oder Antwortwirkung funktioniert + +- Liest Ingest-Service, Admin-Inspektor, Template und Styles +- Prüft Provenienz-Metadaten in NDJSON +- Prüft Diagnostik-Metadaten in NDJSON +- Prüft Sidecar-Lesen ohne LLM-Aufruf +- Prüft Admin-Ansicht mit Provenienz und Heading-Pfad +- Prüft Read-only-Label in UI +- Prüft Kein Antwort-Runtime-Einfluss +- Prüft Genre-Neutralität der Diagnostik + +- mto agent ingest markdown-derived-chunk-diagnostics-self-test ausführen +- Kommando endet erfolgreich +- Ausgabe zeigt status OK +- Alle 8 Cases zeigen status OK +---------------------------------------- + +Retrieval-Pipeline testen + +Ermöglicht die Überprüfung der Retrieval-Pipeline mit detailliertem Debug-Output + +- Prompt als Argument erforderlich +- Leerer Prompt erzeugt Fehler +- json gibt Rohdaten ohne Formatierung aus +- show-text zeigt ungekürzte Chunk-Texte + +- mto:agent:retrieval:test mit Prompt ausführen +- Ausgabe auf Pipeline-Summary prüfen +- mto:agent:retrieval:test --json ausführen +- JSON-Struktur mit duration_ms und results vorhanden +---------------------------------------- + +Retrieval-Qualität testen + +Prüft ob die Konfiguration passende Inhalte findet + +- Erfordert ROLE_KNOWLEDGE_ADMIN +- GET zeigt leere Maske +- POST führt TestRetrieval aus + +- Seite test-retrieval öffnen +- Prompt eingeben und absenden +- Ergebnisse werden angezeigt +---------------------------------------- + +Segmentierung prüfen + +Prüft ob Segmentierung korrekt ausgeführt wird + +- Liest alle relevanten Dateien ein +- Prüft required_files_present +- Prüft execution_uses_complete_segment_plan +- Prüft segment_prompt_is_fragment_only +- Prüft llm_called_per_segment_with_long_transport +- Prüft sidecar_records_segment_processing_without_raw_payloads +- Prüft generated_version_remains_inactive +- Prüft no_index_or_answer_runtime_wiring +- Prüft no_genre_runtime_gate_markers +- Report enthält Status und Zusammenfassung + +- mto:agent:ingest:segmented-markdown-normalization-self-test ausführen +- Status OK oder FAIL prüfen +- Testläufe als Zusammenfassung sehen +---------------------------------------- + +Shop-Suche testen + +Prüft die Shop-Suche mit detaillierter Ausgabe von Suchvorschau, Ergebnissen und optionalem Repair + +- Standard-Query: 'zeige mir produkte unter 5000 euro' +- repair aktiviert zusätzliche Search-Repair-Suche +- json gibt maschinenlesbare Ausgabe aus +- Primärsuche wird immer ausgeführt + +- mto:agent:test:shop-search ausführen +- Suchvorschau und Primärergebnisse prüfen +- mto:agent:test:shop-search laptop --repair ausführen +- Repair-Auswertung mit Ergebnissen prüfen +- mto:agent:test:shop-search laptop --json ausführen +- JSON-Ausgabe mit query, preview und repair prüfen +---------------------------------------- + +Sicherheitsstatus prüfen + +Prüft den Security- und Datenschutz-Bereitschaftsgrad ohne Seiteneffekte + +- Kommandoname: mto:agent:enterprise:security-data-protection-readiness +- json gibt maschinenlesbares JSON aus +- Erfolg bei Status OK +- Fehler bei Status nicht OK + +- php bin/console mto:agent:enterprise:security-data-protection-readiness +- Tabelle mit Cases wird ausgegeben +- php bin/console mto:agent:enterprise:security-data-protection-readiness --json +- JSON-Objekt wird ausgegeben +---------------------------------------- + +Stapel-Upload verifizieren + +Prüft die Integrität des Batch-Upload-Systems ohne Dokumente zu importieren + +- Trockenlauf ohne Dokumentenimport +- Ruft kein LLM auf +- Ändert keine Daten im Wissensspeicher +- Gibt maschinenlesbares JSON aus +- Prüft CSRF-Schutz, Dienstintegration und Fortschrittsanzeige +- Prüft PDF-Schutz, Speichergrenzen und Leerraum-Bereinigung +- Prüft CLI-Progress und keine Agent-Verschaltung + +- PHP-Befehl aus src Command KnowledgeBatchAdminUploadSelfTestCommand.php ausführen +- Alle 10 Cases in der Tabelle prüfen +- Jeder Case zeigt Status OK oder FAIL +---------------------------------------- + +Systemzustand prüfen + +Prüft NDJSON und FAISS-Konsistenz + +- Gibt JSON aus +- OK-Status gibt SUCCESS zurück +- Fehler-Status gibt FAILURE zurück + +- php bin console mto:agent:vector:health +- Konsistente Indices: OK-Status in JSON +- Fehler: FAILURE und Fehlermeldung in JSON +---------------------------------------- + +Tag-Index-Gesundheit prüfen + +Prüft die Konsistenz zwischen Tag-Daten und FAISS-Index + +- summary zeigt Zusammenfassung statt JSON +- Exitcode 0 bei Status OK oder OK_EMPTY +- Exitcode 1 bei allen anderen Status +- Prüft tags_ndjson_exists, vector_exists, meta_valid + +- bin console mto:agent:tag:health ausführen +- LMB auf --summary +- Zusammenfassung mit Status, Zählern und Gültigkeit +- Befehl mit Exitcode 0 beendet +---------------------------------------- + +Tags neu indizieren + +Echtzeitaktualisierung des Neuindizierungsfortschritts im Browser + +- Lädt alle 2 Sekunden neuen Status +- Sendet Ereignis nur bei Hash-Änderung +- Sendet Keepalive alle 10 Sekunden +- Endet bei Verbindungsabbruch + +- Stream-Endpunkt aufrufen +- MIME-Typ text event stream prüfen +- Antwortet mit Stream +- Event-Stream antwortet +---------------------------------------- + +Verankerung testen + +Diagnostiziert die Verankerung von Nachfolgedialogen in der Historie + +- Kein Laufzeitverhalten geändert +- Report als Text oder JSON ausgebbar +- sample führt integrierten Smoke-Test aus +- Historie aus Datei, STDIN oder Option lesbar + +- Sample-Dry-Run ausführen +- Text-Report auf erkennbaren Anker prüfen +- Kernprodukt und Nachfolgedialog identifizieren +---------------------------------------- + +Vergleichsgrenzen validieren + +Prueft, ob alle Dateien und Muster fuer die Chunk-Qualitaetsvalidierung vorhanden sind + +- Liest src Service Admin DocumentChunkQualityComparisonService php +- Liest src Command IngestChunkQualityCommand php +- Liest src Controller Admin DocumentController php +- Liest templates admin document show html twig +- Liest public assets styles base css +- Liest DocumentMarkdownSegmentationPlanService php +- Liest AgentRunner php und KnowledgeIngestService php +- Prueft Dateien auf vorhandene Strings mit str_contains +- Prueft Dateien auf abwesende Strings mit !str_contains +- Gibt FAIL zurueck sobald ein Fall fehlschlaegt +- x-Icon + +- php bin console mto agent ingest chunk-quality-self-test ausfuehren +- Rueckgabe auf vollstaendige Faelle pruefen +- Status OK bei allen gueltigen Implementierungen +---------------------------------------- + +Titelvorschläge-Selbsttest bereitstellen +---------------------------------------- + +Konfigurationsquellen prüfen +---------------------------------------- + +Batch-Markdown-Normalisierung testen diff --git a/daten/RAG/dokumente.md b/daten/RAG/dokumente.md new file mode 100644 index 0000000..19eafa7 --- /dev/null +++ b/daten/RAG/dokumente.md @@ -0,0 +1,127 @@ + +Dokumente +---------------------------------------- + +kern +---------------------------------------- + +Organisiert Dokumente mit Versionierung und prüft deren Bereitschaft für den Wissensindex +---------------------------------------- + +- POST-Operationen erfordern CSRF-Token +- Versionen absteigend nach Versionsnummer sortiert +- Fehler bei API-Routen liefern ok=false mit Meldung +- Dateien im konfigurierten Upload-Verzeichnis gespeichert +- Index-Neuaufbau erfordert bewusste Auslösung +- Titelvorschläge erzeugen: Endpunkt fehlt +- Version ableiten: Endpunkt fehlt +- Version aktivieren: Endpunkt fehlt +- Version ingest: Endpunkt fehlt +- Formularansicht GET fehlt +- TagController mit Tag erstellen, Tag entfernen, Tag zuweisen fehlt +---------------------------------------- + +Abschnitte laden + +Markiert eine Dokumentversion für den nächsten Index-Neuaufbau + +- Nur aktive Versionen sind zulässig +- CSRF-Token erforderlich +- Editor-Rolle erforderlich + +- Abschnitte über Admin-Endpunkt laden mit gültigem Token +- Aktive Version auswählen +- Erfolgsmeldung: Version für Index-Neuaufbau vorgemerkt +---------------------------------------- + +Abschnittsqualität laden + +Zeigt Qualitätskennzahlen der Textabschnitte einer Dokumentversion im Admin-Bereich + +- Benötigt ROLE_EDITOR +- Liefert JSON mit Qualitätsdaten +- Fehler liefert ok=false mit Fehlermeldung + +- Admin-Endpunkt abrufen +- Valides CSRF und Version vorhanden +- JSON mit ok=true und quality-Daten +---------------------------------------- + +Dokument anzeigen + +Zeigt alle Details eines Dokuments mit Versionshistorie und Qualitätsindikatoren + +- Nur Benutzer mit ROLE_EDITOR +- DocumentVersionPreviewService lädt Inhalt +- DocumentChunkInspectionService prüft Segmentierung +- DocumentMarkdownNormalizationInspector analysiert Markdown +- DocumentIndexReadinessService zeigt Indexbereitschaft + +- Admin-Dokumentenansicht öffnen +- Seite zeigt Dokument mit Versionen und Qualitätsdaten +- Chunk-Übersicht sichtbar +- Markdown-Normalisierungsstatus sichtbar +- Index-Bereitschaftsanzeige sichtbar +---------------------------------------- + +Dokument entfernen + +Entfernt ein Dokument dauerhaft aus dem System + +- Entfernt alle Versionen des Dokuments +- Loescht verknuepfte Ingest-Jobs +- Bereinigt zugeordnete Dateien + +- Entfernen-Knopf betaetigen +- Bestaetigung bestaetigen +- Dokument nicht mehr in Uebersicht +---------------------------------------- + +Dokument erstellen + +Erstellt ein neues Dokument aus einer hochgeladenen Datei + +- Erfordert Rolle ROLE_EDITOR +- Nur POST-Requests erzeugen ein Dokument +- CSRF-Token Pflicht +- Hochgeladene Datei Pflicht +- Titel Pflicht +- Titel maximal 255 Zeichen +- Dateiname normiert +- Datei gespeichert im konfigurierten Upload-Verzeichnis + +- Admin-Dokumente-Neu aufrufen +- Formular mit Datei und Titel absenden +- Erfolgsmeldung und Weiterleitung zur Dokumentdetailseite +---------------------------------------- + +Dokumente auflisten + +Zeigt alle Dokumente mit Statistiken und Filtern an + +- Filter werden aus URL-Parametern geladen +- Aktive Filter werden hervorgehoben +- Zeigt Statistiken zur Dokumentenübersicht +- Index-Bereitschaft wird angezeigt + +- admin/documents öffnet die Übersicht +- Dokumente werden mit Titeln angezeigt +- LMB auf Filterfeld +- Filterkriterium auswählen +- Ergebnis zeigt gefilterte Dokumente +---------------------------------------- + +Markdown bereinigen + +Erstellt eine normalisierte Markdown-Version aus dem Original + +- CSRF-Token erforderlich +- Neue Version ist inaktiv +- Abgeleitet von ausgewaehlter Version + +- Seite der Dokumentversion öffnen +- POST an markdown-normalize-Endpunkt senden +- Neue inaktive Version erzeugt +---------------------------------------- + +Version-Chunks abrufen diff --git a/daten/RAG/evaluation.md b/daten/RAG/evaluation.md new file mode 100644 index 0000000..79feecf --- /dev/null +++ b/daten/RAG/evaluation.md @@ -0,0 +1,100 @@ + +Evaluation +---------------------------------------- + +kern +---------------------------------------- + +Führt Testläufe für AI-Agenten aus und liefert strukturierte Berichte +---------------------------------------- + +- ROLE_KNOWLEDGE_ADMIN für alle Admin-Funktionen +- CSRF-Token für alle POST-Operationen +- Berichte als JSON-Dateien gespeichert +- Exitcode FAILURE bei einem oder mehr Fehlern +- Standardtyp retrieval ohne explizite Angabe +- Parallele Ausführung als Child-Prozesse +- Reportdateiname ist retrieval-last-run.json +- Meta-Review-Signale werden als PASS+REVIEW angezeigt +- json gibt den vollständigen Bericht als JSON aus +- no-write unterdrückt das Schreiben der Reportdatei +- list-cases listet Eval-Fälle ohne Ausführung +- duration-profile zeigt Laufzeitprofil der langsamsten Fälle +- jobs bestimmt die Anzahl paralleler Child-Prozesse +- Report enthält scheduled_children und max_running_children +- Report enthält wall_duration_ms und summed_case_duration_ms +- Fail-Fast im Parallelmodus ist soft und sammelt laufende Prozesse +---------------------------------------- + +Berichte bereinigen + +Entfernt alte oder alle Testläufe aus dem Dateisystem, um Speicherplatz freizugeben + +- Nur Admins mit ROLE_KNOWLEDGE_ADMIN +- POST nur mit gültigem CSRF-Token +- mode=trim löscht alle außer der letzten Konfiguration +- mode=delete_all löscht alle historischen Testläufe +- report_scope=all wirkt auf alle Bereiche + +- POST cleanup mit mode trim und CSRF-Token +- Erfolg zeigt gelöschte Anzahl +- POST cleanup mit mode delete_all +- Löschung bestätigt +---------------------------------------- + +Eval-Berichte anzeigen + +Ermöglicht das Anzeigen von Eval-Berichten mit Vergleich und Übersicht + +- ROLE_KNOWLEDGE_ADMIN erforderlich +- type-Parameter bestimmt den Berichtstyp +- scope und genre bestimmen den Eval-Kontext +- compare_report zeigt Vergleichsbericht an + +- Admin-Bereich öffnen +- GET admin evals aufrufen +- Bericht wird mit Übersicht angezeigt +---------------------------------------- + +Eval-Fälle ausführen + +Führt Eval-Fälle für den RetrieX-Agenten aus und meldet Ergebnisse + +- Selector enthält Typ und optional Ziel und Falltyp +- case führt nur den Eval-Fall mit dieser ID aus +- Report wird als JSON-Datei geschrieben +- Exitcode ist FAILURE bei einem oder mehr fehlgeschlagenen Fällen + +- mto:agent:eval:run retrieval ausführen +- Passende Eval-Fälle werden geladen +- Jeder Fall zeigt PASS oder FAIL mit Dauer +- Zusammenfassung zeigt total, passed, failed +---------------------------------------- + +Eval-Fälle parallelisieren + +Führt Eval-Fälle gleichzeitig in Child-Prozessen aus, um die Wandzeit zu verkürzen + +- Erstellt einen Pool mit maximal --jobs Child-Prozessen +- Terminiert überzählige Child-Prozesse bei Timeout +- Fail-Fast bricht das Scheduling nach dem ersten Fehler ab +- Ergebnisse werden in der ursprünglichen Reihenfolge zurückgegeben +- Child-Prozesse werden nach Abschluss bereinigt + +- Kommando mit --jobs 4 ausführen +- Läuft mit der angegebenen Anzahl paralleler Child-Prozesse +- Alle Fälle werden ausgeführt und Ergebnisse gesammelt +- Pool endet mit Ergebnissen in Eingabereihenfolge +---------------------------------------- + +Evaluation ausführen + +Führt Testsuite aus und zeigt das Ergebnis + +- Erfordert Rolle ROLE_KNOWLEDGE_ADMIN +- CSRF-Token erforderlich +- Flash zeigt Zusammenfassung mit Bestehensrate + +- Als Admin Rolle an AdminEvalController senden +- POST an Admin-Evals-Run mit gültigem _token +- Flash-Meldung zeigt Testergebnis diff --git a/daten/RAG/faelle.md b/daten/RAG/faelle.md new file mode 100644 index 0000000..148c764 --- /dev/null +++ b/daten/RAG/faelle.md @@ -0,0 +1,74 @@ + +Fälle +---------------------------------------- + +kern +---------------------------------------- + +Verwalten von Testfällen für das Evaluationssystem +---------------------------------------- + +- Jede POST-Operation erfordert ein gültiges CSRF-Token +- Leerer Entwurf wird bereitgestellt, wenn keine Quelle angegeben ist +- source_type und source_case_id erstellen Entwurf aus Testergebnis +- Erfolgreiches Erstellen leitet auf Indexseite um +- Index zeigt Zusammenfassung aller Fälle nach Typ +- type-Parameter defaultet auf 'retrieval' +- Wizard bietet leeren Entwurf zum Ausfüllen +- Wizard-Erstellung erfordert CSRF-Token +- case_delete erfordert eval_scope als separaten Parameter +---------------------------------------- + +Assistent anzeigen + +Führt durch die Erstellung eines Tests mit Hilfestellung + +- Erfordert ROLE_KNOWLEDGE_ADMIN +- Type ist retrieval, wenn nicht unterstützt +- Leerer Entwurf wird bereitgestellt + +- Admin-Evals-Cases-Wizard aufrufen +- Seite mit Assistent wird angezeigt +---------------------------------------- + +Fall anlegen + +Bereitet ein Formular zum Anlegen eines neuen Testfalls vor + +- Nur ROLE_KNOWLEDGE_ADMIN hat Zugriff +- Erstellt Entwurf aus existierendem Testergebnis bei source_type und source_case_id +- Erstellt leeren Entwurf ohne Quelle + +- Seite für neuen Fall aufrufen +- Formular mit Fall-Entwurf wird angezeigt +---------------------------------------- + +Fall erstellen + +Legt einen neuen Testfall an + +- CSRF-Token erforderlich +- ROLE_KNOWLEDGE_ADMIN erforderlich +- type, id und prompt sind Pflicht +- evalScope bestimmt core oder genre +- Genre ist kontextabhängig optional +- Erfolg leitet auf Indexseite um + +- admin evals cases new öffnen +- Formular ausfüllen und absenden +- Erfolgsmeldung erscheint +- Weiterleitung auf Indexseite +---------------------------------------- + +Fälle löschen bereitstellen + +Ermöglicht das Entfernen nicht mehr benötigter Tests + +- Nur Benutzer mit Rolle KNOWLEDGE_ADMIN +- POST mit gültigem CSRF-Token +- Erfordert type, case_id, eval_scope und _token + +- Seite mit Fall öffnen +- POST an admin-evals-cases-delete mit korrekten Parametern senden +- Flash-Meldung zeigt Bestätigung +- Weiterleitung zur Fall-Erstellungsseite diff --git a/daten/RAG/feedback.md b/daten/RAG/feedback.md new file mode 100644 index 0000000..9313d84 --- /dev/null +++ b/daten/RAG/feedback.md @@ -0,0 +1,128 @@ + +Feedback +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht Admins das Klassifizieren, Exportieren und Verwalten von Nutzerfeedback zu Chat-Antworten +---------------------------------------- + +- ROLE_KNOWLEDGE_ADMIN für Admin-Zugriff +- CSRF-Token für alle POST-Operationen +- Exportformate auf md und jsonl beschränkt +- Feedbackklassifizierung verarbeitet maximal 500 Einträge +- Feedbackklassifizierung begrenzt auf Limit 1–5000 +- Feedbackklassifizierung flushet in 100er-Schritten +- Batch-Statusaktualisierung begrenzt auf 5000 Einträge +- Batch-Status gilt für ausgewählte oder aktuell gefilterte Einträge +- Statistiken zeigen Zusammenfassung aller Fälle +- Statistiken zeigen Gesamt Daumen hoch Daumen runter Offen Erledigt +- Statistiken zeigen Fehlerverdacht, Review-Priorität und Referenzwert je Stufe +- Standardfilter zeigt aktive offene Fälle reviewState=active +---------------------------------------- + +Chat-Feedback anzeigen + +Zeigt Feedbackfälle mit Statistiken, Filtern und Sammelaktionen + +- Statistiken passen sich an Filter an +- Batch-Aktionen gelten nur für sichtbare Einträge +- Löschen entfernt den Eintrag dauerhaft +- Erledigte Fälle verbleiben als Historie + +- Seite über Sidebar öffnen +- Feedback-Tabelle mit Einträgen prüfen +- Filter 'Erledigt' wählen und anwenden +- Tabelle zeigt erledigte Einträge +---------------------------------------- + +Feedback exportieren + +Ermöglicht das Herunterladen von Feedback-Daten zur Analyse + +- Zugriff nur mit ROLE_KNOWLEDGE_ADMIN +- Nur md und jsonl erlaubt +- Dateiname enthält Priorität und Zeitstempel +- Streamt Daten zur Schonung des Speichers +- Content-Type passend zum Format +- Content-Disposition als Anhang + +- Export als md aufrufen +- Dateianhang mit korrektem Namen +- Inhalt ist Markdown +---------------------------------------- + +Feedback klassifizieren + +Wertet Feedback automatisch aus und ordnet es zur Admin-Prüfung ein + +- Batch-Verarbeitung in 100er-Schritten +- Limit zwischen 1 und 5000 +- force verarbeitet bereits klassifizierte Einträge +- Setzt type, score, risk, issue_risk, priority, reference, reason + +- Console-Befehl mto:agent:feedback:classify ausführen +- Verarbeitungszähler in Ausgabe prüfen +- Zusammenfassung nach Typen in Ausgabe +---------------------------------------- + +Feedback löschen + +Entfernt Feedback dauerhaft aus der Verwaltung + +- Nur ROLE_KNOWLEDGE_ADMIN +- CSRF-Token erforderlich +- Feedback muss existieren + +- admin_chat_feedback_show öffnen +- POST an admin_chat_feedback_delete mit gültigem Token +- Weiterleitung zur Übersicht +- Feedback nicht mehr in Liste +---------------------------------------- + +Feedback-Details anzeigen + +Zeigt alle Details eines Feedback-Falls an + +- Erfordert ROLE_KNOWLEDGE_ADMIN +- Feedback wird anhand der UUID geladen +- 404-Exception bei nicht gefundenem Feedback + +- Feedback-Endpunkt mit UUID aufrufen +- Feedback-Detailseite rendert +- Feedback-Objekt in Template verfügbar +---------------------------------------- + +Feedback-Status aktualisieren + +Markiert Feedback als erledigt oder öffnet es wieder + +- Status ist entweder erledigt oder offen +- CSRF-Token erforderlich +- Erledigt mit optionalem Review-Notiz +- Aktion endet mit Redirect + +- Detailseite öffnen +- Status-Button klicken +- Optional Review-Notiz eingeben +- Formular absenden +- Feedback mit aktualisiertem Status +---------------------------------------- + +Feedback-Status prüfen + +Prüft, ob Feedback zu einer Chat-Antwort bereits existiert + +- Ungültige Daten antworten mit HTTP 400 +- Fehler beim Abrufen antworten mit stored=false +- stored ist true bei vorhandenem Feedback +- stored ist false bei fehlendem Feedback + +- Anfrage an Feedback-Status-Endpunkt mit gültigen Daten senden +- Feedback in der Datenbank prüfen +- stored entspricht dem Ergebnis in der Datenbank +- FeedbackId und rating stimmen überein +---------------------------------------- + +Feedback speichern diff --git a/daten/RAG/knowledge-raeume.md b/daten/RAG/knowledge-raeume.md new file mode 100644 index 0000000..a995150 --- /dev/null +++ b/daten/RAG/knowledge-raeume.md @@ -0,0 +1,141 @@ + +Knowledge-Räume +---------------------------------------- + +kern +---------------------------------------- + +Stellt Knowledge-Räume bereit und verwaltet deren Inhalte sowie Anbindungen +---------------------------------------- + +- CSRF-Token wird bei POST-Anfragen geprüft +- no-report verhindert das Schreiben von Berichtsdateien +- Anbindung Tool-Allowlist aktualisiert separate Anbindung +---------------------------------------- + +Batch-Import durchführen + +Importiert Wissensdokumente aus einem Verzeichnis in den Wissensspeicher + +- upload-dir ist Zieldateiverzeichnis +- user-email identifiziert Ersteller +- activate-derived-on-success erfordert normalize-markdown +- dry-run erzeugt keine Dateien oder Versionen +- reindex startet genau einen Indexlauf +- Berichte ohne --no-report in report-dir + +- Batch-Import im Dry-Run-Modus ausführen +- PHPUnit-Test KnowledgeBatchImportCommandTest ausführen +- Erfolgsstatus und Reportdateien prüfen +---------------------------------------- + +Chat-Freigabe umschalten + +Aktiviert oder deaktiviert den Chat-Zugriff für einen gespeicherten Inhalt + +- Nur POST-Anfragen werden akzeptiert +- CSRF-Token wird geprüft +- Kanditat-ID muss existieren + +- Seite mit Anbindungsinhalten öffnen +- POST an Endpunkt senden +- candidate_id senden +- chat_enabled senden +- Übersicht wird angezeigt +---------------------------------------- + +Chat-Verfügbarkeit prüfen + +Schaltet den Chat-Zugriff für einen Wissensraum ein oder aus + +- POST-Request erforderlich +- CSRF-Token wird geprüft +- Ungültiges Token zeigt Fehlermeldung +- Unterscheidet Server-Ressource, gespeicherte Ressource und Standard-Raum +- Erfolgreiche Änderung zeigt Bestätigung + +- POST an admin_knowledge_spaces_chat_availability_update mit _token und chat_enabled +- Leerer RaumId liefert Flash danger +- Gültiger Toggle liefert Flash success +- Chat-Verfügbarkeit geändert +---------------------------------------- + +Facts prüfen + +Prüft die diagnostischen Ingest-Facts im Index auf Vollständigkeit und korrekte Struktur + +- type filtert nach spezifischem Fact-Typ +- query durchsucht Titel, Text und alle Fact-Felder +- Standard-Limit zeigt maximal 10 Chunks +- json gibt maschinenlesbare Ausgabe zurück +- Warnung bei fehlenden oder leeren Fakten + +- Befehl ohne Argumente ausführen +- Chunk-Überschriften mit Metriken prüfen +- Warnung bei leerem Ergebnis prüfen +---------------------------------------- + +Kandidaten wählen + +Wählt einen Tool- oder Resource-Kandidaten zur Wissensraumnutzung aus + +- CSRF-Token erforderlich +- Nur Tool- oder Resource-Kandidaten verarbeitbar +- Kandidat wird nach Auswahl auf approved gesetzt +- Weiterleitung zur Überblickansicht mit Review-Dialog + +- Überblickansicht öffnen +- POST an provider-candidate-select mit source_key, candidate_kind +- Flash-Nachricht über Erfolg oder Warnung +- Redirect zur Überblickansicht mit provider_review_open=1 +---------------------------------------- + +Knowledge-Räume anzeigen + +Stellt alle Knowledge-Räume mit Status und Anbindungen übersichtlich dar + +- Lädt Verfügbarkeit und Chat-Auswahl +- Lädt Anbindungsinhalte und Kandidaten +- Rendert admin knowledge-spaces index html-twig + +- Admin-Seite Knowledge-Räume aufrufen +- Seite mit Wissensraum-Übersicht prüfen +- Knowledge-Räume mit Verfügbarkeit angezeigt +---------------------------------------- + +Live-Vorschau laden + +Lädt Ressourceninhalt live zur Prüfung vor Freigabe + +- POST-Request mit gültigem CSRF-Token +- Gibt JSON mit Inhalt und Status zurück +- Nur für Ressourcen vom Typ resource verfügbar + +- POST an admin knowledge-spaces provider-resource-live-preview mit candidate_id +- Response enthält JSON mit ok und content +- Im Dialog erscheint der live gelesene Inhalt +---------------------------------------- + +Ressourcenprüfung durchführen +---------------------------------------- + +Textteile suchen + +Findet Textteile, die einer Suchanfrage semantisch ähneln + +- Gibt Treffer absteigend nach Ähnlichkeit zurück +- Limit wird auf maximal 200 begrenzt +- Optionale doc_ids filtern Treffer nach Dokument +- Ohne doc_ids werden Treffer aus allen Dokumenten zurückgegeben + +- POST such-chunks mit query und limit +- Antwort enthält sortierte Treffer mit chunk_id +---------------------------------------- + +Wissensräume prüfen + +Prüft die Funktionsfähigkeit aller Wissensraum-Komponenten + +- Admin-Übersicht öffnen +- Diagnose starten +- Alle Prüfungen bestanden diff --git a/daten/RAG/konfiguration.md b/daten/RAG/konfiguration.md new file mode 100644 index 0000000..68a45f6 --- /dev/null +++ b/daten/RAG/konfiguration.md @@ -0,0 +1,129 @@ + +Konfiguration +---------------------------------------- + +kern +---------------------------------------- + +Stellt Konfigurationsdaten für Ingest-Profile, Modelle, Chat-Nachrichten und Agent bereit +---------------------------------------- + +- ROLE_SUPER_ADMIN darf alle Funktionen aufrufen +- ROLE_KNOWLEDGE_ADMIN darf Konfigurationen lesen +- POST erfordert gültiges CSRF-Token +- Flash-Nachrichten zeigen Erfolg und Fehler +- JsonResponse ohne Browser-Cache-Header +- Default-Ausgabe ist JSON +- Ingest-Profil entfernen fehlt +- Model-Konfiguration löschen fehlt +- Model-Konfiguration Retrieval testen fehlt +---------------------------------------- + +Ingest-Profil anlegen + +Legt ein Ingest-Profil an, das Dokument-Importe steuert + +- Nur Super-Admin kann aufrufen +- CSRF-Token erforderlich +- Erfolgsmeldung bei Anlage + +- Seite admin-ingest-profiles-create öffnen +- Alle Felder ausfüllen +- Formular absenden +- Erfolgsmeldung bestätigt Anlage +---------------------------------------- + +Ingest-Profile anzeigen + +- ROLE_KNOWLEDGE_ADMIN erforderlich +- Tabelle mit Spalten +- Aktives Profil hervorgehoben + +- Admin-Bereich öffnen +- Seite "Ingest-Profiles" aufrufen +- Tabelle mit Profilen sichtbar +---------------------------------------- + +Konfiguration aktivieren + +Macht eine Konfiguration zur aktiven Konfiguration + +- Nur SUPER_ADMIN darf diese Funktion auslösen +- POST-Request erforderlich + +- admin_model_config_list öffnen +- POST-Request an activate-Endpunkt senden +- Weiterleitung zur Liste +- Konfiguration ist aktiv +---------------------------------------- + +Konfiguration anzeigen + +Zeigt die aktuelle RetrieX-Konfiguration zur Diagnose + +- Standardausgabe ist JSON +- summary zeigt formatierte Übersicht +- Zeigt alle Konfigurationsbereiche + +- Befehl ausführen: mto:agent:config:dump-effective +- JSON-Ausgabe mit Config-Struktur +---------------------------------------- + +Konfiguration bereitstellen + +Liefert dem Chatfrontend alle nötigen Konfigurationsdaten in einem Request + +- Keine Browser-Cache-Header +- JsonResponse mit Konfigurationsdaten +- Mischt Konfiguration aus drei Quellen + +- GET chat-messages-frontend +- Antwort ist JsonResponse +- Enthält limits.prompt und limits.uploads +- Keine Browser-Cache-Header gesetzt +---------------------------------------- + +Konfigurationen anzeigen + +Zeigt alle Model-Generation-Konfigurationen im Admin-Bereich + +- ROLE_KNOWLEDGE_ADMIN erforderlich + +- Admin-Endpoint für Model-Konfiguration aufrufen +- LMB auf Konfiguration in der Liste +- Liste der Konfigurationen sichtbar +---------------------------------------- + +Konfigurationsmuster prüfen + +Prüft alle PHP-Dateien auf Verwendung von Kernmustern und markierten Token + +- Ohne Option wird eine Zusammenfassung angezeigt +- json gibt das vollständige Ergebnis maschinenlesbar aus +- details zeigt die Warnungen als Tabelle +- all fügt niedrigpriore REVIEW-Befunde hinzu +- Fehlende Dateien werden als skipped_files gezählt + +- mto:agent:config:audit-patterns ausführen +- Zusammenfassung mit Zählern prüfen +- json anhängen und JSON-Struktur validieren +- details anhängen und Tabelle prüfen +- all anhängen und REVIEW-Zeilen prüfen +---------------------------------------- + +Tool-Freigaben aktualisieren + +Schaltet einzelne Werkzeuge einer Anbindung im Chat frei oder sperrt sie + +- Freigabe toggelt zwischen an und aus +- Ungültiges Token zeigt Fehlermeldung +- Erfolg zeigt Bestätigung +- Fehler zeigt Exception-Nachricht + +- Admin-Übersicht öffnen +- POST-Anfrage mit source_key, tool_name und tool_enabled senden +- Flash-Message prüfen +- Zurückleitung zur Übersicht +---------------------------------------- + +Ingest-Profil entfernen diff --git a/daten/RAG/logs.md b/daten/RAG/logs.md new file mode 100644 index 0000000..33fff19 --- /dev/null +++ b/daten/RAG/logs.md @@ -0,0 +1,46 @@ + +Logs +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht Superadmins das Einsehen und Durchsuchen von Systemprotokollen +---------------------------------------- + +- Logdateien liegen im Verzeichnis var log +- Systemlogdateien heißen system-JJJJ-MM-TT.log +- Letzte 1000 Zeilen werden gelesen +- Dateien werden rückwärts gelesen +- Fehlende Systemlogdatei wirft 404 +- Logdateien werden neueste zuerst aufgelistet +- AdminVectorLogController liest 500 Zeilen statt 1000 +- AdminVectorLogController zeigt Meldung statt 404 bei fehlender Datei +---------------------------------------- + +Logdatei anzeigen + +Zeigt den Inhalt einer Systemlogdatei an + +- Erfordert ROLE_SUPER_ADMIN +- Liest die letzten 1000 Zeilen der Datei +- Dateiname folgt dem Muster system-JJJJ-MM-TT.log +- Nicht vorhandene Datei erzeugt 404 +- Liest rückwärts vom Dateiende für Speichereffizienz + +- Route admin system-logs view 2024-01-15 aufrufen +- Seite mit Loginhalt wird angezeigt +- Datei existiert im Dateisystem unter var log +---------------------------------------- + +Logdateien auflisten + +Zeigt alle System-Logdateien zum Download oder zur Einsicht an + +- Nur ROLE_SUPER_ADMIN hat Zugriff +- Listet alle system*.log-Dateien auf +- Neueste Datei zuerst + +- Als Super-Admin anmelden +- admin system-logs aufrufen +- Logdateien absteigend nach Datum diff --git a/daten/RAG/sonstiges.md b/daten/RAG/sonstiges.md new file mode 100644 index 0000000..13a6d7a --- /dev/null +++ b/daten/RAG/sonstiges.md @@ -0,0 +1,64 @@ + +Sonstiges +---------------------------------------- + +kern +---------------------------------------- + +Bietet administrative Verwaltungsfunktionen für Profile, Sicherheitsprüfungen und Dokument-Tags +---------------------------------------- + +- Super-Admin-Rolle für Profile aktivieren und Sicherheitsprüfung +- Editor-Rolle für Tags speichern +- CSRF-Token für jeden POST-Aufruf geprüft +- Flash-Warnung bei ungültigem Token oder fehlerhafter Eingabe +- Erfolgreiche Prüfung leitet zur Übersicht weiter +- activate wirft AccessDeniedException, kein Flash bei ungültigem Token +- POST admin-enterprise-check-deployment-scheduler bereitstellen +- POST admin-enterprise-check-backup-restore bereitstellen +- POST admin-enterprise-restore-dry-run-latest bereitstellen +- GET admin-enterprise-operator-report-json bereitstellen +- GET IngestProfile-Liste bereitstellen +- GET Dokument-Tags bearbeiten bereitstellen +- GET Tag-Rebuild-Status abfragen bereitstellen +---------------------------------------- + +post activate {id} bereitstellen + +Macht ein Ingest-Profil zur aktiven Konfiguration + +- Nur Super-Admins +- CSRF-Token erforderlich + +- Admin-Bereich öffnen +- LMB auf "Aktivieren"-Schaltfläche +- Flash-Benachrichtigung zeigt Erfolg +- Profil in Liste als aktiv markiert +---------------------------------------- + +Sicherheitsnachweis bereitstellen + +Erfüllt die Nachweispflicht für Sicherheit und Datenschutz + +- CSRF-Token erforderlich +- Report aus lokaler Konfiguration +- Prüfung im Betreiberprotokoll erfasst +- Redirect zur Übersicht + +- Enterprise-Operations öffnen +- Prüfung für Sicherheit und Datenschutz auslösen +- Zurückleitung zur Übersicht mit Flash-Meldung +---------------------------------------- + +post {id} tags save bereitstellen + +Speichert Tag-Zuordnungen eines Dokuments und startet den Rebuild + +- Erfordert ROLE_EDITOR +- Prüft CSRF-Token +- Fehlerhafte Eingabe zeigt Flash-Warnung +- Erfolg zeigt Flash-Meldung und leitet weiter + +- Tags-Editor für Dokument öffnen +- Tag-IDs im Formular absenden +- Flash-Meldung "Tags wurden aktualisiert" sichtbar diff --git a/daten/RAG/system.md b/daten/RAG/system.md new file mode 100644 index 0000000..4c2ded1 --- /dev/null +++ b/daten/RAG/system.md @@ -0,0 +1,304 @@ + +System +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht Systemadministration, Betriebsvalidierung und Datenmanagement für Admins +---------------------------------------- + +- ROLE_ADMIN_AREA für Adminbereich +- ROLE_SUPER_ADMIN für Super-Admin-Funktionen +- ROLE_EDITOR für Bearbeitungsfunktionen +- Flash-Meldungen zeigen Operationsergebnisse +- Fehlgeschlagene Validierung bricht Operation ab +- Rollenabhängige Startseite nach Anmeldung +- Restore-Vorschau führt kein Restore aus +- Bestätigungsphrase "KNOWLEDGE ENDGÜLTIG LÖSCHEN" ist hardcoded +- Fehlermeldungstext "Die Anfrage konnte nicht verarbeitet" ist nicht dokumentiert +---------------------------------------- + +Access-Denied-Fehler bereitstellen + +Zeigt eine informative Fehlerseite mit kontextabhängigen Weiterleitungen an + +- Fehlercode 403 im Titel +- Rollenabhängige Startseite +- Anmeldung für Gäste +- Rolle "Chat" führt zum Chat +- Rolle "Admin" führt zum Dashboard + +- Seite ohne Anmeldung aufrufen +- Klick auf geschützte Ressource +- error403-Seite mit Anmelde-Button +---------------------------------------- + +Betriebsbereitschaft prüfen + +Validiert die Enterprise-Readiness-Baseline ohne Chat-Runtime-Nebeneffekte + +- Erkennt fehlende Readiness-, Doku-, Boundary-, Backup- und Command-Artefakte +- Prüft Quell-, Konfigurations-, Dokumentations- und Eval-Verzeichnisse +- Validiert alle Services-Imports in Services-Konfiguration +- Prüft Governance-Dokument auf Maintainability-, Readiness- und Genre-Neutralitätsmarker +- Validiert Enterprise-Dokumente auf Betriebsbaseline-Marker +- Prüft Console-Binary auf Vorhandensein +- Prüft Command-Referenz auf alle Enterprise-Commands +- Prüft zentrale Qualitätschecks in der Command-Referenz +- Warnt bei fehlenden oder nicht beschreibbaren Betriebsverzeichnissen + +- Command ausführen ohne Option +- Tabelle zeigt Status, Case und Details +- Alle Cases mit PASS erscheinen +- Command mit --json ausführen +- JSON-Objekt mit status, summary und cases erscheint +---------------------------------------- + +Cache leeren + +Leert den PHP-Runtime-Cache und den Vector-Service Query-Cache + +- POST erfordert gültiges CSRF-Token +- Erfolgreiches Leeren zeigt success-Flash +- Fehler zeigt danger-Flash und bricht ab + +- POST an admin-runtime-cache-clear mit korrektem _token +- Erfolgreicher Flash erscheint +- Redirect zu admin-dashboard +- Cache nach dem Leeren leer +---------------------------------------- + +Daten neu laden + +Synchronisiert alle Indizes und das Embedding-Modell mit dem Dateisystem + +- Lädt Chunk-Index neu +- Lädt Tag-Index neu +- Lädt Embedding-Modell neu +- Leert den Query-Cache +- Gibt Service-Stempel zurück +- HTTPException bei Fehler + +- POST-Reload-Endpunkt aufrufen +- 200 OK +- status: reloaded +---------------------------------------- + +Daten sichern + +Erstellt periodische Sicherungskopien, um Datenverlust zu verhindern + +- Kopiert Dateien ins Sicherungsverzeichnis +- Entfernt Sicherungen jenseits der Aufbewahrungsfrist +- Datenbankdump als optionale Sicherung +- Dry-Run validiert den Plan ohne zu schreiben +- JSON-Ausgabe für maschinelle Verarbeitung + +- mto:agent:enterprise:backup-run mit --json ausführen +- JSON-Status auf SUCCESS prüfen +- backup_id und target im JSON vorhanden +---------------------------------------- + +Deployment prüfen + +Prüft Deployment-Bereitschaft und protokolliert das Ergebnis + +- CSRF-Token wird geprüft +- DeploymentSchedulerReadinessService liefert Report +- Prüfung wird im OperatorCheckProtocol protokolliert +- Flash-Meldung zeigt Status der Prüfung + +- POST an Admin-Endpoint für Deployment-Prüfung senden +- Weiterleitung zu admin_enterprise_operations +- Flash-Meldung zeigt Deployment-Status +---------------------------------------- + +Dienststatus melden + +Ermöglicht die Überwachung der Betriebsbereitschaft des Dienstes + +- Gibt JSON zurück +- Enthält immer Status ok +- Enthält alle Komponentenzustände + +- GET an health-Endpunkt senden +- Antwort prüfen +- Status ok vorhanden +---------------------------------------- + +Flow-Grenze sperren + +Validiert die passive AgentRunner-Flow-Boundary-Linie ohne Runtime-Nebeneffekte + +- Prueft vollstaendige und geordnete Flow-Sections +- Validiert AgentRunContext gegen deklarierte Boundaries +- Prueft Boundary-Vertraege auf trace-only-Grenzen +- Prueft kritische Runtime-Eigner-Token im AgentRunner +- Prueft Flow-Qellen auf verbotene Runtime-Aufrufsignaturen +- Prueft Patchline-Dokumentation auf aktuellen Flow-Lock + +- Kommando `mto:agent:architecture:flow-boundary-lock-self-test` ausfuehren +- Alle Pruefungen bestaetigen OK +- Status OK zurueckgemeldet +---------------------------------------- + +Neuindizierung starten + +Startet eine vollständige Neuindizierung aller Inhalte als Hintergrundprozess + +- Erfordert ROLE_SUPER_ADMIN +- CSRF-Token wird geprüft +- Fehlgeschlagener Start zeigt Flash-Meldung und Weiterleitung + +- POST an Global-Reindex-Endpoint mit gültigem CSRF-Token absenden +- Redirect nach admin_job_show mit neuer Job-ID prüfen +- Flash-Meldung Global Reindex wurde gestartet prüfen +---------------------------------------- + +Normalisierung prüfen + +Prüft ob die Normalisierungs-Infrastruktur korrekt aufgebaut ist + +- required_files_present +- prompt_is_versioned_and_markdown_only +- llm_transport_is_fit_for_large_ingest_prompt +- segmented_execution_boundary_present +- foundation_is_not_wired_into_automatic_runtime +- provenance_sidecar_is_safe +- validator_cleans_wrapper_and_common_prose +- validator_sanitizes_segment_code_fence_markers +- validator_blocks_failure_answer +- validator_removes_source_echo_markers +- source_noise_cleaner_removes_binary_pdf_artifact_lines +- no_genre_runtime_gate_markers + +- mto:agent:ingest:markdown-normalization-foundation-self-test ausführen +- Alle Testfälle mit OK bestätigt +- Status OK im Report +---------------------------------------- + +Preview prüfen + +Validiert die korrekte Verdrahtung der Admin-Markdown-Normalisierung ohne Nebeneffekte + +- Liest Controller, Template und Inspector +- Prüft explizite Admin-Aktion ohne automatische Verdrahtung +- Prüft read-only Provenienz ohne Prompt- oder Raw-Speicherung +- Prüft genreneutrale Verdrahtung + +- Bin console mto:agent:ingest:markdown-normalization-preview-self-test ausführen +- Ausgabe auf Status OK prüfen +- Alle Testfälle bestanden +---------------------------------------- + +Promptversion aktivieren + +Macht eine gespeicherte Promptversion zur aktiven Version + +- Nur Super-Admins haben Zugriff +- Aktivierung durch POST-Request +- CSRF-Token wird geprüft +- Aktivierte Version wird als aktuell markiert +- Fehler zeigen eine Flash-Meldung + +- System-Prompt-Verwaltung öffnen +- LMB auf "Aktivieren" neben einer inaktiven Version +- Flash-Meldung "Version aktiviert" erscheint +- Version zeigt aktivierten Zustand +---------------------------------------- + +Promptversion löschen + +Entfernt eine nicht mehr benötigte Promptversion dauerhaft + +- Super Admin erforderlich +- Post-Request erforderlich + +- LMB auf Löschen-Button der Version +- Bestätigung bestätigen +- Erfolgsmeldung wird angezeigt +- Version nicht mehr in Liste +---------------------------------------- + +Promptversionen verwalten + +Erstellt neue Versionen und listet vorhandene auf + +- POST erstellt neue Version +- GET listet alle Versionen auf +- Aktive Version hervorgehoben +- Neueste Version zuerst sortiert + +- POST mit gültigen Daten absenden +- Erfolgsmeldung sichtbar +---------------------------------------- + +Restore-Vorschau prüfen + +Zeigt eine Vorschau des letzten Backups ohne Daten wiederherzustellen + +- Nur Super-Admin +- CSRF-Token erforderlich +- Kein Restore wird ausgeführt +- Ergebnis als Flash-Meldung + +- Als Super-Admin anmelden +- POST an Admin-Restore-Endpunkt dry-run latest +- Flash-Meldung mit Ergebnis +- Zurück zur Übersicht +---------------------------------------- + +Simulation ausführen + +Testet die MCP-Evidence-Sanilisierung ohne AgentRunner + +- JSON und Datei schließen sich gegenseitig aus +- Fehlende Eingabe lädt Fixture +- Rückgabe enthält sanitisiertes Payload und EvidenceItem + +- php bin\console mto:agent:mcp:evidence-dry-run --payload-json='{}' +- Befehl zeigt JSON-Ausgabe mit Status +- Status ist OK oder empty +---------------------------------------- + +Systemzustand zurücksetzen + +Setzt alle Dokumentversionen und den Wissensindex auf den Ausgangszustand zurück + +- Nur POST-Requests werden akzeptiert +- CSRF-Token wird geprüft +- Benutzer muss ROLE_EDITOR besitzen +- Löscht alle Dokumentversionen +- Setzt alle Ingest-Jobs zurück +- Leert den Wissensindex +- Gibt eine Bestätigungsmeldung aus + +- POST an Admin-Endpunkt zum Zurücksetzen senden +- CSRF-Token im Request mitgeben +- Erfolgsmeldung prüfen +- Alle Versionen und Ingest-Jobs entfernt +---------------------------------------- + +Verzeichnis bereinigen + +Hält den Eingangsbereich sauber und vermeidet vollaufende Speicher durch verwaiste Dateien + +- Nur POST erlaubt +- CSRF-Token erforderlich +- ROLE_EDITOR erforderlich +- Leere Upload-Ordner werden entfernt +- Alte fehlgeschlagene Ablagen werden verschoben +- Alte übersprungene Ablagen werden verschoben +- Warnungen als Flash-Meldungen ausgegeben + +- POST an Admin-Batch-Cleanup senden +- Gültiges CSRF-Token übergeben +- Berichtsübersicht öffnet sich +- Erfolgsmeldung mit Bereinigungszähler +---------------------------------------- + +Admin-Login bereitstellen +---------------------------------------- + +Fehlerseite anzeigen diff --git a/daten/RAG/tags.md b/daten/RAG/tags.md new file mode 100644 index 0000000..5573d32 --- /dev/null +++ b/daten/RAG/tags.md @@ -0,0 +1,63 @@ + +Tags +---------------------------------------- + +kern +---------------------------------------- + +Verwaltet verschlagwortbare Tags und stellt sie für die semantische Suche bereit +---------------------------------------- + +- Tag erstellen: Formular öffnen, ausfüllen, absenden +- Tag löschen: RMB, Klick auf Tag entfernen +- Tag zuweisen: Formular öffnen, Tag auswählen, speichern +---------------------------------------- + +Tag-Rebuild-Auftrag ausführen + +Erstellt Tag-Suchindex-Dateien + +- Lock verhindert gleichzeitige Ausführung +- tags.ndjson existiert nach Export +- Job endet mit Status completed oder failed +- Lock wird immer freigegeben + +- CLI-Befehl mit --create ausführen +- Job-Status ist running +- tags.ndjson existiert im Export-Verzeichnis +- vector_tags.index ist erstellt +- Job-Status ist completed +---------------------------------------- + +Tags auflisten + +Zeigt alle Tags im Administrationsbereich an + +- Nur für Benutzer mit ROLE_EDITOR sichtbar +- GET-Anfrage auf Admin-Tags-Endpunkt + +- GET-Anfrage an Admin-Tags-Endpunkt senden +- Seite mit Tag-Liste wird angezeigt +---------------------------------------- + +Tags bearbeiten + +- Funktion fehlt +---------------------------------------- + +Tags suchen + +- Ergebnisse nach Ähnlichkeit geordnet +- Enthält label und tag_type +- Optionale Filterung nach doc_ids +- Leerer Query führt zu Fehler + +- Suchanfrage mit query sales senden +- Antwort enthält Tags mit label +- Jedes Ergebnis hat tag_type +---------------------------------------- + +Tag-Zuordnung bearbeiten +---------------------------------------- + +Tag-Rebuild-Status abfragen diff --git a/daten/RAG/titel.md b/daten/RAG/titel.md new file mode 100644 index 0000000..0b7534b --- /dev/null +++ b/daten/RAG/titel.md @@ -0,0 +1,40 @@ + +Titel +---------------------------------------- + +kern +---------------------------------------- + +Ermöglicht das Ändern und Vorschlagen von Dokumenttiteln im Admin-Bereich +---------------------------------------- + +- Titeländerung ändert bestehende Versionen nicht +---------------------------------------- + +Titel aktualisieren + +Ändert den Titel eines Dokuments manuell + +- CSRF-Token erforderlich +- Titel nicht leer +- Titel maximal 255 Zeichen +- Bestehende Versionen unverändert + +- Seite mit Titel-Feld öffnen +- LMB auf Speichern-Button klicken +- Flash-Meldung zeigt Erfolg +- Neuer Titel in der Überschrift +---------------------------------------- + +Titelvorschläge laden + +Erhält auf Basis des Dokumentinhalts alternative Titelvorschläge + +- Editoren-Rolle erforderlich +- CSRF-Token wird geprüft +- Ohne Vorschläge wird Fehler zurückgegeben +- Rückgabe als JSON mit ok-Flag + +- Dokumentdetailseite öffnen +- LMB auf Titelvorschläge-Schaltfläche +- JSON mit Titelvorschlägen empfangen diff --git a/daten/RAG/uploads.md b/daten/RAG/uploads.md new file mode 100644 index 0000000..73420aa --- /dev/null +++ b/daten/RAG/uploads.md @@ -0,0 +1,75 @@ + +Uploads +---------------------------------------- + +kern +---------------------------------------- + +Verwaltet temporäre Datei-Uploads im Chat und persistente Batch-Uploads im Admin-Bereich +---------------------------------------- + +- Upload-Größenlimit liefert Status 413 +- Admin-Uploads erfordern Editor-Rolle +- CSRF-Token bei Admin-Upload geprüft +- Temporäre Uploads werden nach Ablauf gelöscht +- Batch-Reports als JSON und Markdown verfügbar +- Upload-Grenzen werden für das Frontend bereitgestellt +- limits enthält erlaubte Dateitypen, Grenzen pro Sitzung, Dateigröße und Ablaufzeit +---------------------------------------- + +Berechtigungsmodus ändern + +Ändert den Berechtigungsmodus eines Chat-Uploads auf einen erlaubten Wert + +- PATCH oder POST erforderlich +- clientId aus Request-Cookie ermittelt +- authorityMode aus Body gelesen +- Unbekannter Modus führt zu Fehler + +- PATCH auf Chat-Upload-Endpunkt mit authorityMode im Body senden +- Erfolg: status ok und aktualisierter Upload zurück +---------------------------------------- + +Datei hochladen + +Speichert eine Datei und gibt den aktuellen Upload-Status zurück + +- Nur eine Datei pro Anfrage erlaubt +- Dateityp und Größe werden geprüft +- Upload wird mit Client-ID verknüpft +- Fehler werden als JSON zurückgegeben +- Größenlimit-Überschreitung liefert Status 413 + +- POST chat-uploads mit Datei im Feld file +- Antwort enthält status ok und Upload-ID +- Anfrage ohne Datei gibt Fehler zurück +---------------------------------------- + +Upload entfernen + +Entfernt einzelne oder alle Uploads aus der Sitzung + +- DELETE entfernt Upload mit ID +- POST entfernt alle Uploads der Sitzung +- Unbekannte ID gibt Status missing +- Antwort enthält aktualisierte Upload-Liste + +- DELETE auf Upload-ID +- Status ok in Antwort +- Upload nicht mehr in Liste +- POST auf Leeren-Button +- Uploads-Liste leer +---------------------------------------- + +Uploads auflisten + +Zeigt verfügbare Uploads und deren Grenzen an + +- Löscht abgelaufene Uploads des Clients +- Liefert enabled-Flag +- Liefert Uploads des Clients +- Liefert alle Grenzen für das Frontend + +- Anfrage an Chat-Uploads senden +- JSON-Antwort prüfen +- enabled, uploads und limits vorhanden diff --git a/daten/RAG/verlauf.md b/daten/RAG/verlauf.md new file mode 100644 index 0000000..1efb6d0 --- /dev/null +++ b/daten/RAG/verlauf.md @@ -0,0 +1,57 @@ + +Verlauf +---------------------------------------- + +kern +---------------------------------------- + +Bietet Zugriff auf und Löschung von Gesprächsverläufen +---------------------------------------- + +- json-Ausgabe als JSON +- Löscht Konversation +- Löscht Commerce-Referenzen +- Löscht Uploads +- Badge fehlt +- sample Option nicht dokumentiert +- Testen für leere Eingabe fehlt +- Regel Nur eine Eingabequelle gleichzeitig nur dokumentiert nicht getestet +---------------------------------------- + +Verankerungen extrahieren + +Ermöglicht das Extrahieren strukturierter Verankerungen aus Konversationsverläufen + +- Liest Verlaufstext aus Argument, Datei oder STDIN +- Nur eine Eingabequelle gleichzeitig +- json gibt Ergebnis als JSON aus +- max-turns begrenzt die analysierten Turns + +- Befehl mit --sample ausführen +- Extrahierte Verankerungen im Ausgabetext +---------------------------------------- + +Verlauf abrufen + +Lädt gespeicherte Konversation zum Wiederherstellen der Chatansicht + +- Identität aus Cookie +- Rohdaten in Benachrichtigungen umgewandelt +- Leere Geschichte gibt leeres Array zurück + +- History-Endpunkt aufrufen +- Antwort prüfen +- Array mit role und text pro Nachricht +---------------------------------------- + +Verlauf löschen + +Entfernt alle Daten des aktuellen Clients aus dem Verlauf + +- POST-Endpoint +- Löscht Konversation, Commerce-Referenzen und Uploads +- Gibt {"status": "ok"} zurück + +- POST an history-delete senden +- Antwort prüfen: HTTP 200 +- Antwort enthält {"status": "ok"} diff --git a/daten/RAG/versionen.md b/daten/RAG/versionen.md new file mode 100644 index 0000000..32f4ca3 --- /dev/null +++ b/daten/RAG/versionen.md @@ -0,0 +1,75 @@ + +Versionen +---------------------------------------- + +kern +---------------------------------------- + +Verwaltet Versionen eines Dokuments mit Ablegen, Erstellen, Einlesen und Aktivieren +---------------------------------------- + +- Versionen absteigend nach Versionsnummer sortiert +- Preview-Daten als JSON mit ok-Feld +- Version-Aktivierung mit CSRF-Schutz +- Version-Aktivierung zeigt Flash-Nachricht +- Neue Version zeigt Flash-Nachricht +- Ableiten zeigt CSRF-Fehler bei ungültigem Token +- Ableiten zeigt Fehler bei leerem Inhalt +- Neue Version zeigt Fehler bei fehlender Datei +---------------------------------------- + +Version ableiten + +Erstellt eine neue Version aus bearbeitbaren Originaldaten + +- Lädt die Originaldaten-Vorschau der Quellversion +- POST erfordert gültiges CSRF-Token +- Neue Version ist nach Erstellung inaktiv +- Leerer Inhalt wird abgelehnt + +- Ableiten-Seite der Quellversion öffnen +- Bearbeitbaren Quelltext im Formular anzeigen +- POST mit Quelltext und CSRF-Token absenden +- Neue Dokumentversion erstellt und Redirect zu Dokument +---------------------------------------- + +Version einlesen + +- Gibt JSON mit Preview-Daten zurück +- Fehler als JSON mit ok: false + +- Dokument-Detailseite öffnen +- LMB auf Version klicken +- Vorschau-Request abwarten +- JSON enthält ok: true und preview +---------------------------------------- + +Version erstellen + +Ermöglicht das Hinzufügen einer neuen Dokumentversion + +- GET zeigt Formular mit Dokument-ID +- POST erfordert gültiges CSRF-Token +- POST erfordert hochgeladene Datei +- Hochgeladene Datei wird in Upload-Verzeichnis verschoben +- DocumentService erstellt neue Version + +- Admin-URL für neue Dokumentversion aufrufen +- Formular mit Datei und CSRF-Token POSTen +- Erfolgsmeldung Neue Dokumentversion wurde hochgeladen +- Weiterleitung auf Dokumentdetailseite +---------------------------------------- + +Versionvorschau anzeigen + +Zeigt den Originaltext einer Dokumentversion in einem ausschnitt an + +- LMB auf Version +- Zeigt Textausschnitt mit Offset und Limit + +- Dokumentdetail öffnen +- API version preview abrufen +- preview enthält Textausschnitt +---------------------------------------- + +Version aktivieren diff --git a/daten/TFT/.pruefung.json b/daten/TFT/.pruefung.json new file mode 100644 index 0000000..18207e0 --- /dev/null +++ b/daten/TFT/.pruefung.json @@ -0,0 +1,317 @@ +{ + "abdeckung": { + "bedienen:act": { + "abdruck": "965eccb9356235b1", + "funktion": "Shop sperren", + "trug": "b6a2ab03493b74c5" + }, + "bedienen:buy": { + "abdruck": "63c51977c098cde3", + "funktion": "Item kaufen", + "trug": "f3d6ca24335fa3b1" + }, + "bedienen:buyXp": { + "abdruck": "1a0c5247f488c54c", + "funktion": "XP kaufen", + "trug": "45683c6493a79b31" + }, + "bedienen:equip": { + "abdruck": "e9e549414ab5a0d1", + "funktion": "Einheit ausrüsten", + "trug": "8c6d6267f598e37d" + }, + "bedienen:move": { + "abdruck": "8ce9d559861ca921", + "funktion": "", + "trug": "" + }, + "bedienen:next": { + "abdruck": "0b481f13ca9aebf9", + "funktion": "Runde fortsetzen", + "trug": "45149ffb5a41db45" + }, + "bedienen:p": { + "abdruck": "88b57fbbc98d450c", + "funktion": "Gegner einblenden", + "trug": "b7192893969b60f4" + }, + "bedienen:pickAugment": { + "abdruck": "ba2ea2a567fcde9c", + "funktion": "Augment auswählen", + "trug": "7a76e5f3d13ef6d7" + }, + "bedienen:reroll": { + "abdruck": "fd56403509531bb6", + "funktion": "XP kaufen", + "trug": "45683c6493a79b31" + }, + "bedienen:start": { + "abdruck": "710cd74615808655", + "funktion": "Spiel starten", + "trug": "84ca0e724728251f" + }, + "befehl:autoplay": { + "abdruck": "7b035ff596c12934", + "funktion": "", + "trug": "" + }, + "befehl:build-artifact": { + "abdruck": "153fed8ab2aa1f5b", + "funktion": "Statische Daten herunterladen", + "trug": "8390b7b7807ab3f0" + }, + "befehl:calibrate": { + "abdruck": "e816c00e7793250b", + "funktion": "Ranglisten-Matches crawlen", + "trug": "a9e766bc343f6751" + }, + "befehl:crawl": { + "abdruck": "c9bb4cca017189c1", + "funktion": "Statische Daten herunterladen", + "trug": "8390b7b7807ab3f0" + }, + "befehl:extract": { + "abdruck": "9595995ee5598702", + "funktion": "Statische Daten herunterladen", + "trug": "8390b7b7807ab3f0" + }, + "befehl:fetch-static": { + "abdruck": "2207bccdebcd9aa4", + "funktion": "", + "trug": "" + }, + "befehl:refresh": { + "abdruck": "b8b8e201706f4c19", + "funktion": "Spiele automatisch spielen", + "trug": "3ef945fdc4f98631" + }, + "route:get /api/game/{game_id}": { + "abdruck": "7391585929a1342c", + "funktion": "Spielstand abrufen", + "trug": "85b87d6154b2363b" + }, + "route:get /health": { + "abdruck": "bf52cace58ae302a", + "funktion": "Systemzustand prüfen", + "trug": "3a72c3a11d536884" + }, + "route:post /api/game": { + "abdruck": "fe2b8a04ab08ae82", + "funktion": "Spiel starten", + "trug": "84ca0e724728251f" + }, + "route:post /api/game/{game_id}/action": { + "abdruck": "952a1c6a5b3a9372", + "funktion": "Spielaktion ausführen", + "trug": "274b16ec98a7a650" + } + }, + "belege": { + "[\"analyse\", \"Analysedaten generieren\"]": { + "abdruck": "6a39ed91dabae20c", + "beleg": "\"learned\": learned or {},", + "datei": "backend/tft/model/artifact.py" + }, + "[\"analyse\", \"Endboards erfassen\"]": { + "abdruck": "f8be70adea2b51f5", + "beleg": "def extract_all(conn, static: dict) -> tuple[int, Counter]:", + "datei": "backend/tft/matches/extract.py" + }, + "[\"analyse\", \"Platzierungen testen\"]": { + "abdruck": "ed43baf02f00a9f5", + "beleg": "def calibrate(conn, artifact: dict, holdout_only: bool = False, score_fn=None) -> dict:", + "datei": "backend/tft/model/calibrate.py" + }, + "[\"einheit\", \"Einheit ausrüsten\"]": { + "abdruck": "dc58e2411954a192", + "beleg": "def equip(p: PlayerState, item_idx: int, board_idx: int, artifact: dict | None = None) -> None:", + "datei": "backend/tft/sim/player.py" + }, + "[\"einheit\", \"Einheit verschieben\"]": { + "abdruck": "298448c773048dde", + "beleg": "def move(p: PlayerState, where: str, idx: int) -> None:\n src, dst = (p.bench, p.board) if where == \"bench\" else (p.board, p.bench)\n if not (0 <= idx < len(src)):\n raise InvalidAction(\"no unit there\")\n if dst is p.board and len(p.board) >= p.level:\n raise InvalidAction(\"board full for your level\")\n if dst is p.bench and len(p.bench) >= BENCH_SIZE:\n raise InvalidAction(\"bench full\")\n dst.append(src.pop(idx))", + "datei": "backend/tft/sim/player.py" + }, + "[\"pipeline\", \"Pipeline ausführen\"]": { + "abdruck": "55afc728ea543cb6", + "beleg": "for stage in (\"crawl\", \"extract\", \"build-artifact\", \"calibrate\"):", + "datei": "backend/tft/cli.py" + }, + "[\"pipeline\", \"Ranglisten-Matches crawlen\"]": { + "abdruck": "d91e117ee0d050a4", + "beleg": "def crawl(set_number: int, limit: int = 200) -> int:", + "datei": "backend/tft/matches/crawl.py" + }, + "[\"pipeline\", \"Statische Daten herunterladen\"]": { + "abdruck": "b558c5c5a5f4f2d9", + "beleg": "def fetch_static(set_override: int | None = None) -> dict:", + "datei": "backend/tft/staticdata/fetch.py" + }, + "[\"pipeline\", \"Systemzustand prüfen\"]": { + "abdruck": "895ac2187188eb0a", + "beleg": "@app.get(\"/health\")\ndef health() -> dict:\n return {\"status\": \"ok\"}", + "datei": "backend/tft/api/app.py" + }, + "[\"shop\", \"Augment auswählen\"]": { + "abdruck": "1e9f76ada85ce074", + "beleg": "def pick_augment(p: PlayerState, choice: int) -> None:\n if not p.augment_offer:\n raise InvalidAction(\"no augment offer\")\n if not (0 <= choice < len(p.augment_offer)):\n raise InvalidAction(\"invalid choice\")\n p.augments.append(p.augment_offer[choice])\n p.augment_offer = []", + "datei": "backend/tft/sim/player.py" + }, + "[\"shop\", \"Item kaufen\"]": { + "abdruck": "ab0dc67b859c1205", + "beleg": "def buy(p: PlayerState, slot: int, pool: Pool, artifact: dict) -> None:", + "datei": "backend/tft/sim/player.py" + }, + "[\"shop\", \"Shop aktualisieren\"]": { + "abdruck": "191c940daa30b69b", + "beleg": "def reroll(p: PlayerState, pool: Pool, cfg: dict, rng: random.Random) -> None:\n cost = cfg[\"shop\"][\"reroll_cost\"]\n if p.gold < cost:\n raise InvalidAction(\"not enough gold\")\n p.gold -= cost\n refresh_shop(p, pool, cfg, rng)", + "datei": "backend/tft/sim/player.py" + }, + "[\"shop\", \"Shop sperren\"]": { + "abdruck": "fe80becbfaa689c5", + "beleg": "def toggle_lock(self) -> None:\n self.player.shop_locked = not self.player.shop_locked", + "datei": "backend/tft/sim/game.py" + }, + "[\"shop\", \"XP kaufen\"]": { + "abdruck": "1b2d9644e3c6c09f", + "beleg": "def buy_xp(p: PlayerState, cfg: dict) -> None:\n xp = cfg[\"xp\"]\n if p.level >= xp[\"max_level\"]:\n raise InvalidAction(\"max level\")\n if p.gold < xp[\"buy_cost\"]:\n raise InvalidAction(\"not enough gold\")\n p.gold -= xp[\"buy_cost\"]\n p.level, p.xp = economy.apply_xp(p.level, p.xp, xp[\"buy_amount\"], cfg)", + "datei": "backend/tft/sim/player.py" + }, + "[\"spiel\", \"Gegner einblenden\"]": { + "abdruck": "302223719243056a", + "beleg": "@click=\"!p.is_player && (expanded = expanded === p.name ? null : p.name)\"", + "datei": "frontend/src/components/OpponentList.vue" + }, + "[\"spiel\", \"Runde fortsetzen\"]": { + "abdruck": "df80063512e078a7", + "beleg": "def step(self) -> None:\n \"\"\"Resolve the current round and advance to the next planning phase.\"\"\"", + "datei": "backend/tft/sim/game.py" + }, + "[\"spiel\", \"Spiel starten\"]": { + "abdruck": "1fa645dc09353d68", + "beleg": "@app.post(\"/api/game\")\ndef new_game(seed: int | None = None) -> dict:\n artifact, cfg = _load_game_deps()\n game_id = uuid.uuid4().hex[:8]\n GAMES[game_id] = Game(artifact, cfg, seed=seed)\n return {\"game_id\": game_id, **state(game_id)}", + "datei": "backend/tft/api/app.py" + }, + "[\"spiel\", \"Spielaktion ausführen\"]": { + "abdruck": "e113ab7b8e4f225b", + "beleg": "@app.post(\"/api/game/{game_id}/action\")\ndef action(game_id: str, req: ActionRequest) -> dict:", + "datei": "backend/tft/api/app.py" + }, + "[\"spiel\", \"Spiele automatisch spielen\"]": { + "abdruck": "e6d88c6931086b25", + "beleg": "def run(artifact: dict, cfg: dict, policy_name: str, n: int, seed: int = 1) -> dict:", + "datei": "backend/tft/sim/autoplay.py" + }, + "[\"spiel\", \"Spielstand abrufen\"]": { + "abdruck": "7c267f889cc18e5c", + "beleg": "def state(game_id: str) -> dict:", + "datei": "backend/tft/api/app.py" + } + }, + "ohne_code": {}, + "ohne_karte": {}, + "paare": {}, + "stil": { + "[\"analyse\", \"\"]": { + "abdruck": "36a5c535e2b6e294", + "probleme": [] + }, + "[\"analyse\", \"Analysedaten generieren\"]": { + "abdruck": "6c6136aa1f731cea", + "probleme": [] + }, + "[\"analyse\", \"Endboards erfassen\"]": { + "abdruck": "46ff85afaea26861", + "probleme": [] + }, + "[\"analyse\", \"Platzierungen testen\"]": { + "abdruck": "58f4097a7aad42b2", + "probleme": [] + }, + "[\"einheit\", \"\"]": { + "abdruck": "591f6d834b06521d", + "probleme": [] + }, + "[\"einheit\", \"Einheit ausrüsten\"]": { + "abdruck": "2b91a8a929caf2ea", + "probleme": [] + }, + "[\"einheit\", \"Einheit verschieben\"]": { + "abdruck": "0fa02b3c5370a837", + "probleme": [] + }, + "[\"pipeline\", \"\"]": { + "abdruck": "4c05ea483576379e", + "probleme": [] + }, + "[\"pipeline\", \"Pipeline ausführen\"]": { + "abdruck": "62c1b0e18d38c93e", + "probleme": [] + }, + "[\"pipeline\", \"Ranglisten-Matches crawlen\"]": { + "abdruck": "cfbaf9497a9ee888", + "probleme": [] + }, + "[\"pipeline\", \"Statische Daten herunterladen\"]": { + "abdruck": "a5527bcb3a8a8e95", + "probleme": [] + }, + "[\"pipeline\", \"Systemzustand prüfen\"]": { + "abdruck": "1bf0e238f72fcf45", + "probleme": [] + }, + "[\"shop\", \"\"]": { + "abdruck": "75b47d1052ed5c4c", + "probleme": [] + }, + "[\"shop\", \"Augment auswählen\"]": { + "abdruck": "39156336d367d481", + "probleme": [] + }, + "[\"shop\", \"Item kaufen\"]": { + "abdruck": "642d23d43adc285f", + "probleme": [] + }, + "[\"shop\", \"Shop aktualisieren\"]": { + "abdruck": "9a4c846ad728fba7", + "probleme": [] + }, + "[\"shop\", \"Shop sperren\"]": { + "abdruck": "45037477893cfe1e", + "probleme": [] + }, + "[\"shop\", \"XP kaufen\"]": { + "abdruck": "f39788167c4cc160", + "probleme": [] + }, + "[\"spiel\", \"\"]": { + "abdruck": "c9853896271c5be7", + "probleme": [] + }, + "[\"spiel\", \"Gegner einblenden\"]": { + "abdruck": "63d6fda80dd3b2d4", + "probleme": [] + }, + "[\"spiel\", \"Runde fortsetzen\"]": { + "abdruck": "cba0db2ace42f096", + "probleme": [] + }, + "[\"spiel\", \"Spiel starten\"]": { + "abdruck": "06a041341108c024", + "probleme": [] + }, + "[\"spiel\", \"Spielaktion ausführen\"]": { + "abdruck": "4c72ac35204cb4db", + "probleme": [] + }, + "[\"spiel\", \"Spiele automatisch spielen\"]": { + "abdruck": "63a5feadb6e87b2f", + "probleme": [] + }, + "[\"spiel\", \"Spielstand abrufen\"]": { + "abdruck": "3b51dd57c2d1e4e3", + "probleme": [] + } + }, + "verworfen": {} +} diff --git a/daten/TFT/analyse.md b/daten/TFT/analyse.md new file mode 100644 index 0000000..2bd3b7b --- /dev/null +++ b/daten/TFT/analyse.md @@ -0,0 +1,61 @@ + +Analyse +---------------------------------------- + +kern +---------------------------------------- + +Erzeugt ein trainiertes Modell aus Matchdaten und wertet dessen Vorhersagequalität aus +---------------------------------------- + +- Static-Daten sind Grundlage für alle weiteren Schritte +- Spearman-Korrelation misst Vorhersagequalität +- Holdout-Matches werden nicht zum Training genutzt +- Refresh führt alle Schritte sequenziell aus +- fetch-static lädt Community-Dragon-Daten herunter +- crawl lädt bis zu 200 neue Matches pro Lauf +- autoplay führt Spiele mit Policy aus Standard: econ +- autoplay führt 200 Spiele aus Standard +- refresh führt crawl extract build-artifact und calibrate aus +---------------------------------------- + +Analysedaten generieren + +Erstellt eine Analysedatei aus gelernten Spieldaten und statischen Daten + +- Ausgabe ist eine einzelne JSON-Datei +- Analyse enthält gelernte Statistiken pro Set +- Dateipfad wird ausgegeben + +- tft build-artifact ausführen +- artifact.json prüfen +- boards_learned_from enthält Anzahl +---------------------------------------- + +Endboards erfassen + +Extrahiert gespielte Boards aus Rohdaten der Datenbank für die Modellierung + +- Ein Aufruf pro Set +- Unbekannte IDs werden gezählt ausgegeben +- Erfolgsmeldung bei vollständiger Auflösung +- Kenntnis der Datenbankverbindung vorausgesetzt + +- tft extract ausführen +- Anzahl extrahierter Endboards prüfen +- Unbekannte IDs: Ausgabe vorhanden +- Alle IDs aufgelöst: Erfolgsmeldung vorhanden +---------------------------------------- + +Platzierungen testen + +Validierung der Prognosequalität des Modells anhand realer Platzierungen + +- Nur Holdout-Matches werden ausgewertet +- Vergleicht vorhergesagte Platzierung mit tatsächlicher Platzierung +- Ausgabe: Anzahl Holdout-Matches und Spearman-Korrelation +- Lädt aktuelles Artifact für das aktive Set + +- CLI: tft calibrate ausführen +- Ausgabe enthält holdout matches und spearman +- Spearman-Wert zwischen -1 und 1 diff --git a/daten/TFT/einheit.md b/daten/TFT/einheit.md new file mode 100644 index 0000000..bd7c96a --- /dev/null +++ b/daten/TFT/einheit.md @@ -0,0 +1,35 @@ + +Einheit +---------------------------------------- + +kern +---------------------------------------- + +- Einheit auf Board verkaufen +---------------------------------------- + +Einheit ausrüsten + +Weist ein ausgewähltes Item einer Einheit auf dem Board zu + +- Item ist ausgewählt +- Ziel ist eine Board-Einheit +- Item wird von der Itemleiste entfernt +- Unit zeigt das Item nach dem Ausrüsten + +- Item in Itemleiste anklicken +- LMB auf Board-Einheit +- Item auf Unitchip sichtbar +---------------------------------------- + +Einheit verschieben + +Vertauscht eine Bank-Einheit mit einer Brett-Einheit + +- Bewegt Einheit auf freien Brett-Platz +- Tauscht mit Einheit auf angeklicktem Brett-Platz + +- Board mit Einheit öffnen +- Bank mit Einheit öffnen +- LMB auf Bank-Einheit klicken +- Einheit auf Brett verschoben diff --git a/daten/TFT/pipeline.md b/daten/TFT/pipeline.md new file mode 100644 index 0000000..400a0fa --- /dev/null +++ b/daten/TFT/pipeline.md @@ -0,0 +1,60 @@ + +Pipeline +---------------------------------------- + +kern +---------------------------------------- + +- autoplay mit --policy und --games +---------------------------------------- + +Pipeline ausführen + +Führt Crawl, Extraktion, Build und Kalibrierung automatisch hintereinander aus + +- Führt vier Stages sequenziell aus +- Bricht bei Fehler in einer Stage ab +- Druckt Fortschritt für jede Stage +- Gibt den Fehlerort aus + +- tft refresh aufrufen +- Console zeigt alle vier Stages +- Alle Stages ohne Fehler +- refresh schließt erfolgreich +---------------------------------------- + +Ranglisten-Matches crawlen + +Holt neue Ranglisten-Matches von der Challenger- und GM-Leiter + +- Lädt maximal 200 neue Matches pro Lauf +- Nutzt Challenger- und GM-Spieler als Ausgangspunkt +- Bezieht Spieler-IDs aus der Rangliste + +- tft crawl ausführen +- Ausgabe prüfen +- Anzahl neuer Matches ausgegeben +---------------------------------------- + +Statische Daten herunterladen + +Lädt Einheiten, Traits, Items und Augments von Community Dragon herunter + +- Lädt Daten von Community Dragon herunter +- Nutzt aktuellen Set wenn kein --set angegeben +- Speichert Daten lokal unter paths.latest_static_pointer +- Gibt Set-Nummer, Patch und Elementanzahlen aus + +- Terminal öffnen +- tft fetch-static ausführen +- Ausgabe zeigt Set-Nummer, Patch und Elementanzahlen +- tft fetch-static --set 5 ausführen +- Ausgabe zeigt Set-5-Daten +---------------------------------------- + +Systemzustand prüfen + +- Gibt Status "ok" zurück + +- GET-Health-Endpunkt aufrufen +- Status ist ok diff --git a/daten/TFT/shop.md b/daten/TFT/shop.md new file mode 100644 index 0000000..44f3ca4 --- /dev/null +++ b/daten/TFT/shop.md @@ -0,0 +1,83 @@ + +Shop +---------------------------------------- + +kern +---------------------------------------- + +Bietet zufällige Champions zum Kaufen, Aktualisieren und Festhalten an +---------------------------------------- + +- Kostenfarben codieren Champion-Tiers +- Shop zeigt genau 3 Karten +- Kauf reduziert Gold um Kosten +- Kauf entfernt Karte dauerhaft aus dem Angebot +- Refresh kostet reroll_cost Gold +- Refresh zeigt neue zufällige Champions +- Gesperrter Shop behält Angebot zwischen Runden +- 🔒 zeigt gesperrten, 🔓 entsperrten Shop +- Owned Champions zeigen einen Schimmer-Effekt +- Unbezahlbare Karten sind leicht abgedunkelt +- Augment-Bereich zeigt "Augment wählen" als Überschrift +---------------------------------------- + +Augment auswählen + +Spieler wählt ein Augment aus den angebotenen Optionen + +- Drei Augmente zur Auswahl +- Augment-Karten nach Tier farblich markiert +- Gewähltes Augment wird sofort aktiviert + +- Augment-Auswahl öffnen +- LMB auf Augment-Karte +- Augment ausgewählt, Auswahl verschwunden +---------------------------------------- + +Item kaufen + +Fügt ein Item aus dem Shop zum Inventar hinzu + +- Kauf entfernt Item aus dem Shop +- Gold wird um Kosten reduziert + +- Karte im Shop anklicken +- Item im Board oder auf der Bank +- Goldbetrag um Kosten verringert +---------------------------------------- + +Shop aktualisieren + +Bietet neue Champions zum Kauf an + +- Kostet Shop-Gold aus `reroll_cost` +- Shop-Karten zeigen neue Zufallschampions + +- Genug Gold für Refresh bereitstellen +- LMB auf Refresh-Button +- Shop zeigt andere Champions +---------------------------------------- + +Shop sperren + +Verhindert das Kaufen und Rerollen im Shop zwischen zwei Runden + +- 🔒 bei gesperrtem Shop +- 🔓 bei entsperrtem Shop +- Gesperrter Shop behält sein Angebot + +- Shop-Button mit LMB klicken +- Shop ist gesperrt +---------------------------------------- + +XP kaufen + +Gibt XP zum Aufleveln des Spielers + +- Kostet Gold +- Button deaktiviert wenn xp_needed null +- Button deaktiviert wenn Gold < xp_cost + +- Anzeige von Gold und xp_cost prüfen +- Klick auf XP kaufen +- Gold reduziert, XP erhöht diff --git a/daten/TFT/spiel.md b/daten/TFT/spiel.md new file mode 100644 index 0000000..0313f6d --- /dev/null +++ b/daten/TFT/spiel.md @@ -0,0 +1,98 @@ + +Spiel +---------------------------------------- + +kern +---------------------------------------- + +Simuliert einen vollständigen TFT-Spielzug mit Gegnern, Shop und Kampf +---------------------------------------- + +- game_id ist 8-stelliger Hex-String +- Board enthält Einheiten mit Items +- Shop enthält Odds und Kosten +- XP zeigt Fortschritt zum Levelaufstieg +- Augment-Angebot erscheint in passenden Runden +- Kampf endet automatisch mit Zustandsänderungen bei allen Beteiligten +- Spieler HP auf 0 +- Letzte Runde vorbei +- buy_xp als Aktion +- pick_augment als Aktion +- lock als Aktion +- next als Aktion +- Augment-Auswahl zeigt gewählte Augmente +- Shop zeigt Upgrade-Hinweis für 2- und 3-Sterneinheit +- Spielstand enthält reroll_cost und xp_cost +- Spielstand enthält shop_locked und shop_odds +- Spielstand enthält xp und xp_needed +- Spielstand enthält streak +- Spielstand enthält Log der letzten 8 Einträge +- Spielstand enthält placement +- autoplay als eigene Funktion +---------------------------------------- + +Gegner einblenden + +Blickt in die Board-Aufstellung eines Gegners + +- Nur für Nicht-Spieler +- Gegner muss lebendig sein +- Gegner braucht Einheiten auf dem Board + +- LMB auf lebenden Gegner +- Scout-Bereich mit Einheiten-Icon erscheint +- Erneuter Klick blendet Scout aus +---------------------------------------- + +Runde fortsetzen + +Wechselt zur nächsten Spielphase oder löst den Kampf aus + +- Nächste Phase einleiten +- Kampf ▶ im PvP-Modus auslösen + +- Kampf-Button klicken +- Spielzustand fortgeschritten +---------------------------------------- + +Spiel starten + +Beginnt ein neues Spiel mit initialem Spielstand + +- Generiert eindeutige game_id +- Lädt statische Spieldaten +- Initialisiert Spieler und Bots +- Antwortet mit vollständigem Spielstand + +- LMB auf "Neues Spiel" +- Anfrage an Backend abwarten +- Splash-Bildschirm verschwindet, Spiel-Layout erscheint +---------------------------------------- + +Spielaktion ausführen + +Führt Aktionen wie Kaufen, Verkaufen und Bewegen im Spiel aus + +- 404 bei unbekannter Spiel-ID +- 400 bei unbekannter Aktion +- 400 bei ungültiger Aktion +- 400 bei fehlenden Parametern + +- POST an Spielaktion-Endpunkt mit action=buy und slot=0 +- 200 miterialisierter Spielstand zurück +- Aktion ungültig → 400 mit Fehlermeldung +---------------------------------------- + +Spiele automatisch spielen +---------------------------------------- + +Spielstand abrufen + +Gibt den aktuellen Spielstand als JSON zurück + +- Unbekannte game_id wirft HTTP 404 + +- GET auf ungültige game_id +- HTTP 404 mit Fehlermeldung +- GET auf gültige game_id +- HTTP 200 mit Spielstand diff --git a/frontend/k1-1024.png b/frontend/k1-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..42908400fc420eb7146be3657a3c24089d148e7a GIT binary patch literal 31614 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%0A`>tOa>_K(mW!_wJ@xI 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 literal 0 HcmV?d00001 diff --git a/frontend/k1-1280.png b/frontend/k1-1280.png new file mode 100644 index 0000000000000000000000000000000000000000..8c9cd1d50f59b468176fa4038548511e33ad6e41 GIT binary patch literal 32737 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≪O5~d z1aFaw$8?aI{HCLECW!y6m`?xeZ}E;$swp+rdw|Jbd4;;qyCWK?$;sCq;}E@{%Md=1 zrHp|4vqGrJ@1>&JAWVL;y7Q8uOd8FHJg=HcWcxttLRE2PrAA^E@!E-u0J?KJe4}p@ zT3Et>4q6bvIDYUM%C}2QXy}m}Z@lUsk5Jj9CnT53WQ%uyTWud%#?nydIc6A+&3&g(Lz7XDr~wN3$nG1F3KLTyaYlGJLSunc9(jz$wDK}T+9I`ow>PfB^UM3M* z#sB=z?sIS>)L=Gys_UBf1hoady6wkm@mfV!+m*52^=J^mN`7O} z(>qEJ-l>i2ObG$Itwjec*pEF1;lFcnY!|-^nLgfwQ{OUNo@o~5dU3f~lh$aBSMf1_ zR`-^tDb4lf3Whx($J1)HVRLM6PF%{rMvZz3Rh<7*jdeCZ<*<4xKmS|dNTjiNn#ZtP z#IC4)IqoQEg!x{L+Ei3>3-D-bEf}kf-dJPzseL1X(^_s{L{B2(_}6|`*PQqWJ7N_R z--KN!M|gXG4zDWOBHy2?+l@eCg`Cf?!cXwvlZnKOfzM&#HwUO}ySnRZWUxZ_KH1hp zwHG0A@CMn|ur~%?Iqr!L+gUqY5Y=ii<)X65-g5U%C~?%9sYjE29uarZ?zAt z#bz)jZ+OANX2aM4+Cc}4h8I~aps7!dU2}9^r2qf|WlWo2%`$fRj1D`AfLG`WCnf#B z)pALB-3Xhf??Ozs9W8*zf@aMmzGTr|$PkjOjaB%~PF+37a`xa!z7EZtJ=q#Yh0|U) zUir&#sZYSwDZvqa+{&Y&ZP&-FYC3lB+>aMrnkSY67;~s~s_ka?4=0Y2kzz9l5HPvK zj~e1F#_ur4`V;2RhbelEcmi5Cfe$7eT{Qa2NF0C8osEgcVZz33nhhnj_n(o!$0J$| zFy0x0h_c6l*P^}Vkl>`6y(!tHQtXK7s6d1q;?VQVm@ zqwjo5|7C2Uv^V#g+=39VNxJVT7q8fnd)M_`Htk8JrJ@Z&?)O6=iM2xImnON~*wKg^ z6VhrsZ6Utbg*HJYd3lh$SUg=)^#pwmXH~VTtApm3t4pvJgQ_05Meo`7O5$~$mMZ!E zylUYd_b?hQ(J!lCko3M&%HEjMSeTIU8(7)QjNqIyvLg?2NltyCF%4u^949L2ktv)B ztKr$;zX;##Lc3t|VRm?*>&TtNV$i$gczemJ& zu~r=ouqSJoUO;U3Oej6@*?QFReA{`YhnmZgI+FLSsDEaI04pmWFFeO$qP{c5$S3=M z&_1kyEX&nZw;UMFGulDi*l&fmUZIJ8r|#cN(`-eALA6`-)zhwaqB1 z1XGvh@c`%e-pXaSG1%JyEz>2%c15d9(H%FduXXSiC5N62b_SQJ#4_9Q`?jn7ijPq_ zrEg^6@%Wt-e@}KKB%f~8bTt_nUOgksFooFay;W&b0+SlQb*IiBe_cc0=`c(|0-3nR z5Sy5!%1NSbwFQn7JWI6N(`euKQ7aSM?}J9GUtj99-xKUp))@oyZqA5dvsYxom#aoZh9uFTzx6175<-FZUT6sv# zS#IvfyJbxO+P*A=a3qpn7GFO_q{3!gd3otWRv}+rUBd0&R|JSR=+n-O%fRy*M@eGF z+N}O$gnc9sNqhO56Q$^TWA$_bW3OMWw-P*5)G$XcLwC6)Rb9>JPQ_*Gz21}-=q0OF zSvNj#eOQ`Va}XLv!PNTL<-%=S$KD!rM(?k7Wr^LRT^%RCK2Y#U!y$i5mUR<8i8*(; z^o4sxIM-$sTOuq;#h90tPnA(!!Yk$mU4DVRu^rZ+E zW6R42@nL570P>3;eJ<#aazM}k#3`jjo}5%KQi1j6MSryS%E{+upa41A zW?6XhYR9F(+LnaKsp4cgnT*LPuf2#PyW;%d`FF<$p1gHlpBL?j(|4*@_eJ>kk|nOT z#bl;~fWY0>ZiKz?>D7Kfzu5*Kph84Lw++>oc_lKie!O)R_7yF!%>_;!owj>GsI1N* zBPY{;E(*Vl%8^t-C+B8@@{0AJmqT|LyEQF;QO6T!u5Xao!}ABV*WJMKb{gG$sSc?H zfTvyAH;Ywa$F7}K*Nuna%Vr;HB&x=FUz=500biV0IT?2>6PWp4+tKY!4k;7s+wqS4 z)-^HePz<=ao*h$l!-~U7$FDDxMiG$KT3OVH+fYcgxrk3&$xbZ9N44daJ>YbpbMNg* zQ0ryJ+HvXXsZQ6r38{%1HWAU~EjCd)4$(`PQr}&op06(GEi3enNQ9dFx=yM%bM|ID zjf**x4xOE*l^fhuGZQKC-cq68iLkJ&fAEZATwti?a$GCV<5m-yjS1Osw#cgAW^3}q zzQ5MwjbK#)$DWV54mEQ@ircD{ucj-pDoTHUgxlG29LM;2TS(7%nrJ8*y-bMi!GwvS z#LFC9?6d0f!0#wJ?W{TnY!^3ZXXXc@_12y^8CVM6uf=bI zHarLX8s}E>N)_4q9)96C^v$bF+TC;rN*Vr0Tr^N_4T_bvn)W(&*|P73-yYLI5R_x_)VK3<6`?B*L(8-fY89Rou;KBAD~{Lv2TgvhEbkNL&V8#tZzamvV~jz2jKC zbzC|yU%76w&YLSn&uYuGZo+uE!zUZ1eB6&_JkGfVaj1#C#v-^)R(sgQ^%CVb1;-Je z>x{eCm5@md7X|yR>TIf!e{#tMvOtTzaO7OHVl8=Q?jXVKYR- z;MXGTEy}*ETYVvVTjhb4U=oGerF+bq9rDRxI ztDln-7(A{e=^}{bS8Hl2{m1g_CbPI?D??&}9 zyEg4Z1^DpGnOxgSgas;|`#ko0fUkq6>1p<;tX7>UEpKk8N8@;d#H>U5Y=@LHwTcc= z)2RkXZ0%sVY;g3$-ouE&PK?$GYOhX=05=1@E61g20%sR-wLh+^Pw8gAJp6g&@+eY# zWo2DOvj5y_kecMdr>#ZHF>HzkLncR*a-*yJF9r>IAW5l##SG>Mfzl^`;W#oPAj%v0 z)|O2Zy%(Kl^Pqmx{vvs4w@E@vOFIT?a2>+Fsh*g#&w`53rShBbd6mpY}zin;LpXvZhiP z6`TL|DhIj!f}vH>ca=P*z`hL4ZR{~&H||PyKilH~%)RYfH$e;C zU{GcI_w8c`ajF2joj9NO@A2Mi?c99%Z!X~b<(GuPPU1>RDq2r3)?txP3A0|nw|3)! zS@7E$ph|TwAm;Z-d(@qiJ<|-}xmU{Ya7L8Dz9D*RZ<6>o={$^FTjf*J+Sxl2i-lZi zPP7YoOY~`LkC{-c6TNR$DhvT|d_SQM>HEpn;Q0wH_!C(5EXqc$XDByQ|l(vbb>I7e$0gAYJ#Q0w`Zj?JPxfjt<#Z`Nb-5idbtP;KCJIZ*13S=Y# z%F4{fs2M(K5j*&8MU+kAN{WkBhNkRadL9XblW%{1iT;$<(X7B5V7A=H*(pUHdlyiH zkqI~7M`a0n*OaKP4s~QDkM8d3Ce7w0*8GrzDoQ2dqc<)fyNDHR#qUW8D!j!GRUD{F z*Ze8bzq@P8mQXk56}9~~+Yl{Mi4()KYS0+s1;587Mri!N#r3TeC}n$lpdcYbJF{sS z>jWWYjX$A%U6V=kyU+j7B<&HZ!6Cu6YU+P@g@5T6_GoBUKoR8It(P7a92wt)0jZ4t z{7tXW=AgD=m8MKiSwa1B$Hf7Leo-5K5yUm(S0JSjh6~H%sFtP6(x^f;b?;hYz+2A0 z$s4IzD!6P2t$bW!ff?CkU3Pt?$FmH+mxOo#ihuJr-gP}zX4O&ikTCnBX$X*0)very z;_@dnwePda%G$6BzI|DT<8^5MCV==+IVUk#$Q(J~0sJDl25A1+008`dlL^wVjcZC* zr&j7d0pQj5*&^awfYdL4az_@mmt7y@zKiw85oUj%|2KbnoF9}F~~15yJb7A{u= z-r=a!!2eB5a5+)gi7ItEWPS4xR9<(MQ1;uKqDL&@$e0BEYbr~S@sybfIQl1K{&PEQ zB2hD4Huzz%Hy_GzfV{xrrofz%Uw+d-pj73v>DW1Xa^nGC0hcK}=|~fqTC7%{zO*#C zN;UX}N@`T2kCJ+}Apbp~$8;$VP^K3?Q_7>R0}j!R(;JD?BLJjo9lMpz#Og5N`q_P* zQ5cm7#f^gaMEbocOE1yWwO5?opMND*Ti7iXDhZW(?|rT&;xz3uK)NP2|B)Z$gi!6W zj`wpdjDpFq`u+=vj}wUOhZXh8qj49Hwn9Q5QT>BBZt#yB)#%t*gw;h^jwGGVb^kWF zq642LBZaGn{t8dhG#bClSk7=3TvX>T7s+Xv5`dHFYkoKam|gYz5JOj zqW5(|%|xeKac#WgOTJCj-r{e2n|XZ`HylT6UXW3++9+;@*sFL97>ewgMpUz!XaN=z ztRn%kxq1lCz#zf6ec}fZXHras(|Pn;*@&SRjCFj{l*-teuXO>ek#Eush}2>FiLx*} zx+{$i&JB7lMEKb)od?cuE$TAe_NZvqZ1ks_n#EqYO!Yu13BWISQ-NRuAv8>&sEQB3mzV+!OE#2Q)-JsujOErf^OJ2hbQ!h zzuKU0%$dZfW1pO0f->s!2>@N*b8P5UZvRK`LXOctow2ib|4^!(%x19yl{rbxsKLqX5o3hSk6x&J ztO&V>OyW?LZz!<*&B66g^=38ncynq>mS+34l^zNooRnNFavy(4_v7uEonH3YUsg{5 zL&k**CL^>Q``hp*IBq!iKj0dKp~=lzX0%C)lK3q>6ye7U%F(Ea^<2mmXO%FEacp~#vgc}BKoPF!+C@@z-+ zJIY2V`Wb)2Q}z0p_xqD(gn{6nk1?R`4=YIz#53HMl2(`{!ygLmpL1y zk)HGR#DRx7)(S_Yv0x?8m7}ZS?g3&{S_Q2noB22d=>hgTE0iCk5q*=#;Cyua(5+Va z3X+&uv$O2mzp<)`Wzch`Jm~PX7C^Vpz7!dQ%&RSqsFHN;k_w(g)O5q!J*Y<}cg7Mq zi65;_dVP@5`(*toc?vmtBTF1t&TeAvZ3~Z(onUBuX4QEA{U81$4{^IW{)Aee_UVX; zt@2tiV`~tivT+eDK@!m8%ZA9d72cL1V!TAb6g-smbqJ9drDY2Eu$q+RQD8bwFN16~ zEH*-KmSB_)3!<{y&JH56OCK&F-pH!>SACj?TV1b?UE%XLf$}%6l5Ht02X<`P)_~(% zhrVR@0hV|j3{QRDHbQ$6WFOsXs+@3@m|L!^t*!H_$+zR2nTsoTzK{e*e7Q)m=bV(+ zZFIIMbnl`J0F6B-&4y53>`)V3afFF_(XJPLRnxQ6TVac*L{3}oXBW|ncWR4kPCIcTw4&|a`)%mNfGcFkvZMS z+HdQEuM9TwN|4CjzjoBRIdZ9F?Ukm&?syq5Cc@;1RO$6$T*tK$^$>$b(Ul#0C_y6d zM=V`p(mC>UhFkvh#@w*aiwoqaJt>hO_N*s ziZ+nI!c2{24d$$HV!>@~A8YL6QK>?DdfD7+ z@Pyia_e_PGA+1aZr6do|zJ%dl$}DJZWz>FQtR zbnMivTc^Fxy>c_vn8RsGo+|i@rrvThaPA<@LT%FN?la6x?!%0wDF5M(raKPe%Le*B;d*OD~MrItmOyqMP-b_lDXe- zIJ6wh(^2K+b4|ux6W#KxzVN`@4nW~MtSjU?^&3e33%4# zId*vsTh%J?u_8vi+i6{k)X>W%^~xRp+f# zt+L8e&9}wl;q@}BJP1V}uH9bN|B-dLI+q{0Rh}SGTeZ)NaL3|h?F?RwG*+c$1GYsc zBzE0l5;Q6?*v)O>iXYJs6nbCpjoCC6s_D4}{QVImS&W16Y?b|N-Js|=jxz>9?mh8s z%?SK*L<+%uTwd%Vu0l~f7Vp1@9OcJW7k|B3^o46b%PR%#CLYKe8+x~Rl{2xwQLG-W zduua3f7AMXYoH!-VWaP3ERTx(8WqDHa!d}HQLFf@PrE;LC98gVGwWcpu(3)d_|K#% zZ;IB89*#N~9n*Aut08JyvRx-}uYjur>dlWdAT{3BgNtc!f}m3x z`cvhl4yWJTy7iC#Sl~GQN&!!o46(O$af$_BZ*%IX`&52x&04e#UxF~_dfr}T+YvGyf5!q zxh$OOL9G^bBsoW|KdUWOS=18^+Yw6t3+uq?L=aPDm9;6ypB?~WLjXiIk8^K2`;z(F zYTl02mrJ3i1cmmUNIdl#QpPD6s&hBt5(zPKNwvxrPiKZGm`I|Pvn9^mLqZo^I>z@I z_oc+-bRStE1$|UYd@TVwSA^Q@80)OPh@1!?yp48vx|G#YU|EJ{h zR6$lb*mN)FnM$&fu2jc$W@$u(3jfo8wPYNGc;u_%$yC@`*u*dr_KD*| z;txv^k{nu59tFfWeDLr81)Lk3e%5fAEP6la9UWufyqACaA3c$}8uvXuGaW=TxC8%Z zDec_0(6{dD+;INlk{GDV zfmGzetz4$l0;A#sLLU4pg<5rAq>rkSuZXGr5jM>5l;7fX;nXu5F1GK|-1hqm>tXRw z)W)h@-Qcpf7`$=+*_VY(f>A=DdrHow?F>aBIaS%8V~R{Ur8_=+&vP?xo?&rH1nu!O zdc6L~N|ndJx;gH@)6|WH9CE=Y`2OkZFEK_8JbGm}mFFHFMq}8eiQvCExI6jnREud) z38Sr4Atoy2>*!U1E%Pj>)pKC@%U1w&^O#tc^mW{3G=CKoycSM&mz>`GqsSGKX60wf zqVWG{xkb*}r+Ga#MIbz$#;w#EBL)qzUBHwxzV@xam!pwS z=q)f#05~xUIvfbSi4TNGi3a+g*HGNCiOIATSv2Y5twEDGR*^|K^Wb>!ZiBFc=z)3s zzu5~-WR?j9kJMw6i(hB(aDD9gDW_Sk0vszcpHpdG%i2B>8(to>A!kSZqSkl8=tfpA z)kfSS{FcKw2+4D=qaKq2^f&*9yJzTn^6AdLG$>Pwr zW5q2AA8wuZ(My{`_7 zdfomVEEEJ(N|c#B_s&dj}Wq@Utb0sGM$m*L6wsy8|VYc@UJ-dZ{+p z^NU}@8{V9Tr+S^GJ+wSPdji{IGe15d%fplw2tvl?>eGVMB5M~fp!~8|g1?!p*IoIs zYVi_Qnkel2Q}s~LT~ZkjH`GrmA(<7CO^KqXV`UKfYH3AZw!w0f`R-W9@O(UPqaAT3 zQ|$oX%JzfR#!joNYozQ`TE)HtncliqXAh4XW9$mCw-yOkSw4prdP_lsH1q0@u&qPs zkDKhbR@wC`3Z>xZj&qO4lH854j}HjmzuqfQdufkBs`Fe0QlD}TbiIu8>`v>ai+f}9 zM;_{9C0sV1$TJ32|MOU3p>B!0Zr|GQm0f+$6DzST@Dj~h@s)2Jtsf_pZUS`?1-(cb zFfxhBS{SYc<9zYJPd>);%ku?8hJ=<4fHA(F8^Qv7Umy>anXbBb9F091PSkBcA;w~fAlF;8i1^jeunlID z)#W!tiSu{tqxnbi`Qa zvI3f9TZyrCv3nmU>wgxwN_s zpO=jYwMHy7Uhjh>!1?lnL__RwWm~EijWujLAE!IF*;r;ke|#WK(mZ9q;ir)_R)lE27;zO0rAun#hCyR)M)yNd+Eqq=;&arlZ{Q(bzXAGk94R!T%*2+y zCqqPZ+u1nGF&pGZVmS6;Oo>X!xvWB}w)ZkxGHIMwG{rCHzpQA^6pP(D**O)uDll~g z#AEF-6W0y9v6I}-&=3O$p`AO-sbB3JHl~-F`Im&OXX}KVdOQI%DF8{OJnY$s--7EO ztBW1_i0|pFy3V4%@i`TGSYYws0%>1feAf(F%ISmc!lmdg#qZh?R8%x2_#1U#hkDhT zyfC2CP)jzl;n%MQU;M2h+mrnJ=7})p=yQLt^L6i+z`Z~pp7;eWFIZjCELHVg$z})_ zb>-9pi93C%Unr!C@G)@q3YSq11{~gW;%w-r16IYYXX%HWj1LZcN)vhrHS5*Rq&zdz z{iJHBRVK_OX<~q){9W#B7W$v1CW##H~Zk~QY3kuhvJV7 z5NU8)AmNZX*)sJVk_pWMdv^I?@m**n=vKyIm7LUd<+zuk`*Te2DYXJ{#rp7UO>`n` z^i5$1$j;`d&3F9Rbf{U8@7X>8P>tMM7j46nfhpwSCw7dBD$oEv2j2rvoh zi2%VnVEe**O_I9<9Uhv7)+Y3Xx*qkfUF0vJ3&5 zeuxnti=^N05*mYi7L36lZ+&{xMTq`f2jC)%PX0w)US)uNl;6xUCC*wRCMJ$0j*XpP zEiNxEE-!zsr3J}9{D6K{3of9}<7cL%1P#qv$}V+uKz0mhO1q;gQYEtEnmV$~EV#I6 zqy2${ogPHNw7Q#! zfdX1#&|6+(DcxzIu1a=e4eA0h1~8IQ%-v%QUF#v$>!IVlW>2rGRV^8nY0c+{cAP8< z0jWdpgQq(8GFEGk_C^wS0knL6eqF}5FKOM+X35;+(Tex$lEh<8Ls0f;)@$_^@%V^* zPwBZjrIEct5bStcJ&b$qoo;?PAT`EDZkbRO-W@dV=XQ!S zC&fw2g68JeiM!=wwCqAv)rvy7HE~r{}Np&JR`;8p;T2 zU&qaGF5~)GXU}Yl)|6E|warsV?$j=WXdhG#v}4C;A3<~uL*t_f9G9ws1x5NLyPB!dxb zuzEr&Q(umTJL_nxJ-E z<9UP&#QL}RXr(a|zs8uaQw<$D(F z7ZDPz3{N2!aG5Nlum8~^Z|SM1jWV{HY|Qjt#LgB8xwD@%5ZT!<)kR$-cfM_~Q1hwn z4mlT}$tsi-*L&`3Ak=5p$G-0>YBz5V8Llo(RlgTENVmpzeb_kZ=*#OjF1IbaL&AP=Zv}qHQ(ls{hio`S8bE1Yzcj zKXW`kD=Y4DRZ!-RVRt=n+SBVD87&vMd!F6L$U;;a#nm&c`cW^eJGPX5$41njLT z>^<$Kcy#BKDzDG;yFLlT>mpFQQX1nPvr}I%ieIh$cbZa(hnd+T7he3+H_y{L{JO zv!CEDxVw$}DG6$>PdQZW6pYG%`*N^ujLXphZ|`UJ0o^pwSwJQBx-i3*We8WUw^mmo zCEcThw!UFC+{8d^EsFeR!`{@gLK5ufyA2^Es-8Nf_=i{-1pDqKix@uj+bL?7L2hv) zeZEtHlUZjv^{4Pvx7rkZh)q&{3pma;JFz?YWg&mLsv4LW(*=D!g2-vUAv}W_qJGje z&st^5f<8KBKivzo8tYg-JZC`0l;!*>+*Z|3gS4#gbjZOM)q7Rv15|AqJ}Gfpt7JmU z`sYVvaj@OA$jh6I-3R(B!aVD!MD(QHp9Iu+Ed<>?Aqxx;q^HMu*Y6UCk=0;at*MXHKs^j;3>jki-&ZwI5;pD5A{JJ{_OY`gI zGkU)0*rqh(ILkOrOjCE&oHZs;DX8%lcP=&#PYF#77cH>QK*&8KES($?(_xVFJ?MF3 zj`Yeb-)$Ya7a!QqQX&5|vI*q391fUAbO*5V3?&%|1O?OzC8gw}ZW8R=TDHb5R1ot@ zQ3R9#_GTYXJk8$oKBmAX~HDwwnFuQVS|9R{ZoC~J$;=B-FoGj1i& z*3s+rt>sHl+7A!i%z0#DcL4u@H{pRDpH}QQ>%Hl7Fn7F(_n;o_1cev^@EKW+CzoPa zegorNJh z%>UXu2U|v;O1z1zw&6p0OCw$mcWv7U0rZgr`#+V z#`AE*cphv50;T1}jC`@dYi&xU>RJPEGW4x!(YIb!FtxQb&0~HP8>^z)e7ZI?ry6m4*QPaw1ULO}k1#v_F=n1$ayecXC3| z_W|(;1l>Zv10bn?4XZ0!l7HfM2{2Iqlh7K%0dS1TSn8r#?GACR|M}rcwO*`RM1lUN z&0hijh`c-oAJ#%^on~Ogay94-g(L zAdqnXp34N2pSFm|8TuaK2#tKhrYkskZanjSU_M$`{v2O@wWgJPgz&4~=9i1|z>gNR zpP+Fz1c`>t{|APWcw`|0_e5Ug2_;%jnV2x3#R*W zxvP>TFC7l|Etht{@v0E)-!c%7#enlL!st?YNg2MZYerCFj|*SK26gfE&Fl<8d_msp>RDbzS{#v62V*a?Cg->s1b}_E;^E*dw7wY);8sZ-2}@dC)xc90P&j zAkw@6C^OpSKkZiQsH|OZyBqKYi9&AgyyW*WjhA*rZEx?p!1&?(%U*(fs1fI{bOqvz z1u6FD!@M2?-DIwP)yGM`OuKB3N`uX@MFsq~YD0>8KR=q9_*DT$5f7&Od}7@b;Ih&s)@ z$sZXZ5V|7$oo(8FSaXUicRzROkWNcJh``g@yLl^w3dhA^YudWAqU@Sv+)p=O!KIG& zv_i_0BbhLRx>jM~p4WzlAu4@emY0giX6gaWv3PqpqIs@I%3k#cD@bAKUvz^Cz?&kP!xvA&S zXdkg;3sIsSlH)MFI@wC0yrXoDt@dD9p}ic69D1d&dZ91=8qXSyRMB`rv0KWi4Tdqo zT{B+70B_E*#f(F(kd@NpW-NE=`qEf+*Z2ss)eJJ@1v$@>^w!&;gN1=5k|kau4pzP4aXZTI?aRH$5bn_v;RgEvm4*WWkTQU#nE*fJMpMt#r0>0 z>NIC7*RB=?Mp~>85>7s8)$_{5?*6o3(A0ta0BgTRqt0QGwmYzNa^Jo?Fa*=1o5DkOn{1<7Dq8zwZ)oTyH2d&Dqypc&?7@d*L z1~2AwcsuqcplV>dHjL`B!DlKD=fm#(LEHcu&yMZ@h145G-;WMcT)wReZmThMXbO8Q z>Imt{a2&fEAMr%)Zz43t3(4CZo(q0%Y?B^eF3z8#MJV)P#8GrLGa z{SZz%#o$y@G3$ojtyqMVFvp8%x$qNp6S;H_g@{Q0jm6u1uUdYIQzX_*;A35OE@v$N zJr_V7j01G`;t7j%D*r?+j=Fy1PWXaV2KTWYZW3*tRa&w8-U{wsob&cV^A|mGcyKA~ z7$fkXtiL>#j)tM%!B`GjWMN*ENZ-ics143 z`r)EeD*|Pp4xZoeSO}~&oTxn$>{1q<5OQ-M^72hG=vX#2)tq**XxE}ZC)_J7^e{1w zL%-a4VcGi~)QQN2Aes|LCzXby&DPWI)yvnf;I~U2NzwXGlRxu%SOBe5*V}($Gpy~F zGt@WKYQaOjc<1!2+rQ0KiE{lBaxcoNApPiw?GH6FAlG z-ua!7*7z*pbJ^%KDH4TE&o@}stL)KHjrSZ}NvVt@E%rvU9`H&hVR!V zhWb2g)+P&b*5;GRj=AwDB0O&1*mmH!Im#+K@w%z)qow^8^$#1Cn~7%O`$+$A)1NJK$L-5QHo4b3^#}d@jb1{_)6*-V4uMf0ZJziKe5^O# z6YAZ)!WzyrbOs^c~ZC1My zUBu9^urg;=WN>CD+>C00tVogn@6GB=J~o$Y=?p!Ql=3l~{19Ce$Nsai3$VR({eaMhi zz{x8^O1%3MXbAFIbtTJ$n)j|_8Q()T-O@aWP3+`|mhE_SOx-bw;Dc-@ft9P4&O15D11cplgG zCvG&h9Mcf(Nv(A2mcWCk=sM~{P6vrEr^^Q_&1dP&`>pjlo)e<){054?)vPD+3OCiB z%c~J4dr5lJMGwHh&yYXGU>fI!VFM=AcQ^HT+m(K&9op|@-}IgzoNg0Y*3e1osB)Ss zyFF7|UFC*yHw=ECaHjnwq)K76Fk0-u#`V)9cXgBfem~D3F_`_7+G^Mm(IfXm2Et3o zR1p`qT;=`d0m5jmuqc{^GL3~YZwBQ;X74OAPWK(q*V6cT{(H7R-;YF^vz?i|HCLD1 z(@V$NZ{50?^2?E9Wz~3rWPA8->U#VZUMzvqx9;^>!k{bq1D~FwrTF~bAFHQK2V%Ad zE|E_`;$1@y3eB7D0cq&7NId>r!2O3f2Yvs4Rcp^bzh}(oCGnvSkr#|0ak6PU7jz0m zybQes3Y`)uCTy~Byh(!|hJf$!uikU!pU6&_Fr&QH9-FwhZ%Bn4Gn9uns;+DAC@W|$ z72hZ@pJkG1B_1JwnrVG#iOR`NIVjP54bMEY`4pyo{VPWh){QJZDksfbR(jkT#}|9d`pdjJj$>$-pz5EZ5vB{neuoi^%Ih$sBZq3g=g1fHLqX* zH2UdyE=OG@MtHiENlup(i~Nh6HG~8nmj0ZrCN2f*{h;E&-ngBRP&71-8~R%>&t8j8p!*auqmhq)%a7IT{(Sx-_I0 zd{{|c0p>R?a{RcnBv(g`H=2j#$xw*hNG!a7*=KldS*d`0JYP{~<)L$(2JRa zdUTlxh!N3w<=&P?xT5N2KCT-xdqY5SAR~KnZOvYxO4M+_*Vi-EvPO39>WKzaT9~@e zbT4YaNRo(XYf9V9!kpVj6Ph62sW_4zd(TkI#i5K#jFr=;R7I&M-@sG)^y57~V)C3m zrX#Mh#V)DAClLuVWf~zFx(m}cr>>^seNoZom>ABgM_yjxDAGrfD-GuJbF@${T`oHUJb%zUmYuonSyJ!2Z*2X8bqh=Ao5a2)Q;| zoXCJ*x@JPPZEghK+<*D`+bsVTX8ET^2A)5Gm* z28KY#BJi^Sz#&Z|W^?5Ck)?z>=Y6+MUFUuZ1ag?Ff2iQwPx8JYhFcIn^V$GcMc4Aq z%1vP#K=}SIuvNCdYviDk1>r%=$m%TYrRtncx23p528%C|>FOoKRl8QV*?rU|B2KMu1yWxO4F_54cTgC#gde@M-&I|gs8&=DDY&N5|8Z5L zvwZrJ9*yg68*J6lPJ$&CDdJDJ6*Oj)zG=uW+TP;af6zP1W$dr0^m&;+&L&nWcfQn( zP}%m;if)_;Re374ohg{{+(8F1+V}+9U`iU#ZnD|zMBF;jiGFOP>F8l*i~S8x4Aw$i zwKO;X%l?&w;OPf}Z}wr2Utfc7ZNw-Vr>(I@dy!l<1bSU{#iG3X z#x46~EUc)lykI*VF3+Z?Xf6`l!-m&s>?tQKF29w0YYoQQ#BUJ}_%&oigJzRvhL076 zV5(wd7fenP2A~;-&Mv$ zqw@@=R5DrvWq_@h%hT_f`&w3DEp8xVhn$DyvLF+xU~z_Gs3D1jaD6M=te*xm^|_-{ z&9kyI5jSufXFPHbXg5OJ)J2BcfL>H&!B9JKH6Co|{d-R!Hd2HFF{ubUhDmmIdaTnV z##hb?XyjQYBq5v{Q@xnHEaHHePWNg~_*sR^RCa-7FV-A^41A_OS?_C4Z~hxP%NZCR z%mFu-f{0xxc;vMP1{dC)cV6urTJ+uK;L6LwRB@^t?XW z;muuW&9%7Yw=5-*QY=%~vaKcOMaQ|AeP!eZGXfakAq3vLU6sbd*U|6{5UA&t)b%$M zpBD#tcd7&7UYwHk-m-E^!I)!dWI!p$9;s{_ISB{Y+p2z>0J3_F~W1n%e4` z7wUA%n_MSk25{iMkf}nqgiu~KN7j+-7{&W7w*woG+=bEZt;qxS{qVcl^? zSDL8ed4UDVuk`ufkV^lCUGM&2@E79wFE`P%P{$d9N7Nj5D7*L{I0gQm3;5j{jo3iC zo~=m{L3k-8Yx#MoQ@DQI-6h&WKXgL*c8ZlO<}v-cKu|O0zbI^iGHoPKj5I5VIbyUB${;PBwx6>K%Q@b`*XvKQU!2q|6Z<(6?JBcRz- ztsqn&6@P7Ye&6JUKJsJJ+u`8T+M7C#;yxzb%8E(ko&X(q(MO-J**-w~!i$j%fGC`! zaXg~*t|Yn!1+owY*26V6@C<->eKK4g|A5D_c!_+vXQbHEDMcbhHLB9qHcpmkLn~U} z(9W`5D^+EYgldtQ>>uXXEU*5iZ**I}2ZM_kJ?n|1XVSjU>Tw<5h%99_(7?Eh6v*q*x5Sn5nuxUhv&AN#bv1 z?mk!taQi7k=M)R7Vs3*60OQaN3T~HIigAi#6SGuQ(hammiXKX-<@Y+w1I%59O}Flz z_U;6{FAHfPy#Trs;jo#_C zgS&3*25~WTUSI2z0*Xg!YUQLqBLu#wp(WrK=SKy+n6dX6O~BPW?i}_`Cu%}--}}Z> zZzl8b3w;_2qmnd{&TJmw!>6|2rW&-}OX)eMr#PLEW*y+C;%f0Mwv~@mHop>@H>?UC zBA$uCXw1!zT>X`u75vZ~0caQzV5b@qEIC3oaFLza+S*DnWhBdKO04C(FzI(IVubvS zvnHu+qVg%5U>1S>oAx}L%&TOG6_XTJOaEh!4`D(gK>kggfbXSS@=3EfRR}3tGO@r~ zv4q{+oui#;i{GYj6BR8jCO)q_ zo+cIBbdLO6p#GM2u=fr{8u~h-AoQLUl_4Vy(_8?lslqa~Y4UVFIvl$I3k%k0ZwdkH zU)uM`GEcCEC(K(F88Mt?w$2GhT=fvk&ETl7hy3xv)4!Ebwj&HVD2=JA1(zo%o9 z^m7VPgd8fvJWdP%#!hX&M>hhg!@<%30|^LZ3M{X^&?(B%2S*UWHsX^LT;m&9JUVOp zpS)5TU$0ZCrRBhY(?CSQGyxW(39i?TlJBT4IZ+dPR%^o@%d(U`tq-$Z?jK&YHy$EY zH#t+O;HX^RA|%GfkEav1lYz4U*D{h}kt9Swi44__9W)RP(>v?aAH3a{+HRhVfT~Ia zAZ&uwTJE*lM-`PBRzkq}F%cL@G9FqO0B8x>@{AGl7wG?r^!3kc`Ql-J8Zhvm-WB%0 zvp!yY;=hKe$OHhGGM znOVCE4=wwd*^bItEt!Vd3IUfjY0Z!%xc#5OYF-I?wRg|%opghq;#rWdAy8*izm_t6 zvoqX|Mnp4+IgH-`075%>0D#@QIKWq$pLBqnmoylF_d&8x0pb6~p;F+viE<`OO4|A|tJ!mCH<5u$$bUs@nbM z`e49W^by}Yw83emau=92R~*AkrrFDKHz3>!{Q{Js6$hw3k9`gxkf3`4ka{Br_=qd1 zuB6)Sn7%H2+w`6!H;o3lK1lMADZDrj1_iX)qwYBaG_Jx33#j9zSWgc>Y&G44v=i=W z@=B}UPB0lQWPvAj1HF_ zeEfWCzNirlfQusa$f*Ono?ChakSx{gALt~R_}sdgBzKl?)b|rhTPzMPtVnkMDpQwq ze06JMZnk@=E}Qo`Nrhws+Np$3BP#88f!K?%)e`r%;4~lxLI$YXZ}l%`#uEcZl^d^; z7=p?;>XO_b^>ohivUWz~ci{#8RD!mRxm#<~GhQbNJ>X;6U!UAdZh=enxo@aU1nsXL zZ0Jj!M8vYYDTJ6QMP?*aMVc-m0$1WrL2c{Aag~|TAS+~V7>2$V$@J}m?VP z59i_R1Q}*1M#t<^bx>Xwci@g(nX>2g@TnvS62~!+&o}z^dV@{kE|*q}YWIuX@Ow&W zdVGz58CuDtBzFAfK+b+6{LELhZ$-Az)$I!=`hbPZ`thxQd9L1yS?BSaP%EiKVcePT z64aP=ahN+`OgHG4G&8B=jACSTZmD5e<5QLzzk)47`}9dY->q3<$i@YLa!^C z0%8?5UYgC;zn-$&+ONPg$)5g#J|&EIX#1P{;_#-wc;PhubA42P^@m%R%di($J3Bc{ zX-wrUArLELCw9@G4#5=N8`o|;NI=~+73y#*01X(02tiiPwz;?= zQgTf2v!qZ0ld(urs(XWsAU2KPSq%&mh;k!p=(Zy13RuC~D<&%-UhInHmHa>^@;vxV zLB$9uJ@x=sRI5>Q-J7DMC882 zNUmxO^~dt2@^5%LE5c^txqoQj9rOseASGI%Cjct#HJ?MS4n4JX4&OjVa-BTO+ zM5gcrnrN!Ez%K{l_U1jlD?1qp`CgJ9peF7Gr-b5n@SBX;Y7@^p6Cqkyjk32rj(fJE@+2W|Gts3gnCTLGJl7+QE|+_w@oLlF>ST!)D4_%i45{yGWOF z-b>!zL3QB@;F4ymm>o zjq;I`pN|`AoH1u36AtWP;d_{E52h0Q;E+ngI#YjL(Aj92Ff)Iw)#(YBHty z+u#9~g_h%Vn3|9C!*B70#ggi|$%_3uQY`2gc0`8% zydqvZ220=HNc+k{uECstcHbl!9_S2r&>A6Av$yhV5zQakCS%Vq6_2nE98PIXK`Po? zv+e!Rw_PEc4>&oMp_)IpFG&6LW&JeJX|s1?AI*|zAoE%B=4h~RnzrhgJh%bn(Au>_ zGUc-v{`}K^7VWmOOME7B!wgRt4L?T0N%52HgPT&+vF_6i&XRn+&fginG2{pEFU&k{ zSD6B>Y;vvf+TO$O6CO4LVICV&04=4MI(l=)nzPC7sdIHyB6gP1xU`rm}+6l;ASzcFnOMd%rDZg0%W81nu zp@JVrt*mU;wKJbeRb_i7wy!yiYDIzsuJ>)O2EPxXR%Jm3iOa}QtNB0?b2_lSEg!{Q zYEd1`E{@bN;^PyLGoG0xHBBgVcvEO(&HhLQC_(ww=# z3G6{`k24oOHlU|hwA12kUuwF`?igmTn>G<&8K)n zV6f(kF5pa^e|hpisVpSGc^?>P+@5t(o%6L5SoN-I%;@xkm=e?8T-l9)<@ZKyKaiha zNM3ez#sBM=Cj7KPib$nGjQAgz+5_qc29nc zVa_(+&gF@fp~rUfF+i`5P09V%Z44ne>o^RUKCB)@r`?3F#(3EGb2t{Mq#VU}m_&R; z=qj_vQa5(3M6Ktyb-L%%dYVc2D;S1NAoUduOeU_*A*dL7>FwkxMF#M>f$Df5p;$zc z)1jF)4UHEOPBt#`%+b@jQu24Gch5(n2>nrM<_r}oGjT?GqOa_(ra11ws8@wNhDY*H41I=16B5+gVXhidZ}nh z{C>`GpjOA}FM4pm4wIjUPg-D^FWX-Jt&0&J%(Ob&Lw}ws^g-a41(${MJ|>RZ6-ACg_W4UV34fd^S2Zi66gxJzClJ0AGGv$&!ai4zpO9iv&ECQUOJrFYq3jznUQ}7 zrpnaz`#ltIc7#776jx>{S)qtVLf;s}#YWxkt#>x$O41WSZ9ZfJ=jCRa+`!|K6b)j) zw%TWMpjOUGW7kR0v$lw=_%0&%7r9PaSkz3tZLmN#r+X?PywH>&I6#XFB0p9)Tyx_k>m7zGid zhE2z`)Di7nYPX{a0=5x`m#XP!HMh>&B#G<|Q01X9hfl%SH|DQCgk_pk{Ut`wfVH23 zS_M%3$&v>KE++wnc|Tx-oe8q|M?(aN;u`G-A8F&TQyzqDck;D~V%#l-)`L}?tZcJ#7fA5Q5(ZLS{NJ0g^K{Sq^mxr3waZ&?%z zFG|yB=_nD>OHd^Yn_kh4edEeQW0d=gx8%jl2Z(?d@M>_M79mvmw78& zDh=ZZb}6Na!k=wL{zpR@nc{!ChEOtB!!KbQ=Q9QjO?beJwfzZbpu~G_Kltr}aS)!y zKJR>#iuY)+e|Wmc!g+}K;n65rUQ65`;O_Ehytwn0j#=k(M;XNuE{DJ3nSRX)U#8R@(fmCChcf8w|&l{;K78>m8D>iS^^fZcJM5n$Lu(}EyThSrt zXfRa^jeN!}-Rwz%*v&pOKGzxZFUJ?UXV0#>`6lYd-v=>I#)Xk@$J~fFt^54ci&+p? zbn>@t%#Ny4IVPc2jHwY-@`nG89pBgpql~L~VzlIN;9qRw#Ovaop7#l3sq6T$7IIzq6%0aj*l01Gtm;WKaGR2l~Gb@|lC@G6^p z9{Efsp+|5%#%feY1JTpAnM`x^Nf%zE2z%ZDaFkOG%wa2~{Ahp&P?g-5ot&vyI1(_) z4p16+;+9w6QM{h*BNsAew#Zi8rtXosMU_ZjemG0_PL#UT;0yk zz(#@46+sW4OKT%h(UIWkLGs*ylFh8o2qz5$67sFY=TVwz3P0!mzm-~SS+;vOg2QnF z(+pWBXkd4F!&N#$qC z5_&}ynYj)d3O6~KEl61rZc_4iUmo~LO25B2c)QQHYW~{1sa3MC@n0-pU3r^O?vCNL zvCpzyHxO#&Ll8r+aBrzNUKl{u=;tt$kY)a4d(7+beqP(tF9a6(!FDb0EfnfOescqN={E2Ykl6#HAEVr!M}A2?M>AvBSB|xyRqcX-tLr z)HY=40dbRsfB&#tU;caTxaXJ=AXSDihKS(9TI!I)KMmtNuW!RDvIG23$;()+ZKg1t zpE1V~3{iyqS0;*Qq;^_+H(Ct$HQxDSqa<+8hBWcMTq*z0+DCqJxj z3R_$ZhZXfceG*H*oLr;AoROL5`uOp@KON^tjQy z@s`!%vIHLH?PBY&uXMP(C_-Ccwdp_lLSmTi=o5_VkxC#b1r8qd`eT#Xljk|#?V{D-1)p;TtNK9i9RCL<@5k)OR=brV|)u;{c9?TWKfQHnNHxs ztF=Xs_hulKuoJ6N-@jvRI|ka3VT@iiI9$mUahvqKsF5{92y5>_6h^z{0fxU)6#O!gC^nk1qYp!IOg`%TWnq`7C6@;PYKy(+i zsC_6~x+Ya2D+oPtoO_vbH6uyKWMLaN7lUf_?hL3YokLe9BqAZ$B}TQCIiKxY0@oi) z4tv|3hnKdcPu|8Ga~FBW9vGZ%XL7~3gZ|Dwp>*QALW{{A%7bJ*5 z$Nj7@puK6A_L|lVPpv18^;0hG-T;I+b5_dQfX?x6JW%Amv+6;1?7NcmA`DwQ|^FAaph-sS& z?;JCv<{}g9(mRe#-=!AoV+Fq;p$_k4DfS>D8Y$iU{=-Pjq|UA0&~qQEKM%OB_LtDyGaxS zZft4wrXDX}Owjgsj1UgJ%N8Be4PkRuyfZosFLldyDTD^TZo_3Y4c>0RlUNAIGf{WC zNn^ZiIVm=TJ)0_z;N=Kra&C~LZYggWwPgeSlQumi9-xkUcM?rY%cGjpf-Sg(5^I$f z%mt)E_W$Gxe?DARI3D`T9&de(nO5fq9?x|Z2Axtr){%;&qJgJ_8dnOw+r%scrF}Xt zINB}6@8+a}*%TBNcb2-0ocT8AHa-VZIw6Q;;$|cCDkd6o`a`>n}`i15a#q8kqo!pKg+?5~(m9qRV^HG5Sg zhif(;6u1;=qQXLuM+sL-s(4rL`6f~97L!?nTbo^c%bvELgt+czO zbf@koaHE6K@NZZG$Eb2f!pEU< z>?XX?G`W+o3K!r}e}w%`SVk@hw0k1N^TX`?JjN#8COr z=-kM}rNuJ&>7M65nHkRZPi8i0H)7@IkMZBkE#8!$n&64u+1s_HB*f86hbF}pmff3u zL~36?vg#7g8|i;ftp6RvR(}|w0|4B|2L`204gnvrG?)H6?EBxW^dBazV_iX+Qtc8~ z-sS8(;GkD_CHBPBlx4Het;j_swnu3=KO-oqVseH)>H=gKP3fapi9TONR4ByHB7>lb z;o(}v`zoZKC~J29b7;ap2KX^&1;jk2U4H&cUR9@_eYN_MSJY@zt-U9pR;X17voOtO zwSxfXREuL1y7_8a{1LE^5S= zI3M_$1bdOi?s3bykNh0&aKGI~^i61NYnKW9Axd2kF^f@o7Sd(=HuOChRTneNN)MhD zAXLS#Unx33@cM~Q0}r;-b;3w7(`6iDTQDG|gsBUgmQ)UJ2eRx*O=IO}u-Beysi~Ua z^O(tg?y2-m`ZSVNN~c=!MoyJ*0h7=`kM=d0ftR^P*vE!XbP`(CQA)21PD`F15UJ)T zXfD5z%i+EH9UmQyO%t~K^Z+DnNTS;QkC88?tj0Y@Q4n$h7H#69BuAR|^y&(Nic4ld z2ea=~{p&k?4AN2^A3AWq`LMxZin(f1I$gD3iJoURpD#r;mizlZrqb(>oRP(P$u&5k zkLR=`6x`n3sGKKJA%xREw)Z+F1ZtkkZ>d=wv?9u{=(NVHQ6jtDlT^{&)`^$K4WlKl zo2SK|6}s)99u65N%M#frRnal;3$Mvw2=}J^S#;^Qc!sjRu;S0reLtzh2B=G#go#$3GV?)6`!Sga+%9+&dzO5uW8yuKgD&{J`VSe<~ z2Cxz)#{E-nLfiE{ao0~c5q2yAWt5rv$n(lTisBKHUF~O=g?ljteVo*RAz|qtPckdZ zzx?kOV!C(9u`3zvSGn>(Ux|5Uf9OAL7ea_u#r`N3o=~=$tTE>|8Yvf!tIZPWcRJjc z#4|H1EMurVV(XSs`Gs?Wh4Oi@8+<4>o2Qch%fy|eHF z1QX3m|ka_b#2J)lAZToNBTjBJPbaU3*)&Y*}XwZpb1&7_?iq}UN-^j_- z)#BfP=isaFMM)iBWatA=fJ<$|xUfhUBCV_Ze%w$e)ZS5W=mI&G3S>3*h#?JkLH!Th zsIL+xr-qT)CiB7@O6HOc6Rkaa4+$g&?R4(rq~km=f29IlTp*eg6lrSr=iN5nS?6y) zgB`1*`|)O)rWa>Z+>C)Oxr`>zVbWYUq@>iDfSKmMqW>{i-4uvlN5-s zr@h`Xy7r}vI(`I0#(Y76%mSN%b^x-jhmp^*<6d%eQ}9n;no6yf5&~ggHX7S)m~=tP zW%?6iTkT@^8RNq%TQ182H;u|Ymy0Y%8A>Sj%M4qnBs;dS^J?U~XFXF&i#m=}Eu&wu%Is6zHN52=7!lpCIz@l&Nuc$h(I0U3Zpikp z^^;jT+vBZYm!WBXgkMIG+qbtyO_4t6tmI=#0a#5XaJ* z%sr&`RS|5YFy9yMr#;K2gOzTGM#*__)xX_5_TM3@aY}PPu!{dGk>!PLH0oaO<9x(p zpnc{CuAQ7h_0Ty}FbI^50apU_#@!Z^M<}y|svn3i>*ZFED15i~BJGgGOQ<%C3-9wr zEt}u6QF{63K-0RJI?H`Kr?}FGtwXD$t`N{(D5}+FH!V}9l3uJ#5u7V>>U#0H!(jFM zpMWDr2S=zt6O)tAdW!e;Wh3v}dAgqO)ft~!F{8ZeeAOUhO>)nR(PuB34fx^wj=M|c z>AZ|ctGogm7{1{3A$&>wJPEv2ArrQHJU;;U`8XAzIo+66!R4Ixp#vyffi0+vKew{t zw50^&_M*D@rlsvL9Lze?m10v`vz-$?OJj}|bCku#WrmNb|FcC&q!qmImh7bYMM&>$ zSs)&M9Q{~}U;Ng6Ttnh^DW_L0>kBmR`D%r~yf)ozX=+|0k&@cVNa2W|2Xfl4d4;y^ zE#QLv@js~y>ghRsIV_tfHfa?*(tG?p5lg|_n~o)1+>~xnY~MG-bQ$($p#w!NQrkFf z1{UJK$^_V0(=9C9kUpgk9VF}wL@T2-v4vonbH+Ii1~K}X-!Di(%}UUV^zkC7xr@UM zVhXDLW8pT6WVYt-tmDkaMW0|48@bX=RY%v_iPT8A6Jsyj`BKhPxzP$-#3(u#D{^xQ zJ;8g%A8SplNhA=Ju15eH4>SK`I;7;vD@+tF*C0g?@po4#F|Ar%K@0oxW!=W$VH|$X z5L^!IXIm0~jpkR$%&1VvKr&W+t~Msg$TA3JMxahSpx+ko1~{Vk3PV zs=}^UJD(hl7_;kWM~6ctZw6oQ&68k+<9uJ7mm^K}y-LoU_oz!Pw|r&ro@{z~cXVq? zF9?0ojQx4bzgPh4zBEwnvjxtZL}r;DTPw$t&CzAXm63E=bMwL%L=J+S3P~fptIjZ2 zcrB%2$JO|_sfEFajsg}?CE~oVQs!Y}z8&P@R8MN}#b@&v5XTlLkXzqI&>Jaih2W^) z#$=L(+NBDtFN=R)t~WsfW@SmaFgq!Zc3%pwHQXiGO!^?nHdlxNU!K{$LOA>}6$ zy1ciG1DAALWW)R|pS;pPCCAW##6IC1e zy*yvqI;I+N=r4J8P@Kj|0-Fgxe6t_|&TJ3>7kh)Wq7lPod_ZShD**YNp{0YN%(PH6?n;cd|(sN;B7y5 zA1Eb56wfs+9h{wV?rV7f&4bL!LW+u=G%d@q#NJS-vhCnk$t3m>Z&yY{SQDs@nQA3! zxE;OW!2^25&BkzrwCI?ciX{JRE~auR;5U~wWLRu_G_t}hpczBUL2uQ5%xCpWV**aF z;1x|F;>j(N3zh=!fk|^7dHU((sf^#g72=X1(U6?->Z`eEcaTc6U941mMmlF$4Eb{U z<~@b4*yjDShDDmdjH1SsQ6;`mDgjfjf^;_Vy9rvsrqmyDX#DGI;UdD&l_fW`F^p$d z1cuyan-c0~tsVJZ=~jtG!w#phBf{ngWN(Z+Fe%=9H96BP-gG0hVQmO_bbHxv-p3jL zLU%*HjG4Rk;mdtBbU^TcU+qWelevPSYFj!B=w8o0Re97(Q?=V!`t0&)d(d^Hf$vK* zZDlBnCCVG-xG2jqvah{@Fa67WyV38q{Ch=BgELkNXK(vOGDM%0xYkupJ;1**Z2#v3 zWv`)@^l8unHtB9h!1-AA!PLE_=+0D?$dEBtmdm~q_8N4SRgA;AEEmgJ_qgGT61r&M zX1O6QH^)KZys$-iM%3A933(-LeYo845QC$hA0MH6mWTiq-W6-$dXyByY?i}7P1IJKXp?2r zAJaYB;yJ%|#!yE!hr^@YqE;rRw|#$Fj|)zfl(WSlw!4+qc9YEwuAZFGMz;aC!|Z4cR~JeB0hfbu z@|-cB>-~+w$jvue6Hu`I`qH8Kwo{?8y{N^+eKLOiuBeOuvHJ13{Hqh={f@fiOSaRZ z0mgF*6XmwP?nF_{EdEP!?q#=ErG!h;BaUG7c~3^*$S=`l!HM<7-OqE%$0M@|m-@{( zh$1i_qtH+iTZj98?jPF%jnW-ki``v&ko|E_vpXX&-ma{2mETD!%{x}x%wqNGd>n>MI z0=mj*S1in~DHL z8>?QKD5N|&5jna%MqGa)Vlc3=i_6CQ-JB4liB%s%N4edDb*35Zdoib?awe|l&#o_* z<79&jj(a-hrg^|0@)$GwCO(7JMgKHX)m-v6-roiNlD=(jc{-iSERDzVs8Y+$=7~l` z3{_D_QzOUiNo#xSta#HEWiohxj}4zQvHoj@{cqH-W*1J{qE}-8Dg{c+;t*g0eD7 zIk{v$spIVU@gXAKMY^8rb&PHy3@-^A_xkkV4t=RKb zL_aOS`^Wg?vh6B=%izJj0VCew@o|X%U*U`?o~q z|Jl9wAA2}6ZmUjjX^io50WZ$_%{b@*dnix&nJd+Av4>@1mFbF#;!u4VM2K;-0gu3x zg^eU6pwZ|1d#Zz$8sF34ZZNZ10dOT3l&*G#3<;~f%DDBpfb8XUqUHN-0qZ{u23Fo~ zXS1+8U}7Z}5JXP))KB#}`uRmQ_e8j!4tjN%jf{mFG^TmyDuiyKaflC@{533}2`~w` zcl`n=k!sM9w{zhA*!|**r{rL8V7T!RD2X6#pf~(a*V4M^GkZqldahujQaYLKnQYtb zuvdOhnuwX@RzXHbApC;+3a4vJ2@78~*nT3{MdD}4Lr2pBzk6TWMZ&t;r*1Ghxk=q= z&EDmY+q;KTia6G%fP|8E^|-9+;4rjv;3O;#a>Q(uemt^6%7l zjs1CVaacq?Ir=a(el>fHd!~uks5WSo9JuA#Vw5|M{33ND4D5|X56 zYG#Kb8L)?93NrdkHU0vZW(aEA_Fk@cY}JcUo5b%gzhiUGzLR~ALRB($qx3xiHh_XHzRp!Lh) zpddMI#mDao17xzf*!d2HCi)q9Z{w|!oo@0)9d0qi#hc%FQdjL{`_8>~r(u4oSU~#% zgb3bsS(##CrJ-MexW zRJPc6fmgw*VUZ)d*jw5oLzKaHS+RoY43d{~#5&laRvnxIT=?|rXa;x4Y-R@nQ=`C+x+_lI;{-UA|cEC~ge3(lOI6R1j6v3*LM`a7To+!d$qj zkEGz#!E@kKIN2V>fwBT0}EeNNZ@0 zzJ0D2mc#d_4jsqWLB|zU44IE$Ou*o6PrDx1Q$ZTMo7FEp)V(d{sTeq{mMD zgYTt}4u;kBsuGap7O0K3x&D)x@rk;Z&U@o&nZGYC!g+-DCIK@_mlvk`M12LYelcT5 zXg$|Ey+GvY!ls~GOfhj^j9irpKP%Oo){VfHgk{I6y{e-L^FZC(@r;U}1C=lc-dPHp zbmNIV`)|#K@7A1UQwh9jcu}{vX9; z#0Of^&_W3HbGyzi*#{kz-trkSx4u_P^tO&VMr`CFtOs3dH7doYG(%uO2VLcG7snA{ z8|6JX{YZPQe~jcUkIvG8e=TWS$SPZYb;`5C2%_L!)HP0+7ZW_7YiO`Sd|) zjpvAwLxi29U@9&*hZF3=@ciCvTIGr0247>-keVDvk))C00?O6TKbdKk=$3B(Hq%5r zT5fu}!PO~JNJ`tCM7)ei$7HjvL}~gfB#tZFkivg`Z>Yw7q`3b0dQnR5#|r*snr(ok zyF5j*?i0H=D)W5K7IiFr(N5g;`=lbmUqzy$BAe6RZDS&iEv0`L0e6=Iomptrx9!B^ zWX)N`V>?&euWo=x_ABd_AV%S}_4swwUq<(g^xRF3L)u6pQ7q_P%#CMs+8U{Fn4wkU zHB}CiuH{2!mUB~yYCMxd+YPI|riN!QsZVnN$>~Gl%xTqqPCFzIA znjpZmdC0LB=G)!-6Jz(y1v2%-@F6ef2F`{Ljx%|-v~~d!h4G0M<96TM<9W44CemF7 z$pOr@{%u8naI3Y8W^|kJ0snV90IuX?1H=FB<<3R_fAz2bn=0nNXX06s9eianUud-I zS>u_BO!|xqwp34EO9$G{RWSnE_9(*Wr2eJ_I4ZGWQ94nIJ`GN$2(QT9Fo|sweSZRV zt|%J)Im~KAp_s<`9I)~tw2j+4k3HK@d^9OmPD34-y;y6Lk#b-l+TYfy@lM7Mp_woo zVpE)Y{9CKz(SH)G>4KlK;CZmOJOTubYP0`~1&r^k>R|;PTC6eB(mMnloC3GGMK$$# z5)ST%SFVD+mZmiO32KI(f+H7PT!)AQ4wrd)$^)kOjAe&F{*!S-u&eX4my7sh?HgTd z;@{lT$ZGfg()93Mgs zy0faDi8?HBW$ILMiW9z;=E}$R7w$DVZ>>b`nd>PUe3PXZ7@lquo7Ex zz4E*H#?fx!3%R|mW}va;w1+&bl`Y(`C0BK4B0(X6!ercHPrl;qy^FK*6Fgoov>(g1 zHo}6O?nYKMkS4z;i0S56cGA0=DT6*8>!286=ESU8{;o&m>Gp=N&PklrJE5HBH0{Px zIQCOgwf|mmI>D2D?HDhDHdA>)m(Z(lCC1_OmA=mURK2?=Q+?n;CrbA6g06X-dp{o& z8SdPcp`3w@C6ZIPF2-H0dTtnpG~JuGse+fMRI?+mqErBd(-H>i!>2pmaWcWbRDBRS=pO`Uz{vl%@!WC0%ca(NZtAeY-*tV(eyA>{q zFmQj+v7csLcv=Kr7t$LazK`F2vsQl2Q^(DLDIopsi@jT_11ZM5Gx_7+jKxMA%{Z^f z`3522{FkxMRplup;~e)(om5=jT$WZ7gY zJ(D-K?>>PlJshQHYokNIqfQo*QsUSaES0|D>Kb4YU~F%!)GFzJ*$}kpY|PyEBV=qc zlq*fz&jaj52>mQz&lIM-aob;pR8p-#g8h|O;{Md;r*d&^a``%J%i<}s8{C-JtCwT! z2*0`u$nqU5YY{gdw}|TKpNxz(UIwvi7xgn4t#Y}N@O4UoEY_BIb1`BpY7?4=d}oiF znM*G+EHHc<$y?K4aXsvNyfy0Y@VH7^pCp_dnY6Pxr&Zske+wT8@N}#Ye$I{yRid=J z+w#m+f9r+!^R=TffsP9TD#glK z$Y34g@yhN5kg3*3l@U1FEJct?cyFM1l`r>G0LQL{rM-^Zys+MsgRsvzS$g7=90{nH z@l-cnwKh0gZ`Hc#pFx-Z954UZ?8|@4$n)I9bo6d%rgXhHB^E8O;#-S(LM!`?&#N^87Xk_ZFn-!!%R(76a>yRh|OdBK2|k4whEpc8T}l9JZWO(yLcgd zIE}S^1ZRwmJ>bI8poNFe6l~9g=2&?tt*lGCV`fV0VvF|mt$*9Vx`<& z>9AzkI1ocQrR0CynV*UK30yJfmP_(xmR~u|$1x)0KeMKeYX9{|z}=OA>Bwl_EoztB zclI5>l6Aa4Bf6K_x^fmVZ9KsEMrYh->t1*1$%UHLWVJxyhyWvQZ0HY0g*c}d0*7pzsoHpGG#IN|JNoM7mGrz6 zREN6Ff<11t%Hl&omgD?x$2N_ET+E!>p77Yqj~wVjiYjZ-<1E+Y7ByT$E9?xnlB3uR z&JSD`*YC-;X6WAmRG&WXjNe=w>q13l#H@T9@$mi~7vy=87<=#aClzvxIL7mqg+QAy98&o>6kdn*9+X;NVd*9y&_Yh2 zJ#E7_QizlHVq`@=7R(Q%gRd23wc54l2!EmO#0T1kCQ(L-OW?r}f+t@? zx~ofn^!F;*Y|z)9Zb5*bSCn}l!_Y^MPT>Dn?*;kU>?c|+7p4|3jdQ$7S8fZAmjE8R z-lr788tt=Ita#`DLHx8eZ%vqe`dt0xF$bH?S`(O63e+`j}OC`?E ziw?{QxM$^GlQ>e5c=1AnLS0KMreHs8Z37Z0V3dW32JmKWxw!QBU5_{b`0B=tF6Z=PVZ-Y zad_$t?DV!2>?F0s&6Ie6m7lM}neQ{6tv&reh93Wmz&~gDO!J3)X7S+2(2#HJbzYIv z(eLv7{POaynJKs{sp`a&*ylNDe1QaIhK2h3FgeX9WS*cFj(<8&hLJAfM%u}8_@jZa$8#UYrB>Nx^^O0jZZ)I z=Dw;KDZPx930aY4vK}ACauc1uHHxv+*%+TPv_D2p#9>WNe&&ok=#4SI&sd;_ zUS4IlY?Kw0bP>u8XIYv&zuI@KDy8!QU8FZ!n0#V*GLG%LSe{1{rYLBhH0-aZoF_kZ zOHpgQC8i{X(so+gp9-fOay=@S9U%7K5>I#2Ppo9-jJ2(ey_-SfeF-wuKDMnTnHyqD ztBKGojKI;1p}7t?-3`x@ULyVA(ASow(}Y*aV-Af}&ZggFR?R zzKJil((>VE!!)L^qx>zh>mi$6G&7})uC_kiK3Ht|EhEcmP6Cn)n}>N);MN zLl$Mu*)5SY&yztS(a=hnT&sOMDRxMb%PvI}3Z$bU?As=?Av!+_V!!>wTWAjp-QKWTZ%>=Jz7) zvfVOuEbYHj-^)#zzT3~h<0se;POn8Y9(WXx7p4P3=%&f^$g_o?q59YEno)K&AmK~T zfQqPocJ{M+1I_zd*1b($Ig|7IgZEf4Mb#4`6N}#7@Ql})c-ib#sSUPkDT)K0PCfZ2 zUG_~GKO+?)mEviCI$@!|6CXz#7Y0qym#%_w6-q24)FmVsk@h1%% z*6&`7$YQ{(H!nOO?93&zPo`f+R{{-|dmS3~zsu{_em5P2wx~OwLxO(cv~cA2eQYXk zX9o*6)~>aZKq5aB>i5lO@fXn#{M0;vm>e?3wfrBzD)Yhq8IS$(shAEu?X0MD>#U{8 zYy**;Z7iaJ&rF=1XH8k(^?}y(*w6Zk-qNC02q z&1w_}%i9z}ZhOF@V2nM<|6&1DJGP9f?=ik!F<;izUJIH(s02C$q&a|5MRqzG%BndJ z2}zqri5b79Clfh7i^4jVh&Fq^vFt_iD@vW`8|Fnx&t~>MpYJ{reS7tFDqwRbK>HpK zxF>uQv%_)Ee{fH`{Xn6(|NDD^ngL9si611)OAE~5_`qphK4eShI#gTL?RWa)JT}pR`}un%6`dyaIeOBa*A#zV z>s2fUN+KkxI~+SB5RP)ageplR?ogWK9k`CyB_TDeFj%{);;UrnD75tj^SGQ3uSDjIe(cnibQYXqVXtC zl9zL+U{jBm?KL)HQ}|u`r^w#dK2I>lQ$VCWqt&4NYwR*PPoZwd=PH-<7+~tUdYF1) z333zkr1F6MU3-fcig40nBDP|q4B~_R8X!{@C)0rqA>`=Sl0h`NDp{zRHx{wUUG|~P zkTy=|`*^IDRtk-+6OuV4i@Eg9obL`f8igUWPSxeQu7%MeEy}Ip`s+eJ(XMkLuq)Zc zR*cZmUQurD>u-a)CkF;+D^KTa!w-%as7pbq#9Oz~q8aiI)>Kfzo^R9u59;Hd2)fmytRSu<~_H-OGT}zml@F z`0-%}z&}Z{7a#&D0QiHJ4KzS!+*d~~zcQkVk%Iw1uExoYN7^-GP8>3A(mcWT zv9Mb2Pb18NW&f-mihSsqaAY(;wxQ+#v}r!M$+}+5rLt4}{<@-AI7o?(Ps=8uvzmYvXSHn!WEm z@7$_$@7d?wdf(2su2pMwSI;%qnq&OOZ~SN7-)tEEn~3CZW)0Q{JMcK4(L0{D#{Szo z-3APMxTI=vF#({dQP~0QAKF&@Q;knmUaV0gDD5!|RQA_`Wqu1yR8{8H2J7Qq5yK|Jyn=UDFf1K>EB3}aX!7qdHkGs$5j+oB3 zv1DV8KaXJ0<9If4(mf{XON;HIr6mDTCTX>=mscjpQq)z;Eu9Ix`sTtOdsIyol^a62*{uFZMc zXb>)?z1olLaRS=uKRSH9*+^I~mqF97UbI+jW@sE%-{D27k|QX%`j|qSL$;n1YvJd! z{frt~W2eR6s124wcjnQgQ@bdvb$@(s#=ZgmJ`LDOp9{&tc23%`&Ln}9FtHIgnSGy5 zM`N(KsI+5DnjXHr-@{|h41O$vPE<{Y@060767n**DX6X>sMiNPp+}9Bs2LQ^^zbNl>1T4_Q zZBY0kNIiaSUhD2QCon4-orcTP7~BV8_iMivEX@l# zp7%z4?p-T>xdJN#xfy1>63iiSd4$un3e>7g7%bAoiz}HJ)K|@{Sew$-$%uurThmmK zeetB-Cu`HtZQykO5E^m8dI*Km+SuYi<<_!EetoD}pLN`tL|HAO_5}kt?5NVRRUUSR zdwZ?Cx4V>sDqjmB#Lw|J0M{uXL}&W8s;?z2=F{ok`cl={!JE;(lB5O|UxwBj?cX5v ze5?Yrz^szf-mi0o#7D<-B3<$1AIx{R?`5J!P%_{6r`q7!_;vM)g-afp@EhS|@X;V#J zON1L(SBt11gjrhiJ{IaRc$-`rVtP(=Yqh(|=QPaPH{d%AN~De4ODv}iAK3(*S_X!@uMaj{GJsu-7tk2UxlQ#4=EHa!MELD1cO z6Jce^7PWwNCtEpFV^4KQ@0Bc8O?j05>)gPbecDUO$fLB4wbs;d)+BvQOSD0HS;+6^ zN_!ndcCO}e>WKDAm2EFUbbh$r=>1n-5<5!Cy^1!rw}JNM2e{|u6_asua(lv82N8c1 z3HB^4t^3%PtF(9@PdvR&sx=QzZn@XrsO9Hg@!WFtlG(yDERJMsO_Y7sXucfj;NsLm zv2l3~vEK z%GV4&Y4&7|-lLHua?i1^aWlP_L>A&foXe5SR(-B)-qVYDYp{?t5jC+p6xX#aW0=sn`K4zqm+(q&!<*H@fsGQ@Me>R@5w6yG+VYeNle-PKl%!}rk59&v zb%~p#2++B{Xtj9*yji1t71H&p=w>K!dV93xn^=H+FpF`|PmOZiags+hPM+qWSKx+H zE5(V8BUA4nZi?26vG~KUm7ZpsirIaki)N2d(+d$rDVD>52dVa~1{br_fuZLpk~`lt z(mcI}dO=egb^{FjO%-U2s_Z4Y1ojtKHEJrB-idorx2uEZxvCfwRdeCAlHJi(3n3Il zdp(qLj5e=qmVV9ND{j0@&s@6fYq^cfgT**H(sFs8Xzh-BZFq6DU7vkbb~yN%YNL=g zTZvwuhym5VR>a-!>`W0hbXcY981lL`6Kk}1IUu^)eZfJOQIZD5um!Pko*h$*4Jvpu z%Y~Nqf3Fkw=*l77cz^Ja)fL@+*H>6Ph59KxX1Lu)?T+^yFbpw;V9${r7 z?Vr*sQ{M92B`(DVu*zKcDl&uMSWO{c`2(&<^cU8c&v;mS_G+5(LFM~gG$Sx6vz@Jr zW&aY-ZrfkCx2&e)JVt({%Bp42bhQ@&a?ih7h96JbqLj8N1teytEx9)4O>|sf;8MY@ z`dTLKC~q{oCl51<)0LShyAf3@mBuZ|94tORI$Iy+rkFlkv-c9?`K;Z(jVJr*nh2Tc zKA)FwspIhUz!VFxN^{Xmo9QD#yaU{*PgYW?R6~+!tkVKQ4)hjj7rhHjo)o87QD3&Uuj92+%ur^ z6tcl$NTaj!ii`&hd7ZhiJJfo!t^((6#O2u7@7zHVODh82IoIaMp=KA>iTT9UW(5i+ z0m>2)lf+(b;7U4KS`Hm1Cno-8z=o~TyS8_EoyAEMQ`hM+28+I1fPg<&XDXzM8`QfA zm~O1tu?Z2;gX=jVG<0ATZ!a?y2E}i=k({vsU5s|!0#>|nFX1~a&}0{b`e$hdAI*Lf zj+1ByPoNLswj9kWAWDD@k(iXcBc;u5WIeBGI4cP;LbUuDp6c*=)Tau6dsi9lL>pW# zOBU_)M0?mvAm zprDQ`HtY8{M+?(%Rx_s3cUY22<|xSi2$*zyGXL04miU6c%``HKkNPB}Di(_*#SFb9 zd9vBh+OO?uAZj7g;4Vp{S2lZd=z}Z!i54Vg*;Uu|7UFAB+H&8&bZxQ!9Lg&#Mc3V5 zB3wbWwQiKS%{Y(mzMlG(Mblyy)+LeFTf#l-Is0cgl+seYw&9dh_cLNiJ6B+)4N)ca4gF<{$@hX zF5Td4vH|zSYRxx!=cQ*LH(-DRkf>KEY9Z@5Ef)U{;aaYg8L~- zj+nNwo^QqV-}wpHc&3T?W(0LT-tGiHzbVNInsYV_r4Bir;m_~Ai0!*qt?`0R-+{tA+U>^gSET@!p3@I{_na#{IOVmi~YhRcRNfuQR4v`n1 z40Wugl$Dd62rpcgjLc)&zqb9lUyC)&rGGQiOCbNgc!Fv``^IalLr>@Ute`{1DzTz! z1}l))UI3!HfD-RRDqp%UOv0?T7FR+{UXPvpD?_;A<9^bJzciPcIIO~qBB0@FIBA^6%PTV8 z_CK`%_;fO8eHc;As;OYK%GWF9Xy3;P&7$f;R%kz-@VK>i<8wQe5%rE8WLwi8z4AO5 z^SW?&PP=Yh?*{aS*RrEYg)w_RDh@5`j|X8MeT$u5lkhwZ#OsOh5UA!D_$jCK{vTCd zCOW^>XDD)6oSDCCJ#u!u0J=1)_j0;q^4aQa_O#a6e$Q277`|_34pmeks}D;f{6Jp6 zB~H@lM|hh>1`B|`BDPp)#@x|Eg)OGO`xbLBH_6s&O|wTzIj>S-{$+#ZbL}rIaIBcM z*2GA9kRBo*^u+Z%%(o-zd8f}Js+gLpBx+O9??Mt(0!$3tg5wTmdyKr(Q4xW>g zY7p#`R^LI|>DJna@td|mk#bC_XJvE-{11uuFK`xi$ zb}O2XKkcuL`RHVAp3dqkVAh1!A21M75?EYJ>t!rAzHYa?Myi?x!Q$cK(=h;LwUKIC zKojgwFTsD7#QycOqUUzG8P}J{56)2m)gN^gSp*mcr0m^LHBrkq!ZT9_xqgmcS9RH(IMuQXW5D9yNIlX*TCtLi!qp)Ss` zC(4WUxmvCvtOoZk!3V}NL2_Q#GE+6LG)~3XNlisId9T%;Yza|pN8OU)=w&OIk~kiF z4CtM5W7XVjm%UCAa0=_z-Fnsx>@6rX8h(}fVE0_0 zt%~7K>)2K*ioS~RB-H1&276eACAW#s`TYW$exx>7>Fk(lO{$_;mSIUxd^a^8bfU^l ztDrpasrq__XX+6-SwBV${u=dKzjfUC}egTf@g< zTGO;K|HAH+)Fpgw3zMm}3ZR^>8$tU#*C4#bUd^*^quC7`?RiYGuGhOsH_DE1g86=!f8b;okXB%s$DhAwp0$! z2Jyp;R%z5YK*64_wnO_*1{HRHcCBIs2}_m>%K7N$avn>X6^c3W(~LM;q5LqZ@<~jt zF%IBku)^2rp^A$)Oe~lba(u|@Ma>381+&J?5P2Du7)xN*iggeQ&3+WFt@^rwQojZf zZpP}U>{9T_%3$!`uK5D4T1-Nv$wlRXi z&cuTb;W7az5VL4%gSQ_YZq6C2b^Ab@VR!%rBhEH`+jjLt6Sn(EyDE8#9Nx zlLZq{^jf<7g&#Cu>qPM?()uFtyPc&Y?tQG*Eb^A}<-=78U|{Z?T<;M;PMI%#tEPtf zYqzVcgm>9Awx&=?`UjzS)8c77N_*1cl5o|k!E?k66;LN0^6A2XMn{ldsxh; zLA?YvblMdqownn_Bl#J^D|Q(tgJCTtt?eLNoE*Ul)*kk_wd$SJ7nYsM-63mtGiz1-J1N9g*d)wA-YsWxqi>SzAJWuFjo!on65T?ya60 zC(BmBu8f*2OP|~9DHG%rdFMRe1pV!-6_GJgcs*N~bIn;kHMn~85uQv}p~Pemhb ztjJBLDdS9-GmuWq(#B8Mj1!OnJD!2R|Hi9XG09wOraw&!Dd|zZpDS_q)Y(s@Cuc)-_JYO?H9+&Ed0f0!xb518*!E@MSwvi~E%ulF-fI)5rO%-8>$ zp8JQ_SFaGUY)F;JTW@be!y#ILve@X%u5rZY;Y;t(pK^;jnlqahs{@U}mlkX;5iix| z$H{-RWK`2=1}t$LCJ%ds?i2U?_M9iB3Zuyn;(-sytIaE}JCb07Hw%YSv4N!|)Er=< z^8=2OlG&@zLf6!Kn*Y#}CLDPZVOy}^|;t<%bcn(?UyB@z% zhwp#K064Gf+b@FY?60p~6PH#-f=<$x&R(R8c~*-C*je-k!%ilDIw}0Zd%>Z_ws&ul zkQ-YM&=C3JDsCq|=5&;(u^TBR-0R)(F(iy;ydkloEA2M$E;SN-t%0x)c*O5E4cV_SQexZ7< zOByGly&Zj;fq)OntT9DT%33$w~!1O}e(?pto zbsg5H(rFd~>XG~W65lZG;q)n*zOq>#!Bf)lR_P~LUqjHd8eX={qUb!dY9UJ`|1mMg_ElnYO5j0V&wV!1YuMc02#=i^SZdI*Y2Os3 zIby16aru)Cj>^}azJmUSy#W@ZI*eqrXpayUH90U~_u%+~!ZRmUjqaA%Soc-+?=iig zG;D}9y2W1UoKSopqVH!7Xd&i^}H=ufo~c%m%Lc35*IdLq;v`vQ$cmdzS2Dzgaz8sRmE>~8jX21FkI`kqB*}A z(l*rN>w5gouQQFBEQ#gt_T!J-m9+||=om#_6^NRIVrB7Tf&9NqB3XT9x~HZ_ig4bv zHdrre=1QmN<7?QzHkZ1)hZp!qoOn}gD09mCN9e;7G_*{**32k};X*<-HuW?*&YZ&a zuy1DF#&Pf8em)9E)7%5D-&i|+Mj~%>DzjkP#`5!BXk^2X?k~$Lxt`gVkbT||Sl~rU zsQGtyq2JD+b7v0968o@5h6sL_YP;@KO+uZdhlI!M(bKlZyoX2NnAv{p1Z&e?uKN4a z!B!IIRfEw&DGN9yl$7_YU{asYysP9|u>KpM9cRy~6a2H~t+r4N1QUlpP zEzA6OHspU?h_r1he;Z@9N~!CDx)Yv^ebezh0ZZ%JbSQvV(ld71 z{35lDgpd!i49vi{RdL0h%Utr_9?elm@~X=r<8)3=6ry$lg|VQe4k39Uv3r470HDd@ zXTczj8ct!9bXNZ~T|FX@t3asMuIzNoFs~iu&5N3rZg8aNPM>r2auid(TvxGn#BrA; zMWr2-|A1%8x$IXNUNnA5^P>;iw22RRPfc*5$dNOhKN^0dKK?7L&)+I*|1~MeU$Fzr zVTP+CF_OjiP87hdz$@?eN44`L1++iu%DeeZER5q^HCHFInZc?($=(0o!GdY>V8T> z_SM-?ur$|&l@1riE5?e#^74^3MqeC@l36ZoO?i=wTQm`Q{wLc$$s2rt`VS`x0~@vG z%2B2V;*ODxE>fgb3ORQs{7Xq7G4e>zs&4*0)O7fQ5by<4K>Op0+A*??4;SKJrRU*< zTtu2sC}c76bs;gxW7xA;dUzNBP$#-1vGiKF&hgS+T{x5S$o&OQ9`+Hah_`m( zkZIQR$j+iXO2xZjZOCD{ja{Yy0&7o>sd?L%VBcQ=xJ@6xDwIZ2+q3ZEo@n=iAvsx0 zqz%vM)qAI}cb2K2)q`O^mBG(Gz@`MYI%!aq3;%?z%n4nLXCz;qsl#jOjy%ECvwQ4u z!5~V5%k|sP;|Z+5QrT-yvn2I+xlf)t+Hwf)-kmOW|Xoe8iY;Iex74R!pEohrp?l zISmrPnoNEbp=ewV!-gSMrv;ue8q3aO;Y5V(jR%)TBxDgQ>*VHC* z$nRh#GULJs{lNDLqD9GMJHEnr7+2tV&8@bMd6ky)}sMzfy~L8)&K;^6S>0O3F>FC6OguHvYbY{ONG<=`TwEAh z?B?wzOD|f#xnfry7j!B7?bLhbp1S)-_spJ1CN)K%#nN=aSSm@~*=#mTW_`F!!FY>5DAL z$Ff@)@A6e@aCP5zG~;Wng3@li%$Uz%D-%QFCML)d<8j|mQnaMLC0w|L-Rz=CG%4fh zD(NNkz=twezJ=K9#&Zh-pMek^Z7K#w%PQNc$2UIOo)zixi_*(xbd8|iG=CEKUcfYf zbdc2g^%PL;-0jN5C=;Rh3;8y^xp3qPX*_&wgvC-%p;(xmrK&z>KoReZ7^yKuF!$4_ z|feO5vS>R}at##Qc~cZ<N5AXX0Z{xpmHG*OnbJ1Cp{^?D^fUiJQV9{HrkNeyH2+v%FY=ZFEg%?;nd z;XzBAg6>ngip$vK6?yCu<(T7_QeaQVyA6?Lj`Ee8d`DDe%Qd%Jr196MOZ03C*NT&O zr5}#7C3$;>-=*c>(iFhS|yEwM_ zDk32&w>V$(DE?^r6O+R=M((k3;JFUeq6%}1g2VjecVzT=K$VZB2O?Vbr&{MDXtpmp z$pof;TG*bwSEQte<0P8rBKm(b&x%=DY^hJX&9Dk55V%O(TUyX?Sb<4ys$sk-UfsH$ zi!F3@&r#ncg`IR)sUt}9XO`4U z8*c2^L-v|H^{53faXtqWH|?E*B-Z1oejw{B7xe|)550jl`l+)el^bw{qjeGBP%w`V z2P%q^q1ooD$>2Rci95flD!+ElW%p#AUlPx7(5R8T(? zd#vM?He%;)ikx>BMR1ei>PCM6L+&1FX<4DKe3FlyRckw45 z#Wf4hsa3q67J-0=Cf>jpjzH4Z;pe&)-(YWsK>$~T^<==)?CD22lLPr%zacuXDzsRG z82b63%Krj$Wt~8RLi9AT2J6z%>++~;K_W@)toX^@r;m5H=_z`TkL$8NeQWD%Z&Ble z_>Gf<0S{NwL_cU~Q}EesG7-#N`Uo^aFp?b{a`6s`lNA@QZyF3dQI(7N-Q$IioiB?& zzbz5$Z;iKk8A@KsV<%f6#+El#mQ6KTh^FK`>GrI2=40b&Fjq;clA-;s++b-4M2@^= ziP4A_$P+7(Dndk#59xFL=zMgvFZjyn@OQ&$!C@NkLvTC!{6FN1AI7~NM=Lrm`l-H5 zcuQZT5zTVCN>SZKqb25;u1L?p-(Y5H+kUEW<4~Eivqf1X55;FxH?g3pkQOS00^nA+ z4VFlgR(Vv0rS`1`?)uQe0ma>kHQoTMXkA`2kJohz}!asdd=1b78I8gEQixJ*Q7A*xnE55v^`h z_y};o_74makxdau%wE=lP7v|vOF%dd=0gVp()key-e1NwG~K-hG!dF0G-1g$UJ#*T zn*8cS`&+a>q9~wCIoG(LaTQg2yWT|~7xKG*;iL)=I9KIesm7EtN8+>&l*>J!@ntYM z2X}i{2DZ@{X3MYjx0tQ>xQQy>Gd^E71Yw z31v)99qJuSYxw!c&a(T6<*=P0J7k=AN@D#Hpd3_OTE3nc>F%g+S8#bVTcAE4vi{1@ zvxWmU6?S4^s{aHF_vR_t@|^r1odG?m2bReRvxJ5hW0QrVym`7;d2K*RRbQ^rg3Gvh z|G1{hiFs@tJ68p4fb)R%4^vRd!xh7&8tEc8#FNN?8Zi0zjOG8)s^LN9`fF1Dzt8$h z+gJVX63&0$j=yZN`tO1MA2w0@|2H_t2;?Sm2!uyBy$A9G`a}AM26zLKJ^FSVj7+5g O09i>ziIR6le*XuoDt}l2 literal 0 HcmV?d00001 diff --git a/frontend/k1-640.png b/frontend/k1-640.png new file mode 100644 index 0000000000000000000000000000000000000000..61017747a110103802eef2091dcc85ed3705b5f7 GIT binary patch literal 30163 zcmbTeXH=8hyY3yu1xxC(AkuAsfPnN8ASwdVJ4hE1klsTHNl-)Ae$L5*6uH zItf*JNkR`HgdEo1V~=sp`~G)1=Sx1!@ytAPK65_zJ+EJ`JCXXj>P++;^Z)>WN#n(H zLjd4%C;&k7;m^w#Ehr7PNdVw4fX4Hu#(`Nob62fy`Y(6yExo)oZfywGk=OpFF3Q?| zjbN-RDw&okeGGrAG5bUv6VK z$z9doz49FPXD-pzwiO5@G9Sz>h}Ta}Raqwi08dDD$rqn3_d_oM{t5-q0-gXa-v$6K z{rL(2xN_%THP)nR3Il=aupaz@uEni=1VBqmSolCiD2?x{&%?C@qwg%4eYLEt`r%5o z#_@XXCuBO7SXDs})pTE6MsKpo8r{dj!tiHy?#^}w9$L>=y^8OvD>uaOk9GJ=_gLEH z>(2(C`0g$g(?edD-s#3=Gb<*CjfN1#*?D{J3J)9Q)EmeCd$0Aonzn)g!YiyOe>plT zw5&!TmELD|e)F4({6lX*rmHH?G(on?p~GPY2(<+l2DBB{$!g3_Ayd zx6ex9D&DhxS&9V_I;+!B^d&!XUJCUH3?=Yip)6c1;{X3S@?KFHs1tt|hK?N9V$HZ4 zMBKSb!62L$CuXUgCfmhKS2^lM=kJ&}oQ6qWwqzo$y_uM20Q9M{(|YX>+bi@H@5ff- z#^>hn*wOOCR0-joKP(e`l7t=-}k3V7mp@#&1ltKTQh=Sg(v)+9?xP zQI`7*j$_}_3z;asn38NIyzhAGa^`V5r_p;U6PN5Qa*(`BilH<6J+_z-I|HjyWvx7cwHf=@kTz1@`_|PvDiY6!!cxXudHt`t!|ZwQWVm>Hqpa> z^4!RHcyE)@X%e~UIv=qX;o1F7*jU+jk%zReX zL;Tc0GnV7BII&ll8+9hVDWkVB?cg)NV35GKri58XrBKs86W=Z`IP?fhsxX|}Ft#qB zg9?X@&esqMv`jg*=hHf_Dc9?R@SI^}@Zn%4cu^|}Jp=3VLUgj)n-G!|g{j*N?yR?^ zPUbvedNQ*R-g*0Iy!vlF`;1`LInEZAgUyDX^I?eM(b`TtFh(rz$3qJ8i`I|7&_Txq zz1wl@g>{bkh8p6WuvmiRq$L#U+}j41`)W2bZN=;5NIfnQ#uKyBTkRs|nb0<82ek!5 zb6NDX{M;l`{CCLnFKre=%I;H!yj9&GPZ z=jOkHOnnSflph~y^alG!PeBlm;RgCb6VRfNM=6=f_L*@HI5;%FK6Gt>f%{6pLMoa* zuZ>TLlHET!Z^5L0ssuMDdkFhQOc7orpq(joOF!>a-%^d+76vM3B9IfGinEdf%zrnF zGLyvIx!N1{c|ViVi{^TWbdZNkY1fByrcohkFA^Jk!147c~BXYxmjj?&!q zK^SD^W=CC1So^?%>;oM6^^X zi85_9uAy?Wg}gI$Zj_ZqXIJt9l7rr}8!msa8dID~wwZuA=g!1slZOWG%KPF$^xzSG<( zw0rU=jl6Om`(K#%dC_-+CO#)%u{sb9_S4R?- zfDP8R?4`ZWT4;Yz+@&3ejEhh}G)V?pU`E850*1+8vN@?zO%EyOJzF2sc-oQ6$WHdJ zFo@z_IY@sH6g$&!`p0^hufSmR0mOG=T}82q+K51*c>M$>hjYnCYxkW-T>={!1ATUT z*jigNsMr0mHbKXhxDR=Kxwon?zM?uN2{rS6Opqz@Y%*At!)&pgOyQY;VB znH1$XHQf2)-%s1pZ?rXhel{~8=Hs-nhIM}Bx!Jwi<=yWH9_tH_dnc#~y0MC!Gvv%25_MvpkjAptHi}q?2W-`?VOm@e%Nlopic^$8RO$k|I93 zHQ&*Y1d;}m-7dHRy%PI4oitp+{*s*2#mR`|J)l5I7o1tdGpR(6c%y(23vojsr`xRqb6 z&?k81Ki%AYs}|1OyA9uGWm~kPN>sl;%y@c36gPiRdUlOv-zT|$u$*7}M2+o)q-WI1 zO8;xJ)56Nz^a%AZh1q8R>)b#+tjrn;9se+g&f%OY^Pd0efo6$rR4ugTt#mbV$6reF z)5vE`S*bTIKl4p~6Hg=ONoAubtOiHy8Q3MOaMp~r^!Joj$D|)D|M13f7t}dCexaM4 zv!{(ko_akUG_n}@sGn`AFDsDQuE|?C^`)@C>!fsx+4>gjbS2@jJhU)*PEsA&aFV#N z65huAL6m#W3K8<7#(6EnsnGJtg6U{&?(wQ@IL8qFeDgz{i9UWI&#=;GcU#hKbIpCJ zzpFLd{G_X4W&yyukgilGEi|A9>~|xN*_ZxEpFnZzNb0H;x!H-Gt~e%pu*!8t|jlxv2V$4>qHI zpKH8UKgn?DEWV#p*X7N!Zn&LrcFl<(B9Wh+~$)2BDaPq{Ny?%Fzd27byyr_c2s zIjblV_#;?l*m)Zq5i!WQ1#`sLB>1vyc!DfT2YP}1YpL%7&KL1DW`my3hcb7&_O-Ze zESp^;&djYyupiSbFuiLntg>-8hzBeJ$s)PIWqR?s-V3Kns;;IfB5FFE1xhDJ0%(3M zmiKt8i~{cf3AmX|)(o*Jf?^Xi z@XaVpmuN$6<4HM^|^jqjKawVmW4CD)`T$n+@)s^1lGxW<+wFtIuW|v&@PM|Tr?GL5!8s3v!D-0|ub#qjw&JlMNWF2g@hJXkbwC1Gj3rL&g&0CK--a+Y zZC<{Imp?2NE&EvlX$y+Yee3y-#xJ@)kp1vMrRL;Pc`gq_rF z!{2c@E0AxO039DX$K6Bp#T+Rt3EyD0+CiAovJun0{eahE%~}9n)Vm)bm;J5sp{BA0 zOg?|}*p0ynAp^A(VmYg+^g;l`-sqE=q1&nvH1+EqdaZMZAGOfh8#V=(_9s=d7%8tw zR|`D_(3$jAAL~J4^Qjv%M0Q(Wz;@Eg{qMDnPUm?Jax$_dubQ}vabpXv-b9;;x_f5M zkIqlmZ+1^wZ>{4nKwQUb_g`VJ6%RV59jCCt)dBFQouOB{j%LKOr9t3dy zE(124hu++UX~p=hqcy_t#)Gjyu~$D8CIB5Wc!x3 z>wU3~cyO;5)?xPZa?69Tu!R_keNNt1yfK%i38hM8d*LMK)eGg_F~q`I4dKa7c>9n1 zvcjjW{+k~e1d={sa*nEt6AhP_iZp>i`-yqQYclmn_?jeSL@a1{H9am}zA>(46tydx z)E43ufGPi&+??bj#to^?9fruR<&RqRVqf32G)SJ^zn;2rQ>x!c*}}Mz>^B-qB6XL* zrZPSE9mfyRMrsu04ox zYTQ9gJMu@*)fOLa0bR{Ar6?^&l1{vB#NSc1WyJ1y@JhA-&3vzAmFwcT>W$MiLgDY7 z4xs0+FvA9>>8@W|!g;^TuUvYhVG$?LCilUOBww^{Bmj>x3P|59Zj40tpY(AcqMP3z zq&DptSxbXFnPWC*oV(ZFtXJLGXLe|b^_%|C;c>r6r;t&k0yt^ zgn{{dRFV;N9eYcSu=jl~sJe_RC%txSxk^^na_v@VA5=I>BI~Mc!-&p-wQNcL&lY0%HNShhNOk}?+XV_GjULoXXx zSZ#S8TqYgs;=CZ<(z_sxkg?g^5RoTqV9cKmV|Q5OUJLEH&1o@8YF9{EYXau_1+4F z`DsS;y#}jOWWgYh1yL#tlDM3NEc4lQp!!w!5QGY;)T<5BOZ^w{i@coU!AG(geyU`mefkY<<*n9z*Ik_nbD!=*+~P~ zhbgg!mJ1rt(vfp<{!V^d+q7Aq)57iYytMv>02dya2i-qyM#1dzWpP%^LTN0c*OSH= z5h9F*Ie+~J3&l}gD>>!5Mf?pLZO2hEBjG>^Woa$5+nWD8dd ze(;(m`c-?h4C9&0%)nEaY*eHsLYI5CYR3k(^^IbZn)=!#S{mD~ z`w|C4Kj^NxdH#LJy(Mj6&Yd@P;v#E3Bm;C${nu)gX~?TeT?0z`qQ&y$x+D_`mBGh z5W+$B)MJ% zO0Ag6R;qD37J#_5BBv3~rD#T=KgW2dxDRQ^6Pz`%naEOcei$~$MsI3ScvM-fi$MT| zRI3W2LCyHEVHnEZ0X_PCZsL3VnfhydW2Shy6P(*0iZ#)-Vg5KhlFP!+$>>a5=!*EB zJx;d{s|m4f7u5;y!LmuB;{rJ4%CehbnT6!V29b})Rk_W38>R{qQZ#Z51x;-dpFVD^FId>p?SFZp~!nN0YZM$ts2ly+ZJd zjmrX7@ls4c#vJ4;uh7 zk|g@2lIQ5h_5_y`NirLCR~Nk>Xx8jj@gNd6hPgd2qyjTG3H-z6DyY5+32X znpkhyhRUZchQj&b3`mIHZGW%6;`?FBCXMMwV>>A8;z!wt^X*mNh(TbX(WE=ZW5Xh)lWdEZu+&)`<#hr#Z`wJaK*NqVmZ?qr89v2-UQ+`L``tIeV>@tmnj{EXKNp$s@)>`djq!VHGJ=9( zJLfR1L0A(JAg0Q`_?Wa@IP4e#Z#lIl=2_8sRf}AvuWbfbz5&ssCy>6O2WMt5$p_cH z%|4zu*oUzJ+o{U~9;|In>Pz?6mz3Oux=oFrupa+3e5$;cdCbyxiTJ)tsW3Z%Q`&@? z1JyzEWTx~c@{2(i<6fqjyKJD}uKPxXc+Q#gu>jh}hj+F&nFbp^(~Fs>Qm0g`1dl4zpH8c=-j^n0DtQL1~fG^#Pbwbu2a9H z{oS`zw7hcn{}_yStkhjiu5Xi*rlVng+h@Fo*A3+VCD?l&Ni*Fyy8j(&mgpo3>hp~( z;qp-O;pyrq@^MrB!`M#m5$nngH17PV{KG+AvzMR})EIrZiTpn-(LIifvr`2;{m=vP zgX@e~{co_)yF76E+)yayI`KV9^xtr*raa|H`mrqNrGwfIEOojQ?5VXadT3NMwY#Fi>gCPh{P~9~ge+%LC0D-+WGmZkirTyYT_y3;N9@ z>gs$}JXfxVz83agGN}r>Sj-2|OIE}eOh5((hA?rh%ldA7%&+nV+cHFON`R;m$MVOY z>k7-3FpYf+2Zcgz`Cfdn7kr$nWzOt!=rgy9%DOsXlAxtB+2MBG3S8uo$cj)vsbPIn zU9#lMb412yMyxW+i%1%|^^BhpmlpZ=o$nSKrlqe;%F07mrRt04h8L8fMAnkFgj zxXq6hJ3E>-+cxJHfW0}BF-)ThoLVN+a?4`q)m4Wm0PV%qeJE2^4k+Q-JdJsBXg|lr zf(H2EFwzVR(RK8%?0*bx@>a?FY@QAC!do9I=mZD$K)(GLeeasoXBtWPkdm0Ov|oa} z0#M~U%Py-$Bnfeo3e3P*ht`Y?lezh!&pD1|MP;H&+I@bYZx#2_LUrIC=L^7Gw^K=# z%b}W24U}X%+~|uvT@KU6)+*$UWSm;dotg&D0>^p}u}HHb2BDmWB&;b^A)vR|)?LA; z_kq%1MdfLt=Rs>{xoM-HMpf1>9X@(Yxq(pf^EEyThfDHpb69kDE1tFayDs&x2>?t& zH}?yr!c{6WwGf+o3$XUdacT-1bbmO!OVU!=!bg0!@$R`pFh>=Bag5|`G?zG+3S1tx zce=?035L#Z*E1%?du|$*vD4+h0bO#pTtuukiOH3U)Y59mpFY9DwIwn!6{-+=_ zZNouF3T@1WVf8@SEp0Z$ASGmCL3z1|(d8WA0_#@}rAE?I?kb|1;Omz>VugT$%dbP~ z8l}_XE|uIfj0>-#6nFkTuN?O$$(x=Wd@fRusG)SwFBXy6lI#yCrb3kS?Y>msmt|U0uBON z2tvQcHyT~-rH~Qf4Lu4qZu6KDxHM{x_J|;E*Zlf8kyo~vnRgLPZLD(MLw6U*Nf9V- z2R{B?0>b*iDk|&?c4(R%kr|V}oQA9h0(WYEd&1SuQaiPd&&rRE2ot^5d=8&oN_`Mg z!bWV3>QlJ%Yr}FDwu()ZZV}LjNiNBr>eL^H!?n`=GL+?C!hv7a2OCaydEsY5^2>!w zIPSq4h1o0%Z|16|;v?~84b8i}vX!J-N8A!F@)f{A+n|jSFOG|59^PNy3rfN zv+Hy2Bd$i0WKurWX4}T3{(xxV1e3R_ zhkH_Qa2^+&HfK}a+pL(6(P*FDRcdsUNnqS=FQ(-UiN}A++jAUMgX{jo)*%K`I+sL^ z#Qc?TR**@im_E0SVuz2bTOJWl%2a?yAl;e$zAXXvH#rfarnknen- z4tZJhRxuJJ;xSyyP`38{{(DH%+m)qXJ=MRC`0ZW0!Ah7QxiaI%IZ9ij?|^3Pm_wf} zBQ<9JhUfZJxfuh|qRb+W<0QYa@Dh7L=5r*r*_C^%5jKm) z7j8_q!?dF^DtSHUzkMH4vojm~K6z+nwPQYK65dxETjqt_p7>dEWAiAO=sEYq=0>=+ zzv}n*JhEahw%5pSAe9AFS;{5lB&3UI4N*n_?oLCz~P-GH>9oNxgZJ*>?P0f|7Km=NJ>L99x#T zP}^kc?229G?WT7PuS`xzx0|o-brN;l8iG?ip64aF7CEe#Trr<2vDWif`i`qumGHJm zRb*AY*ujIz;InmUyNT9tzu|rmP@Ojp7zd5W)DUzl7u+B2niv-f7nGb!=Cf{1+=u5S zb%)>jRNz01!&cOkTbpGE$QUV3LQk$l>@snp&K)Z4+mxZFh!Utha#T_$DuV;qImlpW z3&N#!3)Z$qQ-{sL^!VEkwgZQOuP0Y|AOPa!x`rqZlNs2bbj{-0> z+uROj{YX{4fZSUVaI5|0I-SO@vngDvfwp;3#WUg8&^BCMQ&U?zu~TiBhMiGwz|i-y4=}nI`F4^*z=ktr{Dt zS+rUWjo;Gy4;JuYFtaB)H6sVEAhkKBO`nq0J;CMjHlz(jGGuVio3T;yAETdEn*7== zEYiwPumzHfM}n)uGOcZ2Nn3_1TDCCPy&am{oIP38{1JC@c>6WN$^E&zUgz^NkB;!4qEB zU(C#P0u(+XtXAI?TE)%6^Q?1&9Y&GD!!-CDH?#U2OP%dzDc{lwtD7lxRq9oOIz&&$ zd7~D5L8`x_Pe?|uib*@m&!#3*zRqq6$rGra0lxHSzRNrsPW>dZZpp~;t7vjgcQ7g= zhO+&UatqdA#|v+{nZkkgwan^0N)KMEGTcw!({y`oRj0?GzWMtXh3#h5xqrD}8Kt}X z9HC^_J$p)C9h!L~F>h5NX{|ewz9r|vN)L(1;80DVMQ_EO1`18?D5lOfN9WISxJYRP zSSf{P-@D+H=ur%?q<}8J)v|5g93tZ;nMUA)`t%jT^|C04Y%QE>>nj7|97kx{+dA z^Ml(J2Z{TI11`)$oMWJC<&!%GC$X*uWYp`?!{J{G%cH#R$^{6|?|)dc3&2R5X&u*U z2UDdjciv-y##7Ig z;QXR9lf~Bgm`>}#PbWHBrfTKE%)H}Y!H%0dr4o(+xc3b#mB=lS~)(_H`HNU!EH zRGgF#d@@;tJD9gf5;UK3oBn}r*{l)u;&sH7YrQ!DZnoO7(qHYdQSOc0yyDeIgVqpK8!4OngtPFVoEC zx7r1J=zGR-{oi$_m-7*$fk!&M6j zseGPpx*jZEWDc2RC~y3Ax*9{flpN;puFw3DQ2QKO4C=eJs3TYiv(acB@Gryar7TOk4!ZpGhR3R=@m2d>!zW9(#ZwPR|Hk z=*_n*v}OD)@ARvJQp;^7eAaf!w?sE#fo^O-=#I2jt)O+r@7( zB^vRSb2RU9+ri4eS1K#=5&(dbPmE@Uq5_>(y2|WmVq0>3M1^}9={R@w*5l_wDTcIO zXI0_qQ`!v;P0kpni~!=^ty>LzG=Q=w*D0T`h!C*b@?q8^`vWJCuPf-8P|N6*T~_Om z=?M3gIzo~s!M|j|>S91!8uF0913FxV+fJ)qObLEbC`CU~tIB7GV0-#L3k8D~C7=MI zLR!n1AH+>WeGEGtikq)E-}o6H^P-m1J<(i{>2_^VOm2wE#h1~$UYBYq(z2Il7t2<9 zkfPs9bFyPcvaJ@q+d#eyD3g)#{lED7+nwaENwl5T^@Z8zbHq}wukC%6ihy8Zb zw(<9kz6>bK@y@0lpGMb#D|6-fV#usu(i_k1(K6lqb!0H}NKy67@#G@9o?guiwBU^S z8hqR`tOKVs630M4I{dB%CHZ-|kYDHPzB`WEF0X?SBHrz-+4=`poR?U0TTJwFhVTV2 z)z7WbBKLmBBwPXn0{W`2SanpUnZ}Yogzi3;N!dlHYZJ;_W3_uH_!imU_BWwrkQX9lLwEs<85{k-M%-)FZ@1h zpck9B%Gu@)@?Z_>`tr6_@$Go%EMVwNAVm9Tp3&N6zi;=b#jA#dh1M|M9c!e_L0lw6 zR%Ua)x^YmaJms;Nkk6C#rZ{sAK&a*eC1-*d+5_Y*y7>dWmY9>>S8Efd`_8&m+P6&9 zV<+KRw|QfF5ZwcMM|@PIyh)8OKnr530+4qD8tGS`$jW^#Urn-=n6=qMUsgq8)3 zwmv*AUO%t$%9Z%XQ1X!eB!^hbJZ9zVr?r)kJgciU0QQh<(D zZ00AvIgyn(%)J*r_fdMgN8>zTe@*q~`%7Q0i(4zU9v_)0Q$l>-Xg~8f?UNWyT)t;E zNbx&V2kI7TvOWz0|EO#99M=({=GIZFleJ0IPX~4i$g|3VlxWLrtX^K=&w14$-QL6Q zZHVm0!g)!4qh&uq+Lja7g@%q8H7iwa_c7BooVNUlp37QHLgn`O=J9JCQm<|FSLQAU zEkJ1BqRUy;Fxw8f{!3E)kD;dBwoPwzyDWL#i1o{?Nfq)-r4)D8O37f9rt(2Rlb`%i zT$m4!#pHHjBYNy+Q=@`TCE*T;L?(zJWn$gy?8)yw0f#|Aif4XH-qhsKdBP8qKAA1` zf$+78ezP%#KfFwfOtRNG8$+~*aA?_KO1YN|4S>gRb6w^Ud6h~(YK8@`{17W1=ER#f zJ5>rUO^HqAv_HCPib}g{a^U4W{+ziTevjo%0X3bAO+e!qWBLcB*rQu>th}S41yJS z%8vf9OqbPBFBi<}VMRaNVR(0fq(IPcHJ#Y!2YG!Yg++B2>8(2mSmux?RTxIJWn)Zi ztd8zRDm=Lu68CKkc~13cyGPz-gg`kwBw^D`E6bEz(y*+;_Zxd;IrGmw^UrdR?oX7@ zan+h0osyee9uCVmkc%}~^Gz-?i$zgCTjFRXH-tI(-WTuuQ?TJF?*dvOxNm&0cdBEu z7AwpEVxKfP&>JWHPF~~rvX8nJp@X#XUlDSkyz_;qP!r1k+@hWMb+dfd*@!@DvR_Nr zDmRCpLyEUvL*gtrd|wo+;dPOydL8)IJ(jf|J*i5UnT6I0^{vAYiUBYvW%9f>E%g;3 zutcyS=Tdft^zN_endvE(-S(p_+ct-7byj}l%DjWVWa9(lmW8YRsJ!UR*`466>K+>T z#0yU*b3of_xFG&#`?u`O4j+h^lj8%f=GRq|@CLO;;G3o&9fc_^`Tj%crI57hUxijf zGL$2;lkxlnct6cV%zGD;w!!D7{$U|l8F8^Y-$Qh60v4A{=8(AfbEdCT=Qm;Vt*c+Y zE6o{)&o><5Wp_0O7nXoxr%E$@8i!12eFTNY%lgUz)wHj3sB}pB@wj1{X1S-(t7tSVe{E=JXA&meECN4B&<(d_=L2@50 z=Kct>)v_zc9m4W^Y~WcMlz@dr5weH2!=^-$!?303YX7nE{pf{+c$TmrLxxHYVoLH_9uRqtgUh`^g5XmiWScGg*pifA>R zALl;${jY-Y9wq|wrV|hTS1GpMh)uQN#l>+<;|ZWUS03oK+w(ETg2*YS4HHet7%jSe zpZ$8kaQd|+5~j{Q0f^$jL67Sr>znv)ajWu5d+u;@PIRQf6uxy6NCeY3&mteLJ<5DR zy#N?KJ&NiX7^-3?_c`rV<)^tvO`m-StbR0$Xh(_fO`5JGQ)~w@B_ST0)xi6(ko!;2 z$Abu&4D??c`D^H-J>~T!E#giL>FD4pB}2-~^de9HGeo_>dY6m^!hBXQp*V`zut^Nt8=cu)_y(q=4ZjW0>ss&4Z-!-eu$*X?D+{Nu8kJDvtL{N zNam30gZJV+Qd&!9ueWn=ANxC?3$%nY#GZ^1X9heL2Io& zyP3SKp6e!FKQbb7+MuoBdmxdmWKI9us?@aqXtdPlxNNohvYtBnNVD5oB!`)2Hw4`c zZMe`C#s-%!PvUJp?M^Z;1|7;fGwXz*zn?iRj6z{dtfG119I* zt6Rkod1_POP^v)GL~j2V<3@_lftlWd)jq25mIV|WBxrqEppt=6o_h})^@s2KwE_0W z0h{XYbgy5W@vrIsp|l#aS7|9-ZG*Ikc7zd-N~I?^GJtj@^65<-Tg$?jQ7cL7T}*sx z{AbevS4c`3e?BOL4EI&xcph@LHCpn6Qt2T}SBRN2asPXc-8WaMc%11Bf=0NlroH=E zsYT>Z?)C4v$iFe60Q?AQFb)&~*@~m#oT`q`)go%(FkLf&Qhsq+Z_-<*E9;Bk;DMK4 z*{6e9PByY{UG*)3HT7pzG+CHAIrO1Y(5l-^>8cE4$2xSM-nz_6UHmXnGaVfaeKwFI z&0xAS#tP9motD;;-RXCKmult@Z#Sr%cv$*@HdJVH34J3K6Yz5ukt_4)>b~2~yilN8 z`}ziohv+dZ@@#XIkWGC5Ntj=E;kIXdgS&wCRvse+ID$|esaRGORWS@^wrM`>zcX=e z-f;%So`TpVAZERq9i?q+hXfbYw_c=4k11|9Za%2J=?b7E>d~mArYT)3xS_@O*CHQr z=jpAx=T zDsey>8JN>ieCQL87Z&GkPqrh`))z_ABsvrj3-SdoE+#N>HsWQyKA%|$Nf+vft4Tb- z=SbfFanR_1y%!K7jUn$i-EeZ(dZZAg>@q(sD^nIBM)3=cTR2##Em;f*pMctY>q+E-z zN#8Y%EJ|Vg7`+$KB$|D+mbL6c<#Er77LU|Px|Wo)y;E6=oA-Irb1=y0ObNdiY6_zG`ljJ@9rONW8U?7asULCX3vCNy97xhB-3e9VIA8zCD;_kw4Kl5s9$N+fpm$#Sy|aa{ zXhJT(RqN3C&L4s2R+BE^6DY~WubyFl%Uk9=bcBmSccM16uAd21GWrZ!(pj$Ga?eWR ziurU=e}ddN_X|b1mZ2S0r{~A!Pv0V4iAAwZh8c<(7(&d*#IUUXd^_z$7}dP~e-}o- z78*{xIgIe6dV0JF`#a9on#1Je^(=7UDg4bU`M@7H4=L`BX)tXAyKH$Wxb+wPeKYM_ z>X4>?*tgWJpCZDOIGqt0=jBIn#Xbp{@0N)?It4upfF6N6p}+>ugJqV5oYUoRT}Q$z z>!VP^wkB^G9;UgZSMd`5wU$mg)Sb_@&n0V)cy@mQMXs-DQywAO>MAEE%+u>US3Q3P zt2qAp;peiF=&Z%0hn7V7CY-wXhsEafeU9N=&Tb`VMt2_L^qdmdq-|D<43wzZEKF-YR>-7%VrQ& z**bT`Qxsevh$90IrlB~xl_q*EmpJ@6N0`AxMZS}bfQ#k&Jk=8Us^MTJ=sqNftb9%G za9QW@+vU)*!Fx*iZ!~HyVzRbuV6PGobP1r(_lVcSg98Ubzd`7)bYIk7{)_U#|7mUJ z|M!S{VQp&KQeTBj8d4K4h~57FWpObst%9GI&i?kjL0W(hscQfL#zEAxAnkKRk=BjU z51QA$#jL=oI&z{HLtC{zl{6H3n4S7UQ0trbQnYW~r+@I)%O>$lHTInIZNZx%OqG^%U3xG0j4zB>hSR4kwxS@?MM0FH6U#sM z)o4AT`GviZhnQFkk%$XuSJ=Y1d2PK51_dSNx=~8B4kw4Jto#3AjS?%1WcvdFtTLV- z#F)}lX?UblVkMV`~ z1|Ns*O{HC522Io-`_xWij0$K0#=5QJSxHyT1%{m{zI+15A(K=!)B3i!o1##F`cDUB z(_{Pd+y0?x&;B95GdJ9WgJ4@{@h&3gMt!X-hP1oijb?;9bQroz|5?&9Hjp0oS+h{>pQ=?W;l0AD&Nt3>cFxXuHFd@>&GKH~ zy)a=lGs(L%6}j1)MtbfV)B7~6zp?G_8|r^Sc$!^go6&{y=?tbhN&w#6hg+7N#!EAXxTbBlQ+>z}EV$cvc&KHkz! zGKTfx!AeSknMPSbUmMfO>y=cB&$&xRLqaS;PrhCJ-sUDucNAKC@ftaN|7@}}s%yjN zT0WY}I+k>NzQ28ZV?9yyEK_Kz6kE!*ExmDby3kUxcq=h*)#|eD3~%sD0gWMUGHBtK zLE>oaM{dpLj*`;0qNY^WvbF&X+X1#cfnouXI(8xc_+%}p+HELw6rs#{eMKN{rT~JD z6h7W$BoQ{gP7VYsH9G}}`T7Su+0I#ZtccdRI3^;}d~uk$sLbHy4;rVp>Lr%7*OV>t z7!F0c3Uz>q*`N@s@Ajr^@=3;luZo?`iri%RGU*53WWh#GE81H}8a^N5mk)0+&(=!3bP0b zJd(243^ZNxrIdz!+(k!omUmj$KC9{?oQ8Zyff#}l1$W#S(3w2Men>rBIYl(mr0PVEM>`ToEEUw}KI8~b);ToEOGZxwIk3~a9jcMn1udyOR(Ox#MdTsqbQ-#5AS!(XY}0**z!07 z=>;*3GJa$}!{?T&3qshU|n(gjMIv6&}Ut9%UDu% zT~OmQ+5Qs&*O@r>`YET1s9sT@RB7wB_+;o^EyD{R(;t^!PW7*)V@AXCKi2$wEiIqc za3w?@Y#aE#z-xPVf3e61W2K|hmX+gAdbWfy(y&QeQ9|>yze@Zm*sc3AvfFn%myd!c zQj`|Z$}f3a{LxhrS{{b;v3=&*#8l1gM-gu`xN5_dturxrU6PRy1F=iO>eI9wd^0s) z-20b?^BYk>a!f-dfjUQg7HNbrs?k{-q|eLG18EH7uDu z7k;UBa&BzZ2J*-#x1!(us)x+^ff$JEya8Q|d37PT0!%BgVjvf#6?Bt|Z@uqK3&iBk zR2>hy8*oj0b9{ba(3OB>_g0JATHEI{3PfRGIZ51vc1MPOq>RXcN*(Mzk5sRQS2A+1e_Abv;q{ zyT?QWNhp{t$D^`1GfD&z(wh+J5K55V0+y|)^b#Vy2Bg=7UKFJlArK$|LT{nB&~q2(-12UD=broSe&5bF z$S)ye&avhi< zt1q=X;WbMEXRy+BI32mUto*_f%1Cyo;?cm(M^B9@EiWF5P)eB=ZT!}P9%0eV=uauO*?16jx4}9Jial7<9m~dJA`wgw>y3BKCMP1HK*=yeMbM2fa z*zS7~&bF^+vn(bzGLqx38zlQZV7_7Hi>kY<^cMt~!%&D6ep17}{8Bxyqt+O!xgxQ< zO3d+oDLlEzTdv&uz?hMfD0rY7BHI5BS>p(u_!agkx^)I(5WZmmP%Y=V=kaJ>rn~;< zh@U!ovZp8#7R{HrwYOAp8C}KfRG_YzY@8+I+s=p=M}-BA^yRKtC}6j$N*XcPi<7yAW)(EXfxrcMAi2X!T> zzSs(2`D=G^CVzyd%)LwYN>cK@7}cHHx}Ta9cM#S?E4(FIJVq<;Abg zQaEEp{p9{f0)Z#{W3;@JYkEK{`MG;m+dub3EChrk+z0yP4ekG3@A^di_~twI6IDul zeChl1)x$1Hmfmxu&SKWuxI;YjyX0=>a+rWtec8R~gU4Q`*?Qi{vIfe`X6<~T>_O8B zQ`q~npr+>Hq%%gjrA&Bv35V!Zb8NDpi;TO5ZmUUViJL#BB~s0y^UA{-8AGd=(rVmm zjC3mnei$A5>(SZa`;c}H;6t>>4)tEf6Qr<1Ek_)Kj~qV8mFcQ4=MQuUh~fe--2h$< zA1fFbQo=n@ls0Wv1FGP;F@m^8HQzB_zqq7@e2AAdTxqY>yPxx=!5pr@e<&eZ#xmSy z!VNreB-Rl`nii57Ls(5)h@lFnTuKw7>U|9{M~%8QQ%t}HKW9Q%fpTs!7WIUpF$wFT z$%kY4$nN9vQVzVL_$=#5nFHYr}LcFR^wcqO2F5pGI%w zR=R-4+LK>Py&2D_C6?nB@PF2Wt;-$^QHwJ_4 zUSwuV;LvBvy^NIWJd&0ceQJIyM#S!Hl zN2CAD-E4Cvyos%{2}sQ~_0-|aiAd<1jnnEl`YqwI@#LW1CY%i`r4Pt>V^XG1_JO%DEXwKnUjj^o zbvf}H{uqU&Tgsf4${$C|AUOd~^OgsSdV9_A?YGemIY`aa8za{EU~0FknzK{p8IU6W z2x(iAIsbVE&1F_jHPG1Cts?bVS#a`dov6at=^}i66+n%?^;TZpu z{v3*zgss}RT4mhv(;Lgx_785B+vHe~qJ^vsq{z#ylic$+7@T++mnG^v7qUNZtD6mM zR+?Xcj*J$nkOQrdPNIe|X3b*%dSX@bCl%A+%IMCwRMSH)H;Mdd#Qt(${cK=#@Q$<- zl@2o4yn7(JcrsUXO+{6_%+1fWS91>Ga7D!FAP&2qX!V#yf;UUcTXxIUmzzR}H>$WY zSQlJNPDI=6KievbL=HR8M8h|<9XHMWJT4?u&3#;LX_G{1(yv~bn7jOIWh58iysj6u z4JrhPs|R)t*2xlIFnMkq1d{q;Ek$3$u#lx+S*64_zV}PJgZ$&Zsd}c>-=E}qZEnDj zhy7TELRpqw*)6EQ2yAQ%ni#c5V z3kJ;}P6shblF&NxA)WXs(Zwam*Cj+cG;Z#z*TFdNPM- zvTIZqE$+gtwbUvK_)yBt6f}=95psV`^nO!hs|-j?}^|fGvQrC@06L6 z0O4Bc{yVA;`r=EzaI1`gG$I#C#y)*es&r=JQ&#!m+%{}vgfO>V^uTQV#(Ngk*dh23 z%y&O8WW?WOEGwq+h4V|R;++7$qxsDg+T)UBm$3mu!-Pcf*;qgK16apIgnZ`is>$&# zC|!o#wH`tR*u2#e6naxb&alIfh1oU z?N=aO`vuzr%~#xu;(S13)8b@wYfWS-c|*%ba?s0V#PMj|_MrLJJslS&?P+YE{%6?$ z6T1_d5fR-ZP?Bhb%eHO1jqDdppnFn$;pDZH3oZG$#` zJ0Q)M;q2K)sU~sX`I_l-oF@7?k&)j{iZ)G?gWF+dct-6Kv5SiD$mbKV}2(f}Vq)VW@b~MR-Ekv|FZpoK9|q;DW9j z^<12wr@w6j8Z5lQ)z63U;J2JBOH8qSi~n%($M2dzFX4qv-aiU=66IMz9)R? z7VkZ#ZHLWmjLxf@9)hoObi>);Wk0)~$`cl_LYx|Xf`}dsLiK{!AFZTBZu0HH>RkrE zr)69-cNOmC}#o-1~Uz1||c7WHOR>UrnSmBj8q+9p@>q@K9-PkZOC>mAl# zt~uCG40--RBzIWNFz##qFFwcIewkXDm70W)coH4E^T+NhcMdqhDb2k6{!od?o zrT6>n?IuODnRNK&a}jMiDGS0@xH?IAPTBNT`t4T=a|Sa<1s)83MKNw`p_Ow^q3WuG zTncOW68l9Mtqn_Sbvoi-DWU`C!)$6r5mA=}8BcSgWrcbfcH7>BbG*B=U_#z(g7fi) zXu38d{ifa=6}^NXj}_P@)O%@ljfatQWsHsCdFt3TFN3j)!fFk}T!)DwK@LUEFI+=P z#Yv(Rqd-r4+oL#z&3<=6yY6&^63MB;M8Ew)=8%JF=)!zLmD@qB8aWBKDA1zhY*uZp zF+<(<5Xici;HnT*8&7JORL+pm_x6G;d{#&=jgMyc8#^q&XEsYS)^mJcWATd=rI1s} z4H?wQTB|vB=c_mM7);nU-p*5SuJR`qxvbSm5MRQN7eV2hi_f+m@+%f3SFhgo9sxa< zi*@HJs5mCp^#x6o9JRIyM8wTCT==kOW=hUc*^mu78vSJiAy*#GxUZVNeY?(e5h<5fGI5VI2` zWbGwaX>pj{oO4!^1x~5XPVq(FR6*Ah4jzQj%(qf+LL&x&3@=fd%sgYI-ceN(jl{@E za1E-yYiQEr(#WjD!TbB?=wm-*(wWmb4SsJ&my(5fvrbvI84g5r&3;yK!(mA>`}T2~ zfpel4e0BC*Fza)NDnJ3{+1Vn7g_GTonDIitoz$xP__P6~K=NvVQL0LeTVkN7o7MW& z12n7$@4n&Xzbvs|$O*jSV?4GIPRQ2kkyw%qbUWW#2cN#OxB1)JaJyE5z!kbAR)WJ3 zwtF>S0~p&w75o(2h1&nah*NA0S>G3=`Tr?BYck;x_^Sn9&xt<*uQr=;bf#()d^(Ls z@Yw&a-nnC?^`@IkD2n=&--7VWGuZ(nK z+}^%z66-%=1@`C-b`k3T3oQ618b8+2Ocz0nY)RNb6=Uifx8DC6)dEf{Vk%3vo z4w#s>;=8}Kz`m@+`^KN=B+)kK#bXUS#7ktHx5J&gJ*<&Nh!K69fq3_chS0 zn5(J!d1_S{fD6lAI47E;*kMOfRymIi5)Z1a&=l=9i(+zg7M&EYe&NV|J@G^UTY6Dt zmYuQHo&36fD&D~DksaIP80R*&pBbK}rVx^&B*yx-a((x0k5}=jMGc#iOZf!4Lcl6` z1N8a~a2^i@CTwW|_!vE;=E$l8ZK;u7!aCfk7=x&H4PkHh=&U_he&^?Vo6b`-m!pWO zzqnm4A5+Qm;Jb{?p79 zfD&T8X^mW{S^EdQtOaZWo1repu5#&HEit5v_vtk5)keAKbfkx_^(u=EkxWc?w##*F zth>jo2M~AGAI1(ooH1tVcfSzl!^bDx`o(nR#S=|?x<*znvz08OcNUu((&=;0_uR~- zb<6JDpO+w*GX7Qk8PM~zBy6n-9PXvVPaO?C zGN3rET^$J(@%(0un#4InL&2qe=IS@dhIMsXD16ZKTA-JXYSM-g)J1MI7CvEwsk1Mx zF?g@5Tc{nrY|UvV#24BHzTuAZHa`8BADyW&t}c1YFS%HbDD2QQg3Y42~dQSXC1r=ofB%1_5Q8{ zb&~a~_hS=VR8Lxbl4o-Ws@>1b-yg%L<(I7D)fRmZeT}}3Ew^AQ9;FBd_&w@$C204D zxg%{^W93EeIqvpvQ_m$~oW=}A8#58AsrA#5ixUvHv8t6R0zZD-)``I}(Ub-Pqc*=0 zpDFMSSm~FxQ7IM=`p!03ZRgx@1SGuA(Or^J%-lz=ObpLnoilbG| z{jqmM{O^Umi8xmY4+G`Y)xe^#u>_AbvE3latMq_8;(B}YD6JY>!7@ghO%;muxqb?80O#p@;U{=ALnl_n9txp@(>N!_d)OUxHuje=jWnA;3 ze#-_+iv#o$&pYbrA0JOqSfnb}Ciq*kSS0Q`FBS4|`1_Nc}{W}pe^aiqqLdfo@S zEdXUu^~ALs{bomo6*-k z74yqR*_S0fgk3nW^Yd>uPhOg`6$*)-_*C>L=If6Dc{O@>W?7pCp_CkbB)gWEgMRO- zOD0qQZqSw@1$M!FZtP=b6+HK%5@Vg9Gj!ZN7%Wh?WgZy=h#eIyqf)fX9IfH43tD_Q zWgz+H$zLe|uXcLb7SNw0)%Z7b^U3uK69XS9JEYD2O&@@Md~J`@QLuVkyD(yo4IdNH z8$6Cds~w7~kmYiBwm0IKzaoHY$)M&Gul0X*;Kv)NPWZN1>9gc--9u2z1k5|war?=Y7}n-WdRAL8_3#H_s&!+K zIF31e?wn;n6uvfcJ!jVNLsqg{4vjah>(*}zyUPO#wb4TEt;%6v#?w{SGj8UkQGurP zm%$T1h_-cT{U!45%#-T9e2-n&WI+Tz^(&Itt}a!<*YW_xLS&AzWYrA9?(*+B+5}3FC+beK*`)#S$01^TwCc>RPP}oWX#{U zbT>${5bn3FdnujXT#FU_`KY)WGO{b&<3Ka))Ang-67 zSF!%LTn~OyBz^3O-^{`_Brh!yQTk@JlA(4V&G%12m4}An>PKIgJyKs8X(!l{ij2%; z2m4COp_KWQT`{NR9fGzQfhNlTN<~A=*kJsp|6|Ve%|-iFkH_~I0wR&Fm24y<%-4 zP=q{1Yp9#Ht{Q8QcUqL%?1a}l!E=r18Ov6cwR6?@8*nAU_6E&|>03j`Hww2`Rtrl# zT>yrEa-jz8XvvWp&Wh%2Hy|w)sE33ErK%i*52b zbRY1NVjHB48mfQ60$v$(d?K`nuatZGqu-sy@Bdj(WP<(H- zzV8wc89sc!_LR7R)|bFIEWLajhr9n(#d+%`3P;(X=^xKrT}hCf*Eh&d)H+y_By)xs zHn436mYK6Q=dR3DAD_O%m5}YwXfsBVq+$>hQ2Sp6BCR^I{&MHw%!khY$#OU#bLqde zmb?bs!0+%+kqP&xK(Al8J?xl#09a0`hq3KT)=%RAO2kcp5a zk-?6n1U2#-Dvx6`@n2o00)0*L$QADkvQ1WRJ0Pp}EY1{&3*Zq&%Zc+1XCC*4TV==4 zj+D}hb6qVLSS&u3>nUD>(g`r~YT2o!`Wc`WJUwHCP8amK&cMz85e@mbBFg&Vbdpd& z`Xz(-ay9YC8WlB&hwnW4eNK$N{MH(ksh1=4-dO74f%HUv{E)fXmsMSecKHXCp|qm_ zqhq180u<1QWvO+G$47c@2H<23%dC3sD6p*LQ~0ojM+iriYybJjl?q` zkWba}Cvbz5mMmrV-|61+zlT90$^ozG*F43*6p5-3jV&4jop!|i*Ru)pMKBagV)3ag z5zic)wVZ+~2D_;s(W~ zgH{d<4^Qwy8ilA@LV=$SBMs+*JkW{+Z*B#$uSnOfV(~R0&mC_O3i9BVE6}(s`GE!-Yny| zJky3`^8(`#4I=8d9)Z$+tDfNHffsi^vTe_2*M|bu-JVd$){9;;`PLSMNB`35s>YcE z`kQ^l$ssytKze8YB6v%!V|G)hcyW(UU+24O(}xN*!B#K+6y|=|R9wgh{|JG3Z-DMQ zRn47J{ZC!qcZ(RLx#iReZStrf^!6*M2p$L4*yuoJ_)&TomiPrD$@glg<+z4bOOgoZ zk+=MDqk6jl*eHh2g8AQ3$#tqY0~8-`HrLAW?9d8V52x9ln0}FNrLH*6@fUZATBWV# zAm_#pkMCuOSj;M)p0_s%DS6{FDSZ~8Iu8&>*Dmz8&Rk+ zO@)5=VwS7kwJr{M=x`~12wtck9eX2Yd@a8~@!OzXWdmHlyiRrVvvFLNVFi$tLZA9@ zm~1zRSq`n3scO@I6?IE0CFx2(I=!AF?hDU?dVA#W)iysnrsrzx3YDmxT@Doana1Z= z_6gmK`53|bDWl@4f?qgk+ZcSKhnQWJP+y!1jH99PmJT`oG= z&a%(`@!nRQwwGsg*k>t?{b+5r)Bb>5j%|1ce@_}_Vl7o&}4*_v9`hf-a=ohK<> zgb*#}L36F%BuSa3q->Q*y0|t(mum4mj&;;~a}T#hGl*=whuia!*n5XH797PYlB-|%TfKDM5l|c!DU0h#?rE^*x#_~is94VE(yJQv znUlBnkM92e!h)RpK;-kkSdc$)>^hySq@~x#XePD=}HYrI0=p9mq9iImz;x$c`~x(4*us%B$*xt)@(xqJWm!nlJB=ZJ4jV{Yv>uO|z8na*Q|6nE@tFL|{;VlM#i~6I~nSEYGYWT4Zg?aR4lGR zvNbyIYdTB*p&~@n=+Lk`(4r!ksgxdFinbxL;%eh;_y|#hb@6&Qb)*0X%2aaq_V%;a z$L;c7QNbsBCxd-NM%HG)!^}pL4F@8SzHTwS@w^^=Cqu%b9dV|}`HX2*kf)TQstijI zH`YwowCJN|OdZ7JmP9*tH=EWa=GzA>DZAkaQGMN*MEVKEPu6t z^YPxwb^5E<*=!r|I_u@LO*r^J5Gr5z4Q+}E)U!~H9<99yy}yZPwn#3~nI;z)ADGtd zBXkNerGtKe1LIEPM_Pi99#Yl>dXx?q^mRT9-c{YQ%hC$fh;+Ps@jwsoEe3oRM~Z3% zRIJBvf0IsdKnzGzKgqqGpSh8VlRt5k+!kEy*KRIzC+9sWvXK@V_Uf|g&#jM7|D=!~ zm2Z4*_xS*#=(tLZ)Gs}E7g0gy;Yr5GABcT4Kh)jxCB?m?A$#av_rv09iA`LhLBVTv z3uJ3vE(;W-d{cmG-s`(x{Vz~u>-jy&c8WK%Y=hwsLSj$AP-7=-+(ZTWr9fD9RUm+I zH@w9l_Z4i3hvlPi(hGd2ckYXzM^lGuDc(a5P}cGtuySHTjXoQCrAb@@LiHrq*x2L- zsff|b0PfHIbUpzG6Oy@ZNs1DCR7pSl&BV<|udmWo_Mv2cn)&A)cMUrEFsgg8JFu>w zPq)|-qs+6(nyM}Se82k3el&Ky%yhUd^>ud~5@>GFU2fGjbJ8!{r^K)tqM>WA7m=m- zfz79DtzBj(e-4;OD>O9@8cXk3ZkaccHi4Q_Nuh)VGDXgGqdq{wbO+M@T&3P41RWr)9J$# zqq-l41~JdG@GZF6xKM-Pjh!M|{Cx>7tiDddA-r7lbPP}!ye~J z<1v&w)zQY@+e7pg=dE<~$Ga1}phKnJ6q$PJL|QFK{3)o-2LKz0=^B}u81n$pu*Tw?C!86F*3LyVl|?^9dxtJJfnF0L@0BDJ-j!@U zy7z5FTxiQvwf`MEV-+7?xA&P+O!T|PO(huXY5Sq%cDp0~0YxCappTaBZ+Z=Tdn)q+^MC#;e`nLLGnJ~&{|Y4Lfsyh}`AZ}A zf`7+@|5Zwy&lwnFXHfBTKt=bYA*k5;aKL|^bE3%>>^89W34DrT_)fNlZM2U>9P(sc zDO2u!q|6y>QHOKT!Ec;n22hc_Zack>lM$ZxJMY&1;4CjM{X%g=Gs@17_W)*P=O0M} z@2&C?ci|`<$obJJSzNDdk^SxH%|o^U1t3!AcJ-Vw|6#)~{k{S@?jZei5&d67Hq6EK zH4mDbM-HNx|NpAMGw7?${IJh2lM&t1brhluv(I zw0`R4^t7k_$FkaiBd~yosCW49oj*IUBmFrk`rLkIV_6r0eF4Q@69q7o-~PMM;lE!N z_K#-*9R8oXp4+#do&$l-iJX3?An5N4iT=kf{OP;!kCp#(tNI`7`H%Jd8yM1`ae^Jm pfG??w+MoQO61<}cFl-=@ih|~|qNgw4{u9N;J)Zyo literal 0 HcmV?d00001 diff --git a/frontend/k1-820.png b/frontend/k1-820.png new file mode 100644 index 0000000000000000000000000000000000000000..471602306cdcdc3025f8dbaf3b1559d7275c0bee GIT binary patch literal 31744 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 XBr_kOxOLAeWO-?o7e&9mdjG!w(rVG^ literal 0 HcmV?d00001 diff --git a/frontend/komfort.png b/frontend/komfort.png new file mode 100644 index 0000000000000000000000000000000000000000..8b8ae9f8265fc1a6a45c4399efa614ddd210578f GIT binary patch literal 22205 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 A9smFU literal 0 HcmV?d00001 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 0af5a25..92d5a13 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,10 +1,21 @@ @@ -127,6 +216,25 @@ main { overscroll-behavior: contain; } +/* Mittlere Fenster: drei Spalten passen nicht mehr. Bei 760px blieben für die + Karten 200px übrig, und die Kartenköpfe liefen über. Das Panel legt sich dann + unter den Arbeitsbereich, die Projektliste bleibt daneben. */ +@media (min-width: 46.01rem) and (max-width: 64rem) { + .raster.pruefung { + grid-template-columns: 15rem 1fr; + grid-template-rows: 1fr 45vh; + /* Benannte Bereiche statt Auto-Platzierung: mit `grid-row` allein landete + der Arbeitsbereich unter der Leiste statt daneben. */ + grid-template-areas: + "leiste inhalt" + "leiste panel"; + } + .raster.pruefung > aside { grid-area: leiste; } + .raster.pruefung > main { grid-area: inhalt; } + .raster.pruefung > .panel, + .raster.pruefung > .chat { grid-area: panel; } +} + /* Schmale Fenster: die Projektliste legt sich als Leiste nach oben */ @media (max-width: 46rem) { .raster, .raster.pruefung { @@ -141,16 +249,31 @@ main { margin-top: 3rem; text-align: center; } -/* Fortschritt sitzt unter den Prüf-Icons */ -.pruefen { - display: inline-flex; - flex-direction: column; - align-items: center; - line-height: 1.1; -} -.pruefen .knoepfe { display: flex; } .fortschritt { - font-size: 0.65rem; + font-size: 0.7rem; color: var(--dezent); + margin-left: 0.2rem; } +.icon-knopf.an { color: var(--akzent); background: var(--code-bg); } + +/* Ein Schalter statt zweier Reiter. Beschriftet mit dem, was zu sehen ist — + das Pfeilpaar sagt, dass ein Klick die andere Seite zeigt. */ +.schalter { + border: 1px solid var(--rand); + background: none; + color: var(--dezent); + border-radius: 0.4rem; + padding: 0.2rem 0.55rem; + margin-right: 0.3rem; + cursor: pointer; + font: inherit; + font-size: 0.78rem; + white-space: nowrap; +} +.schalter.planung { + color: var(--akzent-text); + background: var(--akzent); + border-color: var(--akzent); +} +.schalter .zahl { margin-left: 0.3rem; font-weight: 700; } diff --git a/frontend/src/api.js b/frontend/src/api.js index 2b0c34a..1679d80 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -33,16 +33,37 @@ export const projektUmbenennen = (alt, neu) => export const projektLoeschen = (name) => req(`/projekte/${p(name)}`, { method: 'DELETE' }) -export const fetchFeatures = (projekt) => req(`/projekte/${p(projekt)}/features`) +export const fetchFeatures = (projekt, sicht = 'planung') => + req(`/projekte/${p(projekt)}/features?sicht=${sicht}`) export const featureAnlegen = (projekt, roh) => req(`/projekte/${p(projekt)}/features`, { method: 'POST', body: { roh } }) export const featureSpeichern = (projekt, id, roh) => req(`/projekte/${p(projekt)}/features/${p(id)}`, { method: 'PUT', body: { roh } }) export const featureLoeschen = (projekt, id) => req(`/projekte/${p(projekt)}/features/${p(id)}`, { method: 'DELETE' }) +export const featureVerschieben = (projekt, id, ziel) => + req(`/projekte/${p(projekt)}/features/${p(id)}/projekt`, { method: 'PUT', body: { ziel } }) + export const pruefungStarten = (projekt, art = 'stil') => req(`/projekte/${p(projekt)}/pruefung`, { method: 'POST', body: { art } }) export const fetchPruefung = (projekt) => req(`/projekte/${p(projekt)}/pruefung`) export const pruefungBeenden = (projekt) => req(`/projekte/${p(projekt)}/pruefung`, { method: 'DELETE' }) + +export const fetchPlanung = (projekt) => req(`/projekte/${p(projekt)}/planung`) +export const planungStarten = (projekt) => + req(`/projekte/${p(projekt)}/planung`, { method: 'POST' }) +export const planungUmsetzen = (projekt) => + req(`/projekte/${p(projekt)}/planung/umsetzen`, { method: 'POST' }) +export const planungAbbrechen = (projekt) => + req(`/projekte/${p(projekt)}/planung`, { method: 'DELETE' }) +export const planungZuruecksetzen = (projekt, titel) => + req(`/projekte/${p(projekt)}/planung/zuruecksetzen`, { method: 'POST', body: { titel } }) + +export const fetchChat = (projekt) => req(`/projekte/${p(projekt)}/chat`) +export const chatFragen = (projekt, text) => + req(`/projekte/${p(projekt)}/chat`, { method: 'POST', body: { text } }) +export const chatLeeren = (projekt) => + req(`/projekte/${p(projekt)}/chat`, { method: 'DELETE' }) + diff --git a/frontend/src/components/ChatPanel.vue b/frontend/src/components/ChatPanel.vue new file mode 100644 index 0000000..e78e87f --- /dev/null +++ b/frontend/src/components/ChatPanel.vue @@ -0,0 +1,170 @@ + + +