@ansvar/ch-livestock-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/.github/workflows/check-freshness.yml +52 -0
  2. package/.github/workflows/ci.yml +21 -0
  3. package/.github/workflows/codeql.yml +31 -0
  4. package/.github/workflows/ghcr-build.yml +45 -0
  5. package/.github/workflows/gitleaks.yml +23 -0
  6. package/.github/workflows/ingest.yml +58 -0
  7. package/.github/workflows/publish.yml +24 -0
  8. package/CHANGELOG.md +24 -0
  9. package/CODEOWNERS +1 -0
  10. package/COVERAGE.md +62 -0
  11. package/DISCLAIMER.md +41 -0
  12. package/Dockerfile +26 -0
  13. package/LICENSE +17 -0
  14. package/PRIVACY.md +28 -0
  15. package/README.md +145 -0
  16. package/SECURITY.md +33 -0
  17. package/TOOLS.md +261 -0
  18. package/data/coverage.json +23 -0
  19. package/data/database.db +0 -0
  20. package/data/sources.yml +29 -0
  21. package/dist/db.d.ts +26 -0
  22. package/dist/db.d.ts.map +1 -0
  23. package/dist/db.js +220 -0
  24. package/dist/db.js.map +1 -0
  25. package/dist/http-server.d.ts +2 -0
  26. package/dist/http-server.d.ts.map +1 -0
  27. package/dist/http-server.js +294 -0
  28. package/dist/http-server.js.map +1 -0
  29. package/dist/jurisdiction.d.ts +18 -0
  30. package/dist/jurisdiction.d.ts.map +1 -0
  31. package/dist/jurisdiction.js +16 -0
  32. package/dist/jurisdiction.js.map +1 -0
  33. package/dist/metadata.d.ts +10 -0
  34. package/dist/metadata.d.ts.map +1 -0
  35. package/dist/metadata.js +21 -0
  36. package/dist/metadata.js.map +1 -0
  37. package/dist/server.d.ts +3 -0
  38. package/dist/server.d.ts.map +1 -0
  39. package/dist/server.js +240 -0
  40. package/dist/server.js.map +1 -0
  41. package/dist/tools/about.d.ts +15 -0
  42. package/dist/tools/about.d.ts.map +1 -0
  43. package/dist/tools/about.js +27 -0
  44. package/dist/tools/about.js.map +1 -0
  45. package/dist/tools/check-freshness.d.ts +15 -0
  46. package/dist/tools/check-freshness.d.ts.map +1 -0
  47. package/dist/tools/check-freshness.js +26 -0
  48. package/dist/tools/check-freshness.js.map +1 -0
  49. package/dist/tools/get-breeding-guidance.d.ts +37 -0
  50. package/dist/tools/get-breeding-guidance.d.ts.map +1 -0
  51. package/dist/tools/get-breeding-guidance.js +39 -0
  52. package/dist/tools/get-breeding-guidance.js.map +1 -0
  53. package/dist/tools/get-feed-requirements.d.ts +40 -0
  54. package/dist/tools/get-feed-requirements.d.ts.map +1 -0
  55. package/dist/tools/get-feed-requirements.js +35 -0
  56. package/dist/tools/get-feed-requirements.js.map +1 -0
  57. package/dist/tools/get-housing-requirements.d.ts +39 -0
  58. package/dist/tools/get-housing-requirements.d.ts.map +1 -0
  59. package/dist/tools/get-housing-requirements.js +35 -0
  60. package/dist/tools/get-housing-requirements.js.map +1 -0
  61. package/dist/tools/get-movement-rules.d.ts +36 -0
  62. package/dist/tools/get-movement-rules.d.ts.map +1 -0
  63. package/dist/tools/get-movement-rules.js +31 -0
  64. package/dist/tools/get-movement-rules.js.map +1 -0
  65. package/dist/tools/get-stocking-density.d.ts +37 -0
  66. package/dist/tools/get-stocking-density.d.ts.map +1 -0
  67. package/dist/tools/get-stocking-density.js +35 -0
  68. package/dist/tools/get-stocking-density.js.map +1 -0
  69. package/dist/tools/get-welfare-standards.d.ts +38 -0
  70. package/dist/tools/get-welfare-standards.d.ts.map +1 -0
  71. package/dist/tools/get-welfare-standards.js +32 -0
  72. package/dist/tools/get-welfare-standards.js.map +1 -0
  73. package/dist/tools/list-sources.d.ts +18 -0
  74. package/dist/tools/list-sources.d.ts.map +1 -0
  75. package/dist/tools/list-sources.js +51 -0
  76. package/dist/tools/list-sources.js.map +1 -0
  77. package/dist/tools/search-animal-health.d.ts +28 -0
  78. package/dist/tools/search-animal-health.d.ts.map +1 -0
  79. package/dist/tools/search-animal-health.js +33 -0
  80. package/dist/tools/search-animal-health.js.map +1 -0
  81. package/dist/tools/search-livestock-guidance.d.ts +27 -0
  82. package/dist/tools/search-livestock-guidance.d.ts.map +1 -0
  83. package/dist/tools/search-livestock-guidance.js +25 -0
  84. package/dist/tools/search-livestock-guidance.js.map +1 -0
  85. package/docker-compose.yml +12 -0
  86. package/eslint.config.js +27 -0
  87. package/package.json +54 -0
  88. package/scripts/ingest.ts +553 -0
  89. package/server.json +10 -0
  90. package/src/db.ts +268 -0
  91. package/src/http-server.ts +327 -0
  92. package/src/jurisdiction.ts +30 -0
  93. package/src/metadata.ts +31 -0
  94. package/src/server.ts +264 -0
  95. package/src/tools/about.ts +28 -0
  96. package/src/tools/check-freshness.ts +42 -0
  97. package/src/tools/get-breeding-guidance.ts +53 -0
  98. package/src/tools/get-feed-requirements.ts +53 -0
  99. package/src/tools/get-housing-requirements.ts +52 -0
  100. package/src/tools/get-movement-rules.ts +45 -0
  101. package/src/tools/get-stocking-density.ts +52 -0
  102. package/src/tools/get-welfare-standards.ts +47 -0
  103. package/src/tools/list-sources.ts +65 -0
  104. package/src/tools/search-animal-health.ts +48 -0
  105. package/src/tools/search-livestock-guidance.ts +33 -0
  106. package/tests/db.test.ts +96 -0
  107. package/tests/helpers/seed-db.ts +97 -0
  108. package/tests/jurisdiction.test.ts +41 -0
  109. package/tests/tools/about.test.ts +32 -0
  110. package/tests/tools/check-freshness.test.ts +55 -0
  111. package/tests/tools/list-sources.test.ts +56 -0
  112. package/tests/tools/search-livestock-guidance.test.ts +63 -0
  113. package/tsconfig.json +19 -0
