diff --git a/.claude/skills/cowork-projekt-match/SKILL.md b/.claude/skills/cowork-projekt-match/SKILL.md new file mode 100644 index 0000000..16fd4fa --- /dev/null +++ b/.claude/skills/cowork-projekt-match/SKILL.md @@ -0,0 +1,146 @@ +--- +name: cowork-projekt-match +description: >- + ARCHIV / BASIS — NICHT aktiv aufrufen. Unveränderte Referenzfassung des aus Claude Cowork + übernommenen und für diese Umgebung angepassten Skills, bevor er zu `projekt-anlegen` + erweitert wurde. Dient nur als Vergleichs-/Wiederherstellungsbasis. Für die tatsächliche + Projektbewertung und CRM-Erfassung stattdessen IMMER den Skill `projekt-anlegen` verwenden. +--- + +# (ARCHIV) Cowork-Projekt-Match — Basisfassung vor der Erweiterung zu `projekt-anlegen` + +> Diese Datei ist eine eingefrorene Referenz. Aktiv weiterentwickelt und verwendet wird +> ausschließlich `.claude/skills/projekt-anlegen/SKILL.md`. + +# Projekt anlegen: Projektangebote bewerten und ins EspoCRM eintragen + +Pipeline: Ausschreibung beschaffen → Anforderungen extrahieren → einordnen → gegen Lebenslauf bewerten → Matches berechnen → **Review im Chat (Pflicht)** → als Opportunity ins EspoCRM schreiben (per Shell) → verifizieren. + +## Voraussetzungen und feste Pfade + +| Zweck | Pfad | +|---|---| +| Lebenslauf (Markdown) | `vorgaben/Lebenslauf_Dr-Ing_Thomas_Langer.md` | +| EspoCRM-Zugangsdaten | `.secrets/espocrm-api.md` | + +Beide Dateien mit dem Read-Tool lesen. Ohne Lebenslauf keine Bewertung, ohne Zugangsdaten kein CRM-Eintrag. + +Die Zugangsdaten-Datei enthält Base-URL, Auth-Header-Schema, API-Key sowie verifizierte Entitäts- und Feldnamen. **Der API-Key darf niemals im Chat angezeigt, in Dateien geschrieben oder in Commits/Doku übernommen werden** — er wird nur zur Laufzeit in eine Shell-Variable gelesen und direkt in `curl`-Aufrufe eingesetzt. + +## Schritt 1: Ausschreibung beschaffen + +Die Projektausschreibung kommt auf zwei Wegen: +- **URL:** Nennt der Nutzer eine URL, hole den Seitentext mit dem **WebFetch-Tool**. +- **Text:** Fügt der Nutzer den Ausschreibungstext direkt in den Chat ein, nutze diesen. + +Bei Login-geschützten Portalen ist das Einfügen von Text nötig. Ist unklar, welche Quelle gilt, nachfragen. + +Daraus entnehmen: +- **Projektname**: der Titel der Ausschreibung, ohne Portal-Zusatz (z. B. ohne „auf www.freelancermap.de"). +- **Projekt-URL**: die tatsächliche URL der Seite, falls vorhanden. +- **Beschreibung und Aufgaben**: nur Kontext für die Bewertung, keine Tabellenzeilen. +- **Anforderungen**: jede Anforderung einzeln, im Originalwortlaut (behutsam kürzen ist erlaubt, Bedeutung nie verändern). Rahmenbedingungen (Start, Einsatzort/Remote-Anteil, Auslastung, Laufzeit) zählen als Anforderungen der Kategorie Misc. + +## Schritt 2: Einordnung (Kat.) + +Jede Anforderung bekommt genau eine Kategorie: + +- **Must** — zwingend. Signale: eigener Abschnitt „Must-haves"/„Anforderungen", Wörter wie „zwingend", „erforderlich", „vorausgesetzt", „sehr gute Kenntnisse". +- **Nice** — optional. Signale: Abschnitt „Nice-to-haves", Wörter wie „von Vorteil", „wünschenswert", „idealerweise", „plus". +- **Misc** — Rahmenbedingungen (Start, Ort, Auslastung, Laufzeit) und alles, was weder Muss noch Wunsch-Qualifikation ist. + +Explizite Abschnittsüberschriften der Ausschreibung haben Vorrang vor Signalwörtern. Steht „idealerweise" innerhalb einer Must-Anforderung (z. B. „… und idealerweise Kubernetes"), bleibt die Zeile Must — der idealerweise-Teil ist dann für die Bewertung nicht ausschlaggebend. + +## Schritt 3: Bewertung gegen den Lebenslauf + +Lebenslauf vollständig lesen und jede Anforderung nüchtern bewerten: + +- **✅** nur bei klarer Evidenz im Lebenslauf. +- **❌** wenn der Lebenslauf nichts Belastbares hergibt. Streng bleiben — eine geschönte Bewertung macht die Match-Zahlen wertlos. Kalibrierung aus der Praxis: Proof-of-Concept-Erfahrung deckt „produktiven Betrieb" nicht ab; „mehrjährig" wörtlich nehmen; ein ALM-Produktname (z. B. „Azure DevOps Server") belegt keine Cloud-Plattform-Erfahrung. +- **❔** nur bei echter Teilevidenz, wenn die Entscheidung von Wissen abhängt, das nur Thomas hat — solche Fälle klärt das Review. +- „wie z. B."-Aufzählungen: gleichwertige Alternativen zählen als Abdeckung (Beispiel: Ollama/llama.cpp/Transformers decken „LLM-Inference-Stacks wie z. B. vLLM, TGI, Triton" ab). +- Rahmenbedingungen (Misc): Ortsbezug kann der Lebenslauf beantworten (Büro in Unterhaching bei München). Verfügbarkeit, Auslastung und Laufzeit kann er nicht beantworten → ❔ vorschlagen, Thomas setzt im Review ✅ oder ❌. + +## Schritt 4: Match-Berechnung + +- **Must-have-Match**: Mittelwert über alle Must-Zeilen mit ✅ = 100 %, ❔ = 25 %, ❌ = 0 %. +- **Nice-to-have-Match**: dasselbe über alle Nice-Zeilen. +- Misc-Zeilen gehen in keinen Match ein. +- Auf ganze Prozent runden. Ist eine Kategorie leer, „–" statt einer Zahl schreiben. + +## Schritt 5: Ausgabeformat (exakt einhalten) + +Der Inhalt des CRM-Feldes „Beschreibung" — genau dieses Format, Spaltenüberschriften wörtlich (`Kat.` und `❔` halten die Spalten schmal): + +```markdown +Must-have-Match: 50 % · Nice-to-have-Match: 33 % + +| Nr. | Kat. | ❔ | Anforderung | +|---|---|---|---| +| 1 | Must | ❌ | Mehrjährige praktische Erfahrung im Aufbau und Betrieb von AI-/LLM-Plattformen | +| 2 | Must | ✅ | Erfahrung mit RAG-Systemen, Vektordatenbanken und Anbindung relevanter Datenquellen | +| 3 | Nice | ✅ | Kenntnisse in LLM-Inference-Stacks (z. B. vLLM, TGI, Triton, Ray) | +| 4 | Misc | ✅ | Hybrid: ca. 40 % onsite München, 60 % remote | +``` + +- `Nr.` fortlaufend ab 1, Reihenfolge: erst alle Must-, dann Nice-, dann Misc-Zeilen (innerhalb der Kategorie in Reihenfolge der Ausschreibung). +- `Kat.` ∈ {Must, Nice, Misc}; Bewertungsspalte ∈ {✅, ❌, ❔}. +- Beide Match-Zahlen in einer Zeile, getrennt durch ` · `. + +## Schritt 6: Review im Chat — immer vor dem CRM-Eintrag + +Niemals ohne explizite Freigabe ins CRM schreiben. Im Chat zeigen: + +1. Vorgesehener **Name** der Opportunity (= Projektname) und **Projektlink**. +2. Den wörtlichen Beschreibungs-Markdown in einem Codeblock (damit das Format sichtbar ist). +3. Kurze Begründungen zu allen ❌- und ❔-Bewertungen außerhalb der Tabelle — hier stecken die Ermessensentscheidungen, die Thomas korrigieren können muss. + +Korrekturen kommen als „Nr. X → ✅/❌/❔". Danach Matches neu berechnen und die geänderten Werte nennen. Erst nach Freigabe weiter zu Schritt 7. + +## Schritt 7: CRM-Eintrag per Shell (curl) + +Diese Umgebung erreicht die CRM-Domain direkt — der API-Zugriff läuft per `curl` aus der Shell (kein Browser nötig). + +**Key und Base-URL sicher laden** (Werte landen in Variablen, werden nicht ausgegeben): + +```bash +KEY=$(grep -oE '[0-9a-f]{32}' .secrets/espocrm-api.md | head -1) +BASE=$(grep -oE 'https://[^ `]+/api/v1' .secrets/espocrm-api.md | head -1) +``` + +**Duplikat-Prüfung** — existiert der Name schon, „ (2)", „ (3)", … anhängen: + +```bash +curl -s -G "$BASE/Opportunity" -H "X-Api-Key: $KEY" \ + --data-urlencode 'where[0][type]=startsWith' \ + --data-urlencode 'where[0][attribute]=name' \ + --data-urlencode 'where[0][value]=' \ + --data-urlencode 'select=name' --data-urlencode 'maxSize=100' +``` + +Aus der zurückgegebenen `list` die vorhandenen Namen prüfen und den eindeutigen Namen bestimmen. + +**Anlegen:** Die Beschreibung enthält Markdown mit Zeilenumbrüchen und `|`. Um Shell-Escaping zu vermeiden, den Payload mit dem **Write-Tool** als JSON-Datei nach `/tmp/opp.json` schreiben: + +```json +{"name": "", "description": "", "cProjektlink": ""} +``` + +Dann posten (`-i` zeigt die Header inkl. `X-Status-Reason` bei Fehlern): + +```bash +curl -s -i -X POST "$BASE/Opportunity" -H "X-Api-Key: $KEY" \ + -H 'Content-Type: application/json' --data @/tmp/opp.json +``` + +Der minimale Payload (`name`, `description`, `cProjektlink`) reicht — Stage und Wahrscheinlichkeit setzt das CRM selbst. Bei HTTP 400 steht die Ursache im `X-Status-Reason`-Header. Nachträgliche Korrekturen: `PUT "$BASE/Opportunity/"` mit den geänderten Feldern. Danach `/tmp/opp.json` löschen. + +## Schritt 8: Verifizieren und berichten + +Nach dem POST den Datensatz gegenlesen: + +```bash +curl -s -G "$BASE/Opportunity/" -H "X-Api-Key: $KEY" +``` + +Prüfen: stimmen Name und Projektlink, hat die Beschreibung die Match-Zeile und alle Tabellenzeilen, sind ✅/❌/❔ intakt. Dann im Chat melden: gewählter Name (inkl. evtl. Duplikat-Suffix), beide Match-Zahlen und der Direktlink `https://crm.creature-go.com/#Opportunity/view/`.