Selectedleafs pos operations
Versionierte Heimat meiner Agent Skills für Claude (claude.ai, Claude Code, API).
npx -y skills add wemwi/skill-library --skill selectedleafs-pos-operationsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Konsolidierter Runtime-Skill für die selectedleafs POS-Operations-Agenten (Kommissionsware an Kiosk-Partner-Stores). Bündelt Restock (Protokoll auswerten → Drive → City-Channel), Inventory (Bestandsprotokoll ablegen), Invoice (Provisionsabrechnung), Telegram-Handwerk (Format, Pinned), Store (neuen POS-Partner anlegen + 🎉-Broadcast), Salesperson (neuen Vertriebler anlegen: Lexware-Kontakt + Provisions-Sheet-Kopie + POS-SHEET-Notiz) und ein Werte-Verzeichnis (City→Channel-Map, Drive-Root, Topics). Jeder Agent liest nur seine reference(s); diese SKILL.md ist die Landkarte (Dispatch + Invarianten), die Tiefe steckt in references/. IMMER laden, sobald ein POS-Operations-Agent eine Aufgabe verarbeitet — auch ohne das Wort Skill. Triggers on: pos-restock, pos-store, pos-salesperson, pos-operations, Übergabeprotokoll, Kommissionsware, UL-Nummer; telegram post, City-Channel, restock post, neuer partner post, pinned post; Bestandsprotokoll, Provisionsabrechnung, Vertriebler anlegen, Provisions-Sheet, POS-SHEET.
SKILL.md
10.5 KB, as published. Nobody here has run it
selectedleafs POS-Operations — Router
Landkarte für die POS-Operations-Agenten. Diese Datei dispatcht und hält die domänenübergreifenden Invarianten — sie trägt keine Domänen-Prozedur. Die operative Tiefe steckt in references/. Jeder Agent liest nur die reference(s) seiner Domäne (Allowlist), plus registry.md für statische Werte. Das Telegram-Post-Handwerk ist nach seiner Natur aufgeteilt: die geteilte Nachrichten-Konvention (Emoji-Semantik, Format-Klassen, parse_mode/Escaping) steht als Invariante 6 unten — sie gilt für jeden Post und lebt deshalb nicht bei einem einzelnen Agenten; die konkreten Post-Templates liegen bei der erzeugenden Domäne (📦/🌿 in restock.md, 🎉 in store.md); das Channel-Lifecycle (Kanal live schalten, Pinned, Launch, Legal — ein rein manueller Schritt) liegt als Runbook in city.md. Ein separates telegram.md gibt es nicht mehr (in 5.8.0 aufgelöst).
Dispatch — welche reference?
| Sub-Task / Auslöser | reference |
|---|---|
Übergabeprotokoll/Lieferschein auswerten, Store/Stadt/Sorten ableiten, neu vs. aufgefüllt, PDF komprimieren + in Drive ablegen, 📦/🌿 in den City-Channel posten (Channel-Ziel aus registry.md, kein telegram.md-Load nötig) | references/restock.md |
Statische Werte nachschlagen: City→Channel-Map (direkter Lookup, kein Override-Mechanismus), Drive-Root-parentFolderId, Operations-chat_id/Topic, (später) Sheet-IDs | references/registry.md |
| Bestandsprotokoll ablegen — Store-Match (Name → Metaobjekt) + Datum lesen, ohne Sorten-Parsing/Write-back/Post | references/inventory.md |
| Provisionsabrechnung POS-Partner (Lexware → Vertriebler-Sheet), Rechnung-Insert, paid-Status-Update | references/invoice.md |
Neuen POS-Partner anlegen (headless One-Shot: Shopify liftr_store + ggf. liftr_district, Lexware-Kontakt + POS-PARTNER-Notiz, Provisionszeile im Vertriebler-Sheet, 2 Drive-Ordner; Teaser-Bild aus Telegram-Upload → Shopify Files; Status/Rückfrage ins Operations-Topic) plus einmaliger 🎉-„Neuer Partner"-Broadcast in den City-Channel (§8.5, nur CREATE-Zweig, best-effort; Channel-Lookup aus registry.md §1) | references/store.md |
Neue Stadt onboarden + City-Channel live schalten — manuelles Runbook (kein Agent; store.md §5.1 läuft für die erste Stadt fail-closed): Channel-Setup, Pinned, Launch-Post, Legal-Anker | references/city.md |
Neuen Vertriebler anlegen (dialog-initiiert: Lexware-Kontakt als Lieferant + eigener Vertriebler-Ordner <Nachname>, <Vorname> mit Sheet-Kopie Provision · <Nachname> · <Jahr> + POS-SHEET-Notiz + Stammdaten Name/Jahr/Besteuerung + optionale Ordner-Freigabe an die E-Mail; damit ohne Skill-Bump für Bridge und alle POS-Agenten sichtbar, registry.md §4) | references/salesperson.md |
Jahres-Rollover aller Vertriebler (cron-getrieben, Jahreswechsel): pro Vertriebler leere Vorlage kopieren → Stammdaten (Name/Jahr/Besteuerung, letztere aus dem Alt-Sheet) + aktuelle Stores (Lexware-POS-PARTNER-Enumeration → Stores!B) befüllen → POS-SHEET-Marker zuletzt umsetzen; altes Sheet bleibt Archiv (registry.md §2/§4) | references/rollover.md |
Die Post-Templates der Restock-Domäne (📦/🌿) liegen in restock.md, der 🎉-Broadcast in store.md — jede Kette kommt ohne Sprung in eine fremde reference aus; die geteilte Nachrichten-Grammatik dafür steht in Invariante 6. City→Channel ist ein direkter Lookup in registry.md — kein Ableitungsmechanismus, kein Override, da Test- und Prod-Agenten getrennte System-Prompts/Configs fahren (global-agent-framework), nicht einen geteilten Per-Run-Schalter. references referenzieren einander nicht quer — wer eine Domäne fährt, kommt mit seiner reference (+ registry.md) aus. city.md ist die Ausnahme im Sinne von: es ist ein manuelles Runbook, das kein laufender Agent lädt, sondern ein Mensch beim City-Onboarding.
Universelle Invarianten (für alle Domänen)
Diese sechs Grundsätze gelten domänenübergreifend; die Domänen-references konkretisieren sie, widersprechen ihnen aber nie:
-
Idempotenz-Grundsatz — jede Einheit genau einmal. Vor Posten/Ablegen/Schreiben prüfen, ob die Einheit (Protokoll, Beleg, Partner) schon verarbeitet wurde, und bei Treffer abbrechen. Der Idempotenz-Schlüssel ist deterministisch aus stabiler Quelle (z. B. Protokollnummer), nie aus volatilem/geratenem Input. Drive/Ziel ist die Quelle der Wahrheit — kein externer State nötig (web-only-tauglich).
-
IDs aus Registry oder Webhook — nie raten. Statische Ziele (Channel, Drive-Root, Operations-Chat) kommen aus
registry.mdbzw. der Agent-Config; lauf-spezifische IDs (file_id, per-Laufchat_id) aus der Webhook-Injektion. Ist eine ID nicht eindeutig auflösbar → nicht öffentlich raten, sondern still abbrechen + Rückfrage in den Operations-Chat (Mensch-im-Loop-Ersatz). -
Append-only bei kuratierten Listen. Schreibseitige Mutationen an Sortiments-/Listendaten (
product_listetc.) nur anhängen, nie entfernen, idempotent (kein Doppel-Eintrag, kein Clobbern bestehender Werte). Löschen/Auslisten bleibt manueller Menschen-Job. -
Kein Chip-Spaltentyp auf Spalten, die ein Agent liest oder schreibt. Eine native Sheets-Table-Spalte mit
columnTypePLACE_CHIP,FILES_CHIP,PEOPLE_CHIPo. ä. liefert über die Values-API einen leeren Wert — kein Fehler, kein Hinweis, der Agent liest still Nichts und schreibt still ins Leere. Chips sind ein reines UI-Feature. Jede Spalte, die in einer Agenten-Kette vorkommt (Key, Match-Spalte, Wertespalte), bleibt ein einfacher Typ. Aufgefallen anStores!C(PLACE_CHIP); der Duplikat-Check aufStores!Bwar nie betroffen, jede künftige Logik aufCwäre es gewesen. Chip-Inhalt ≠ Chip-Spaltentyp: einen Rich-Link-Chip perupdate_cells_chipsin eine Nicht-Chip-Spalte zu schreiben ist erlaubt, solange kein Agent die Zelle per Values-API liest und die Rück-Lesung überget_range_chipsläuft — so setztstore.md§8.4 die Protokoll-Ordner-Chips (E/F, rein menschlich). Verboten bleibt allein der Chip-Spaltentyp auf Lese-/Match-/Key-Spalten. -
Lexware-
note-Marker sind zeilen-gebunden — eine Zeile je Marker, so lesen UND schreiben. Dienoteeines Kontakts ist ein menschlich sichtbares Freitextfeld und trägt seitPOS-TGmehrere Marker gleichzeitig (Vertriebler-Kontakt:POS-SHEETundPOS-TG). Lesen extrahiert den Wert der eigenen Marker-Zeile (getrimmter Rest dieser Zeile, nie „alles nach dem ersten Doppelpunkt"); Schreiben ändert nur die eigene Zeile und lässt jeden anderen Marker unangetastet (read-modify-write, zeilen-gebundene Regex, kein Dotall, nie die ganzenoteneu setzen). Ein Verstoß läuft still in die falsche (geldrelevante) Sheet-ID oder löschtPOS-TG— gleiche Klasse wie Invariante 4. Vollständige Definition + Lifecycle:registry.md§4. -
Telegram-Posts folgen einer geteilten Konvention — Emoji trägt den Ausgang, nicht den Typ. Jeder Post (interner Status und öffentlicher Broadcast) folgt derselben Grammatik; die konkreten Zeilen leben in der §Status-Sektion der jeweiligen Domänen-reference, die Regeln hier.
Emoji-Präfix = Ausgang, genau vier, trennscharf:
Emoji Bedeutung Regel ✅ Erfolg Einheit verarbeitet / Batch ohne Ausnahmen ℹ️ No-op Idempotenz-Treffer, nichts zu tun, kein Problem ⚠️ Aufmerksamkeit nötig Lauf lief, aber ein Mensch muss ran (Mehrdeutigkeit, Jahr-Mismatch, Dublette prüfen, fehlendes Pflicht-/Input-Feld) ❌ Technischer Fehlschlag Tool/Netz/Upload kaputt, Re-Run/Wiederholung ist die Antwort (kein Datenproblem) Der Lauf-Typ (Backstop, Rollover, Sync, Restock …) steht im Titel-Text, nie im Emoji — deshalb kein Sonder-Emoji wie
♻️/↩︎mehr. Broadcast-Anker sind separat und typ-tragend: 📦 Restock · 🌿 Neue Sorte · 🎉 Neuer Partner · 🕒 Öffnungszeiten (diese stehen in der Broadcast-Zeile, nicht als Status-Ausgang).Zwei Format-Klassen:
- Single-Unit (restock, inventory, invoice-Event, store, salesperson) — genau eine Zeile pro Lauf:
{emoji} {Schlüssel} — {Entität}: {Ergebnis}.Der Schlüssel (UL-…,RG-…, Datum, Name) steht in<code>. - Batch (rollover, invoice-Backstop) — report-by-exception: fette Kopfzeile mit Aggregat + Zählerzeile (die aufgehen muss: Summe = geprüfte Einheiten, das ist der Detektor gegen still fehlgezählte Einheiten), dann nur die Ausnahmen (⚠️/❌) einzeln — je mit Grund, nie nackt. Erfolge werden nicht einzeln gelistet. Kappung bei Masse: erste ~15 Ausnahmen, dann „…und {N} weitere" (Telegram-Limit 4096 Zeichen). Batch-Kopf führt mit ✅ (0 Ausnahmen) bzw. ⚠️ (Ausnahmen > 0) bzw. ❌ (Lauf gar nicht angelaufen).
Mechanik (jeder Post):
parse_mode = HTML. Jeder interpolierte dynamische Wert (Store-/Kontaktname, Adresse,<konkreter Fehler>) wird escaped:&→&,<→<,>→>— sonst bricht ein Name mit&die Nachricht still. Fett via<b>…</b>, Schlüssel/IDs via<code>…</code>. Ein fehlgeschlagener Status-Post darf den Lauf nicht kippen (best-effort). General-Topic wird durch Weglassen vonmessage_thread_idadressiert (message_thread_id: 1wird als „thread not found" abgelehnt). - Single-Unit (restock, inventory, invoice-Event, store, salesperson) — genau eine Zeile pro Lauf: