seepuls/docs/CURATOR.md
Till JS f1af194a71 feat(venues): Event-Sources via Venue-YAML kuratierbar (venue-direkt zuerst)
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>
2026-05-29 16:15:21 +02:00

180 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.md`](../../mana/docs/CONTENT_PIPELINES.md)
> ist 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`](../.claude/skills/seepuls-curate-venue.md) | Venue anlegen oder erweitern | YAML in `apps/api/src/data/curated/venues/<slug>.yml` |
| [`/seepuls-validate-venue`](../.claude/skills/seepuls-validate-venue.md) | Read-only-Check eines Draft-Venue (7 Findings) | — |
| [`/seepuls-curate-events`](../.claude/skills/seepuls-curate-events.md) | 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 | 3080 realistisch | 5005000 |
| 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:
1. **Nach Plan-Stufe** — Boundaries festklopfen, Slug bestätigen,
Modus festlegen.
2. **Nach Design-Stufe** — strukturierte Daten (YAML oder JSONL) als
Markdown-Preview, ja/nein.
3. **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 (510 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: true` ist 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`](../../mana/docs/AGGREGATOR_POLICY.md).
## Importer-Workflow
```bash
# 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):
```yaml
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:
1. **Skill-Pfad** (manuell, dieser Workflow): `/seepuls-curate-venue`
→ YAML-SOT → Importer. Reviewer-Stops Pflicht.
2. **Crawl-Pfad** (automatisch): `POST /api/v1/admin/venues/from-url`
→ mana-research → mana-llm → DB-row mit `crawl_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-events` fehlt
(analog `/cards-validate-deck`).
- **Wikidata-Anbindung** für Venues — analog `/zitare-curate-author`
Wikidata-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`](../../mana/docs/CONTENT_PIPELINES.md)
- Aggregator-Policy: [`../mana/docs/AGGREGATOR_POLICY.md`](../../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`