@@ -0,0 +1,553 @@
1
+ /**
2
+ * Switzerland Livestock MCP — Data Ingestion Script
3
+ *
4
+ * Populates the database with Swiss livestock data from:
5
+ * - TSchV (Tierschutzverordnung, SR 455.1) — Mindestanforderungen pro Tierart
6
+ * - DZV (Direktzahlungsverordnung) — RAUS/BTS-Programme, Tierwohlbeitraege
7
+ * - TVD (Tierverkehrsdatenbank) — Registrierung, Meldepflicht, Transport
8
+ * - Zuchtorganisationen — Braunvieh Schweiz, swissherdbook, Mutterkuh Schweiz, Suisseporcs
9
+ * - BLV Fachinformationen — Tiergesundheit, Schlachtung, Soemmerung
10
+ *
11
+ * All data in German (primary federal language for agricultural regulation).
12
+ * Usage: npm run ingest
13
+ */
14
+
15
+ import { createDatabase } from '../src/db.js';
16
+ import { mkdirSync, writeFileSync } from 'fs';
17
+
18
+ mkdirSync('data', { recursive: true });
19
+ const db = createDatabase('data/database.db');
20
+
21
+ const now = new Date().toISOString().split('T')[0];
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Helper: batch insert
25
+ // ---------------------------------------------------------------------------
26
+ function batchInsert(table: string, columns: string[], rows: unknown[][]) {
27
+ const placeholders = columns.map(() => '?').join(', ');
28
+ const stmt = db.instance.prepare(
29
+ `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders})`
30
+ );
31
+ const insertMany = db.instance.transaction((data: unknown[][]) => {
32
+ for (const row of data) {
33
+ stmt.run(...row);
34
+ }
35
+ });
36
+ insertMany(rows);
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // 1. Welfare Standards — TSchV Mindestanforderungen + RAUS + BTS
41
+ // ---------------------------------------------------------------------------
42
+
43
+ interface WelfareStandard {
44
+ species: string;
45
+ production_system: string;
46
+ requirement: string;
47
+ min_space_m2: number | null;
48
+ details: string;
49
+ }
50
+
51
+ const welfareStandards: WelfareStandard[] = [
52
+ // --- Rinder ---
53
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Liegeflaeche Milchkuh Laufstall', min_space_m2: 4.5, details: 'TSchV Anhang 1, Tab. 1: Mindestflaeche Liegebereich pro Milchkuh im Laufstall. Anbindehaltung weiterhin erlaubt mit RAUS-Auslauf.' },
54
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Liegeflaeche Mutterkuh Laufstall', min_space_m2: 4.5, details: 'TSchV Anhang 1: Mutterkühe gleicher Platzbedarf wie Milchkuehe im Laufstall.' },
55
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Liegeflaeche Aufzuchtrind >400kg', min_space_m2: 3.5, details: 'TSchV Anhang 1: Aufzuchtrinder ueber 400 kg Lebendgewicht.' },
56
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Liegeflaeche Aufzuchtrind 200-400kg', min_space_m2: 2.5, details: 'TSchV Anhang 1: Aufzuchtrinder 200-400 kg Lebendgewicht.' },
57
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Liegeflaeche Kalb <200kg', min_space_m2: 1.5, details: 'TSchV Anhang 1: Kaelber bis 200 kg. Einzelhaltung nur erste 2 Wochen erlaubt, danach Gruppenhaltung obligatorisch.' },
58
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Anbindehaltung Milchkuh', min_space_m2: null, details: 'Anbindehaltung noch erlaubt (TSchV Art. 39). RAUS-Auslauf obligatorisch: mind. 90 Tage Weide (1.5.-31.10.) + 30 Halbtage Winter. Standlaenge mind. 1.65m (Kurzstand) oder 1.95m (Mittellangstand).' },
59
+ { species: 'Rinder', production_system: 'TSchV-Minimum', requirement: 'Tageslicht und Beleuchtung', min_space_m2: null, details: 'TSchV Art. 33: Fensterflaeche mind. 1/20 der Bodenflaeche. Kuenstliches Licht mind. 15 Lux im Tierbereich waehrend 8h.' },
60
+ { species: 'Rinder', production_system: 'RAUS', requirement: 'Auslauf Sommer (1.5.-31.10.)', min_space_m2: null, details: 'RAUS-Programm DZV: Mind. 26 Tage/Monat Weidegang waehrend Vegetationsperiode. Weidefläche angepasst an Bestandesgroesse.' },
61
+ { species: 'Rinder', production_system: 'RAUS', requirement: 'Auslauf Winter (1.11.-30.4.)', min_space_m2: null, details: 'RAUS-Programm DZV: Mind. 13 Tage/Monat Auslauf im Freien (Laufhof oder Weide). Laufhofflaeche mind. 2.5 m2/GVE.' },
62
+ { species: 'Rinder', production_system: 'RAUS', requirement: 'Beitrag RAUS Rinder', min_space_m2: null, details: 'DZV: RAUS-Beitrag 190 CHF/GVE (Milchkuehe, Mutterkühe, Aufzuchtrinder). Kumulation mit BTS moeglich.' },
63
+ { species: 'Rinder', production_system: 'BTS', requirement: 'Laufstall mit Liegebereich', min_space_m2: null, details: 'BTS-Programm DZV: Laufstall obligatorisch (keine Anbindehaltung). Liegebereich mit Einstreu. Fressplatzbreite mind. 0.70m/Kuh.' },
64
+ { species: 'Rinder', production_system: 'BTS', requirement: 'Beitrag BTS Rinder', min_space_m2: null, details: 'DZV: BTS-Beitrag 90 CHF/GVE (Rindvieh). Kumulation mit RAUS: Total 280 CHF/GVE.' },
65
+
66
+ // --- Schweine ---
67
+ { species: 'Schweine', production_system: 'TSchV-Minimum', requirement: 'Bucht Mastschwein >60kg', min_space_m2: 0.9, details: 'TSchV Anhang 1, Tab. 3: Mindestflaeche pro Mastschwein ueber 60 kg Lebendgewicht. Davon max. 50% Spaltenbodenanteil.' },
68
+ { species: 'Schweine', production_system: 'TSchV-Minimum', requirement: 'Bucht Mastschwein 25-60kg', min_space_m2: 0.6, details: 'TSchV Anhang 1: Mastschwein 25-60 kg Lebendgewicht.' },
69
+ { species: 'Schweine', production_system: 'TSchV-Minimum', requirement: 'Bucht Zuchtsau saeugend', min_space_m2: 5.5, details: 'TSchV Anhang 1: Abferkelbucht mind. 5.5 m2 inkl. Ferkelnest. Kastenstand nur waehrend Abferkeln und erste Tage (max. Dauer diskutiert).' },
70
+ { species: 'Schweine', production_system: 'TSchV-Minimum', requirement: 'Gruppenhaltung traechtige Sauen', min_space_m2: 2.5, details: 'TSchV Art. 46: Traechtige Sauen muessen in Gruppen gehalten werden (Ausnahme: 10 Tage vor Abferkeln). Mind. 2.5 m2/Sau.' },
71
+ { species: 'Schweine', production_system: 'TSchV-Minimum', requirement: 'Beschaeftigungsmaterial', min_space_m2: null, details: 'TSchV Art. 44: Schweine muessen jederzeit Zugang zu Raufutter (Stroh, Heu) oder anderem Beschaeftigungsmaterial haben. Ketten allein genuegen nicht.' },
72
+ { species: 'Schweine', production_system: 'TSchV-Minimum', requirement: 'Verbot Vollspaltenboeden', min_space_m2: null, details: 'TSchV Art. 45: Buchtenboden max. 50% perforiert. Liegebereich muss eingestreut oder mit Komfortauflage versehen sein.' },
73
+ { species: 'Schweine', production_system: 'RAUS', requirement: 'Auslauf Schweine', min_space_m2: null, details: 'RAUS-Programm: Alle Schweine muessen taeglich Zugang zu Aussenklima-Bereich haben. Auslaufflaeche: Mastschwein 0.45 m2, Zuchtsau 1.3 m2.' },
74
+ { species: 'Schweine', production_system: 'RAUS', requirement: 'Beitrag RAUS Schweine', min_space_m2: null, details: 'DZV: RAUS-Beitrag 155 CHF/GVE (Schweine). Zuechter und Maester separat anspruchsberechtigt.' },
75
+ { species: 'Schweine', production_system: 'BTS', requirement: 'Mehrflaeche und Einstreu', min_space_m2: null, details: 'BTS-Programm: Mind. 20% mehr Flaeche als TSchV-Minimum. Liegebereich vollstaendig eingestreut. Mastschwein >60kg: mind. 1.1 m2 total.' },
76
+ { species: 'Schweine', production_system: 'BTS', requirement: 'Beitrag BTS Schweine', min_space_m2: null, details: 'DZV: BTS-Beitrag 155 CHF/GVE (Schweine). Kumulation mit RAUS: Total 310 CHF/GVE.' },
77
+
78
+ // --- Gefluegel ---
79
+ { species: 'Gefluegel', production_system: 'TSchV-Minimum', requirement: 'Besatzdichte Legehennen', min_space_m2: null, details: 'TSchV Anhang 1, Tab. 9: Max. 7 Legehennen pro m2 nutzbare Flaeche (Bodenhaltung). Kaefighaltung verboten seit 1992 in der Schweiz.' },
80
+ { species: 'Gefluegel', production_system: 'TSchV-Minimum', requirement: 'Besatzdichte Mastpoulets', min_space_m2: null, details: 'TSchV Anhang 1: Max. 30 kg Lebendgewicht pro m2 (Bodenhaltung). Ca. 13-15 Tiere/m2 bei Schlachtgewicht.' },
81
+ { species: 'Gefluegel', production_system: 'TSchV-Minimum', requirement: 'Einrichtung Legehennen', min_space_m2: null, details: 'TSchV Art. 59-62: Sitzstangen (mind. 14 cm/Tier), Legenester (1 Nest pro 5 Hennen), Einstreu im Scharrbereich (mind. 1/3 der Flaeche), erhoehte Sitzgelegenheiten.' },
82
+ { species: 'Gefluegel', production_system: 'TSchV-Minimum', requirement: 'Licht Gefluegel', min_space_m2: null, details: 'TSchV Art. 58: Tageslicht obligatorisch (Fensterflaeche mind. 1/20 der Bodenflaeche). Dunkelphase mind. 8h.' },
83
+ { species: 'Gefluegel', production_system: 'RAUS', requirement: 'Weide Legehennen', min_space_m2: null, details: 'RAUS-Programm: Taeglich Zugang zur Weide bei guenstiger Witterung. Weideflaeche mind. 2.5 m2/Tier. Rotation empfohlen (Parasitenmanagement).' },
84
+ { species: 'Gefluegel', production_system: 'RAUS', requirement: 'Beitrag RAUS Gefluegel', min_space_m2: null, details: 'DZV: RAUS-Beitrag 280 CHF/GVE fuer Legehennen (1 GVE = ca. 111 Hennen). Mastgefluegel: 280 CHF/GVE.' },
85
+ { species: 'Gefluegel', production_system: 'BTS', requirement: 'Voliere/Bodenhaltung', min_space_m2: null, details: 'BTS-Programm Gefluegel: Wintergarten (ueberdachter, geschuetzter Aussenklimabereich) obligatorisch. Mind. 1/3 der Stallflaeche als Scharrbereich.' },
86
+
87
+ // --- Schafe ---
88
+ { species: 'Schafe', production_system: 'TSchV-Minimum', requirement: 'Flaeche Mutterschaf mit Lamm', min_space_m2: 1.5, details: 'TSchV Anhang 1, Tab. 5: Mindestflaeche Mutterschaf mit Lamm. Ohne Lamm: 1.0 m2. Haltung im Freien ganzjaehrig erlaubt mit Witterungsschutz.' },
89
+ { species: 'Schafe', production_system: 'TSchV-Minimum', requirement: 'Flaeche Mastlamm', min_space_m2: 0.5, details: 'TSchV Anhang 1: Mastlamm bis 40 kg. Ueber 40 kg: 0.7 m2.' },
90
+ { species: 'Schafe', production_system: 'TSchV-Minimum', requirement: 'Witterungsschutz', min_space_m2: null, details: 'TSchV Art. 36: Bei ganzjaehriger Weidehaltung ist ein natuerlicher oder kuenstlicher Witterungsschutz (Unterstand, Hecken, Wald) obligatorisch.' },
91
+ { species: 'Schafe', production_system: 'RAUS', requirement: 'Auslauf Schafe', min_space_m2: null, details: 'RAUS-Programm: Ganzjaehriger Weidegang oder Laufhof. Sommer: taeglicher Weidegang. Winter: mind. 13 Tage/Monat Auslauf.' },
92
+ { species: 'Schafe', production_system: 'RAUS', requirement: 'Beitrag RAUS Schafe', min_space_m2: null, details: 'DZV: RAUS-Beitrag 190 CHF/GVE (Schafe). 1 GVE = ca. 7 Mutterschafe.' },
93
+
94
+ // --- Ziegen ---
95
+ { species: 'Ziegen', production_system: 'TSchV-Minimum', requirement: 'Flaeche Milchziege', min_space_m2: 1.5, details: 'TSchV Anhang 1, Tab. 6: Mindestflaeche pro ausgewachsene Ziege. Erhoehte Liegeflaechenelemente obligatorisch (Ziegen klettern naturgemaess).' },
96
+ { species: 'Ziegen', production_system: 'TSchV-Minimum', requirement: 'Flaeche Zicklein', min_space_m2: 0.5, details: 'TSchV Anhang 1: Zicklein bis 15 kg Lebendgewicht.' },
97
+ { species: 'Ziegen', production_system: 'TSchV-Minimum', requirement: 'Erhoehte Liegeflaechen', min_space_m2: null, details: 'TSchV Art. 56: Ziegen muessen erhoehte Liegeflaechen (Plattformen, Regale) zur Verfuegung haben. Mindestens fuer 50% der Herde gleichzeitig.' },
98
+ { species: 'Ziegen', production_system: 'RAUS', requirement: 'Auslauf Ziegen', min_space_m2: null, details: 'RAUS-Programm: Analog Schafe — ganzjaehriger Zugang zu Freigelände. Ziegen benoetigen zusaetzlich Klettermoeglich­keiten im Auslauf.' },
99
+ { species: 'Ziegen', production_system: 'RAUS', requirement: 'Beitrag RAUS Ziegen', min_space_m2: null, details: 'DZV: RAUS-Beitrag 190 CHF/GVE (Ziegen). 1 GVE = ca. 7 Milchziegen.' },
100
+
101
+ // --- Pferde ---
102
+ { species: 'Pferde', production_system: 'TSchV-Minimum', requirement: 'Boxengroesse Einzelhaltung', min_space_m2: null, details: 'TSchV Anhang 1, Tab. 7: Mindestflaeche = (2 x Wh)^2, wobei Wh = Widerristhoehe. Fuer Pferd mit Wh 1.60m: mind. 10.24 m2. Kuerzeste Seite mind. 1.5 x Wh.' },
103
+ { species: 'Pferde', production_system: 'TSchV-Minimum', requirement: 'Gruppenhaltung Pferde', min_space_m2: null, details: 'TSchV Anhang 1: Gruppenauslaufhaltung: mind. 3 x Wh^2 pro Pferd Liegebereich + Auslauf. Fuer Wh 1.60m: mind. 7.68 m2 Liegebereich/Pferd.' },
104
+ { species: 'Pferde', production_system: 'TSchV-Minimum', requirement: 'Bewegung Pferde', min_space_m2: null, details: 'TSchV Art. 59: Pferde und andere Equiden muessen taeglich Auslauf im Freien haben (Weide, Paddock). Anbindehaltung (Staenderhaltung) verboten.' },
105
+ { species: 'Pferde', production_system: 'TSchV-Minimum', requirement: 'Sozialkontakt', min_space_m2: null, details: 'TSchV Art. 59: Pferde muessen Sicht-, Hoer- und Geruchskontakt zu Artgenossen haben. Dauerhafte Einzelhaltung ohne Artgenossenkontakt verboten.' },
106
+ { species: 'Pferde', production_system: 'RAUS', requirement: 'Auslauf Pferde RAUS', min_space_m2: null, details: 'RAUS-Programm: Pferde muessen taeglich Auslauf im Freien haben. Ganzjaehrig: mind. 2h/Tag Weide oder Paddock. Weidesaison (Mai-Okt): ganztaegiger Zugang empfohlen.' },
107
+ { species: 'Pferde', production_system: 'RAUS', requirement: 'Beitrag RAUS Pferde', min_space_m2: null, details: 'DZV: RAUS-Beitrag 190 CHF/GVE (Pferde/Equiden). 1 GVE = ca. 0.7 Pferde (abhaengig von Groesse/Alter).' },
108
+ ];
109
+
110
+ const welfareColumns = ['species', 'production_system', 'requirement', 'min_space_m2', 'details', 'language', 'jurisdiction'];
111
+ batchInsert('welfare_standards', welfareColumns,
112
+ welfareStandards.map(w => [w.species, w.production_system, w.requirement, w.min_space_m2, w.details, 'DE', 'CH'])
113
+ );
114
+
115
+ // ---------------------------------------------------------------------------
116
+ // 2. Stocking Densities — TSchV Anhang 1 Platzbedarf
117
+ // ---------------------------------------------------------------------------
118
+
119
+ interface StockingDensity {
120
+ species: string;
121
+ age_class: string;
122
+ housing_type: string;
123
+ animals_per_m2: number | null;
124
+ regulatory_minimum: string;
125
+ }
126
+
127
+ const stockingDensities: StockingDensity[] = [
128
+ // Rinder
129
+ { species: 'Rinder', age_class: 'Milchkuh', housing_type: 'Laufstall', animals_per_m2: null, regulatory_minimum: '4.5 m2 Liegeflaeche/Kuh, Laufgang mind. 2.5m breit' },
130
+ { species: 'Rinder', age_class: 'Milchkuh', housing_type: 'Anbindestall', animals_per_m2: null, regulatory_minimum: 'Standlaenge 1.65m (Kurzstand) oder 1.95m (Mittellangstand), Breite 1.20m' },
131
+ { species: 'Rinder', age_class: 'Aufzuchtrind >400kg', housing_type: 'Laufstall', animals_per_m2: null, regulatory_minimum: '3.5 m2 Liegeflaeche/Tier' },
132
+ { species: 'Rinder', age_class: 'Aufzuchtrind 200-400kg', housing_type: 'Laufstall', animals_per_m2: null, regulatory_minimum: '2.5 m2 Liegeflaeche/Tier' },
133
+ { species: 'Rinder', age_class: 'Kalb <200kg', housing_type: 'Gruppenhaltung', animals_per_m2: null, regulatory_minimum: '1.5 m2/Kalb, Einzelhaltung max. 2 Wochen nach Geburt' },
134
+ { species: 'Rinder', age_class: 'Mastbulle >400kg', housing_type: 'Laufstall', animals_per_m2: null, regulatory_minimum: '3.5 m2/Tier, Spaltenbodenanteil max. 50%' },
135
+
136
+ // Schweine
137
+ { species: 'Schweine', age_class: 'Mastschwein >60kg', housing_type: 'Bucht', animals_per_m2: 1.11, regulatory_minimum: '0.9 m2/Tier (TSchV), BTS: 1.1 m2/Tier' },
138
+ { species: 'Schweine', age_class: 'Mastschwein 25-60kg', housing_type: 'Bucht', animals_per_m2: 1.67, regulatory_minimum: '0.6 m2/Tier' },
139
+ { species: 'Schweine', age_class: 'Zuchtsau trächtig', housing_type: 'Gruppenhaltung', animals_per_m2: 0.4, regulatory_minimum: '2.5 m2/Sau, Gruppenhaltung obligatorisch' },
140
+ { species: 'Schweine', age_class: 'Zuchtsau saeugend', housing_type: 'Abferkelbucht', animals_per_m2: null, regulatory_minimum: '5.5 m2 Abferkelbucht inkl. Ferkelnest' },
141
+ { species: 'Schweine', age_class: 'Absetzferkel', housing_type: 'Bucht', animals_per_m2: 2.86, regulatory_minimum: '0.35 m2/Tier (bis 25 kg)' },
142
+ { species: 'Schweine', age_class: 'Eber', housing_type: 'Einzelbucht', animals_per_m2: null, regulatory_minimum: '6.0 m2/Eber, Sicht- und Geruchskontakt zu anderen Schweinen' },
143
+
144
+ // Gefluegel
145
+ { species: 'Gefluegel', age_class: 'Legehenne', housing_type: 'Bodenhaltung', animals_per_m2: 7, regulatory_minimum: 'Max. 7 Hennen/m2 nutzbare Flaeche, Kaefighaltung seit 1992 verboten' },
146
+ { species: 'Gefluegel', age_class: 'Legehenne', housing_type: 'Freilandhaltung', animals_per_m2: 7, regulatory_minimum: 'Max. 7 Hennen/m2 Stallflaeche + mind. 2.5 m2 Weide/Tier' },
147
+ { species: 'Gefluegel', age_class: 'Mastpoulet', housing_type: 'Bodenhaltung', animals_per_m2: null, regulatory_minimum: 'Max. 30 kg/m2 Lebendgewicht (ca. 13-15 Tiere/m2)' },
148
+ { species: 'Gefluegel', age_class: 'Masttrute', housing_type: 'Bodenhaltung', animals_per_m2: null, regulatory_minimum: 'Max. 3 Truten/m2 (Hähne) bzw. 5 Truten/m2 (Hennen)' },
149
+
150
+ // Schafe
151
+ { species: 'Schafe', age_class: 'Mutterschaf mit Lamm', housing_type: 'Stall', animals_per_m2: 0.67, regulatory_minimum: '1.5 m2/Tier' },
152
+ { species: 'Schafe', age_class: 'Mutterschaf ohne Lamm', housing_type: 'Stall', animals_per_m2: 1.0, regulatory_minimum: '1.0 m2/Tier' },
153
+ { species: 'Schafe', age_class: 'Mastlamm <40kg', housing_type: 'Stall', animals_per_m2: 2.0, regulatory_minimum: '0.5 m2/Tier' },
154
+
155
+ // Ziegen
156
+ { species: 'Ziegen', age_class: 'Milchziege', housing_type: 'Stall', animals_per_m2: 0.67, regulatory_minimum: '1.5 m2/Tier, erhoehte Liegeflächen obligatorisch' },
157
+ { species: 'Ziegen', age_class: 'Zicklein <15kg', housing_type: 'Stall', animals_per_m2: 2.0, regulatory_minimum: '0.5 m2/Tier' },
158
+ { species: 'Ziegen', age_class: 'Ziegenbock', housing_type: 'Stall', animals_per_m2: null, regulatory_minimum: '2.0 m2/Tier, Sichtkontakt zu Herde' },
159
+
160
+ // Pferde
161
+ { species: 'Pferde', age_class: 'Pferd Wh 1.60m', housing_type: 'Einzelbox', animals_per_m2: null, regulatory_minimum: '10.24 m2 = (2 x 1.60)^2, kuerzeste Seite mind. 2.40m' },
162
+ { species: 'Pferde', age_class: 'Pferd Wh 1.60m', housing_type: 'Gruppenhaltung', animals_per_m2: null, regulatory_minimum: '7.68 m2 Liegebereich/Pferd + Auslauf' },
163
+ { species: 'Pferde', age_class: 'Pony Wh 1.30m', housing_type: 'Einzelbox', animals_per_m2: null, regulatory_minimum: '6.76 m2 = (2 x 1.30)^2' },
164
+ ];
165
+
166
+ const stockingColumns = ['species', 'age_class', 'housing_type', 'animals_per_m2', 'regulatory_minimum', 'language', 'jurisdiction'];
167
+ batchInsert('stocking_densities', stockingColumns,
168
+ stockingDensities.map(s => [s.species, s.age_class, s.housing_type, s.animals_per_m2, s.regulatory_minimum, 'DE', 'CH'])
169
+ );
170
+
171
+ // ---------------------------------------------------------------------------
172
+ // 3. Housing Requirements — Detaillierte Stallbauanforderungen
173
+ // ---------------------------------------------------------------------------
174
+
175
+ interface HousingRequirement {
176
+ species: string;
177
+ age_class: string;
178
+ system: string;
179
+ space: string;
180
+ ventilation: string;
181
+ flooring: string;
182
+ temperature: string;
183
+ }
184
+
185
+ const housingRequirements: HousingRequirement[] = [
186
+ // Rinder
187
+ { species: 'Rinder', age_class: 'Milchkuh', system: 'Laufstall', space: '4.5 m2 Liegeflaeche, Fressplatzbreite 0.70m, Laufgang 2.5m', ventilation: 'Natuerliche Lueftung bevorzugt, max. 3 m/s Luftgeschwindigkeit im Tierbereich', flooring: 'Liegebereich: Gummimatte oder Stroh. Laufbereich: rutschfest, max. 50% perforiert. Spaltenweite max. 35mm (Kuehe)', temperature: 'Optimal 5-15°C, keine Minimalanforderung bei Aussenklimastaellen' },
188
+ { species: 'Rinder', age_class: 'Milchkuh', system: 'Anbindestall', space: 'Standlaenge 1.65m (Kurzstand) oder 1.95m (Mittellangstand), Breite 1.20m', ventilation: 'Wie Laufstall, plus Fensterflaeche 1/20 Bodenflaeche', flooring: 'Standflaeche trittfest, Liegebereich eingestreut oder Gummimatte, Hinterer Gitterrost max. 35mm Spalten', temperature: 'Wie Laufstall' },
189
+ { species: 'Rinder', age_class: 'Milchkuh', system: 'BTS', space: 'Laufstall obligatorisch. Fressplatzbreite mind. 0.70m. Liegebereich mit Einstreu oder Tiefstreu.', ventilation: 'Wie Laufstall', flooring: 'Liegebereich vollstaendig eingestreut (Stroh, Spaene). Kein Vollspaltenboden im Liegebereich.', temperature: 'Wie Laufstall' },
190
+ { species: 'Rinder', age_class: 'Kalb', system: 'Gruppenhaltung', space: '1.5 m2/Kalb (<200kg), Einzeliglu max. 2 Wochen nach Geburt', ventilation: 'Gut belueftet, Zugluft vermeiden', flooring: 'Eingestreuter Liegebereich, rutschfester Boden', temperature: 'Kaelbernest: Infrarotwaerme empfohlen bei <5°C' },
191
+
192
+ // Schweine
193
+ { species: 'Schweine', age_class: 'Mastschwein', system: 'Bucht', space: '0.9 m2/Tier >60kg, Liegebereich mind. 0.6 m2', ventilation: 'Zwangslueftung oder natuerliche Lueftung, NH3 <20ppm, CO2 <3000ppm', flooring: 'Max. 50% Spaltenanteil (Betonroste), Liegebereich planbefestigt und eingestreut', temperature: 'Optimal 16-22°C, Ferkel: 28-32°C (Ferkelnest)' },
194
+ { species: 'Schweine', age_class: 'Mastschwein', system: 'BTS', space: '1.1 m2/Tier >60kg (+20% gegenueber TSchV), Liegebereich mind. 0.7 m2', ventilation: 'Wie Standardbucht', flooring: 'Liegebereich vollstaendig eingestreut, planbefestigt. Aktivitaetsbereich kann Teilspalten haben.', temperature: 'Wie Standardbucht' },
195
+ { species: 'Schweine', age_class: 'Zuchtsau', system: 'Abferkelbucht', space: '5.5 m2 Abferkelbucht, Ferkelnest mind. 0.7 m2', ventilation: 'Getrennte Klimazonen: Sau 16-20°C, Ferkel 28-32°C', flooring: 'Planbefestigt, Liegebereich Sau eingestreut, Ferkelnest beheizt', temperature: 'Sau: 16-20°C, Ferkelnest: 28-32°C (Fussbodenheizung oder Infrarot)' },
196
+
197
+ // Gefluegel
198
+ { species: 'Gefluegel', age_class: 'Legehenne', system: 'Bodenhaltung', space: 'Max. 7 Hennen/m2, mind. 1/3 Scharrbereich mit Einstreu, Sitzstangen 14cm/Tier', ventilation: 'Gute Lueftung, NH3 <20ppm, relative Luftfeuchtigkeit 60-80%', flooring: 'Mind. 1/3 eingestreuter Scharrbereich, Rest Gitterrost/Spaltenboden ueber Kotgrube', temperature: 'Optimal 18-22°C, max. 30°C (Hitzestress ab 27°C)' },
199
+ { species: 'Gefluegel', age_class: 'Legehenne', system: 'BTS', space: 'Wie Bodenhaltung, plus Wintergarten (ueberdachter Aussenklimabereich) obligatorisch', ventilation: 'Wintergarten: offene Seite, wind- und regengeschuetzt', flooring: 'Scharrbereich mind. 1/3, Wintergarten: Naturboden oder eingestreut', temperature: 'Stall: 18-22°C, Wintergarten: Aussentemperatur' },
200
+ { species: 'Gefluegel', age_class: 'Mastpoulet', system: 'Bodenhaltung', space: 'Max. 30 kg/m2, Einstreu ganzflaechig', ventilation: 'Wie Legehennen, besonders wichtig: CO2 und NH3 Kontrolle', flooring: 'Ganzflaechig eingestreut (Holzspaene, Stroh), 5-10cm Einstreutiefe', temperature: 'Kueken: 33°C Tag 1, Absenkung 3°C/Woche bis 20°C' },
201
+
202
+ // Schafe
203
+ { species: 'Schafe', age_class: 'Mutterschaf', system: 'Stall', space: '1.5 m2/Tier mit Lamm, 1.0 m2 ohne Lamm', ventilation: 'Natuerliche Lueftung, Schafe vertragen Kaelte gut aber keine Zugluft', flooring: 'Stroh-Tiefstreu bevorzugt, trittfester Boden', temperature: 'Keine Minimalanforderung, Lammungsbereich: >5°C empfohlen' },
204
+
205
+ // Ziegen
206
+ { species: 'Ziegen', age_class: 'Milchziege', system: 'Stall', space: '1.5 m2/Tier, erhoehte Liegeflächen fuer mind. 50% der Herde', ventilation: 'Ziegen empfindlich auf Feuchtigkeit — gute Belueftung essenziell', flooring: 'Trocken, eingestreut, erhoehte Plattformen aus Holz', temperature: 'Ziegen vertragen Kaelte gut bei trockenen Bedingungen' },
207
+
208
+ // Pferde
209
+ { species: 'Pferde', age_class: 'Pferd Wh 1.60m', system: 'Einzelbox', space: '10.24 m2, kuerzeste Seite 2.40m, Deckenhoehe mind. 1.5 x Wh (2.40m)', ventilation: 'Natuerliche Lueftung, gute Luftqualitaet kritisch (Staub, Ammoniak)', flooring: 'Gummimatte + Einstreu (Stroh oder Spaene), min. 10cm Einstreutiefe', temperature: 'Keine Heizung noetig, Zugluftfreiheit wichtiger als Waerme' },
210
+ { species: 'Pferde', age_class: 'Pferd Wh 1.60m', system: 'Gruppenhaltung', space: '7.68 m2 Liegebereich/Pferd + Auslauf, Fressplaetze mind. 1 pro Tier', ventilation: 'Offenstall/Aktivstall: natuerliche Lueftung', flooring: 'Liegebereich: Tiefstreu oder Strohmatratze. Auslauf: befestigt, draeniert.', temperature: 'Offenstall: Witterungsschutz, Windschutz an Liegebereich' },
211
+ ];
212
+
213
+ const housingColumns = ['species', 'age_class', 'system', 'space', 'ventilation', 'flooring', 'temperature', 'language', 'jurisdiction'];
214
+ batchInsert('housing_requirements', housingColumns,
215
+ housingRequirements.map(h => [h.species, h.age_class, h.system, h.space, h.ventilation, h.flooring, h.temperature, 'DE', 'CH'])
216
+ );
217
+
218
+ // ---------------------------------------------------------------------------
219
+ // 4. Movement Rules — TVD, Transport, Soemmerung, Schlachtung
220
+ // ---------------------------------------------------------------------------
221
+
222
+ interface MovementRule {
223
+ species: string;
224
+ rule_type: string;
225
+ description: string;
226
+ }
227
+
228
+ const movementRules: MovementRule[] = [
229
+ // TVD — Rinder
230
+ { species: 'Rinder', rule_type: 'TVD', description: 'Alle Rinder muessen innerhalb von 3 Arbeitstagen nach Geburt in der TVD registriert werden. Zwei Ohrmarken (links + rechts) mit UELN-Nummer. Begleitdokument bei jedem Standortwechsel obligatorisch.' },
231
+ { species: 'Rinder', rule_type: 'TVD', description: 'Meldepflicht: Geburt, Zugang, Abgang, Tod, Schlachtung — jeweils innert 3 Arbeitstagen via agate.ch oder Meldestelle. Sanktionen bei verspaeteter Meldung (Beitragsabzuege).' },
232
+ { species: 'Rinder', rule_type: 'TVD', description: 'Tierpass (Rinderpass): Begleitet jedes Rind bei Standortwechsel. Enthaelt UELN, Rasse, Geschlecht, Geburtsdatum, Mutter-ID, Herkunftsland.' },
233
+
234
+ // TVD — Schweine
235
+ { species: 'Schweine', rule_type: 'TVD', description: 'Schweine: Betriebsregistrierung obligatorisch. Ohrmarken bei Abgang vom Geburtsbetrieb. Bestandeskontrolle: Zu- und Abgaenge innert 3 Arbeitstagen melden.' },
236
+ { species: 'Schweine', rule_type: 'TVD', description: 'Schweinepass nicht erforderlich, aber Begleitdokument bei Transport zum Schlachthof obligatorisch (Herkunft, Behandlungen, Absetzfristen).' },
237
+
238
+ // TVD — Schafe/Ziegen
239
+ { species: 'Schafe', rule_type: 'TVD', description: 'Schafe: Zwei Ohrmarken (eine elektronisch) obligatorisch. Registrierung innert 30 Tagen nach Geburt (90 Tage bei Soemmerung). Begleitdokument bei Standortwechsel.' },
240
+ { species: 'Ziegen', rule_type: 'TVD', description: 'Ziegen: Gleiche Regelung wie Schafe — zwei Ohrmarken, elektronische Kennzeichnung, Meldepflicht innert 30 Tagen.' },
241
+
242
+ // TVD — Pferde
243
+ { species: 'Pferde', rule_type: 'TVD', description: 'Equiden: Equidenpass (UELN) obligatorisch. Mikrochip-Implantation. Registrierung bei der Tierverkehrsdatenbank (Identitas AG). Pass begleitet Tier lebenslang.' },
244
+
245
+ // Transport
246
+ { species: 'Rinder', rule_type: 'Transport', description: 'Maximale Transportdauer: 8 Stunden. Schlachttiere: max. 6 Stunden. Transportbewilligung fuer gewerblichen Transport erforderlich. Sachkundenachweis fuer Fahrer obligatorisch. Transportfaehigkeit: nur gesunde, nicht verletzte Tiere.' },
247
+ { species: 'Schweine', rule_type: 'Transport', description: 'Maximale Transportdauer: 8 Stunden (Schlachttiere: 6h). Ladedichte: max. 235 kg/m2 fuer Mastschweine. Rampenneigung max. 20°. Dusche/Befeuchtung ab 25°C Aussentemperatur.' },
248
+ { species: 'Gefluegel', rule_type: 'Transport', description: 'Kuecken: max. 4 Stunden Transport (72h nach Schlupf). Mastgefluegel: max. 8 Stunden. Transportkisten: Mindesthoehe 23cm (Masthühner), natuerliche Belueftung.' },
249
+ { species: 'Schafe', rule_type: 'Transport', description: 'Maximale Transportdauer: 8 Stunden. Schafe und Ziegen gemeinsam transportierbar. Genügend Platz zum Stehen und Liegen.' },
250
+ { species: 'Pferde', rule_type: 'Transport', description: 'Maximale Transportdauer: 8 Stunden. Einzeltransport oder Gruppe (vertraegliche Tiere). Pferde muessen angebunden oder in Einzelboxen stehen koennen. Transportbewilligung + Sachkunde.' },
251
+
252
+ // Soemmerung/Alpung
253
+ { species: 'Rinder', rule_type: 'Soemmerung', description: 'Soemmerung/Alpung: Alpzeit 56-120 Tage (je nach Hoehenzone und Kanton). Normalbesatz: 0.5-2.5 GVE/ha (abhaengig von Standort und Vegetationsperiode). Soemmerungsbeitrag: 400 CHF/NST (Normalstoss). Meldung an TVD bei Alpaufzug und -abzug.' },
254
+ { species: 'Rinder', rule_type: 'Soemmerung', description: 'Alpkaese-Produktion: Verarbeitung auf der Alp erlaubt (vereinfachte Hygieneauflagen). GVE-Berechnung: 1 Milchkuh = 1 GVE, 1 Aufzuchtrind (1-2j) = 0.6 GVE, 1 Kalb (<1j) = 0.3 GVE.' },
255
+ { species: 'Schafe', rule_type: 'Soemmerung', description: 'Schafe auf Alpen: 1 GVE = ca. 7 Mutterschafe. Herdenschutz (Wolf): Nachtpferch, Schutzhunde, Behirtung. Bund und Kantone finanzieren Herdenschutzmassnahmen.' },
256
+ { species: 'Ziegen', rule_type: 'Soemmerung', description: 'Ziegen auf Alpen: Haeufig zusammen mit Schafen. Gleiche GVE-Umrechnung. Ziegenkaeserei auf Alpen traditionell (v.a. Tessin, Buenden).' },
257
+
258
+ // Schlachtung
259
+ { species: 'Rinder', rule_type: 'Schlachtung', description: 'Betaeubungspflicht obligatorisch (Bolzenschuss oder Elektrobetaeubung). Schaechten (Schlachtung ohne Betaeubung) seit 1893 in der Bundesverfassung verboten (BV Art. 80). Fleischkontrolle durch amtlichen Tierarzt.' },
260
+ { species: 'Schweine', rule_type: 'Schlachtung', description: 'Betaeubung: CO2-Betaeubung (Standard Grossschlachthof) oder Elektrobetaeubung. Schaechten verboten. Transportfaehigkeitskontrolle vor Schlachtung. Schlachtgebuehr und Entsorgungskosten.' },
261
+ { species: 'Gefluegel', rule_type: 'Schlachtung', description: 'Betaeubung: Elektrisches Wasserbad oder CO2. Baeuerliche Hofschlachtung: max. wenige Tiere/Woche fuer Direktvermarktung (kantonal geregelt). Betaeubungspflicht gilt auch auf dem Hof.' },
262
+ { species: 'Schafe', rule_type: 'Schlachtung', description: 'Betaeubung: Bolzenschuss oder Elektrobetaeubung. Hofschlachtung fuer Eigengebrauch erlaubt (Meldepflicht, Fleischkontrolle bei Direktvermarktung). Schaechten verboten.' },
263
+ ];
264
+
265
+ const movementColumns = ['species', 'rule_type', 'description', 'language', 'jurisdiction'];
266
+ batchInsert('movement_rules', movementColumns,
267
+ movementRules.map(m => [m.species, m.rule_type, m.description, 'DE', 'CH'])
268
+ );
269
+
270
+ // ---------------------------------------------------------------------------
271
+ // 5. Breeds — Schweizer Rassen
272
+ // ---------------------------------------------------------------------------
273
+
274
+ interface Breed {
275
+ species: string;
276
+ name: string;
277
+ purpose: string;
278
+ notes: string;
279
+ }
280
+
281
+ const breeds: Breed[] = [
282
+ // Rinder
283
+ { species: 'Rinder', name: 'Braunvieh (Brown Swiss)', purpose: 'Zweinutzung (Milch + Fleisch)', notes: 'Aelteste Rinderrasse der Welt. Ursprung Innerschweiz. Brown Swiss (US-Typ) = Milchbetont, Original Braunvieh = Zweinutzung. Braunvieh Schweiz (Zuchtorganisation). Ca. 15% des CH-Milchkuhbestands.' },
284
+ { species: 'Rinder', name: 'Original Braunvieh (OB)', purpose: 'Zweinutzung, Alptauglichkeit', notes: 'Traditionelle Schweizer Rasse, kleiner und robuster als Brown Swiss. Besonders geeignet fuer Berggebiet und Alpung. Schutzbedarf wegen kleinem Bestand. ProSpecieRara-Rasse.' },
285
+ { species: 'Rinder', name: 'Simmental / Fleckvieh', purpose: 'Zweinutzung (Milch + Fleisch)', notes: 'Ursprung Simmental (BE). Weltweit verbreitet. Schweizer Fleckvieh: Milchbetonter Typ. Swissherdbook (Zuchtorganisation). Groesste Rasse in CH nach Holstein.' },
286
+ { species: 'Rinder', name: 'Holstein', purpose: 'Milch', notes: 'Hoechste Milchleistung aller Rassen (8000-10000 kg/Laktation). Zunehmender Anteil in Talzone-Milchbetrieben. Swissherdbook. Ca. 30% des CH-Milchkuhbestands.' },
287
+ { species: 'Rinder', name: 'Eringer (Herens)', purpose: 'Fleisch, Tradition (Kuhkaempfe)', notes: 'Ursprung Wallis. Kleine, robuste Kampfrasse. "Combats de reines" (Kuhkaempfe) — kulturelle Tradition im Wallis. Fleischproduktion, Alpsoemmerung. Geschuetzte Rasse.' },
288
+ { species: 'Rinder', name: 'Grauvieh', purpose: 'Zweinutzung, Alptauglichkeit', notes: 'Ursprung Graubuenden. Kleine, genuegsame Rasse fuer extreme Berglagen. ProSpecieRara-Rasse. Bestand ca. 1500 Tiere. Kaeseproduktion (Alpkaese).' },
289
+ { species: 'Rinder', name: 'Hinterwaelder', purpose: 'Zweinutzung, extensiv', notes: 'Kleine Rasse, urspruenglich Schwarzwald, auch in CH Berggebiet. Sehr leichtfuttrig und gelaendegaengig. ProSpecieRara.' },
290
+ { species: 'Rinder', name: 'Evolener', purpose: 'Zweinutzung, Alptauglichkeit', notes: 'Seltene Walliser Rasse, verwandt mit Eringer. Sehr kleine Population. ProSpecieRara-Schutzprogramm.' },
291
+
292
+ // Schweine
293
+ { species: 'Schweine', name: 'Schweizer Edelschwein (Grosses Weisses)', purpose: 'Mutterrasse, Milchleistung', notes: 'Hauptrasse in CH-Schweinezucht. Suisseporcs (Zuchtorganisation). Mutterlinie in Kreuzungsprogrammen. Gute Wurfgroesse und Milchleistung.' },
294
+ { species: 'Schweine', name: 'Schweizer Landrasse', purpose: 'Mutterrasse', notes: 'Zweithaeufigte Rasse. Kreuzung mit Edelschwein = F1-Sauen fuer Mastferkelproduktion. Robust, gute Muttereigenschaften.' },
295
+ { species: 'Schweine', name: 'Duroc', purpose: 'Vaterrasse (Fleischqualitaet)', notes: 'Endstufeneber fuer Fleischqualitaet (intramuskulaeres Fett, Zartheit). Premo-Programm (Suisseporcs).' },
296
+ { species: 'Schweine', name: 'Pietrain', purpose: 'Vaterrasse (Fleischansatz)', notes: 'Endstufeneber fuer Fleischansatz und Magerkeit. Stresssensibilitaet beachten (MHS-Gen). In CH seltener als Duroc.' },
297
+
298
+ // Schafe
299
+ { species: 'Schafe', name: 'Weisses Alpenschaf', purpose: 'Milch, Fleisch, Wolle', notes: 'Haeufigste Schafrasse in der Schweiz. Robust, alptauglich. Swisssheep (Zuchtorganisation).' },
300
+ { species: 'Schafe', name: 'Schwarznasenschaf (Walliser)', purpose: 'Fleisch, Landschaftspflege, Wolle', notes: 'Ikonische Walliser Rasse mit schwarzer Nase und Spiralhoernern. UNESCO Immaterielles Kulturerbe (Kandidat). Touristenattraktion, robuste Bergrasse.' },
301
+ { species: 'Schafe', name: 'Engadinerschaf', purpose: 'Fleisch, Landschaftspflege', notes: 'Seltene Buendner Rasse. ProSpecieRara. Alptauglich, genuegsam.' },
302
+ { species: 'Schafe', name: 'Braunkoepfiges Fleischschaf', purpose: 'Fleisch (Mastlamm)', notes: 'Fruehreife Fleischschafrasse, besonders geeignet fuer Mast. Schweizer Zuchtlinie.' },
303
+ { species: 'Schafe', name: 'Spiegelschaf', purpose: 'Fleisch, Milch', notes: 'Schweizer Rasse, ProSpecieRara. Helle Flecken um die Augen (Spiegel). Bestand ca. 1200 Tiere.' },
304
+
305
+ // Ziegen
306
+ { species: 'Ziegen', name: 'Saaneziege (Saanenziege)', purpose: 'Milch', notes: 'Weltweit verbreitete Schweizer Milchziegenrasse. Ursprung Saanen (BE). Weiss, hornlos. Hoechste Milchleistung (800-1000 kg/Laktation). Schweizerischer Ziegenzuchtverband (SZZV).' },
307
+ { species: 'Ziegen', name: 'Toggenburger Ziege', purpose: 'Milch', notes: 'Ursprung Toggenburg (SG). Braun mit weissen Streifen im Gesicht. Robuste Milchziege, alptauglich.' },
308
+ { species: 'Ziegen', name: 'Appenzellerziege', purpose: 'Milch, Landschaftspflege', notes: 'Weisse Ziegenrasse aus dem Appenzellerland. Mittelgross, robust. ProSpecieRara.' },
309
+ { species: 'Ziegen', name: 'Buendner Strahlenziege', purpose: 'Milch, Fleisch', notes: 'Schwarze Ziege mit weissen Streifen (Strahlen) im Gesicht. Graubuenden. ProSpecieRara-Rasse. Traditionelle Alpziegenrasse.' },
310
+ { species: 'Ziegen', name: 'Walliser Schwarzhalsziege', purpose: 'Fleisch, Landschaftspflege', notes: 'Zweifarbig: vordere Haelfte schwarz, hintere weiss. Robuste Bergrasse. ProSpecieRara. Beliebtes Motiv, touristisch wertvoll.' },
311
+ { species: 'Ziegen', name: 'Stiefelgeiss', purpose: 'Milch, Fleisch', notes: 'Seltene Schweizer Rasse, weiss mit braunen "Stiefeln" an den Beinen. ProSpecieRara. Bestand ca. 800 Tiere.' },
312
+
313
+ // Pferde
314
+ { species: 'Pferde', name: 'Freiberger (Franches-Montagnes)', purpose: 'Arbeit, Freizeit, Militaer', notes: 'Einzige Schweizer Pferderasse. Ursprung Jura. Vielseitiger Kaltblut-/Warmbluttyp. Vom Bund gefoerdert (Schweizerisches Nationalgestuet Avenches). Bestand ca. 25000.' },
315
+ { species: 'Pferde', name: 'Warmblut CH', purpose: 'Sport (Springen, Dressur)', notes: 'Schweizer Warmblut (ZVCH). Sport- und Freizeitpferd. Zucht basiert auf internationalen Blutlinien + CH-Stutenstamm.' },
316
+ ];
317
+
318
+ const breedColumns = ['species', 'name', 'purpose', 'notes', 'language', 'jurisdiction'];
319
+ batchInsert('breeds', breedColumns,
320
+ breeds.map(b => [b.species, b.name, b.purpose, b.notes, 'DE', 'CH'])
321
+ );
322
+
323
+ // ---------------------------------------------------------------------------
324
+ // 6. Feed Requirements — Fuetterung pro Tierart und Produktionsstadium
325
+ // ---------------------------------------------------------------------------
326
+
327
+ interface FeedRequirement {
328
+ species: string;
329
+ age_class: string;
330
+ production_stage: string;
331
+ feed_type: string;
332
+ quantity_kg_day: number | null;
333
+ energy_mj: number | null;
334
+ protein_g: number | null;
335
+ notes: string;
336
+ }
337
+
338
+ const feedRequirements: FeedRequirement[] = [
339
+ // Rinder — Milchkuh
340
+ { species: 'Rinder', age_class: 'Milchkuh', production_stage: 'Laktation', feed_type: 'Grundfutter (Heu, Grassilage, Maissilage)', quantity_kg_day: null, energy_mj: 110, protein_g: 2800, notes: 'NEL-Bedarf: ca. 110 MJ NEL/Tag bei 25 kg Milch/Tag. Grundfutter bildet Basis (60-80% der Ration). Kraftfutter max. 40% Trockenmasse. GMF-Programm (DZV): mind. 75% Graslandprodukte in der Jahresration (Raufutter-Anteil).' },
341
+ { species: 'Rinder', age_class: 'Milchkuh', production_stage: 'Trockenstehend', feed_type: 'Heu, Duerrfutter', quantity_kg_day: null, energy_mj: 55, protein_g: 900, notes: 'Galtphase 6-8 Wochen. Energiereduziert fuettern. Mineralstoff-Ergaenzung (Ca, P, Mg). Uebergangsration 2 Wochen vor Abkalben.' },
342
+ { species: 'Rinder', age_class: 'Milchkuh', production_stage: 'GMF-Programm', feed_type: 'Graslandprodukte (mind. 75%)', quantity_kg_day: null, energy_mj: null, protein_g: null, notes: 'Graslandbasierte Milch- und Fleischproduktion (DZV): Mind. 75% der Ration aus Grasland (Heu, Gras, Grassilage). Max. 10% Kraftfutter (Getreide, Extraktionsschrote). Beitrag: 200 CHF/GVE. Foerdert Gruenland-Nutzung statt Ackerfutter-Import.' },
343
+
344
+ // Rinder — Aufzucht
345
+ { species: 'Rinder', age_class: 'Aufzuchtrind', production_stage: 'Aufzucht', feed_type: 'Heu, Grassilage, Mineralstoffe', quantity_kg_day: null, energy_mj: 45, protein_g: 500, notes: 'Tagesration: ca. 6-8 kg Trockenmasse Raufutter, ergaenzt mit Mineralstoffen. Erstkalbealter Ziel: 24-26 Monate. Gute Aufzucht = hohe Lebensleistung.' },
346
+ { species: 'Rinder', age_class: 'Kalb', production_stage: 'Aufzucht', feed_type: 'Milch/Milchaustauscher, Heu, Starterfutter', quantity_kg_day: null, energy_mj: 25, protein_g: 400, notes: 'Kolostrum (Biestmilch) in ersten 6h obligatorisch. Ab Woche 1 Heu und Wasser anbieten. Abtraenken ab 8-12 Wochen.' },
347
+
348
+ // Schweine
349
+ { species: 'Schweine', age_class: 'Mastschwein', production_stage: 'Mast', feed_type: 'Vormast-/Endmastfutter, Nebenprodukte', quantity_kg_day: 2.5, energy_mj: 33, protein_g: 380, notes: 'Phasenfuetterung: Vormast (25-60kg) proteinreicher, Endmast (60-110kg) energiereich, weniger Protein. Futterverwertung: ca. 2.8 kg Futter/kg Zuwachs. Schweizer Futtermittelbranche: viel Nebenprodukte (Molke, Schotte, Getreidenebenprodukte).' },
350
+ { species: 'Schweine', age_class: 'Zuchtsau', production_stage: 'Laktation', feed_type: 'Saeugefutter, ad libitum', quantity_kg_day: 6.0, energy_mj: 75, protein_g: 950, notes: 'Saeugende Sau: hoher Energiebedarf (10-14 Ferkel). Ad libitum fuettern ab Tag 3 nach Abferkeln. Wasserversorgung: mind. 20 Liter/Tag.' },
351
+ { species: 'Schweine', age_class: 'Absetzferkel', production_stage: 'Aufzucht', feed_type: 'Ferkelstarter, Prestarter', quantity_kg_day: 0.8, energy_mj: 14, protein_g: 180, notes: 'Absetzen mit 28-35 Tagen. Futterwechsel langsam (Verdauungsprobleme). Warm (28°C), trocken, zugfrei. N-reduzierte Fuetterung: Ressourceneffizienzbeitrag (DZV) fuer reduzierte N-Ausscheidung.' },
352
+
353
+ // Gefluegel
354
+ { species: 'Gefluegel', age_class: 'Legehenne', production_stage: 'Legeperiode', feed_type: 'Legemehl/Legekorn', quantity_kg_day: 0.12, energy_mj: 1.5, protein_g: 20, notes: 'Ca. 120 g Futter/Tag. Ca-Bedarf: 3.5-4.0 g/Tag (Eierschalenbildung). Muschelkalk als Calciumquelle. Legeleistung: 280-320 Eier/Jahr (Legehybride).' },
355
+ { species: 'Gefluegel', age_class: 'Mastpoulet', production_stage: 'Mast', feed_type: 'Starterfutter, Mastfutter, Endmastfutter', quantity_kg_day: null, energy_mj: null, protein_g: null, notes: 'Phasenfuetterung: Starter (Woche 1-2, 23% RP), Mast (Woche 3-5, 21% RP), Endmast (ab Woche 5, 19% RP). Schlachtalter konventionell: 35-42 Tage. Freiland/Bio: 56-81 Tage.' },
356
+
357
+ // Schafe
358
+ { species: 'Schafe', age_class: 'Mutterschaf', production_stage: 'Laktation', feed_type: 'Heu, Grassilage, Kraftfutter', quantity_kg_day: null, energy_mj: 18, protein_g: 220, notes: 'Saeugephase 6-8 Wochen. Energiebedarf steigt mit Lammanzahl. Gutes Heu + moderate Kraftfuttergabe. Mineralstoffe (Se, Co, Cu beachten).' },
359
+ { species: 'Schafe', age_class: 'Mastlamm', production_stage: 'Mast', feed_type: 'Weide, Heu, Kraftfutter', quantity_kg_day: null, energy_mj: 10, protein_g: 130, notes: 'Schlachtgewicht 38-42 kg lebend. Intensive Weidemast oder Stallmast. Tageszunahme Ziel: 250-350 g/Tag.' },
360
+
361
+ // Pferde
362
+ { species: 'Pferde', age_class: 'Pferd 500kg', production_stage: 'Erhaltung', feed_type: 'Heu, Stroh, Mineralstoffe', quantity_kg_day: 8.0, energy_mj: 70, protein_g: 500, notes: 'Raufutter bildet Basis (mind. 1.5 kg Heu/100 kg Koerpergewicht). Pferde: empfindliches Verdauungssystem, kleine Portionen, regelmaessig fuettern. Kein Silage fuer Pferde (Botulismus-Risiko).' },
363
+ { species: 'Pferde', age_class: 'Pferd 500kg', production_stage: 'Arbeit (mittel)', feed_type: 'Heu, Hafer, Mischfutter', quantity_kg_day: 10.0, energy_mj: 95, protein_g: 700, notes: 'Sportpferd/Arbeitspferd: erhoehter Energiebedarf. Hafer traditionelles Kraftfutter. Elektrolyte bei Schweissarbeit. Wasser ad libitum.' },
364
+ ];
365
+
366
+ const feedColumns = ['species', 'age_class', 'production_stage', 'feed_type', 'quantity_kg_day', 'energy_mj', 'protein_g', 'notes', 'language', 'jurisdiction'];
367
+ batchInsert('feed_requirements', feedColumns,
368
+ feedRequirements.map(f => [f.species, f.age_class, f.production_stage, f.feed_type, f.quantity_kg_day, f.energy_mj, f.protein_g, f.notes, 'DE', 'CH'])
369
+ );
370
+
371
+ // ---------------------------------------------------------------------------
372
+ // 7. Animal Health — Tiergesundheit, Tierseuchen, Praevention
373
+ // ---------------------------------------------------------------------------
374
+
375
+ interface AnimalHealth {
376
+ species: string;
377
+ condition: string;
378
+ symptoms: string;
379
+ prevention: string;
380
+ regulatory_status: string;
381
+ details: string;
382
+ }
383
+
384
+ const animalHealthData: AnimalHealth[] = [
385
+ // Rinder
386
+ { species: 'Rinder', condition: 'BVD (Bovine Virusdiarrhoe)', symptoms: 'Durchfall, Fieber, Aborte, Missbildungen bei Kaelbern (persistent infiziert, PI-Tiere)', prevention: 'Nationales BVD-Ausrottungsprogramm seit 2008. Ohrgewebeprobe bei Geburt (BVD-Antigentest). PI-Tiere muessen eliminiert werden.', regulatory_status: 'Zu bekaempfende Tierseuche (TSV), Meldepflicht', details: 'Schweiz praktisch BVD-frei seit ~2017. Letzte PI-Tiere werden nachverfolgt. Impfung verboten (stoert Surveillance).' },
387
+ { species: 'Rinder', condition: 'IBR (Infektioese Bovine Rhinotracheitis)', symptoms: 'Nasenausfluss, Fieber, Atemwegssymptome, Aborte', prevention: 'Schweiz gilt als IBR-frei. Import nur aus IBR-freien Bestaenden/Laendern. Ueberwachung durch Tankmilchproben.', regulatory_status: 'Zu bekaempfende Tierseuche (TSV), Meldepflicht', details: 'IBR-Freiheit seit 1993. Wichtiger Handelsvorteil fuer CH-Zuchtviehexport.' },
388
+ { species: 'Rinder', condition: 'Mastitis (Euterentzuendung)', symptoms: 'Geschwollenes Euter, Flocken/Klumpen in Milch, Fieber, Schmerzen', prevention: 'Melkhygiene, Zitzendesinfektion, regelmaessige Milchprobe (Zellzahlkontrolle), Trockenstellen mit Antibiotika oder Zitzenversiegler', regulatory_status: 'Keine Meldepflicht, aber wirtschaftlich bedeutendste Rinderkrankheit', details: 'Erreger: Staphylococcus aureus, Streptococcus uberis/agalactiae, E. coli. Zellzahl-Limite CH: 350000 Zellen/ml Tankmilch.' },
389
+ { species: 'Rinder', condition: 'Moderhinke (Klauenfaeule)', symptoms: 'Lahmheit, fauler Geruch, Klauenhorn-Abloesung, weisse Belaege', prevention: 'Klauenbad, Klauenpflege alle 6 Monate, trockene Laufflaechen, Sanierungsprogramm bei Bestandesproblem', regulatory_status: 'Zu ueberwachende Tierseuche (bei Schafen strikter)', details: 'Erreger: Dichelobacter nodosus. Problem besonders in feuchten Bedingungen. Auch bei Schafen und Ziegen.' },
390
+
391
+ // Schweine
392
+ { species: 'Schweine', condition: 'PRRS (Porzines Reproduktives und Respiratorisches Syndrom)', symptoms: 'Atemwegsprobleme, Aborte, Totgeburten, verminderte Fruchtbarkeit', prevention: 'Schweiz ist PRRS-frei. Strikte Importkontrollen. Quarantaene bei Import.', regulatory_status: 'Zu bekaempfende Tierseuche, Meldepflicht', details: 'PRRS-Freiheit ist wichtiger Statusvorteil der Schweizer Schweinezucht.' },
393
+ { species: 'Schweine', condition: 'Afrikanische Schweinepest (ASP)', symptoms: 'Hohes Fieber, Hautblutungen, Aborte, schneller Tod', prevention: 'Praevention: kein Futter aus Kuechen/Restaurants an Schweine verfuettern, Wildschwein-Monitoring, Biosicherheit auf Betrieb', regulatory_status: 'Hochansteckende Seuche, sofortige Meldepflicht, Tilgung', details: 'ASP noch nicht in der Schweiz (Stand 2026). Notfallplaene vorhanden. Wildschweinguertel in Grenznaehe zu EU-Ausbruchsgebieten.' },
394
+ { species: 'Schweine', condition: 'Salmonellose', symptoms: 'Durchfall, Fieber, bei Sauen: Aborte, Ferkelsterblichkeit', prevention: 'Hygiene, Reinigungs-/Desinfektionsprogramm, Rein-Raus-Verfahren, Futtermittelhygiene', regulatory_status: 'Meldepflicht (Salmonella Enteritidis und Typhimurium)', details: 'Nationales Salmonellen-Bekaempfungsprogramm bei Zuchtbetrieben. IS ABV-Meldung bei Antibiotikabehandlung.' },
395
+
396
+ // Gefluegel
397
+ { species: 'Gefluegel', condition: 'Aviäre Influenza (Vogelgrippe)', symptoms: 'Hohes Fieber, Atemwegssymptome, starker Legeabfall, hohe Mortalitaet (hochpathogen)', prevention: 'Aufstallungspflicht bei erhoehtem Risiko (Herbst/Winter, Vogelzug). Biosicherheit: Handewaschen, Schuhwechsel, kein Kontakt mit Wildvoegeln.', regulatory_status: 'Hochansteckende Tierseuche, sofortige Meldepflicht, Sperrzone', details: 'BLV verordnet periodisch Aufstallungspflicht waehrend Vogelzugsaison. Impfung in CH nicht erlaubt (EU-Handelsvorgaben).' },
398
+ { species: 'Gefluegel', condition: 'Salmonellose Gefluegel', symptoms: 'Oft subklinisch bei adulten Tieren, Kueckensterben, verunreinigte Eier', prevention: 'Nationales Salmonellen-Bekaempfungsprogramm: Pflichtuntersuchung aller Legehennenbetriebe >1000 Plaetze. Impfung moeglich.', regulatory_status: 'Meldepflicht (S. Enteritidis, S. Typhimurium), Bestandessanierung', details: 'Schweiz hat tiefe Salmonellen-Praevalenz dank konsequenter Bekaempfung. Eier: Stempelung mit Betriebsnummer obligatorisch.' },
399
+ { species: 'Gefluegel', condition: 'Kokzidiose', symptoms: 'Blutiger Durchfall, Abmagerung, verminderte Leistung', prevention: 'Impfung (Lebendvakzine bei Legehennen), Hygiene, Einstreumanagement', regulatory_status: 'Keine Meldepflicht', details: 'Haeufigste parasitaere Erkrankung beim Gefluegel. Erreger: Eimeria spp. Antiparasitika (Kokzidiostatika) in CH reguliert.' },
400
+
401
+ // Schafe
402
+ { species: 'Schafe', condition: 'Moderhinke (Klauenfaeule Schafe)', symptoms: 'Starke Lahmheit, fauler Geruch, Klauenhorn-Abloesung', prevention: 'Klauenbad, Separierung lahmer Tiere, Bestandessanierung (Impfung Footvax), trockene Weide', regulatory_status: 'Zu bekaempfende Tierseuche bei Schafen (TSV Art. 227a, seit 2024)', details: 'Moderhinke bei Schafen seit 2024 meldepflichtig und bekaempfungspflichtig in der Schweiz. Kantonale Bekaempfungsprogramme.' },
403
+ { species: 'Schafe', condition: 'Parasitenbefall (Magen-Darm-Wuermer)', symptoms: 'Abmagerung, Durchfall, Blutarmut, Flaschenhals (Haemonchus)', prevention: 'Weidemanagement (Rotation), gezielte Entwurmung (selektiv, nicht Giesskanne), Weidewechsel nach Behandlung', regulatory_status: 'Keine Meldepflicht', details: 'Magen-Darm-Nematoden: haeufigste Gesundheitsproblem bei Weideschafen. Resistenzen gegen Entwurmungsmittel zunehmend — selektive Behandlung (FEC-Methode).' },
404
+
405
+ // Allgemein
406
+ { species: 'Rinder', condition: 'Tuberkulose (Bovine TB)', symptoms: 'Chronischer Husten, Abmagerung, geschwollene Lymphknoten', prevention: 'Schweiz gilt als TB-frei seit 1959. Ueberwachung durch Schlachthofkontrolle (Fleischbeschau). Import nur aus TB-freien Laendern.', regulatory_status: 'Auszurottende Tierseuche, sofortige Meldepflicht', details: 'Sporadische Einzelfaelle durch Import oder Wildtierkontakt. Sofortige Bestandessperre und Untersuchung bei Verdacht.' },
407
+ ];
408
+
409
+ const healthColumns = ['species', 'condition', 'symptoms', 'prevention', 'regulatory_status', 'details', 'language', 'jurisdiction'];
410
+ batchInsert('animal_health', healthColumns,
411
+ animalHealthData.map(h => [h.species, h.condition, h.symptoms, h.prevention, h.regulatory_status, h.details, 'DE', 'CH'])
412
+ );
413
+
414
+ // ---------------------------------------------------------------------------
415
+ // 8. FTS5 Search Index — All data indexed for full-text search
416
+ // ---------------------------------------------------------------------------
417
+
418
+ console.log('Building FTS5 search index...');
419
+
420
+ // Index welfare standards
421
+ const welfareRows = db.all<{ species: string; production_system: string; requirement: string; details: string }>(
422
+ 'SELECT species, production_system, requirement, details FROM welfare_standards'
423
+ );
424
+ for (const row of welfareRows) {
425
+ db.run(
426
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
427
+ [row.requirement, `${row.production_system}: ${row.details}`, row.species, 'Tierschutz/Welfare', 'CH']
428
+ );
429
+ }
430
+
431
+ // Index stocking densities
432
+ const stockingRows = db.all<{ species: string; age_class: string; housing_type: string; regulatory_minimum: string }>(
433
+ 'SELECT species, age_class, housing_type, regulatory_minimum FROM stocking_densities'
434
+ );
435
+ for (const row of stockingRows) {
436
+ db.run(
437
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
438
+ [`Besatzdichte ${row.age_class} ${row.housing_type}`, row.regulatory_minimum, row.species, 'Platzbedarf/Besatzdichte', 'CH']
439
+ );
440
+ }
441
+
442
+ // Index housing requirements
443
+ const housingRows = db.all<{ species: string; age_class: string; system: string; space: string; ventilation: string; flooring: string; temperature: string }>(
444
+ 'SELECT species, age_class, system, space, ventilation, flooring, temperature FROM housing_requirements'
445
+ );
446
+ for (const row of housingRows) {
447
+ db.run(
448
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
449
+ [
450
+ `Stallbau ${row.age_class} ${row.system}`,
451
+ `Platz: ${row.space}. Lueftung: ${row.ventilation}. Boden: ${row.flooring}. Temperatur: ${row.temperature}`,
452
+ row.species,
453
+ 'Stallbau/Housing',
454
+ 'CH',
455
+ ]
456
+ );
457
+ }
458
+
459
+ // Index movement rules
460
+ const movementRows = db.all<{ species: string; rule_type: string; description: string }>(
461
+ 'SELECT species, rule_type, description FROM movement_rules'
462
+ );
463
+ for (const row of movementRows) {
464
+ db.run(
465
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
466
+ [`${row.rule_type} ${row.species}`, row.description, row.species, 'TVD/Transport/Soemmerung', 'CH']
467
+ );
468
+ }
469
+
470
+ // Index breeds
471
+ const breedRows = db.all<{ species: string; name: string; purpose: string; notes: string }>(
472
+ 'SELECT species, name, purpose, notes FROM breeds'
473
+ );
474
+ for (const row of breedRows) {
475
+ db.run(
476
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
477
+ [row.name, `${row.purpose}. ${row.notes}`, row.species, 'Zucht/Rassen', 'CH']
478
+ );
479
+ }
480
+
481
+ // Index feed requirements
482
+ const feedRows = db.all<{ species: string; age_class: string; production_stage: string; feed_type: string; notes: string }>(
483
+ 'SELECT species, age_class, production_stage, feed_type, notes FROM feed_requirements'
484
+ );
485
+ for (const row of feedRows) {
486
+ db.run(
487
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
488
+ [`Fuetterung ${row.age_class} ${row.production_stage}`, `${row.feed_type}. ${row.notes}`, row.species, 'Fuetterung/Ernaehrung', 'CH']
489
+ );
490
+ }
491
+
492
+ // Index animal health
493
+ const healthRows = db.all<{ species: string; condition: string; symptoms: string; prevention: string; details: string }>(
494
+ 'SELECT species, condition, symptoms, prevention, details FROM animal_health'
495
+ );
496
+ for (const row of healthRows) {
497
+ db.run(
498
+ 'INSERT INTO search_index (title, body, species, category, jurisdiction) VALUES (?, ?, ?, ?, ?)',
499
+ [row.condition, `Symptome: ${row.symptoms}. Praevention: ${row.prevention}. ${row.details}`, row.species, 'Tiergesundheit', 'CH']
500
+ );
501
+ }
502
+
503
+ // ---------------------------------------------------------------------------
504
+ // 9. Metadata + Coverage
505
+ // ---------------------------------------------------------------------------
506
+
507
+ db.run("INSERT OR REPLACE INTO db_metadata (key, value) VALUES ('last_ingest', ?)", [now]);
508
+ db.run("INSERT OR REPLACE INTO db_metadata (key, value) VALUES ('build_date', ?)", [now]);
509
+ db.run("INSERT OR REPLACE INTO db_metadata (key, value) VALUES ('schema_version', '1.0')", []);
510
+
511
+ // Count records
512
+ const counts = {
513
+ welfare_standards: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM welfare_standards') as { c: number }).c,
514
+ stocking_densities: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM stocking_densities') as { c: number }).c,
515
+ housing_requirements: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM housing_requirements') as { c: number }).c,
516
+ movement_rules: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM movement_rules') as { c: number }).c,
517
+ breeds: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM breeds') as { c: number }).c,
518
+ feed_requirements: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM feed_requirements') as { c: number }).c,
519
+ animal_health: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM animal_health') as { c: number }).c,
520
+ search_index: (db.get<{ c: number }>('SELECT COUNT(*) as c FROM search_index') as { c: number }).c,
521
+ };
522
+
523
+ console.log('Ingestion complete:');
524
+ console.log(` welfare_standards: ${counts.welfare_standards}`);
525
+ console.log(` stocking_densities: ${counts.stocking_densities}`);
526
+ console.log(` housing_requirements: ${counts.housing_requirements}`);
527
+ console.log(` movement_rules: ${counts.movement_rules}`);
528
+ console.log(` breeds: ${counts.breeds}`);
529
+ console.log(` feed_requirements: ${counts.feed_requirements}`);
530
+ console.log(` animal_health: ${counts.animal_health}`);
531
+ console.log(` search_index: ${counts.search_index}`);
532
+
533
+ // Write coverage.json
534
+ const coverage = {
535
+ server: 'ch-livestock-mcp',
536
+ jurisdiction: 'CH',
537
+ version: '0.1.0',
538
+ last_ingest: now,
539
+ data: counts,
540
+ tools: 11,
541
+ sources: [
542
+ 'TSchV — Tierschutzverordnung (BLV)',
543
+ 'DZV — RAUS/BTS-Programme (BLW)',
544
+ 'TVD — Tierverkehrsdatenbank (Identitas)',
545
+ 'Zuchtorganisationen (Braunvieh Schweiz, swissherdbook, Suisseporcs)',
546
+ ],
547
+ };
548
+
549
+ writeFileSync('data/coverage.json', JSON.stringify(coverage, null, 2) + '\n');
550
+ console.log('Written data/coverage.json');
551
+
552
+ db.close();
553
+ console.log('Done.');
package/server.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "io.github.Ansvar-Systems/ch-livestock",
3
+ "description": "Swiss livestock regulations via MCP -- TSchV welfare standards, RAUS/BTS programmes, TVD movement rules, housing requirements, breed data",
4
+ "homepage": "https://github.com/Ansvar-Systems/ch-livestock-mcp",
5
+ "is_official": true,
6
+ "remote": {
7
+ "transportType": "streamableHttp",
8
+ "url": "https://mcp.ansvar.eu/ch-livestock/mcp"
9
+ }
10
+ }