@ansvar/ch-environmental-compliance-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.
- package/.github/workflows/check-freshness.yml +49 -0
- package/.github/workflows/ci.yml +21 -0
- package/.github/workflows/codeql.yml +25 -0
- package/.github/workflows/ghcr-build.yml +45 -0
- package/.github/workflows/gitleaks.yml +18 -0
- package/.github/workflows/ingest.yml +59 -0
- package/.github/workflows/publish.yml +24 -0
- package/CHANGELOG.md +15 -0
- package/CODEOWNERS +1 -0
- package/COVERAGE.md +50 -0
- package/DISCLAIMER.md +48 -0
- package/Dockerfile +26 -0
- package/LICENSE +17 -0
- package/PRIVACY.md +23 -0
- package/README.md +116 -0
- package/SECURITY.md +25 -0
- package/TOOLS.md +142 -0
- package/data/coverage.json +24 -0
- package/data/database.db +0 -0
- package/data/sources.yml +36 -0
- package/dist/db.d.ts +25 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +197 -0
- package/dist/db.js.map +1 -0
- package/dist/http-server.d.ts +2 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +274 -0
- package/dist/http-server.js.map +1 -0
- package/dist/jurisdiction.d.ts +18 -0
- package/dist/jurisdiction.d.ts.map +1 -0
- package/dist/jurisdiction.js +16 -0
- package/dist/jurisdiction.js.map +1 -0
- package/dist/metadata.d.ts +10 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +22 -0
- package/dist/metadata.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +220 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/about.d.ts +15 -0
- package/dist/tools/about.d.ts.map +1 -0
- package/dist/tools/about.js +27 -0
- package/dist/tools/about.js.map +1 -0
- package/dist/tools/check-environmental-compliance.d.ts +30 -0
- package/dist/tools/check-environmental-compliance.d.ts.map +1 -0
- package/dist/tools/check-environmental-compliance.js +103 -0
- package/dist/tools/check-environmental-compliance.js.map +1 -0
- package/dist/tools/check-freshness.d.ts +15 -0
- package/dist/tools/check-freshness.d.ts.map +1 -0
- package/dist/tools/check-freshness.js +26 -0
- package/dist/tools/check-freshness.js.map +1 -0
- package/dist/tools/get-ammonia-rules.d.ts +24 -0
- package/dist/tools/get-ammonia-rules.d.ts.map +1 -0
- package/dist/tools/get-ammonia-rules.js +31 -0
- package/dist/tools/get-ammonia-rules.js.map +1 -0
- package/dist/tools/get-bff-requirements.d.ts +26 -0
- package/dist/tools/get-bff-requirements.d.ts.map +1 -0
- package/dist/tools/get-bff-requirements.js +36 -0
- package/dist/tools/get-bff-requirements.js.map +1 -0
- package/dist/tools/get-buffer-zone-rules.d.ts +23 -0
- package/dist/tools/get-buffer-zone-rules.d.ts.map +1 -0
- package/dist/tools/get-buffer-zone-rules.js +30 -0
- package/dist/tools/get-buffer-zone-rules.js.map +1 -0
- package/dist/tools/get-eip-requirements.d.ts +31 -0
- package/dist/tools/get-eip-requirements.d.ts.map +1 -0
- package/dist/tools/get-eip-requirements.js +40 -0
- package/dist/tools/get-eip-requirements.js.map +1 -0
- package/dist/tools/get-nutrient-loss-limits.d.ts +24 -0
- package/dist/tools/get-nutrient-loss-limits.d.ts.map +1 -0
- package/dist/tools/get-nutrient-loss-limits.js +31 -0
- package/dist/tools/get-nutrient-loss-limits.js.map +1 -0
- package/dist/tools/get-water-protection-zones.d.ts +32 -0
- package/dist/tools/get-water-protection-zones.d.ts.map +1 -0
- package/dist/tools/get-water-protection-zones.js +36 -0
- package/dist/tools/get-water-protection-zones.js.map +1 -0
- package/dist/tools/list-sources.d.ts +18 -0
- package/dist/tools/list-sources.d.ts.map +1 -0
- package/dist/tools/list-sources.js +61 -0
- package/dist/tools/list-sources.js.map +1 -0
- package/dist/tools/search-environmental-rules.d.ts +25 -0
- package/dist/tools/search-environmental-rules.d.ts.map +1 -0
- package/dist/tools/search-environmental-rules.js +26 -0
- package/dist/tools/search-environmental-rules.js.map +1 -0
- package/docker-compose.yml +12 -0
- package/eslint.config.js +26 -0
- package/package.json +54 -0
- package/scripts/ingest.ts +911 -0
- package/server.json +16 -0
- package/src/db.ts +238 -0
- package/src/http-server.ts +307 -0
- package/src/jurisdiction.ts +30 -0
- package/src/metadata.ts +32 -0
- package/src/server.ts +244 -0
- package/src/tools/about.ts +28 -0
- package/src/tools/check-environmental-compliance.ts +143 -0
- package/src/tools/check-freshness.ts +42 -0
- package/src/tools/get-ammonia-rules.ts +44 -0
- package/src/tools/get-bff-requirements.ts +52 -0
- package/src/tools/get-buffer-zone-rules.ts +43 -0
- package/src/tools/get-eip-requirements.ts +57 -0
- package/src/tools/get-nutrient-loss-limits.ts +44 -0
- package/src/tools/get-water-protection-zones.ts +50 -0
- package/src/tools/list-sources.ts +75 -0
- package/src/tools/search-environmental-rules.ts +35 -0
- package/tests/db.test.ts +80 -0
- package/tests/helpers/seed-db.ts +173 -0
- package/tests/jurisdiction.test.ts +35 -0
- package/tests/tools/about.test.ts +26 -0
- package/tests/tools/check-freshness.test.ts +50 -0
- package/tests/tools/list-sources.test.ts +61 -0
- package/tests/tools/search-environmental-rules.test.ts +47 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,911 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switzerland Environmental Compliance MCP — Data Ingestion Script
|
|
3
|
+
*
|
|
4
|
+
* Populates the database with Swiss environmental compliance data from:
|
|
5
|
+
* - BAFU — Gewaesserschutzgesetz (GSchG), Gewaesserschutzverordnung (GSchV)
|
|
6
|
+
* - BAFU — Luftreinhalte-Verordnung (LRV), Ammoniakemissionen
|
|
7
|
+
* - BLW — Direktzahlungsverordnung (DZV), OELN, BFF-Typen
|
|
8
|
+
* - Agroscope — Agrammon-Emissionsfaktoren
|
|
9
|
+
* - Parlament — Pa.Iv. 19.475 Absenkpfad Naehrstoffverluste
|
|
10
|
+
* - BAFU — VBBo (Verordnung ueber Belastungen des Bodens)
|
|
11
|
+
*
|
|
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
|
+
// 1. Grundwasserschutzzonen — GSchG Art. 20, GSchV Anhang 4
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
interface WaterProtectionZone {
|
|
28
|
+
zone_type: string;
|
|
29
|
+
name: string;
|
|
30
|
+
restrictions: string;
|
|
31
|
+
description: string;
|
|
32
|
+
legal_basis: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const waterProtectionZones: WaterProtectionZone[] = [
|
|
36
|
+
{
|
|
37
|
+
zone_type: 'S1',
|
|
38
|
+
name: 'Fassungsbereich',
|
|
39
|
+
restrictions: 'Kein Zugang fuer Unbefugte. Keine Bauten, keine Anlagen, keine Bewirtschaftung. Kein Duenger, kein Pflanzenschutzmittel. Nur Grundwasserentnahme gestattet.',
|
|
40
|
+
description: 'Unmittelbarer Bereich um die Grundwasserfassung (Brunnen, Quelle). Strengste Schutzzone. Typisch 10-15m Radius um die Fassung.',
|
|
41
|
+
legal_basis: 'GSchG Art. 20, GSchV Anhang 4 Ziff. 12',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
zone_type: 'S2',
|
|
45
|
+
name: 'Engere Schutzzone',
|
|
46
|
+
restrictions: 'Kein Duenger (weder Hofdunger noch Mineraldunger). Keine Pflanzenschutzmittel. Keine Grabungen unter die Humusschicht. Keine Lagerung wassergefaehrdender Stoffe. Keine Tierhaltungsanlagen. Nur extensive Bewirtschaftung (Wiese).',
|
|
47
|
+
description: 'Engere Umgebung der Fassung. Soll verhindern, dass Keime und abbaubare Verunreinigungen die Fassung erreichen. Typisch 100-200m, Mindestaufenthaltszeit Grundwasser 10 Tage.',
|
|
48
|
+
legal_basis: 'GSchG Art. 20, GSchV Anhang 4 Ziff. 222',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
zone_type: 'S3',
|
|
52
|
+
name: 'Weitere Schutzzone',
|
|
53
|
+
restrictions: 'Eingeschraenkte Duengung und PSM-Anwendung gemaess kantonalen Auflagen. Keine neuen Tierhaltungsanlagen ohne Bewilligung. Keine Deponien. Keine Versickerungsanlagen fuer verschmutztes Abwasser. Baubewilligungen mit Auflagen.',
|
|
54
|
+
description: 'Aeusserer Schutzbereich. Soll verhindern, dass nicht abbaubare Verunreinigungen (z.B. Kohlenwasserstoffe) die Fassung erreichen. Umfasst typisch das gesamte Einzugsgebiet.',
|
|
55
|
+
legal_basis: 'GSchG Art. 20, GSchV Anhang 4 Ziff. 232',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
zone_type: 'Sm',
|
|
59
|
+
name: 'Quellenbereich (Quellschutzzone)',
|
|
60
|
+
restrictions: 'Analog S1/S2 je nach kantonaler Festlegung. Keine Eingriffe in den Untergrund. Keine Entwaldung. Drainagen verboten.',
|
|
61
|
+
description: 'Schutzzone um Quellfassungen. Quellenspezifische Abgrenzung nach hydrogeologischem Gutachten. Besonders relevant im Berggebiet und Jura.',
|
|
62
|
+
legal_basis: 'GSchG Art. 20, GSchV Anhang 4 Ziff. 123',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
zone_type: 'Zu',
|
|
66
|
+
name: 'Zustroembereich',
|
|
67
|
+
restrictions: 'In bestimmten Zustraembereichen (Art. 62a GSchG): Pestizidverbote oder -einschraenkungen, Nitratreduktionsprogramme mit Beitraegen, verschaerfte Duengungsauflagen. Kantonale Festlegung.',
|
|
68
|
+
description: 'Gesamtes Einzugsgebiet einer Grundwasserfassung ausserhalb der Schutzzonen. Massnahmen bei erhoehten Nitrat- oder PSM-Konzentrationen. Art. 62a GSchG ermoeglicht Abgeltungen fuer Bewirtschaftungseinschraenkungen.',
|
|
69
|
+
legal_basis: 'GSchG Art. 29 / Art. 62a, GSchV Art. 29',
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const insertWaterZone = db.instance.prepare(
|
|
74
|
+
`INSERT OR REPLACE INTO water_protection_zones (zone_type, name, restrictions, description, legal_basis, jurisdiction, language)
|
|
75
|
+
VALUES (?, ?, ?, ?, ?, 'CH', 'DE')`
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
for (const z of waterProtectionZones) {
|
|
79
|
+
insertWaterZone.run(z.zone_type, z.name, z.restrictions, z.description, z.legal_basis);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(`Inserted ${waterProtectionZones.length} water protection zones`);
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// 2. Pufferstreifen — OELN (DZV), ChemRRV, SPe-Auflagen
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
interface BufferZone {
|
|
89
|
+
type: string;
|
|
90
|
+
distance_m: number;
|
|
91
|
+
requirement: string;
|
|
92
|
+
source_law: string;
|
|
93
|
+
notes: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const bufferZones: BufferZone[] = [
|
|
97
|
+
{
|
|
98
|
+
type: 'Gewaesser — ungeduengt',
|
|
99
|
+
distance_m: 6,
|
|
100
|
+
requirement: 'Entlang aller oberirdischen Gewaesser (Baeche, Fluesse, Seen): 6m Pufferstreifen ohne Duengung (weder Hofdunger noch Mineraldunger).',
|
|
101
|
+
source_law: 'DZV Anhang 1 Ziff. 9.7 (OELN)',
|
|
102
|
+
notes: 'Gemessen ab Boeschungsoberkante. Gilt fuer alle Direktzahlungsempfaenger.',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: 'Gewaesser — unbehandelt',
|
|
106
|
+
distance_m: 6,
|
|
107
|
+
requirement: 'Entlang aller oberirdischen Gewaesser: 6m Pufferstreifen ohne Pflanzenschutzmittel-Anwendung.',
|
|
108
|
+
source_law: 'DZV Anhang 1 Ziff. 9.6 (OELN)',
|
|
109
|
+
notes: 'Gemessen ab Boeschungsoberkante. Zusaetzliche 6m SPe-Reduktionszone bei vielen PSM.',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: 'Hecken und Feldgehoelze',
|
|
113
|
+
distance_m: 3,
|
|
114
|
+
requirement: 'Entlang Hecken, Feld- und Ufergehoelzen: 3m Pufferstreifen ohne Duenger und Pflanzenschutzmittel.',
|
|
115
|
+
source_law: 'DZV Anhang 1 Ziff. 9.7 (OELN)',
|
|
116
|
+
notes: 'Gemessen ab Stockausschlag. BFF-Anrechnung moeglich.',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: 'Nachbarflaechen',
|
|
120
|
+
distance_m: 0.5,
|
|
121
|
+
requirement: 'Mindestens 50 cm Abstand zu Nachbarflaechen bei Duenger- und PSM-Ausbringung.',
|
|
122
|
+
source_law: 'ChemRRV Anhang 2.5',
|
|
123
|
+
notes: 'Bei Geblaesespritze im Rebbau/Obstbau groesserer Abstand noetig. Kantonale Regelungen koennen strenger sein.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'SPe 3 — 20m Reduktion',
|
|
127
|
+
distance_m: 20,
|
|
128
|
+
requirement: '20m Pufferstreifen zu Oberflaechengewaessern fuer PSM mit SPe 3-Auflage (20m). Keine PSM-Anwendung in diesem Streifen.',
|
|
129
|
+
source_law: 'ChemRRV Anhang 2.5 / PSM-Zulassung BLW',
|
|
130
|
+
notes: 'Spezifische Auflage je PSM-Produkt. Reduktion moeglich mit Abdriftminderungstechnik (50%/75%/90%).',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
type: 'SPe 3 — 50m Reduktion',
|
|
134
|
+
distance_m: 50,
|
|
135
|
+
requirement: '50m Pufferstreifen zu Oberflaechengewaessern fuer PSM mit SPe 3-Auflage (50m). Keine PSM-Anwendung in diesem Streifen.',
|
|
136
|
+
source_law: 'ChemRRV Anhang 2.5 / PSM-Zulassung BLW',
|
|
137
|
+
notes: 'Nur bei bestimmten Herbiziden und Insektiziden mit hoher Gewaessertoxizitaet. Reduktion moeglich mit anerkannter Technik.',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: 'SPe 3 — 100m Reduktion',
|
|
141
|
+
distance_m: 100,
|
|
142
|
+
requirement: '100m Pufferstreifen zu Oberflaechengewaessern fuer PSM mit SPe 3-Auflage (100m). Keine PSM-Anwendung in diesem Streifen.',
|
|
143
|
+
source_law: 'ChemRRV Anhang 2.5 / PSM-Zulassung BLW',
|
|
144
|
+
notes: 'Strengste SPe-Auflage. Gilt fuer einzelne hochgiftige Wirkstoffe. Reduktion moeglich auf 50m mit 90%-Abdriftminderung.',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'Grundwasserschutzzone S2',
|
|
148
|
+
distance_m: 0,
|
|
149
|
+
requirement: 'In der Schutzzone S2 ist jegliche Duengung und PSM-Anwendung verboten. Nur extensive Wiesennutzung erlaubt.',
|
|
150
|
+
source_law: 'GSchV Anhang 4 Ziff. 222',
|
|
151
|
+
notes: 'Kein fixer Abstand — Verbot gilt fuer die gesamte S2-Flaeche.',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
type: 'Biotope / Naturschutzgebiete',
|
|
155
|
+
distance_m: 6,
|
|
156
|
+
requirement: '6m Pufferstreifen ohne Duenger und PSM rund um Biotope von nationaler und regionaler Bedeutung.',
|
|
157
|
+
source_law: 'DZV Anhang 1 Ziff. 9.7 (OELN) / NHG',
|
|
158
|
+
notes: 'Kantone koennen groessere Abstande festlegen. Gilt fuer Moore, Trockenwiesen, Auengebiete.',
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const insertBuffer = db.instance.prepare(
|
|
163
|
+
`INSERT OR REPLACE INTO buffer_zones (type, distance_m, requirement, source_law, notes, jurisdiction, language)
|
|
164
|
+
VALUES (?, ?, ?, ?, ?, 'CH', 'DE')`
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
for (const b of bufferZones) {
|
|
168
|
+
insertBuffer.run(b.type, b.distance_m, b.requirement, b.source_law, b.notes);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
console.log(`Inserted ${bufferZones.length} buffer zone rules`);
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// 3. Ammoniakemissionen — LRV, Agrammon, Agroscope
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
interface AmmoniaRule {
|
|
178
|
+
technique: string;
|
|
179
|
+
emission_factor: number | null;
|
|
180
|
+
requirement: string;
|
|
181
|
+
legal_basis: string;
|
|
182
|
+
effective_date: string | null;
|
|
183
|
+
notes: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const ammoniaRules: AmmoniaRule[] = [
|
|
187
|
+
{
|
|
188
|
+
technique: 'Prallteller (Breitverteiler)',
|
|
189
|
+
emission_factor: 100,
|
|
190
|
+
requirement: 'Referenztechnik. Ab 2024 auf offener Ackerflaeche nicht mehr zulaessig (Schleppschlauch-Pflicht). Auf Gruenland weiterhin erlaubt, aber emissionsarm empfohlen.',
|
|
191
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5',
|
|
192
|
+
effective_date: null,
|
|
193
|
+
notes: 'Emissionsfaktor 100% = Referenzwert. Reale NH3-Verluste bei Guelleausbringung ca. 15-25% des ausgebrachten NH4-N je nach Witterung.',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
technique: 'Schleppschlauch',
|
|
197
|
+
emission_factor: 50,
|
|
198
|
+
requirement: 'Obligatorisch ab 1. Januar 2024 auf offener Ackerflaeche (LRV-Revision). Auf Gruenland empfohlen. Reduktion der Ammoniakemissionen um ca. 50% gegenueber Prallteller.',
|
|
199
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5 (Revision 2022)',
|
|
200
|
+
effective_date: '2024-01-01',
|
|
201
|
+
notes: 'Schleppschlauch legt Guelle in Streifen auf den Boden. Weniger Oberflaechenkontakt = weniger NH3-Verlust. Kosten ca. 3-5 CHF/m3 Guelle Mehrkosten.',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
technique: 'Schleppschuh',
|
|
205
|
+
emission_factor: 40,
|
|
206
|
+
requirement: 'Empfohlene emissionsarme Technik. Reduktion ca. 60% gegenueber Prallteller. Guelle wird zwischen Pflanzenreihen am Boden abgelegt.',
|
|
207
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5',
|
|
208
|
+
effective_date: null,
|
|
209
|
+
notes: 'Besonders geeignet fuer Gruenland. Kosteneffizient ab ca. 200 ha Ausbringflaeche (Gemeinschaft/Lohnunternehmer).',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
technique: 'Guelledrill / Injektion',
|
|
213
|
+
emission_factor: 10,
|
|
214
|
+
requirement: 'Beste verfuegbare Technik (BVT). Reduktion ca. 90% gegenueber Prallteller. Guelle wird direkt in den Boden eingebracht.',
|
|
215
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5',
|
|
216
|
+
effective_date: null,
|
|
217
|
+
notes: 'Nur auf Ackerflaeche praktikabel (nicht auf Gruenland). Hohe Zugkraftanforderung. Hoehere Kosten, aber beste Emissionsminderung und Duengerwirkung.',
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
technique: 'Guellegrube — offen',
|
|
221
|
+
emission_factor: 100,
|
|
222
|
+
requirement: 'Referenz-Lagertechnik. Abdeckungspflicht fuer neue Guellgruben (LRV). Bestehende offene Gruben: kantonale Sanierungsfristen.',
|
|
223
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5',
|
|
224
|
+
effective_date: null,
|
|
225
|
+
notes: 'NH3-Verluste bei offener Lagerung ca. 5-10% des Gesamt-N im Jahr. Schwimmschicht reduziert Emissionen teilweise.',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
technique: 'Guellegrube — abgedeckt (fest)',
|
|
229
|
+
emission_factor: 20,
|
|
230
|
+
requirement: 'Feste Abdeckung (Betondeckel, Zeltdach) reduziert Emissionen um ca. 80%. Fuer Neuanlagen obligatorisch.',
|
|
231
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5',
|
|
232
|
+
effective_date: null,
|
|
233
|
+
notes: 'Investitionskosten ca. 80-150 CHF/m2. Strukturverbesserungsbeitraege moeglich (SVV). Gleichzeitig Geruchsreduktion.',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
technique: 'Guellegrube — Schwimmfolie',
|
|
237
|
+
emission_factor: 30,
|
|
238
|
+
requirement: 'Schwimmende Abdeckung (Folie, LECA-Kugeln, Stroh) als Nachruestung fuer bestehende offene Gruben. Reduktion ca. 70%.',
|
|
239
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5',
|
|
240
|
+
effective_date: null,
|
|
241
|
+
notes: 'Kostenguenstige Nachruestung ca. 15-30 CHF/m2. Wartung erforderlich (Folienintegritaet pruefen). Stroh/LECA weniger effektiv als Folie.',
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
technique: 'Laufhof / Laufstall',
|
|
245
|
+
emission_factor: null,
|
|
246
|
+
requirement: 'Emissionsarme Stallboeden (Gummilaufflaechen, haeufige Entmistung, V-Rinnen, Quergefaelle). Agrammon-Modell berechnet stallspezifische Emissionen.',
|
|
247
|
+
legal_basis: 'LRV Anhang 2 Ziff. 5 / Agrammon',
|
|
248
|
+
effective_date: null,
|
|
249
|
+
notes: 'NH3-Emissionen stark abhaengig von Stalltyp, Entmistungshaeufigkeit und Lueftung. Agrammon-Eingabe beruecksichtigt individuelle Betriebsdaten. Neue Staelle: Emissionsarme Bauweise empfohlen.',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
technique: 'Fuetterung — N-reduziert',
|
|
253
|
+
emission_factor: null,
|
|
254
|
+
requirement: 'Phasengerechte Fuetterung und N-angepasste Rationen reduzieren NH3 um 10-20%. Ressourceneffizienzbeitrag moeglich (DZV).',
|
|
255
|
+
legal_basis: 'DZV Art. 82 / LRV',
|
|
256
|
+
effective_date: null,
|
|
257
|
+
notes: 'N-reduzierte Fuetterung bei Schweinen: NPr-Futter senkt N-Ausscheidung um 15-20%. Bei Milchkuehen: Harnstoffgehalt in Milch als Indikator.',
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
technique: 'Weidegang',
|
|
261
|
+
emission_factor: null,
|
|
262
|
+
requirement: 'NH3-Emissionen bei Weidehaltung deutlich tiefer als bei Stallhaltung (Harn und Kot nicht konzentriert). Agrammon verrechnet Weideanteil.',
|
|
263
|
+
legal_basis: 'Agrammon-Modell',
|
|
264
|
+
effective_date: null,
|
|
265
|
+
notes: 'RAUS-Betriebe profitieren von tieferen berechneten NH3-Emissionen. Vollweide (z.B. saisonale Abkalbung) hat tiefste Stallemissionen.',
|
|
266
|
+
},
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
const insertAmmonia = db.instance.prepare(
|
|
270
|
+
`INSERT OR REPLACE INTO ammonia_rules (technique, emission_factor, requirement, legal_basis, effective_date, notes, jurisdiction, language)
|
|
271
|
+
VALUES (?, ?, ?, ?, ?, ?, 'CH', 'DE')`
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
for (const a of ammoniaRules) {
|
|
275
|
+
insertAmmonia.run(a.technique, a.emission_factor, a.requirement, a.legal_basis, a.effective_date, a.notes);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
console.log(`Inserted ${ammoniaRules.length} ammonia rules`);
|
|
279
|
+
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
// 4. Biodiversitaetsfoerderflaechen (BFF) — DZV, OELN
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
interface BffType {
|
|
285
|
+
id: string;
|
|
286
|
+
name: string;
|
|
287
|
+
quality_level: string;
|
|
288
|
+
payment_chf_ha: number;
|
|
289
|
+
min_area_pct: number;
|
|
290
|
+
botanical_criteria: string;
|
|
291
|
+
notes: string;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const bffTypes: BffType[] = [
|
|
295
|
+
// QI types
|
|
296
|
+
{
|
|
297
|
+
id: 'extensiv-wiese-qi',
|
|
298
|
+
name: 'Extensiv genutzte Wiese',
|
|
299
|
+
quality_level: 'QI',
|
|
300
|
+
payment_chf_ha: 450,
|
|
301
|
+
min_area_pct: 7,
|
|
302
|
+
botanical_criteria: 'Keine Duengung. Erste Mahd ab 15. Juni (Talzone). Keine Herbizide.',
|
|
303
|
+
notes: 'Haeufigster BFF-Typ. Mindestens 7% der LN als BFF (inkl. alle BFF-Typen). Talzone: 450 CHF/ha, Huegelzone/BZ: hoeher.',
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'wenig-intensiv-wiese-qi',
|
|
307
|
+
name: 'Wenig intensiv genutzte Wiese',
|
|
308
|
+
quality_level: 'QI',
|
|
309
|
+
payment_chf_ha: 300,
|
|
310
|
+
min_area_pct: 0,
|
|
311
|
+
botanical_criteria: 'Maessige Duengung erlaubt (max. 1 Duengergabe Hofdunger). Erste Mahd ab 15. Juni.',
|
|
312
|
+
notes: 'Uebergangsstufe zwischen intensiv und extensiv. Geringerer Beitrag als extensiv.',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
id: 'streuflaeche-qi',
|
|
316
|
+
name: 'Streuflaeche',
|
|
317
|
+
quality_level: 'QI',
|
|
318
|
+
payment_chf_ha: 450,
|
|
319
|
+
min_area_pct: 0,
|
|
320
|
+
botanical_criteria: 'Keine Duengung. Mahd ab 1. September. Streue muss abgefuehrt werden.',
|
|
321
|
+
notes: 'Typisch in Riedgebieten, Flachmooren. Wichtig fuer Amphibien und seltene Pflanzen.',
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
id: 'hecke-qi',
|
|
325
|
+
name: 'Hecke, Feld- und Ufergehoelz',
|
|
326
|
+
quality_level: 'QI',
|
|
327
|
+
payment_chf_ha: 1700,
|
|
328
|
+
min_area_pct: 0,
|
|
329
|
+
botanical_criteria: 'Mindestens 5 einheimische Straucharten. Mindestbreite 2m. Pflege: sektionsweise alle 5-8 Jahre auf den Stock setzen.',
|
|
330
|
+
notes: 'Mit Krautsaum (3m) beidseitig. Wichtiger Lebensraum fuer Voegel und Kleinsaeuger. Vernetzungselement.',
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
id: 'buntbrache-qi',
|
|
334
|
+
name: 'Buntbrache',
|
|
335
|
+
quality_level: 'QI',
|
|
336
|
+
payment_chf_ha: 3800,
|
|
337
|
+
min_area_pct: 0,
|
|
338
|
+
botanical_criteria: 'Einsaat empfohlener Saatmischung (ca. 30 Arten). Mindeststandzeit 2 Jahre. Keine Duengung, keine PSM. Mindestgroesse 5 Aren.',
|
|
339
|
+
notes: 'Hoechster Beitrag aller BFF-Typen auf Ackerflaeche. Anrechenbar an 3.5% BFF auf Ackerflaeche. Wichtig fuer Feldlerche, Feldhase.',
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
id: 'rotationsbrache-qi',
|
|
343
|
+
name: 'Rotationsbrache',
|
|
344
|
+
quality_level: 'QI',
|
|
345
|
+
payment_chf_ha: 3300,
|
|
346
|
+
min_area_pct: 0,
|
|
347
|
+
botanical_criteria: 'Einsaat empfohlener Mischung. Standzeit 1-3 Jahre (kuerzere Rotation als Buntbrache). Keine Duengung, keine PSM.',
|
|
348
|
+
notes: 'Flexibler als Buntbrache. Anrechenbar an 3.5% BFF auf Ackerflaeche.',
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
id: 'saum-ackerflaeche-qi',
|
|
352
|
+
name: 'Saum auf Ackerflaeche',
|
|
353
|
+
quality_level: 'QI',
|
|
354
|
+
payment_chf_ha: 3300,
|
|
355
|
+
min_area_pct: 0,
|
|
356
|
+
botanical_criteria: 'Streifen entlang Feldraendern (3-12m breit). Einsaat empfohlener Mischung. Keine Duengung, keine PSM. Mindeststandzeit 2 Jahre.',
|
|
357
|
+
notes: 'Ergaenzt Bunt-/Rotationsbrache. Strukturelement am Feldrand.',
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
id: 'nuetzlingsstreifen-qi',
|
|
361
|
+
name: 'Nuetzlingsstreifen',
|
|
362
|
+
quality_level: 'QI',
|
|
363
|
+
payment_chf_ha: 3300,
|
|
364
|
+
min_area_pct: 0,
|
|
365
|
+
botanical_criteria: 'Streifen in oder am Rand von Ackerkulturen (3-5m breit). Empfohlene Mischung mit Blutenpflanzen. Keine PSM, keine Duengung. Jaehrliche Neuansaat moeglich.',
|
|
366
|
+
notes: 'Foerdert Nuetzlinge (Schwebfliegen, Marienkaefer, Schlupfwespen). Seit 2023 als BFF-Typ anerkannt.',
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
id: 'bluehstreifen-qi',
|
|
370
|
+
name: 'Bluehstreifen fuer Bestaeubende und andere Nuetzlinge',
|
|
371
|
+
quality_level: 'QI',
|
|
372
|
+
payment_chf_ha: 3300,
|
|
373
|
+
min_area_pct: 0,
|
|
374
|
+
botanical_criteria: 'Empfohlene Bluehstreifenmischung. 3-12m breit. Keine PSM, keine Duengung. Mindeststandzeit 100 Tage.',
|
|
375
|
+
notes: 'Neuer BFF-Typ (DZV-Revision). Foerdert Wildbienen und andere Bestaeubende.',
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
id: 'hochstamm-feldobst-qi',
|
|
379
|
+
name: 'Hochstamm-Feldobstbaeume',
|
|
380
|
+
quality_level: 'QI',
|
|
381
|
+
payment_chf_ha: 0,
|
|
382
|
+
min_area_pct: 0,
|
|
383
|
+
botanical_criteria: 'Stammhoehe mindestens 1.6m (Steinobst) bzw. 1.2m (Kernobst). Einzelbaum-Beitrag. Mindestabstand 10m. Schnitt alle 5 Jahre.',
|
|
384
|
+
notes: 'Beitrag pro Baum (15 CHF/Baum QI). Wichtig fuer Steinkauz, Gartenrotschwanz. Max. 100 Baeume pro ha anrechenbar.',
|
|
385
|
+
},
|
|
386
|
+
|
|
387
|
+
// QII types — Qualitaetsstufe II (botanische Qualitaet + Vernetzung)
|
|
388
|
+
{
|
|
389
|
+
id: 'extensiv-wiese-qii',
|
|
390
|
+
name: 'Extensiv genutzte Wiese',
|
|
391
|
+
quality_level: 'QII',
|
|
392
|
+
payment_chf_ha: 1520,
|
|
393
|
+
min_area_pct: 0,
|
|
394
|
+
botanical_criteria: 'Mindestens 6 von ca. 30 regionsspezifischen Indikatorpflanzen nachgewiesen. Kontrolle durch kantonale Fachstelle oder delegierte Organisation. Indikatorpflanzen z.B.: Margerite, Salbei, Esparsette, Wiesenflockenblume, Knolliger Hahnenfuss, Aufrechte Trespe.',
|
|
395
|
+
notes: 'QII-Beitrag: 1520 CHF/ha total (= QI 450 + QII-Zuschlag 1070). Hoechster Flaechenanteil der QII-Flaechen.',
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
id: 'wenig-intensiv-wiese-qii',
|
|
399
|
+
name: 'Wenig intensiv genutzte Wiese',
|
|
400
|
+
quality_level: 'QII',
|
|
401
|
+
payment_chf_ha: 1020,
|
|
402
|
+
min_area_pct: 0,
|
|
403
|
+
botanical_criteria: 'Mindestens 6 Indikatorpflanzen (analog extensiv, aber angepasste Artenliste fuer Fettwiesen).',
|
|
404
|
+
notes: 'QII-Beitrag: 1020 CHF/ha total (= QI 300 + QII-Zuschlag 720).',
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
id: 'streuflaeche-qii',
|
|
408
|
+
name: 'Streuflaeche',
|
|
409
|
+
quality_level: 'QII',
|
|
410
|
+
payment_chf_ha: 1370,
|
|
411
|
+
min_area_pct: 0,
|
|
412
|
+
botanical_criteria: 'Mindestens 6 Indikatorpflanzen (spezifische Riedarten: Seggen, Wollgras, Mehlprimel, Sumpfdotterblume).',
|
|
413
|
+
notes: 'QII-Beitrag: 1370 CHF/ha total (= QI 450 + QII-Zuschlag 920). Hochwertige Flachmoore.',
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
id: 'hecke-qii',
|
|
417
|
+
name: 'Hecke, Feld- und Ufergehoelz',
|
|
418
|
+
quality_level: 'QII',
|
|
419
|
+
payment_chf_ha: 2050,
|
|
420
|
+
min_area_pct: 0,
|
|
421
|
+
botanical_criteria: 'Mindestens 5 Straucharten, davon min. 3 dornentragend. Totholzanteil. Gepflegter Krautsaum mit Indikatorarten.',
|
|
422
|
+
notes: 'QII-Beitrag: 2050 CHF/ha total (= QI 1700 + QII-Zuschlag 350). Dornenstraeucher wichtig fuer Neuntoeter.',
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
id: 'hochstamm-feldobst-qii',
|
|
426
|
+
name: 'Hochstamm-Feldobstbaeume',
|
|
427
|
+
quality_level: 'QII',
|
|
428
|
+
payment_chf_ha: 0,
|
|
429
|
+
min_area_pct: 0,
|
|
430
|
+
botanical_criteria: 'Mindestens 10 Hochstammbaeume pro ha, mindestens 2 Sorten. Unternutzung als QII-Wiese oder -Weide.',
|
|
431
|
+
notes: 'Beitrag pro Baum (30 CHF/Baum QII). Vernetzung: Obstgarten im Vernetzungsperimeter.',
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
id: 'vernetzung',
|
|
435
|
+
name: 'Vernetzungsbeitrag',
|
|
436
|
+
quality_level: 'QI',
|
|
437
|
+
payment_chf_ha: 1000,
|
|
438
|
+
min_area_pct: 0,
|
|
439
|
+
botanical_criteria: 'BFF-Flaeche liegt in einem kantonalen Vernetzungsprojekt. Lage, Typ und Pflege gemaess Vernetzungskonzept. Zielarten definiert.',
|
|
440
|
+
notes: 'Zusaetzlich zu QI/QII-Beitraegen. Kantonale Vernetzungsprojekte mit Leitarten (z.B. Feldlerche, Neuntoeter). Max. 1000 CHF/ha.',
|
|
441
|
+
},
|
|
442
|
+
|
|
443
|
+
// BFF minimum requirements
|
|
444
|
+
{
|
|
445
|
+
id: 'bff-minimum-ln',
|
|
446
|
+
name: 'Mindestanteil BFF auf LN',
|
|
447
|
+
quality_level: 'QI',
|
|
448
|
+
payment_chf_ha: 0,
|
|
449
|
+
min_area_pct: 7,
|
|
450
|
+
botanical_criteria: 'Mindestens 7% der landwirtschaftlichen Nutzflaeche (LN) als BFF (alle BFF-Typen zusammen).',
|
|
451
|
+
notes: 'OELN-Pflicht. Gilt fuer alle Betriebe mit Direktzahlungen. Spezialkulturen: 3.5% auf offener Ackerflaeche.',
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
id: 'bff-minimum-acker',
|
|
455
|
+
name: 'Mindestanteil BFF auf Ackerflaeche',
|
|
456
|
+
quality_level: 'QI',
|
|
457
|
+
payment_chf_ha: 0,
|
|
458
|
+
min_area_pct: 3.5,
|
|
459
|
+
botanical_criteria: 'Ab 2024: Mindestens 3.5% der offenen Ackerflaeche als BFF (Buntbrache, Rotationsbrache, Saum, Nuetzlingsstreifen, Bluehstreifen).',
|
|
460
|
+
notes: 'Neue Anforderung ab 2024 (Pa.Iv. 19.475). Vorher nur 7% auf gesamter LN. Ackerflaechen-BFF haben hohe oekologische Wirkung.',
|
|
461
|
+
},
|
|
462
|
+
];
|
|
463
|
+
|
|
464
|
+
const insertBff = db.instance.prepare(
|
|
465
|
+
`INSERT OR REPLACE INTO bff_types (id, name, quality_level, payment_chf_ha, min_area_pct, botanical_criteria, notes, jurisdiction, language)
|
|
466
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 'CH', 'DE')`
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
for (const b of bffTypes) {
|
|
470
|
+
insertBff.run(b.id, b.name, b.quality_level, b.payment_chf_ha, b.min_area_pct, b.botanical_criteria, b.notes);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
console.log(`Inserted ${bffTypes.length} BFF types`);
|
|
474
|
+
|
|
475
|
+
// ---------------------------------------------------------------------------
|
|
476
|
+
// 5. Naehrstoffverlust-Absenkpfad — Pa.Iv. 19.475, LwG Art. 6a
|
|
477
|
+
// ---------------------------------------------------------------------------
|
|
478
|
+
|
|
479
|
+
interface NutrientLossLimit {
|
|
480
|
+
nutrient: string;
|
|
481
|
+
year: number;
|
|
482
|
+
limit_pct: number;
|
|
483
|
+
target: string;
|
|
484
|
+
legal_basis: string;
|
|
485
|
+
notes: string;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const nutrientLossLimits: NutrientLossLimit[] = [
|
|
489
|
+
// Stickstoff (N)
|
|
490
|
+
{
|
|
491
|
+
nutrient: 'N',
|
|
492
|
+
year: 2023,
|
|
493
|
+
limit_pct: 0,
|
|
494
|
+
target: 'Referenzjahr (Durchschnitt 2014-2016)',
|
|
495
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
496
|
+
notes: 'Basiswert: Durchschnitt der Stickstoffverluste 2014-2016.',
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
nutrient: 'N',
|
|
500
|
+
year: 2025,
|
|
501
|
+
limit_pct: 10,
|
|
502
|
+
target: '-10% Stickstoffverluste gegenueber Referenz',
|
|
503
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
504
|
+
notes: 'Zwischenziel. Verschaerfte Suisse-Bilanz: Toleranzgrenze N sinkt auf 105% (vorher 110%).',
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
nutrient: 'N',
|
|
508
|
+
year: 2027,
|
|
509
|
+
limit_pct: 15,
|
|
510
|
+
target: '-15% Stickstoffverluste gegenueber Referenz',
|
|
511
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
512
|
+
notes: 'Zwischenziel. Bei Nichterreichen: Verschaerfung der Massnahmen durch Bundesrat.',
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
nutrient: 'N',
|
|
516
|
+
year: 2030,
|
|
517
|
+
limit_pct: 20,
|
|
518
|
+
target: '-20% Stickstoffverluste gegenueber Referenz',
|
|
519
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
520
|
+
notes: 'Endziel. Massnahmen: emissionsarme Ausbringung, N-angepasste Fuetterung, optimierte Hofdungerlagerung, reduzierte Mineraldungermengen.',
|
|
521
|
+
},
|
|
522
|
+
// Phosphor (P)
|
|
523
|
+
{
|
|
524
|
+
nutrient: 'P',
|
|
525
|
+
year: 2023,
|
|
526
|
+
limit_pct: 0,
|
|
527
|
+
target: 'Referenzjahr (Durchschnitt 2014-2016)',
|
|
528
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
529
|
+
notes: 'Basiswert: Durchschnitt der Phosphorverluste 2014-2016.',
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
nutrient: 'P',
|
|
533
|
+
year: 2025,
|
|
534
|
+
limit_pct: 10,
|
|
535
|
+
target: '-10% Phosphorverluste gegenueber Referenz',
|
|
536
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
537
|
+
notes: 'Zwischenziel. Suisse-Bilanz P-Toleranz bleibt bei 100% (war bereits strenger als N).',
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
nutrient: 'P',
|
|
541
|
+
year: 2027,
|
|
542
|
+
limit_pct: 15,
|
|
543
|
+
target: '-15% Phosphorverluste gegenueber Referenz',
|
|
544
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
545
|
+
notes: 'Zwischenziel. Erosionsschutz und Pufferstreifen als Hauptmassnahmen.',
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
nutrient: 'P',
|
|
549
|
+
year: 2030,
|
|
550
|
+
limit_pct: 20,
|
|
551
|
+
target: '-20% Phosphorverluste gegenueber Referenz',
|
|
552
|
+
legal_basis: 'LwG Art. 6a (Pa.Iv. 19.475)',
|
|
553
|
+
notes: 'Endziel. Massnahmen: Bodenschutz, Pufferstreifen, Abflussverhinderung, P-effiziente Fuetterung.',
|
|
554
|
+
},
|
|
555
|
+
];
|
|
556
|
+
|
|
557
|
+
const insertNutrientLoss = db.instance.prepare(
|
|
558
|
+
`INSERT OR REPLACE INTO nutrient_loss_limits (nutrient, year, limit_pct, target, legal_basis, notes, jurisdiction, language)
|
|
559
|
+
VALUES (?, ?, ?, ?, ?, ?, 'CH', 'DE')`
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
for (const l of nutrientLossLimits) {
|
|
563
|
+
insertNutrientLoss.run(l.nutrient, l.year, l.limit_pct, l.target, l.legal_basis, l.notes);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
console.log(`Inserted ${nutrientLossLimits.length} nutrient loss limits`);
|
|
567
|
+
|
|
568
|
+
// ---------------------------------------------------------------------------
|
|
569
|
+
// 6. Environmental Rules — UVP, VBBo, general rules
|
|
570
|
+
// ---------------------------------------------------------------------------
|
|
571
|
+
|
|
572
|
+
interface EnvironmentalRule {
|
|
573
|
+
topic: string;
|
|
574
|
+
rule: string;
|
|
575
|
+
authority: string;
|
|
576
|
+
legal_basis: string;
|
|
577
|
+
threshold: string | null;
|
|
578
|
+
notes: string;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const environmentalRules: EnvironmentalRule[] = [
|
|
582
|
+
// UVP — Umweltvertraeglichkeitspruefung
|
|
583
|
+
{
|
|
584
|
+
topic: 'UVP',
|
|
585
|
+
rule: 'UVP-Pflicht Schweinehaltung',
|
|
586
|
+
authority: 'Kanton (Bau- und Umweltamt)',
|
|
587
|
+
legal_basis: 'UVPV Anhang Ziff. 80.4',
|
|
588
|
+
threshold: 'Ab 500 Mastschweinplaetze oder 150 Zuchtsauenplaetze',
|
|
589
|
+
notes: 'Schwellenwerte kantonal leicht abweichend. UVP-Bericht durch anerkanntes Buero. Kosten ca. 20,000-50,000 CHF.',
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
topic: 'UVP',
|
|
593
|
+
rule: 'UVP-Pflicht Gefluegelhaltung',
|
|
594
|
+
authority: 'Kanton (Bau- und Umweltamt)',
|
|
595
|
+
legal_basis: 'UVPV Anhang Ziff. 80.4',
|
|
596
|
+
threshold: 'Ab 10,000 Legehennenplaetze oder 20,000 Mastpouletplaetze',
|
|
597
|
+
notes: 'Grosse Gefluegelbetriebe. Emissionen (NH3, Staub, Geruch) im Fokus.',
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
topic: 'UVP',
|
|
601
|
+
rule: 'UVP-Pflicht Rindviehhaltung',
|
|
602
|
+
authority: 'Kanton (Bau- und Umweltamt)',
|
|
603
|
+
legal_basis: 'UVPV Anhang Ziff. 80.4',
|
|
604
|
+
threshold: 'Ab ca. 150-200 GVE Rindvieh (kantonal unterschiedlich)',
|
|
605
|
+
notes: 'Kantonale Schwellenwerte variieren stark. Einige Kantone: UVP ab 150 GVE, andere ab 200 GVE.',
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
topic: 'UVP',
|
|
609
|
+
rule: 'UVP-Pflicht Biogasanlage',
|
|
610
|
+
authority: 'Kanton (Bau- und Umweltamt)',
|
|
611
|
+
legal_basis: 'UVPV Anhang Ziff. 21',
|
|
612
|
+
threshold: 'Ab 5,000 t Jahreskapazitaet Substrat',
|
|
613
|
+
notes: 'Landwirtschaftliche Biogasanlagen. Co-Substrate (Abfaelle) erhoehen UVP-Wahrscheinlichkeit.',
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
topic: 'UVP',
|
|
617
|
+
rule: 'UVP-Pflicht Gewaesserverbauung und Melioration',
|
|
618
|
+
authority: 'Kanton (Tiefbauamt / Umweltamt)',
|
|
619
|
+
legal_basis: 'UVPV Anhang Ziff. 30.2 / 80.3',
|
|
620
|
+
threshold: 'Gueterzusammenlegungen ab 400 ha, groessere Gewaesserverbauungen',
|
|
621
|
+
notes: 'Meliorationen und Gueterzusammenlegungen. Auch Drainageprojekte ab gewisser Groesse.',
|
|
622
|
+
},
|
|
623
|
+
|
|
624
|
+
// VBBo — Schwermetall-Richtwerte
|
|
625
|
+
{
|
|
626
|
+
topic: 'VBBo',
|
|
627
|
+
rule: 'Richtwert Cadmium (Cd) im Boden',
|
|
628
|
+
authority: 'BAFU / kantonale Fachstelle Bodenschutz',
|
|
629
|
+
legal_basis: 'VBBo Art. 8 / Anhang 1',
|
|
630
|
+
threshold: 'Richtwert 0.8 mg Cd/kg TS',
|
|
631
|
+
notes: 'Bei Ueberschreitung: Nutzungseinschraenkungen fuer Nahrungsmittelpflanzen. Sanierungswert: 2 mg/kg. Quellen: Mineraldunger (Phosphatduenger), Klaerschlamm (seit 2006 verboten).',
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
topic: 'VBBo',
|
|
635
|
+
rule: 'Richtwert Kupfer (Cu) im Boden',
|
|
636
|
+
authority: 'BAFU / kantonale Fachstelle Bodenschutz',
|
|
637
|
+
legal_basis: 'VBBo Art. 8 / Anhang 1',
|
|
638
|
+
threshold: 'Richtwert 40 mg Cu/kg TS',
|
|
639
|
+
notes: 'Bei Ueberschreitung: Einschraenkung Hofdungerausbringung. Sanierungswert: 150 mg/kg. Quellen: Kupferspritzmittel (Rebbau, Obstbau), Schweineguelle.',
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
topic: 'VBBo',
|
|
643
|
+
rule: 'Richtwert Zink (Zn) im Boden',
|
|
644
|
+
authority: 'BAFU / kantonale Fachstelle Bodenschutz',
|
|
645
|
+
legal_basis: 'VBBo Art. 8 / Anhang 1',
|
|
646
|
+
threshold: 'Richtwert 150 mg Zn/kg TS',
|
|
647
|
+
notes: 'Bei Ueberschreitung: Duengungs-Einschraenkungen. Sanierungswert: 300 mg/kg. Quellen: Schweineguelle (Zink als Futterzusatz), Klaerschlamm.',
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
topic: 'VBBo',
|
|
651
|
+
rule: 'Richtwert Blei (Pb) im Boden',
|
|
652
|
+
authority: 'BAFU / kantonale Fachstelle Bodenschutz',
|
|
653
|
+
legal_basis: 'VBBo Art. 8 / Anhang 1',
|
|
654
|
+
threshold: 'Richtwert 50 mg Pb/kg TS',
|
|
655
|
+
notes: 'Bei Ueberschreitung: Nutzungseinschraenkungen fuer Gemuese. Sanierungswert: 200 mg/kg. Quellen: historisch (verbleites Benzin), Altlasten.',
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
topic: 'VBBo',
|
|
659
|
+
rule: 'Massnahmen bei Ueberschreitung Richtwerte',
|
|
660
|
+
authority: 'Kantonale Fachstelle Bodenschutz',
|
|
661
|
+
legal_basis: 'VBBo Art. 9-10',
|
|
662
|
+
threshold: null,
|
|
663
|
+
notes: 'Stufenmodell: (1) Richtwert ueberschritten = vertiefte Abklaerung, (2) Pruefwert ueberschritten = Gefaehrdungsabschaetzung, (3) Sanierungswert ueberschritten = Nutzungseinschraenkung/Sanierung. Bodenanalyse alle 10-15 Jahre empfohlen.',
|
|
664
|
+
},
|
|
665
|
+
|
|
666
|
+
// Gewaesserraum
|
|
667
|
+
{
|
|
668
|
+
topic: 'Gewaesserschutz',
|
|
669
|
+
rule: 'Gewaesserraum — Mindestbreite',
|
|
670
|
+
authority: 'Kanton (Tiefbauamt / Umweltamt)',
|
|
671
|
+
legal_basis: 'GSchG Art. 36a / GSchV Art. 41a-41c',
|
|
672
|
+
threshold: null,
|
|
673
|
+
notes: 'Kantone legen Gewaesserraum fest: Mindestbreite 11m bei Fliessgewaessern, mehr bei groesseren Gewaessern. Im Gewaesserraum: keine Bauten, keine Duengung, extensive Bewirtschaftung. Entschaedigung moeglich.',
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
topic: 'Gewaesserschutz',
|
|
677
|
+
rule: 'Hofdungerannahmevertrag',
|
|
678
|
+
authority: 'Kanton (Amt fuer Landwirtschaft)',
|
|
679
|
+
legal_basis: 'DZV Art. 24 / GSchG',
|
|
680
|
+
threshold: null,
|
|
681
|
+
notes: 'Pflicht bei Hofdungerabgabe und -aufnahme zwischen Betrieben. Vertrag muss Menge, Naehrstoffgehalt und Abgabe-/Annahmezeitpunkt enthalten. Kantonale Meldepflicht (HODUFLU-System).',
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
topic: 'Gewaesserschutz',
|
|
685
|
+
rule: 'Lagerkapazitaet Hofdunger',
|
|
686
|
+
authority: 'BAFU / Kanton',
|
|
687
|
+
legal_basis: 'GSchV Anhang 2 Ziff. 23',
|
|
688
|
+
threshold: 'Mindestens 5 Monate Lagerkapazitaet (Talzone), 6 Monate (Bergzone)',
|
|
689
|
+
notes: 'Ausreichende Lagerkapazitaet verhindert Ausbringung bei unguenstigen Bedingungen (Frost, Naesse, Sommer). Einige Kantone verlangen mehr (z.B. LU: 6 Monate Talzone).',
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
topic: 'Gewaesserschutz',
|
|
693
|
+
rule: 'Ausbringverbot Hofdunger',
|
|
694
|
+
authority: 'Kanton',
|
|
695
|
+
legal_basis: 'ChemRRV Anhang 2.6 Ziff. 3.2.1',
|
|
696
|
+
threshold: null,
|
|
697
|
+
notes: 'Kein Hofdunger auf wassergesaettigte, gefrorene, schneebedeckte oder ausgetrocknete Boeden. Sommersperrfrist: einige Kantone verbieten Ausbringung im Sommer bei hohen Temperaturen.',
|
|
698
|
+
},
|
|
699
|
+
|
|
700
|
+
// Allgemeine Umweltregeln
|
|
701
|
+
{
|
|
702
|
+
topic: 'Erosionsschutz',
|
|
703
|
+
rule: 'Angemessener Bodenschutz (OELN)',
|
|
704
|
+
authority: 'BLW / Kanton',
|
|
705
|
+
legal_basis: 'DZV Anhang 1 Ziff. 5 (OELN)',
|
|
706
|
+
threshold: null,
|
|
707
|
+
notes: 'OELN-Anforderung: Erosionsschutzmassnahmen auf erosionsgefaehrdeten Flaechen (>2t/ha/Jahr Bodenabtrag). Massnahmen: Mulchsaat, Begruenung, Untersaat, Hangquerbearbeitung, Pufferstreifen.',
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
topic: 'PSM-Gewaesserschutz',
|
|
711
|
+
rule: 'Aktionsplan Pflanzenschutzmittel — 50% Risikoreduktion',
|
|
712
|
+
authority: 'BLW / BAFU',
|
|
713
|
+
legal_basis: 'Aktionsplan PSM (Bundesrat 2017)',
|
|
714
|
+
threshold: '50% Risikoreduktion fuer Oberflaechengewaesser und Grundwasser bis 2027',
|
|
715
|
+
notes: 'Massnahmen: PSM-freie Pufferstreifen, Abdriftminderungstechnik, Reduktion besonders gewaessertoxischer Wirkstoffe, Foerderung biologischer Alternativen.',
|
|
716
|
+
},
|
|
717
|
+
];
|
|
718
|
+
|
|
719
|
+
const insertRule = db.instance.prepare(
|
|
720
|
+
`INSERT OR REPLACE INTO environmental_rules (topic, rule, authority, legal_basis, threshold, notes, jurisdiction, language)
|
|
721
|
+
VALUES (?, ?, ?, ?, ?, ?, 'CH', 'DE')`
|
|
722
|
+
);
|
|
723
|
+
|
|
724
|
+
for (const r of environmentalRules) {
|
|
725
|
+
insertRule.run(r.topic, r.rule, r.authority, r.legal_basis, r.threshold, r.notes);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
console.log(`Inserted ${environmentalRules.length} environmental rules`);
|
|
729
|
+
|
|
730
|
+
// ---------------------------------------------------------------------------
|
|
731
|
+
// 7. FTS5 Search Index — populate from all tables
|
|
732
|
+
// ---------------------------------------------------------------------------
|
|
733
|
+
|
|
734
|
+
db.run('DELETE FROM search_index');
|
|
735
|
+
|
|
736
|
+
// Water protection zones
|
|
737
|
+
const wpzRows = db.all<{ zone_type: string; name: string; restrictions: string; description: string }>(
|
|
738
|
+
'SELECT zone_type, name, restrictions, description FROM water_protection_zones'
|
|
739
|
+
);
|
|
740
|
+
const insertFts = db.instance.prepare(
|
|
741
|
+
'INSERT INTO search_index (title, body, topic, jurisdiction) VALUES (?, ?, ?, ?)'
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
for (const z of wpzRows) {
|
|
745
|
+
insertFts.run(
|
|
746
|
+
`Grundwasserschutzzone ${z.zone_type} — ${z.name}`,
|
|
747
|
+
`${z.restrictions} ${z.description}`,
|
|
748
|
+
'Gewaesserschutz',
|
|
749
|
+
'CH'
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// Buffer zones
|
|
754
|
+
const bzRows = db.all<{ type: string; distance_m: number; requirement: string; notes: string }>(
|
|
755
|
+
'SELECT type, distance_m, requirement, notes FROM buffer_zones'
|
|
756
|
+
);
|
|
757
|
+
for (const b of bzRows) {
|
|
758
|
+
insertFts.run(
|
|
759
|
+
`Pufferstreifen ${b.type} (${b.distance_m}m)`,
|
|
760
|
+
`${b.requirement} ${b.notes ?? ''}`,
|
|
761
|
+
'Pufferstreifen',
|
|
762
|
+
'CH'
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// Ammonia rules
|
|
767
|
+
const arRows = db.all<{ technique: string; requirement: string; notes: string }>(
|
|
768
|
+
'SELECT technique, requirement, notes FROM ammonia_rules'
|
|
769
|
+
);
|
|
770
|
+
for (const a of arRows) {
|
|
771
|
+
insertFts.run(
|
|
772
|
+
`Ammoniakemissionen — ${a.technique}`,
|
|
773
|
+
`${a.requirement} ${a.notes ?? ''}`,
|
|
774
|
+
'Ammoniak',
|
|
775
|
+
'CH'
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// BFF types
|
|
780
|
+
const bffRows = db.all<{ name: string; quality_level: string; botanical_criteria: string; notes: string }>(
|
|
781
|
+
'SELECT name, quality_level, botanical_criteria, notes FROM bff_types'
|
|
782
|
+
);
|
|
783
|
+
for (const b of bffRows) {
|
|
784
|
+
insertFts.run(
|
|
785
|
+
`BFF ${b.quality_level} — ${b.name}`,
|
|
786
|
+
`${b.botanical_criteria} ${b.notes ?? ''}`,
|
|
787
|
+
'BFF',
|
|
788
|
+
'CH'
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Nutrient loss limits
|
|
793
|
+
const nllRows = db.all<{ nutrient: string; year: number; target: string; notes: string }>(
|
|
794
|
+
'SELECT nutrient, year, target, notes FROM nutrient_loss_limits'
|
|
795
|
+
);
|
|
796
|
+
for (const l of nllRows) {
|
|
797
|
+
insertFts.run(
|
|
798
|
+
`Absenkpfad ${l.nutrient} ${l.year}`,
|
|
799
|
+
`${l.target} ${l.notes ?? ''}`,
|
|
800
|
+
'Naehrstoffe',
|
|
801
|
+
'CH'
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Environmental rules
|
|
806
|
+
const erRows = db.all<{ topic: string; rule: string; legal_basis: string; notes: string }>(
|
|
807
|
+
'SELECT topic, rule, legal_basis, notes FROM environmental_rules'
|
|
808
|
+
);
|
|
809
|
+
for (const r of erRows) {
|
|
810
|
+
insertFts.run(
|
|
811
|
+
r.rule,
|
|
812
|
+
`${r.legal_basis} ${r.notes ?? ''}`,
|
|
813
|
+
r.topic,
|
|
814
|
+
'CH'
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const ftsCount = db.get<{ count: number }>('SELECT COUNT(*) as count FROM search_index');
|
|
819
|
+
console.log(`FTS5 index rebuilt: ${ftsCount?.count ?? 0} entries`);
|
|
820
|
+
|
|
821
|
+
// ---------------------------------------------------------------------------
|
|
822
|
+
// 8. Metadata
|
|
823
|
+
// ---------------------------------------------------------------------------
|
|
824
|
+
|
|
825
|
+
db.run(`INSERT OR REPLACE INTO db_metadata (key, value) VALUES ('last_ingest', ?)`, [now]);
|
|
826
|
+
db.run(`INSERT OR REPLACE INTO db_metadata (key, value) VALUES ('build_date', ?)`, [now]);
|
|
827
|
+
db.run(`INSERT OR REPLACE INTO db_metadata (key, value) VALUES ('schema_version', '1.0')`, []);
|
|
828
|
+
|
|
829
|
+
// ---------------------------------------------------------------------------
|
|
830
|
+
// 9. Coverage JSON + sources YAML
|
|
831
|
+
// ---------------------------------------------------------------------------
|
|
832
|
+
|
|
833
|
+
const coverage = {
|
|
834
|
+
server: 'ch-environmental-compliance-mcp',
|
|
835
|
+
jurisdiction: 'CH',
|
|
836
|
+
version: '0.1.0',
|
|
837
|
+
last_ingest: now,
|
|
838
|
+
data: {
|
|
839
|
+
water_protection_zones: waterProtectionZones.length,
|
|
840
|
+
buffer_zones: bufferZones.length,
|
|
841
|
+
ammonia_rules: ammoniaRules.length,
|
|
842
|
+
bff_types: bffTypes.length,
|
|
843
|
+
nutrient_loss_limits: nutrientLossLimits.length,
|
|
844
|
+
environmental_rules: environmentalRules.length,
|
|
845
|
+
fts_entries: ftsCount?.count ?? 0,
|
|
846
|
+
},
|
|
847
|
+
tools: 11,
|
|
848
|
+
sources: [
|
|
849
|
+
'BAFU — GSchG/GSchV (Gewaesserschutz)',
|
|
850
|
+
'BAFU — LRV (Luftreinhaltung, Ammoniak)',
|
|
851
|
+
'BLW — DZV (BFF, OELN)',
|
|
852
|
+
'Agroscope — Agrammon (Emissionsfaktoren)',
|
|
853
|
+
'Parlament — Pa.Iv. 19.475 (Absenkpfad)',
|
|
854
|
+
'BAFU — VBBo (Bodenbelastung)',
|
|
855
|
+
],
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
writeFileSync('data/coverage.json', JSON.stringify(coverage, null, 2) + '\n');
|
|
859
|
+
|
|
860
|
+
const sourcesYml = `# Data sources for ch-environmental-compliance-mcp
|
|
861
|
+
sources:
|
|
862
|
+
- name: Gewaesserschutzgesetz (GSchG) / Gewaesserschutzverordnung (GSchV)
|
|
863
|
+
authority: BAFU (Bundesamt fuer Umwelt)
|
|
864
|
+
url: https://www.bafu.admin.ch/bafu/de/home/themen/wasser/fachinformationen/gewaesserschutz.html
|
|
865
|
+
license: Swiss Federal Administration — free reuse
|
|
866
|
+
update_frequency: periodic (amendments as enacted)
|
|
867
|
+
last_retrieved: "${now}"
|
|
868
|
+
|
|
869
|
+
- name: Luftreinhalte-Verordnung (LRV) / Agrammon
|
|
870
|
+
authority: BAFU / Agroscope
|
|
871
|
+
url: https://www.bafu.admin.ch/bafu/de/home/themen/luft/fachinformationen/luftschadstoffquellen/emissionen-der-landwirtschaft.html
|
|
872
|
+
license: Swiss Federal Administration — free reuse
|
|
873
|
+
update_frequency: periodic (Agrammon model updates)
|
|
874
|
+
last_retrieved: "${now}"
|
|
875
|
+
|
|
876
|
+
- name: Direktzahlungsverordnung (DZV) — BFF und OELN
|
|
877
|
+
authority: BLW (Bundesamt fuer Landwirtschaft)
|
|
878
|
+
url: https://www.blw.admin.ch/blw/de/home/instrumente/direktzahlungen/biodiversitaetsbeitraege.html
|
|
879
|
+
license: Swiss Federal Administration — free reuse
|
|
880
|
+
update_frequency: annual (DZV revisions)
|
|
881
|
+
last_retrieved: "${now}"
|
|
882
|
+
|
|
883
|
+
- name: Pa.Iv. 19.475 — Absenkpfad Naehrstoffverluste
|
|
884
|
+
authority: Parlament / BLW
|
|
885
|
+
url: https://www.blw.admin.ch/blw/de/home/nachhaltige-produktion/umwelt/naehrstoffe.html
|
|
886
|
+
license: Swiss Federal Administration — free reuse
|
|
887
|
+
update_frequency: annual targets through 2030
|
|
888
|
+
last_retrieved: "${now}"
|
|
889
|
+
|
|
890
|
+
- name: VBBo — Verordnung ueber Belastungen des Bodens
|
|
891
|
+
authority: BAFU
|
|
892
|
+
url: https://www.bafu.admin.ch/bafu/de/home/themen/boden/fachinformationen/bodenschutz.html
|
|
893
|
+
license: Swiss Federal Administration — free reuse
|
|
894
|
+
update_frequency: periodic
|
|
895
|
+
last_retrieved: "${now}"
|
|
896
|
+
`;
|
|
897
|
+
|
|
898
|
+
writeFileSync('data/sources.yml', sourcesYml);
|
|
899
|
+
|
|
900
|
+
console.log('\nIngestion complete:');
|
|
901
|
+
console.log(` Water protection zones: ${waterProtectionZones.length}`);
|
|
902
|
+
console.log(` Buffer zone rules: ${bufferZones.length}`);
|
|
903
|
+
console.log(` Ammonia rules: ${ammoniaRules.length}`);
|
|
904
|
+
console.log(` BFF types: ${bffTypes.length}`);
|
|
905
|
+
console.log(` Nutrient loss limits: ${nutrientLossLimits.length}`);
|
|
906
|
+
console.log(` Environmental rules: ${environmentalRules.length}`);
|
|
907
|
+
console.log(` FTS5 entries: ${ftsCount?.count ?? 0}`);
|
|
908
|
+
console.log(` Coverage: data/coverage.json`);
|
|
909
|
+
console.log(` Sources: data/sources.yml`);
|
|
910
|
+
|
|
911
|
+
db.close();
|