Files
veye-lalwa/prompt-kimi-cli-veille-legislative.md
T

170 lines
18 KiB
Markdown
Raw Permalink Normal View History

# PROMPT POUR KIMI CLI — Plateforme « Veille Législative Guadeloupe »
> Copie-colle l'intégralité de ce fichier comme instruction initiale à Kimi CLI, lancé à la racine d'un dossier projet vide dans lequel tu auras préalablement copié les fichiers d'entrée listés en §2.
---
## 1. Rôle et mission
Tu es un développeur full-stack senior spécialisé SvelteKit, Python et systèmes de veille documentaire. Ta mission : construire une **plateforme web de veille législative française** (lois, projets de loi, propositions de loi, décisions du Conseil constitutionnel) focalisée sur les **impacts sur les libertés des individus, des associations et des entreprises, avec un zoom Guadeloupe/outre-mer**.
La plateforme a deux composantes inséparables :
1. **Un pipeline d'automatisation Python** qui ingère les fichiers de recherche existants (seed), puis met à jour la base en continu depuis les sources officielles (Légifrance, Assemblée nationale, Sénat, Conseil constitutionnel).
2. **Une application web SvelteKit** présentant ces données avec recherche plein texte, filtres à facettes, vues calendaires et pages de détail.
Travaille en itérations vérifiables : chaque phase se termine par des commandes de test exécutables et un rapport de ce qui fonctionne. N'invente jamais de données : si une source est indisponible, code une dégradation gracieuse et documente-la.
## 2. Fichiers d'entrée (déjà générés — à ingérer)
J'ai copié dans `./data/input/` l'ensemble des livrables d'une recherche approfondie (date d'arrêté : 25 juillet 2026, périmètre : 1er mai → 30 septembre 2026). **Inventaire et rôle de chaque fichier :**
| Fichier | Rôle dans le pipeline |
|---|---|
| `./data/input/lois-france-2026-guadeloupe.agent.final.md` | Rapport consolidé complet (~37 000 mots, 10 chapitres + bibliographie) — **source de vérité métier** pour le seed |
| `./data/input/lois-france-2026-guadeloupe.agent.outline.md` | Plan du rapport — utile pour la taxonomie des chapitres |
| `./data/input/lois-france-2026-guadeloupe_ref.md` | Bibliographie consolidée (481 références) — **source des URLs de citation** à rattacher aux entrées |
| `./data/input/lois-france-2026-guadeloupe_sec00.md``sec10.md` | Les 11 chapitres séparés (sec00 = synthèse exécutive, sec10 = **annexe avec 2 tableaux structurés : 27 lois promulguées + ~22 textes en attente** — parsing prioritaire pour le seed) |
| `./data/input/research/lois-2026_dim01.md``dim12.md` | 12 rapports de dimension avec blocs structurés `Claim / Source / URL / Date / Excerpt / Confidence`**matière brute sourcée** (dim07 et dim12 = outre-mer/Guadeloupe, dim04 = loi Riposte, dim08 = entreprises, dim09 = associations, dim11 = calendrier) |
| `./data/input/research/lois-2026_cross_verification.md` | Tiers de confiance (high/medium/low) + conflits tranchés — **à stocker comme métadonnée de confiance** sur chaque entrée |
| `./data/input/research/lois-2026_insight.md` | 7 insights transversaux — à exposer comme « analyses » dans l'UI |
| `./data/input/research/lois-2026_phase5_validation.md` | 5 verdicts factuels tranchés (sources primaires) — règle de résolution de conflits pour le pipeline |
| `./data/input/plan.md` | Plan de travail initial (contexte) |
**Consignes d'ingestion :**
- Écris un parseur Python (`pipeline/seed_from_research.py`) qui extrait des fichiers ci-dessus un maximum d'entrées structurées. Les tableaux markdown de `sec10.md` sont le chemin le plus fiable pour les statuts et numéros ; les blocs `Claim/Source/URL/Date` des dim files fournissent citations et extraits.
- Chaque fait importé conserve sa **citation d'origine** (URL + date + extrait verbatim) et son **niveau de confiance**.
- Le format des marqueurs `[^dimXX-N^]` dans les chapitres permet de relier un fait du rapport à sa source dans les dim files : implémente cette résolution.
- Ne perds aucune entrée : objectif ≥ 49 textes législatifs au seed (27 promulgués + ~22 en attente/en navette).
## 3. Stack technique imposée (mes choix — ne pas dévier sans me demander)
- **Frontend** : SvelteKit 2 + Svelte 5 (runes) + TypeScript + Tailwind CSS. **SSR hybride avec `@sveltejs/adapter-node`** (je self-héberge sur VPS) — architecture de rendu détaillée et non négociable au §3bis. htmx admis pour les interactions ponctuelles si plus simple.
- **Recherche** : SQLite FTS5 côté serveur via `better-sqlite3` dans les `load` functions (recherche plein texte + filtres SQL) — pas d'Elastic, pas d'Algolia, pas de SaaS. Prévoir une abstraction pour passer à Meilisearch plus tard si le volume explose.
- **Base de données** : SQLite (fichier unique, backup = copie), accès via `better-sqlite3` ou Drizzle ORM. Migrations versionnées.
- **Pipeline** : Python 3.12, `httpx` + `selectolax`/`BeautifulSoup` pour le scraping, `pydantic` pour la validation, `structlog` pour les logs. Dépendances épinglées (`uv` ou `pip-tools`).
- **Automatisation** : `systemd timers` (pas de cron démon dépendant d'un framework ; fournir les unités `.service`/`.timer`). Fallback documenté : cron classique.
- **Licences** : stack 100 % open source, zéro tracker, zéro CDN externe (polices et assets auto-hébergés). Budget cible : tourne sur un VPS à ≤ 10 €/mois.
- **PWA** : manifest + service worker minimal (consultation hors-ligne des dernières données), mobile-first.
## 3bis. Architecture de rendu SvelteKit (décidée — ne pas dévier)
Choix d'architecture validé par analyse de la doc officielle (https://svelte.dev/docs/kit/project-types, /adapters, /page-options, /adapter-node, /adapter-static) : **« transitional app » SSR sur `@sveltejs/adapter-node`, avec prerender ciblé des pages figées**. Interdits : mode SPA (`ssr = false` global, `fallback` de adapter-static — déconseillés par la doc pour SEO/perf) ; SSG intégral (rebuild à chaque veille + `url.searchParams` interdit au prerender, incompatible avec les facettes partageables).
### Matrice de rendu par route
| Route | Option | Justification |
|---|---|---|
| `/` (tableau de bord) | SSR (défaut) | Données fraîches du dernier run pipeline, sans rebuild |
| `/recherche` | SSR (défaut) | Facettes lues côté serveur dans `url.searchParams` → URLs de filtres partageables ; FTS5 dans la `load` |
| `/textes/[slug]` | SSR (défaut) | Fiches fraîches dès que le pipeline écrit SQLite ; SEO optimal pour les contenus publics |
| `/calendrier` | SSR (défaut) | Échéances vivantes |
| `/a-propos`, `/methode` | `export const prerender = true` | Pages figées : exclues du manifest SSR, servies en statique |
| `/api/*` | `+server.js` | API JSON consommée par les `load` et réutilisable par d'autres projets |
Configuration attendue dans `svelte.config.js` :
```js
import adapter from '@sveltejs/adapter-node';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter({ precompress: true })
}
};
export default config;
```
Et dans `src/routes/a-propos/+layout.js` (ou équivalent) : `export const prerender = true;`. Ne JAMAIS poser `ssr = false` au layout racine, ni `export const csr = false` global (les pages de détail `/textes/[slug]` peuvent poser `csr = dev` pour profiter du HMR tout en restant HTML+CSS en production si elles n'ont pas d'interactivité).
### Exécution en production (systemd, documentée par la doc adapter-node)
- Service systemd de l'app web configuré en **activation par socket** (`LISTEN_PID`/`LISTEN_FDS`, socket unit sur le port interne) + `Environment=IDLE_TIMEOUT=300` : l'app se met en sommeil sans trafic et systemd la réveille à la première requête — empreinte quasi nulle sur le VPS, cohérent avec les timers du pipeline (§5).
- Reverse proxy nginx/Caddy devant, avec `ORIGIN=https://<domaine>` (ou `PROTOCOL_HEADER=x-forwarded-proto` + `HOST_HEADER=x-forwarded-host`) pour éviter l'erreur « Cross-site POST form submissions are forbidden ».
- Variables en production : `node --env-file=.env build` (Node ≥ 20.6) — les `.env` ne sont PAS chargés automatiquement en prod.
- Fournir les unités `systemd/veille-web.service` + `veille-web.socket` documentées dans le README, en plus des timers du pipeline.
- `precompress: true` + compression gérée au niveau du reverse proxy.
## 4. Modèle de données (SQLite)
Table principale `textes` (adapter les noms mais conserver la sémantique) :
- `id` (slug : ex. `loi-2026-491`, `pjl-pacte-migration`, `dc-2026-915`)
- `numero_officiel` (ex. « 2026-491 », nullable), `type` (`loi` | `loi_organique` | `pjl` | `ppl` | `ordonnance` | `decision_cc` | `decret` | `accord_international`)
- `titre_court`, `titre_officiel`
- `statut` — enum STRICT : `promulguee` | `adoptee_non_promulguee` | `saisie_cc` | `validee_cc` | `censuree_partiellement` | `navette` | `deposee_non_examinee` | `annoncee` | `rejetee` — avec `statut_date` (date du dernier changement)
- `date_depot`, `date_adoption`, `date_promulgation`, `date_entree_vigueur`, `prochaine_echeance`, `prochaine_echeance_label`
- `themes` (JSON array : `justice`, `securite`, `numerique`, `social`, `fiscal`, `environnement`, `agriculture`, `sante`, `memoire_patrimoine`, `outre_mer`, `economie`, `migration`, `institutions`)
- `impacts` (JSON : sous-ensembles de `individus`, `associations`, `entreprises`, chacun en `positif` | `negatif` | `mixte` | `neutre`, avec note courte)
- `guadeloupe_pertinence` (`forte` | `moyenne` | `faible`) + `guadeloupe_note` (texte court)
- `resume` (français, 3-5 phrases), `points_cles` (JSON array)
- `confiance` (`high` | `medium` | `low`), `source_seed` (fichier d'origine)
- `derniere_verif` (timestamp pipeline)
Tables liées : `sources` (url, titre, editeur, date, tier `T1|T2`, extrait_verbatim, FK texte), `evenements` (timeline par texte : date, type d'étape, description, source), `decisions_cc` (numéro d'affaire, date saisine, date décision, résultat, FK texte), `veille_log` (chaque run du pipeline : timestamp, ajouts, modifications, alertes).
## 5. Phase 2 — Pipeline d'automatisation (`pipeline/`)
Écris `pipeline/update.py` exécutant, dans l'ordre :
1. **Collecte** (chaque collecteur isolé, tolérant à l'échec, avec cache HTTP et user-agent honnête) :
- Journal officiel : flux des lois/décrets récents (Légifrance — API PISTE si la clé `LEGIFRANCE_CLIENT_ID/SECRET` est présente dans `.env`, sinon scraping léger des pages de promulgations de l'Assemblée nationale : `https://www.assemblee-nationale.fr/dyn/actualites-accueil/promulgations-de-lois` et du Sénat `https://www.senat.fr/lois/index.html`).
- Assemblée nationale : dossiers législatifs récents + ordre du jour (open data AN si exploitable, sinon scraping).
- Sénat : dossiers législatifs en discussion.
- Conseil constitutionnel : décisions DC récentes (`https://www.conseil-constitutionnel.fr/decisions`) — matcher les numéros d'affaires en attente dans la base (ex. 2026-910 à 2026-915 DC au seed).
- vie-publique.fr : fil d'actualité législative (enrichissement contextuel).
2. **Matching et mise à jour** : réconciliation par `numero_officiel` puis par similarité de titre (fuzzy, seuil documenté). Changement de `statut` détecté → nouvel `evenement` en timeline + mise à jour `statut_date`. Règle de résolution de conflit : source primaire (JO/Légifrance > AN/Sénat > CC > presse), conformément au fichier `phase5_validation.md`.
3. **Classification** : heuristiques de thèmes et d'impacts (mots-clés configurables dans `pipeline/config.yaml`) pour les NOUVEAUX textes ; les entrées seedées gardent leurs valeurs manuelles. Toute classification automatique est marquée `confiance='low'` et flaggée « à vérifier » dans l'UI.
4. **Enrichissement Guadeloupe/outre-mer** : règles de détection (mots-clés : Guadeloupe, outre-mer, DROM, collectivités d'OM, chlordécone, octroi de mer, RUP…) qui posent `guadeloupe_pertinence` provisoire + flag de revue.
5. **Rapport de run** : écrit dans `veille_log` + optionnellement email/Matrix/webhook (config `.env`, désactivé par défaut).
6. **Sortie statique** : régénère `data/textes.json` (dump complet) pour le mode dégradé et le build statique.
Fournis : `systemd/veille-legislative.service` + `veille-legislative.timer` (run 2×/jour, 6h et 18h, + run intensif le dimanche pour le JO), un `Makefile` ou des scripts `just`/`npm run` pour `seed`, `update`, `dev`, `build`, et un `README-pipeline.md` (installation, clés API, dépannage). Mode `--dry-run` obligatoire. Tests : `pytest` sur les parseurs avec fixtures HTML figées.
## 6. Phase 3 — Application web (`web/` ou racine SvelteKit)
Interface **en français**, sobre et institutionnelle (pas de gadget). Pages :
- **`/` (accueil/tableau de bord)** : barre de recherche plein texte (SQLite FTS5, surlignage des correspondances), compteurs par statut, « prochaines échéances » (30 jours), derniers changements détectés par le pipeline (depuis `veille_log`), encart « point de veille » affichant les insights du fichier `lois-2026_insight.md`.
- **Filtres à facettes** (panneau latéral, combinables, reflétés dans l'URL pour partage) : statut, thème, type de texte, impact sur libertés (individus/associations/entreprises × positif/négatif/mixte), pertinence Guadeloupe, période (mois de promulgation/adoption), confiance. Chips actifs retirables.
- **Liste de résultats** : cartes compactes (titre, badges statut/thèmes/Guadeloupe, date clé, résumé 2 lignes), tri par date ou pertinence, pagination ou scroll infini. Badge visuel distinct par statut (code couleur sobre + label texte, accessibilité daltonienne).
- **`/textes/[slug]` (détail)** : résumé complet, points clés, timeline des événements, impacts par catégorie, note Guadeloupe, bloc décision CC éventuelle, **liste des sources avec URLs et extraits verbatim**, niveau de confiance affiché honnêtement, bouton copier-citation.
- **`/calendrier`** : vue chronologique aoûtoctobre 2026 (décisions CC attendues ~20-24 août, entrées en vigueur du 1er septembre, sénatoriales 27 septembre, PLF 2027) alimentée par `prochaine_echeance` + `evenements`.
- **`/a-propos/methode`** : explique la distinction promulgué/adopté/navette, la date d'arrêté des données seed, le fonctionnement du pipeline et ses limites (aucune donnée inventée ; entrées « à vérifier »).
- **API JSON** : `GET /api/textes` (query params : `q`, `statut`, `theme`, `impact`, `guadeloupe`, `from`, `to`), `GET /api/textes/[slug]`, `GET /api/echeances` — consommée par le front SvelteKit en SSR/load functions.
Accessibilité : WCAG AA (contraste, navigation clavier, aria-labels). Performance : page d'accueil < 100 Ko de JS. Aucune dépendance front superflue (pas de framework UI lourd ; composants maison + Tailwind).
## 7. Données seed attendues (garde-fous de vérification)
À l'issue du seed, ces entrées DOIVENT exister avec ces valeurs (extraits du corpus — tests d'acceptation) :
- `loi-2026-491` : chlordécone, `promulguee`, 12 juin 2026, `guadeloupe_pertinence=forte`, thèmes `sante/outre_mer/memoire_patrimoine`.
- `loi-2026-534` : fraudes sociales et fiscales, `promulguee`, 25 juin 2026, décision CC 2026-904 DC rattachée.
- `loi-riposte` : `adoptee_non_promulguee` + événement « saisie CC n° 2026-915 DC du 24 juillet 2026 », AFD 500 € dans les points clés (montant tranché par `phase5_validation.md` — pas 1 500 €).
- `ppl-aide-a-mourir` : adoption 15 juillet 2026 (291/241), 4 saisines dont n° 2026-910 DC.
- `pjl-pacte-migration` : `navette`, adoption Sénat 20 mai 2026, examen AN renvoyé à l'automne.
- `loi-2026-403` : simplification vie économique, 25 articles censurés (déc. 2026-903 DC), clause marchés publics ultramarins.
- Sénatoriales 27 septembre 2026 : la Guadeloupe n'est PAS concernée (série 2, décret 2026-301) — si l'entrée calendrier existe, elle doit être correcte.
## 8. Livrables et critères d'acceptation
1. Repo structuré : `pipeline/`, `web/` (ou racine SvelteKit), `data/`, `systemd/`, `tests/`, `README.md` (installation complète sur Debian/Ubuntu vierge), `.env.example`.
2. `make seed` (ou équivalent) : base SQLite remplie, ≥ 49 textes, 100 % des entrées avec ≥ 1 source URL, compte-rendu d'import (succès/échecs par fichier).
3. `make update --dry-run` : collecte réelle sans écriture, rapport des diffs détectés.
4. `npm run build` : build SvelteKit sans erreur ; `npm run check` : 0 erreur TypeScript.
5. `pytest` : parseurs couverts (≥ 70 % sur `pipeline/`).
6. Conformité rendu (§3bis) : grep prouvant qu'aucun layout/page ne pose `ssr = false` ; `prerender = true` présent sur `/a-propos` et `/methode` ; `adapter-node` en place ; `node build` démarre et répond sur `HOST=127.0.0.1` ; unités `veille-web.service`/`veille-web.socket` fournies.
7. Démo : recherche « chlordécone » → 1 résultat pertinent avec sources ; filtre `statut=saisie_cc` → ≥ 7 textes ; filtre `guadeloupe=forte` → liste non vide ; URL de recherche avec facettes (ex. `/recherche?statut=saisie_cc&guadeloupe=forte`) servie en SSR avec résultats identiques au rechargement direct ; page détail d'un texte avec timeline et sources.
7. Documentation des dégradations : ce qui fonctionne sans clé PISTE, ce qui la requiert.
## 9. Méthode de travail imposée
- Phase 0 : lis TOUS les fichiers de `./data/input/` (au minimum sec10, cross_verification, insight, phase5 + les dim files par survol structuré) avant d'écrire la moindre ligne ; produis un plan d'implémentation et attends ma validation.
- Une phase à la fois ; après chaque phase, exécute les tests/commandes de vérification et montre-moi la sortie réelle.
- Aucune donnée législative inventée : tout contenu vient des fichiers d'entrée ou des sources collectées, avec URL. En cas de doute, marque « à vérifier » plutôt que deviner.
- Commentaires de code en français, nommage en français pour le domaine métier.
- Ne modifie jamais les fichiers de `./data/input/` (lecture seule).
Commence par la Phase 0.