Optionaler eventSource-Block (url + crawlIntervalHours) im Venue-YAML. import-venues legt daraus idempotent eine inaktive scope='venue'-Source an (deterministische ID es_yaml_<slug>) — Re-Import lässt active + Crawl-State (failCount/Backoff) unangetastet, Reviewer-Aktivierung bleibt also erhalten. Strategie: venue-direkt zuerst (eigene Programmseiten, §87a-unkritisch, self-hostbar), stadtweite Guidle-Discovery als bewusste 2. Phase. Seed: 3 verifizierte Programm-URLs (zebra-kino /monatsprogramm, kula /program, kult-x kultur.kult-x.ch). Aktivierung bleibt Reviewer-Stop (probe -> active:true), wartet auf Service-Key (α-1c). Doku in CURATOR.md + STATUS.md (α-3.7). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.9 KiB
Curator-Workflow — Seepuls
Wie Inhalte in den Seepuls-Korpus kommen. Drei Skills, klare Reviewer- Stops, dieselbe Disziplin wie bei Cardecky und Zitare.
Cross-Repo-Pattern:
../mana/docs/CONTENT_PIPELINES.mdist die Single-Source-of-Truth für Pipeline-Patterns. Seepuls folgt dem dort dokumentierten 5-Stufen-Skelett (Plan → Recherche → Design → Validate → Publish) mit Reviewer-Stops nach Plan und Design.
Drei Skills
| Skill | Aufgabe | SOT |
|---|---|---|
/seepuls-curate-venue |
Venue anlegen oder erweitern | YAML in apps/api/src/data/curated/venues/<slug>.yml |
/seepuls-validate-venue |
Read-only-Check eines Draft-Venue (7 Findings) | — |
/seepuls-curate-events |
Events einer Venue pflegen (Crawl-Mode + Manual-Mode) | DB direkt (seepuls.events) |
SOT-Wahl: warum Venues YAML, Events DB?
| Aspekt | Venues | Events |
|---|---|---|
| Lebenszeit | langlebig, ändern sich selten | kurzlebig (verschwinden nach Datum) |
| Volumen | 30–80 realistisch | 500–5000 |
| Audit-Trail | git-getracktes YAML wertvoll | DB-crawl_jobs reicht |
| Re-Import | idempotent, ersetzt manuelle Korrekturen | Dedupe-Upsert via external_id_hash |
| Curator-Disziplin | jeder Eintrag will durchdacht sein | Bulk-Streams, automatisch |
Venues sind die wenigen handgepflegten Anker; Events fließen daran vorbei.
Workspace-Disziplin
Drafts leben außerhalb des Repos in ~/Documents/seepuls-drafts/<slug>/:
~/Documents/seepuls-drafts/
├─ museum-rosenegg/ ← venue-draft
│ ├─ plan.md
│ ├─ research/{sources,notes}.md
│ ├─ design/venue.yml
│ ├─ validate/report.md
│ └─ publish/import.log
└─ museum-rosenegg-events-2026-06-15/ ← events-draft (datum-gestempelt)
├─ plan.md
├─ research/probe.json
├─ design/events.jsonl
├─ validate/report.md
└─ publish/run.log
Vorteil: Audit-Trail bleibt, ohne den Repo aufzublähen. Re-Run nach Unterbrechung möglich.
Pflicht-Reviewer-Stops
Auch wenn der User „mach einfach" gesagt hat:
- Nach Plan-Stufe — Boundaries festklopfen, Slug bestätigen, Modus festlegen.
- Nach Design-Stufe — strukturierte Daten (YAML oder JSONL) als Markdown-Preview, ja/nein.
- Vor Publish — Compliance-Veto durch
mana-compliance-Subagent bei sensiblen Inhalten.
Stops sind kurz und retten den Korpus vor Müll. Bei Bulk-Operationen reicht Sampling-Stop (5–10 zufällige Einträge + Streitfall-Liste).
Lizenz und Attribution
Venues und Events sind keine kreativen Schöpfungen — wir aggregieren öffentliche Veranstaltungs-Daten Dritter. Die Felder folgen daher der Aggregator-Policy, nicht der CC-Lizenz-Logik von Zitare oder Cardecky:
attributionRequired: trueist Default (sichtbare Quell-Domain im Frontend).source.url+source.refs[]sind Pflicht für Audit + Take-Down.- Bilder via Hot-Link (siehe
mana/docs/AGGREGATOR_POLICY.md§3). - Lebende Personen (Künstler:innen einer Veranstaltung) werden nur als Title-String erfasst, keine Personen-Profile.
Volle Policy: ../mana/docs/AGGREGATOR_POLICY.md.
Importer-Workflow
# Venue-YAML editieren oder via Skill anlegen, dann:
pnpm --filter ./apps/api db:import-venues
# Output: "X inserted, Y updated, 0 errors"
# Idempotent: zweiter Run = 0 inserted, X+Y updated
Bei Schema-Validierungs-Fehlern bricht der Importer mit exit 1 ab. Das YAML muss korrigiert werden, kein Auto-Fix.
Event-Source einer Venue mit-kuratieren
Optionaler Block im Venue-YAML — die eigene Event-/Programm-Seite der
Venue (NICHT ein stadtweiter Sammelkalender, das ist scope='city' per
Admin-API):
eventSource:
url: 'https://zebra-kino.de/monatsprogramm/'
# crawlIntervalHours: 24 # optional, 6..168, Default 24
Der Importer legt daraus idempotent eine scope='venue'-Source an
(deterministische ID es_yaml_<slug>), inaktiv. Re-Import
aktualisiert URL/Intervall, lässt aber active und den Crawl-State
(failCount/Backoff) unangetastet — eine vom Reviewer freigegebene Source
wird nicht zurückgesetzt.
Aktivierung bleibt manueller Reviewer-Stop (AGGREGATOR_POLICY):
POST /api/v1/admin/event-sources/<id>/probe # Vorschau, kein DB-Write
PATCH /api/v1/admin/event-sources/<id> # { "active": true }
robots.txt + Crawl-Delay des Event-Source-Hosts prüft die Pipeline zur Probe-/Crawl-Zeit automatisch.
Anti-Halluzinations-Regeln (kompakt)
- Niemals Adressen oder Koordinaten raten — Nominatim oder Quellen-Beleg.
- Niemals Description LLM-paraphrasieren — direkte Übernahme aus offizieller Quelle, ≤ 200 Zeichen.
- Niemals Social-URLs erfinden — leer lassen wenn nicht auf der Website verlinkt.
- Niemals Datum aus Free-Form raten — strict-ISO oder droppen.
- Niemals Event ohne
starts_at— kein Datum, kein Event.
Bulk-Mode
Erst ab größeren Mengen relevant:
- Venues: ≥ 10 auf einmal (z.B. „alle Konstanzer Museen aus konstanz.de/tourismus"). Sampling-Stop auf 5.
- Events: ≥ 30 auf einmal (z.B. ein Saison-Programm). Sampling-Stop auf 10 + alle Streitfälle (Datum unklar etc.).
Verhältnis zur automatischen Crawl-Pipeline
Seepuls hat zwei Wege, eine Venue/Events anzulegen:
- Skill-Pfad (manuell, dieser Workflow):
/seepuls-curate-venue→ YAML-SOT → Importer. Reviewer-Stops Pflicht. - Crawl-Pfad (automatisch):
POST /api/v1/admin/venues/from-url→ mana-research → mana-llm → DB-row mitcrawl_status='pending-review'. Reviewer löst die Pending-Review später per UI.
Beide schreiben in dieselbe seepuls.venues-Tabelle. crawl_status
unterscheidet (manual-entry vs pending-review vs claimed).
YAML-SOT existiert nur für manual-entry-Venues.
Offene Punkte
- Venues aus Crawl-Pfad nach YAML-SOT migrieren: wenn ein pending-review-Eintrag vom Reviewer akzeptiert wird, sollte er optional ins YAML wandern (für git-getrackte Persistenz). Heute: manueller Export aus DB.
- Events-Validator-Skill
/seepuls-validate-eventsfehlt (analog/cards-validate-deck). - Wikidata-Anbindung für Venues — analog
/zitare-curate-authorWikidata-Enrich. V2. - mana-compliance-Subagent muss für Venue/Event-Diffs sinnvolle Veto-Heuristiken haben (Werte: keine kommerzielle Werbung, keine Tracking-Wrapper, robots-Respect). Aktuell generischer Mission-Check.
Referenzen
- Cross-Repo-Pattern:
../mana/docs/CONTENT_PIPELINES.md - Aggregator-Policy:
../mana/docs/AGGREGATOR_POLICY.md - Skills:
.claude/skills/seepuls-curate-{venue,events}.md,.claude/skills/seepuls-validate-venue.md - YAML-Format:
apps/api/src/data/curated/venues/README.md - Importer:
apps/api/src/jobs/import-venues.ts