Splits the 250-line hand-rolled SKILL.md into a 96-line SKILL.md
(under the 100-line soft cap from agentskills-extras) plus
references/sql-recipes.md (134 lines). Description rewritten in
imperative voice with explicit pushy triggers — including the short-
message case ('Hey', 'wer bin ich?') so Claude doesn't second-guess
when the prefix [PALIADIN:<uuid>] is present but the body looks like
normal chat.
SKILL.md keeps: persona, response-file format, classifier table,
action chips, hard rules, full example, first-turn rule. Out: 8 SQL
recipes, moved to references/sql-recipes.md with a concrete pointer
trigger ('Read before any project / deadline / appointment / court /
glossary / deadline-rule / UPC-judgment lookup').
install-paliadin-skill now mirrors the entire skill tree (SKILL.md +
references/) and clears stale aux files on each run. Manual one-shot
— m's call to skip a post-merge auto-refresh hook for now.
4.5 KiB
4.5 KiB
SQL recipes — Paliadin tool catalogue
Read this file before any project / deadline / appointment / court / glossary / deadline-rule / UPC-judgment lookup. Every query goes through the Supabase MCP via mcp__supabase__execute_sql. Two schemas in the same physical DB:
paliad.*— Patentpraxis-Daten (projects, deadlines, appointments, parties, courts, deadline_rules, users)data.*— youpc.org UPC case law (judgments, headnotes, knowledge graph)
Every project-scoped query MUST include paliad.can_see_project(project_id) — even when m is global_admin (see SKILL.md rule 4).
1. whats_on_my_plate — Dashboard-Übersicht
SELECT
(SELECT count(*) FROM paliad.deadlines d
WHERE paliad.can_see_project(d.project_id)
AND d.status = 'pending' AND d.due_date < current_date) AS overdue,
(SELECT count(*) FROM paliad.deadlines d
WHERE paliad.can_see_project(d.project_id)
AND d.status = 'pending' AND d.due_date = current_date) AS today,
(SELECT count(*) FROM paliad.deadlines d
WHERE paliad.can_see_project(d.project_id)
AND d.status = 'pending'
AND d.due_date BETWEEN current_date AND current_date + 7) AS this_week,
(SELECT count(*) FROM paliad.appointments a
WHERE (a.project_id IS NULL OR paliad.can_see_project(a.project_id))
AND a.start_at::date = current_date) AS appointments_today;
2. list_my_projects
SELECT id, kind, label, status, parent_id, path
FROM paliad.projects
WHERE paliad.can_see_project(id)
AND status = 'active'
ORDER BY path
LIMIT 25;
3. get_project_detail (per slug oder id)
SELECT p.*,
(SELECT json_agg(d ORDER BY d.due_date)
FROM paliad.deadlines d WHERE d.project_id = p.id
AND paliad.can_see_project(d.project_id)) AS deadlines,
(SELECT json_agg(a ORDER BY a.start_at)
FROM paliad.appointments a WHERE a.project_id = p.id
AND paliad.can_see_project(a.project_id)) AS appointments,
(SELECT json_agg(pa) FROM paliad.parties pa WHERE pa.project_id = p.id) AS parties
FROM paliad.projects p
WHERE paliad.can_see_project(p.id)
AND (p.id::text = '<UUID>' OR p.slug = '<slug>')
LIMIT 1;
4. search_my_deadlines (status / Datum / Projekt)
SELECT d.id, d.title, d.due_date, d.status, p.label AS project_label, d.event_id
FROM paliad.deadlines d
JOIN paliad.projects p ON p.id = d.project_id
WHERE paliad.can_see_project(d.project_id)
AND ($status::text IS NULL OR d.status = $status)
AND ($due_after::date IS NULL OR d.due_date >= $due_after)
AND ($due_before::date IS NULL OR d.due_date <= $due_before)
ORDER BY d.due_date ASC
LIMIT 25;
5. list_my_appointments (Zeitfenster)
SELECT a.id, a.title, a.start_at, a.end_at, a.location, p.label AS project_label
FROM paliad.appointments a
LEFT JOIN paliad.projects p ON p.id = a.project_id
WHERE (a.project_id IS NULL OR paliad.can_see_project(a.project_id))
AND a.start_at >= $from
AND a.start_at <= $to
ORDER BY a.start_at ASC
LIMIT 25;
6. lookup_court (firm-wide reference)
SELECT c.slug, c.name, c.country, c.kind, c.address
FROM paliad.courts c
WHERE c.name ILIKE '%' || $q || '%'
OR c.slug ILIKE '%' || $q || '%'
ORDER BY similarity(c.name, $q) DESC
LIMIT 10;
7. lookup_deadline_rule (Fristenrechner-Konzepte)
SELECT r.rule_code, r.concept_label, r.trigger_event, r.deadline_text,
r.deadline_text_en, r.legal_source, r.deadline_notes, r.deadline_notes_en
FROM paliad.deadline_rules r
WHERE r.concept_label ILIKE '%' || $q || '%'
OR r.rule_code ILIKE '%' || $q || '%'
OR r.legal_source ILIKE '%' || $q || '%'
ORDER BY similarity(r.concept_label, $q) DESC
LIMIT 5;
8. lookup_youpc_case (UPC-Rechtsprechung — cross-schema)
SELECT j.node_id, j.upc_number, j.court_division, j.judgment_type,
j.proceedings_type, j.decision_date, j.headnote_summary,
j.tags
FROM data.judgments j
WHERE j.upc_number ILIKE '%' || $q || '%'
OR j.headnote_summary ILIKE '%' || $q || '%'
OR j.tags::text ILIKE '%' || $q || '%'
ORDER BY j.decision_date DESC
LIMIT 5;
Volltext eines Urteils (wenn m fragt "was steht in dem Urteil?"):
SELECT content
FROM data.judgment_markdown_content
WHERE judgment_node_id = <node_id>
ORDER BY chunk_index
LIMIT 1;
Glossar — keine SQL-Tabelle
Der Patent-Glossar lebt statisch in internal/handlers/glossary.go (JSON beim Boot geladen). Für reine Begriffsfragen reicht dein Wissen + optional Cross-Check via paliad.deadline_rules.legal_source.