Compare commits

..

2 Commits

Author SHA256 Message Date
tlg
9699e61952 Spec für projekt-anlegen-Erweiterung festhalten
Rahmenbedingungen-Datei (Verfügbarkeit/Auslastung/Laufzeit/Einsatzort mit
automatischer //-Bewertung), Extraktion von Käufer-Typ/Ansprechperson/
Firma, CRM-Ablauf Firma→Kontakt→Verkaufschance mit Dedup-Review und
Agentur→Reseller/Über-Agentur-Mapping. CRM-Felder gegen API verifiziert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 12:18:21 +02:00
tlg
c5dc65966c Basisfassung als cowork-projekt-match archivieren (vor Erweiterung)
Inaktive Referenzkopie des adaptierten Cowork-Skills; aktiv bleibt projekt-anlegen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 11:22:11 +02:00
2 changed files with 278 additions and 0 deletions

View File

@@ -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]=<PROJEKTNAME>' \
--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": "<EINDEUTIGER_NAME>", "description": "<BESCHREIBUNG_MARKDOWN>", "cProjektlink": "<PROJEKT_URL>"}
```
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/<id>"` 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/<id>" -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/<id>`.

View File

@@ -0,0 +1,132 @@
# Design: Erweiterung des Skills `projekt-anlegen`
**Datum:** 2026-06-12
**Status:** Freigegeben (Brainstorming abgeschlossen)
**Sprache:** Deutsch
**Basis:** Die unveränderte Ausgangsfassung ist als inaktiver Skill `cowork-projekt-match` archiviert. Aktiv erweitert wird `.claude/skills/projekt-anlegen/SKILL.md`.
## 1. Zweck
Den aus Claude Cowork übernommenen und an diese Umgebung angepassten Skill `projekt-anlegen` zum gewünschten Zielzustand erweitern:
1. Rahmenbedingungen (Verfügbarkeit, Auslastung, Laufzeit, Einsatzort) **automatisch** aus einer festen Vorgaben-Datei bewerten — damit Thomas sie nicht in jedem Review manuell setzen muss.
2. Aus der Ausschreibung zusätzlich **Käufer-Typ**, **Ansprechperson** und **Firmenname** extrahieren.
3. Beim CRM-Eintrag zuerst **Firma**, dann **Kontakt**, dann **Verkaufschance** anlegen (mit Dedup-Prüfung) und korrekt verknüpfen.
### Erfolgskriterien
- Misc-Anforderungen werden ohne Rückfrage mit ✅/❌/❔ bewertet, sofern die Regeln greifen.
- Firma und Kontakt werden vor der Verkaufschance angelegt oder wiederverwendet; keine ungewollten Dubletten.
- Agenturen erhalten `type = Reseller` und landen im Feld „Über Agentur" (`cAccount1`); der Endkunde landet bei Direktaufträgen im Feld `account`.
## 2. Verifizierte CRM-Fakten (EspoCRM)
- **`Account.type`** ist ein Enum mit den API-Werten `Customer`, `Investor`, `Partner`, `Reseller`. „Wiederverkäufer" (Oberfläche) = API-Wert **`Reseller`**.
- **`Contact`** verknüpft die Firma über `accountId`/`accountName`; Personenname über `firstName`/`lastName` (+ optional `salutationName`, `emailAddress`).
- **`Opportunity`**-Verknüpfungen: `account` (Hauptfirma, link), `cAccount1` (= „Über Agentur", link), `contacts` (linkMultiple). Setzen beim Anlegen über `accountId`, `cAccount1Id`, `contactsIds: [<id>]`.
- Zugriff direkt per `curl` (Key/Base aus `.secrets/espocrm-api.md`), wie in der aktuellen Skill-Fassung etabliert.
## 3. Neue Vorgaben-Datei `vorgaben/rahmenbedingungen.md`
Genau dieser Inhalt wird angelegt:
```markdown
# Rahmenbedingungen (Misc-Bewertung)
Feste Kriterien für die automatische Bewertung von Rahmenbedingungen (Kategorie Misc)
durch den Skill `projekt-anlegen`. Ändern sich selten.
## Kriterien
| Dimension | Vorgabe | Bewertung |
|---|---|---|
| Verfügbar ab | sofort | Projektstart ≤ 8 Wochen ab heute → ✅; > 8 Wochen → ❌; nicht genannt → ❔ |
| Auslastung | 100 % (Vollzeit) | 75100 % → ✅; < 75 % → ❔; nicht genannt → ❔ |
| Laufzeit | keine Einschränkung | jede Laufzeit → ✅ |
| Einsatzort / Remote | 100 % Remote oder Onsite ≤ 50 km um Sauerlach | siehe Einsatzort-Regel |
## Einsatzort-Regel
- 100 % Remote → ✅ (Ort egal).
- Onsite/Hybrid, Ort ≲ 50 km Luftlinie um Sauerlach → ✅.
- Onsite/Hybrid, Ort grenzwertig ≈ 5060 km → ❔.
- Onsite/Hybrid, Ort ≳ 60 km → ❌.
- Einsatzort/Remote-Anteil unklar oder nicht genannt → ❌.
### Referenz-Distanzen ab Sauerlach (Luftlinie, gerundet)
- München-Zentrum ≈ 25 km ✅ · Holzkirchen ≈ 10 km ✅ · Wolfratshausen ≈ 15 km ✅ · Rosenheim ≈ 40 km ✅
- Augsburg ≈ 75 km ❌ · Landshut ≈ 80 km ❌ · Ingolstadt ≈ 95 km ❌ · Nürnberg ≈ 150 km ❌ · Stuttgart ≈ 200 km ❌
Hinweis: „heute" = aktuelles Datum der Session. „8 Wochen" = 56 Tage.
```
## 4. Extraktion erweitern (Skill-Schritt 1)
Zusätzlich zu Projektname/URL/Anforderungen aus der Ausschreibung ziehen:
- **Käufer-Typ:** Agentur (Wiederverkäufer) **oder** Endkunde (Direktauftrag).
- Signale für Agentur: bekannte Personaldienstleister/Vermittler (z. B. Hays, GULP/Randstad, SThree/Computer Futures, Aristo), Formulierungen wie „im Auftrag unseres Kunden", „für unseren Kunden", Vermittler-Kontext des Portals.
- Ist der Typ nicht eindeutig bestimmbar, im Review nachfragen.
- **Ansprechperson:** vollständiger Name (für Aufteilung in Vor-/Nachname siehe §6).
- **Firmenname:** Name der Agentur bzw. des Endkunden.
## 5. Rahmenbedingungen automatisch bewerten (Skill-Schritt 3/4)
Misc-Anforderungen zu Verfügbarkeit/Auslastung/Laufzeit/Einsatzort werden gegen `vorgaben/rahmenbedingungen.md` bewertet und erhalten direkt ✅/❌/❔ gemäß den Regeln in §3 — **statt** des bisherigen pauschalen ❔. Greift eine Regel nicht eindeutig (Auslastung/Start nicht genannt, Ort grenzwertig), bleibt es ❔.
- Distanzbeurteilung: Luftlinie vom genannten Onsite-Ort nach Sauerlach schätzen; Referenz-Distanzen aus §3 als Anker. Klar innerhalb → ✅, klar außerhalb → ❌, grenzwertig/unbekannter Ort → ❔ bzw. ❌ gemäß Regel.
- Startdatum: „heute + 8 Wochen" (56 Tage) gegen den genannten Projektstart prüfen.
- Misc-Zeilen gehen weiterhin **nicht** in die Match-Prozente ein; die automatische Bewertung ist informativ und spart das manuelle Setzen.
## 6. CRM-Schreibablauf (Skill-Schritt 7) — Reihenfolge Firma → Kontakt → Verkaufschance
Alle Schreibvorgänge erst **nach** der Review-Freigabe (§7).
### 6.1 Firma (`Account`)
1. Dedup-Suche per Name (Kern-Token), inkl. naher Varianten (z. B. „Aristo Recruitment" vs. „Aristo Recruitment GmbH").
2. Exakter/eindeutiger Treffer → bestehenden Datensatz wiederverwenden (im Review als „bestehend" ausweisen).
3. Ähnlich-aber-nicht-identisch → Kandidaten im Review auflisten; Thomas entscheidet „wiederverwenden" oder „neu anlegen". Nie still anlegen oder zusammenführen.
4. Kein Treffer → neu anlegen: `POST /Account` mit `{name, type}`.
- Agentur → `type = "Reseller"`.
- Endkunde (Direktauftrag) → `type = "Customer"`.
### 6.2 Kontakt (`Contact`)
1. Dedup-Suche per Name analog zu 6.1.
2. Kein/zu bestätigender Treffer → nach Freigabe neu anlegen: `POST /Contact` mit `{firstName, lastName, accountId}` (verknüpft mit der Firma aus 6.1).
- Namensaufteilung: letztes Token = `lastName`, der Rest = `firstName`. Ungewöhnliche Fälle im Review klären.
### 6.3 Verkaufschance (`Opportunity`)
`POST /Opportunity` wie bisher (`name`, `description` = Match-Tabelle, `cProjektlink`) **plus** Verknüpfungen:
- `contactsIds: [<contactId>]`
- **Agentur:** `cAccount1Id = <agenturAccountId>` („Über Agentur"); `account` bleibt **leer**.
- **Direktauftrag:** `accountId = <endkundeAccountId>`; `cAccount1` bleibt leer.
Duplikat-Regel für den Opportunity-Namen (Suffix „ (2)", „ (3)", …) bleibt wie in der aktuellen Fassung.
## 7. Review erweitern (Skill-Schritt 6)
Vor jedem Schreibvorgang zeigt das Review zusätzlich zur bestehenden Match-Tabelle und den ❌/❔-Begründungen:
- **Käufer-Typ** (Agentur/Direktauftrag) mit Kurzbegründung.
- **Firma:** Name und `type`; „neu anlegen" oder „bestehende nutzen: <Name/ID>"; bei Mehrdeutigkeit die Kandidatenliste.
- **Kontakt:** Name; „neu" oder „bestehend".
- **Verknüpfungs-Zuordnung** der Verkaufschance (account vs. cAccount1, Kontakt).
Erst nach Freigabe werden Firma, Kontakt und Verkaufschance in dieser Reihenfolge geschrieben (§6).
## 8. Geänderte/neue Dateien
- Neu: `vorgaben/rahmenbedingungen.md` (§3).
- Geändert: `.claude/skills/projekt-anlegen/SKILL.md` (Schritte 1, 3/4, 6, 7; Voraussetzungen um `rahmenbedingungen.md` ergänzt).
- Ggf. ergänzt: `CLAUDE.md` (Hinweis auf `vorgaben/rahmenbedingungen.md`).
- Unberührt: `cowork-projekt-match` (Archiv).
## 9. Bewusst NICHT enthalten (YAGNI)
- Keine automatische Geokodierung/Distanz-API — Distanz wird anhand der Referenz-Anker geschätzt; Grenzfälle → ❔.
- Keine automatische Zusammenführung bestehender CRM-Dubletten.
- Keine Änderung der Must/Nice-Bewertungslogik oder der Match-Berechnung.
## 10. Offene Annahme (im Spec-Review zu bestätigen)
- **Projektstart „nicht genannt" → ❔** (Review entscheidet). Alle anderen „nicht genannt"-Fälle sind oben explizit geregelt.
## Selbstreview
- Alle vier Rahmen-Dimensionen haben eindeutige ✅/❌/❔-Regeln inkl. „nicht genannt"-Fall (Start = ❔, Auslastung = ❔, Einsatzort = ❌, Laufzeit n/a). ✓
- CRM-Feldnamen gegen die API verifiziert (`type=Reseller/Customer`, `account`/`cAccount1`/`contacts`). ✓
- Schreibreihenfolge und Verknüpfungen für beide Käufer-Typen konsistent. ✓
- Keine Platzhalter; Dedup-Verhalten entspricht der getroffenen Entscheidung (Kandidaten im Review). ✓