From 69c91cb6614054ba34f6631543a8f1cf066efd34 Mon Sep 17 00:00:00 2001 From: Archicratia Date: Mon, 16 Mar 2026 21:14:41 +0100 Subject: [PATCH] docs: formalize localhost auto-sync architecture --- docs/OPS-LOCALHOST-AUTO-SYNC.md | 964 ++++++++++++++++++++++++++++++++ docs/START-HERE.md | 645 ++++++++++++++++++--- 2 files changed, 1540 insertions(+), 69 deletions(-) create mode 100644 docs/OPS-LOCALHOST-AUTO-SYNC.md diff --git a/docs/OPS-LOCALHOST-AUTO-SYNC.md b/docs/OPS-LOCALHOST-AUTO-SYNC.md new file mode 100644 index 0000000..c426481 --- /dev/null +++ b/docs/OPS-LOCALHOST-AUTO-SYNC.md @@ -0,0 +1,964 @@ +# OPS — Localhost auto-sync + +## Objet + +Ce document fige l’architecture locale qui permet de garder le **localhost éditorial** aligné sur `origin/main`, sans dépendre de la mémoire de l’opérateur. + +But recherché : + +- quand une PR est mergée sur `main`, le **localhost** doit pouvoir se réaligner automatiquement ; +- le serveur local Astro doit tourner depuis un **worktree dédié** ; +- le dépôt de développement principal ne doit pas être pollué par ce mécanisme ; +- l’exploitation doit rester simple à diagnostiquer ; +- l’installation doit pouvoir être **réappliquée proprement** après oubli, incident, ou redémarrage machine. + +--- + +## Principes + +L’architecture locale repose sur **trois espaces distincts** : + +1. **Repo canonique de développement** + - Chemin : + `/Volumes/FunIA/dev/archicratie-edition/site` + - Usage : + développement normal, nouvelles fonctionnalités, corrections manuelles, branches de travail, commits, PR. + +2. **Worktree localhost dédié** + - Chemin : + `~/ops-local/archicratie/localhost-worktree` + - Branche locale : + `localhost-sync` + - Usage : + exécuter `astro dev` sur une copie locale réalignée automatiquement sur `origin/main`. + +3. **Ops local hors repo** + - Chemin : + `~/ops-local/archicratie` + - Usage : + scripts d’exploitation, logs, état, automatisation LaunchAgent. + +--- + +## Pourquoi cette séparation + +Il ne faut pas utiliser le dépôt de développement principal comme serveur localhost permanent. + +Sinon on mélange : + +- travail en cours ; +- commits non poussés ; +- essais temporaires ; +- état réellement publié sur `main`. + +Le résultat devient ambigu. + +Le **worktree localhost** sert donc de **miroir exécutable de `main`**, tandis que le repo canonique reste l’espace de développement. + +--- + +## Vue d’ensemble + +Flux logique : + +1. `origin/main` avance après merge d’une PR. +2. Un agent local de sync : + - fetch `origin/main` depuis le repo canonique ; + - réaligne le worktree localhost ; + - exécute `npm ci` si nécessaire ; + - déclenche le redémarrage de l’agent Astro local. +3. Un agent Astro local : + - démarre `astro dev` depuis le worktree localhost ; + - écoute sur `127.0.0.1:4321`. +4. Le site local accessible sur `http://127.0.0.1:4321` reflète alors `main`. + +--- + +## Référence des chemins + +### Repo canonique + +```text +/Volumes/FunIA/dev/archicratie-edition/site +``` + +### Worktree localhost + +```text +/Users/s-funia/ops-local/archicratie/localhost-worktree +``` + +### Ops local + +```text +/Users/s-funia/ops-local/archicratie +``` + +### Scripts principaux + +```text +/Users/s-funia/ops-local/archicratie/auto-sync-localhost.sh +/Users/s-funia/ops-local/archicratie/run-astro-localhost.sh +/Users/s-funia/ops-local/archicratie/doctor-localhost.sh +/Users/s-funia/ops-local/archicratie/install-localhost-sync.sh +``` + +### Logs ops + +```text +/Users/s-funia/ops-local/archicratie/logs/auto-sync-localhost.log +/Users/s-funia/ops-local/archicratie/logs/astro-localhost.log +``` + +### État du dernier sync + +```text +/Users/s-funia/ops-local/archicratie/last-sync.env +``` + +### LaunchAgents + +```text +~/Library/LaunchAgents/me.archicratie.localhost-sync.plist +~/Library/LaunchAgents/me.archicratie.localhost-astro.plist +``` + +### Logs launchd + +```text +~/Library/Logs/archicratie-localhost-sync.out.log +~/Library/Logs/archicratie-localhost-sync.err.log +~/Library/Logs/archicratie-localhost-astro.out.log +~/Library/Logs/archicratie-localhost-astro.err.log +``` + +--- + +## Architecture retenue + +### 1. Le repo canonique + +Le repo canonique reste la source locale de travail : + +```bash +cd /Volumes/FunIA/dev/archicratie-edition/site +``` + +C’est ici qu’on fait : + +- création de branches ; +- développement ; +- tests manuels de nouvelles fonctionnalités ; +- commits ; +- pushes ; +- PR. + +### 2. Le worktree localhost + +Le localhost ne tourne **pas** depuis le repo canonique. +Il tourne depuis un worktree dédié : + +```bash +cd ~/ops-local/archicratie/localhost-worktree +git branch --show-current +``` + +Branche attendue : + +```text +localhost-sync +``` + +Ce worktree suit `origin/main` via le script d’auto-sync. + +### 3. Le dossier ops local + +Les scripts d’exploitation ne doivent pas être mis dans le repo, ni sur un volume externe soumis à des restrictions de lancement. +Ils sont placés sous `HOME` : + +```text +~/ops-local/archicratie +``` + +Motif : + +- compatibilité avec `launchd` ; +- logs persistants ; +- visibilité claire ; +- indépendance du dépôt. + +--- + +## Pourquoi les scripts et le worktree localhost ne sont plus sur `/Volumes/...` + +Deux difficultés réelles ont été rencontrées. + +### 1. Exécution LaunchAgent depuis un volume externe + +Erreur observée : + +```text +/bin/bash: /Volumes/FunIA/dev/_ops-local/archicratie/auto-sync-localhost.sh: Operation not permitted +``` + +Conclusion : + +- le LaunchAgent peut échouer si le script est lancé depuis un chemin sur volume externe ; +- le plus robuste est de placer les scripts ops sous `HOME`. + +### 2. Exécution Astro depuis l’ancien localhost sous `/Volumes/...` + +Erreur observée : + +```text +Error: EPERM: operation not permitted, open '/Volumes/FunIA/dev/archicratie-localhost/node_modules/astro/bin/astro.mjs' +``` + +Conclusion : + +- l’ancien localhost situé sur `/Volumes/FunIA/dev/archicratie-localhost` n’est **plus** une base fiable pour l’exploitation automatisée ; +- le worktree localhost doit lui aussi être placé sous `HOME`. + +Donc : + +- **bon choix** : `~/ops-local/archicratie` +- **mauvais choix** : `/Volumes/FunIA/dev/_ops-local/...` +- **ancien chemin obsolète** : `/Volumes/FunIA/dev/archicratie-localhost` + +--- + +## Rôle exact du script `auto-sync-localhost.sh` + +Le script a quatre responsabilités : + +1. **Vérifier l’environnement** + - `git` + - `bash` + - `node` + - `npm` + +2. **Garantir le runtime Node** + - Node `22.x` + - npm `10.x` + +3. **Réaligner le worktree localhost** + - fetch du repo canonique ; + - s’assurer que le worktree localhost existe ; + - checkout `localhost-sync` ; + - reset hard sur `origin/main` ; + - clean si nécessaire ; + - `npm ci` si nécessaire. + +4. **Déclencher le redémarrage d’Astro** + - relancer l’agent LaunchAgent Astro ; + - laisser `run-astro-localhost.sh` porter le démarrage réel du serveur. + +--- + +## Rôle exact du script `run-astro-localhost.sh` + +Ce script a une responsabilité unique : + +- démarrer `astro dev` **depuis le worktree localhost** ; +- sur `127.0.0.1:4321` ; +- avec le bon runtime Node ; +- en produisant les logs Astro dédiés. + +Il ne doit jamais démarrer depuis le repo canonique. + +--- + +## Rôle exact du script `doctor-localhost.sh` + +Le doctor sert à produire un **diagnostic lisible et opératoire** sur : + +- le runtime Node ; +- les LaunchAgents ; +- le worktree localhost ; +- l’alignement sur `origin/main` ; +- l’état du serveur Astro ; +- la réponse HTTP de `localhost:4321` ; +- les fichiers d’état et les logs. + +C’est la **commande de référence** pour savoir si l’installation est saine. + +--- + +## Rôle exact du script `install-localhost-sync.sh` + +Le script d’installation sert à **reconstruire proprement toute l’architecture locale** : + +- écrire ou réécrire `auto-sync-localhost.sh` ; +- écrire ou réécrire `run-astro-localhost.sh` ; +- écrire ou réécrire les deux LaunchAgents ; +- recharger les LaunchAgents ; +- exécuter `doctor-localhost.sh` en fin d’installation. + +C’est la **commande de réinstallation standard** après oubli, casse, dérive ou changement de configuration. + +--- + +## Runtime Node requis + +Le projet exige : + +```json +{ + "node": ">=22 <23", + "npm": ">=10 <11" +} +``` + +Le runtime retenu localement est donc : + +```text +/opt/homebrew/opt/node@22/bin/node +/opt/homebrew/opt/node@22/bin/npm +``` + +Vérification : + +```bash +"$(brew --prefix node@22)/bin/node" -v +"$(brew --prefix node@22)/bin/npm" -v +``` + +Résultat attendu : + +```text +v22.x +10.x +``` + +--- + +## LaunchAgents + +L’architecture finale repose sur **deux LaunchAgents**, avec des responsabilités distinctes. + +### 1. LaunchAgent sync + +Fichier : + +```text +~/Library/LaunchAgents/me.archicratie.localhost-sync.plist +``` + +Rôle : + +- réaligner périodiquement le worktree localhost sur `origin/main` ; +- relancer l’agent Astro si nécessaire. + +### 2. LaunchAgent Astro + +Fichier : + +```text +~/Library/LaunchAgents/me.archicratie.localhost-astro.plist +``` + +Rôle : + +- exécuter `run-astro-localhost.sh` ; +- lancer `astro dev` depuis le worktree localhost. + +--- + +## Contenu de référence du LaunchAgent sync + +```xml + + + + + Label + me.archicratie.localhost-sync + + ProgramArguments + + /bin/bash + /Users/s-funia/ops-local/archicratie/auto-sync-localhost.sh + + + RunAtLoad + + + StartInterval + 60 + + WorkingDirectory + /Users/s-funia + + EnvironmentVariables + + HOME + /Users/s-funia + PATH + /opt/homebrew/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + LANG + fr_FR.UTF-8 + LC_ALL + fr_FR.UTF-8 + + + StandardOutPath + /Users/s-funia/Library/Logs/archicratie-localhost-sync.out.log + + StandardErrorPath + /Users/s-funia/Library/Logs/archicratie-localhost-sync.err.log + + +``` + +--- + +## Contenu de référence du LaunchAgent Astro + +```xml + + + + + Label + me.archicratie.localhost-astro + + ProgramArguments + + /bin/bash + /Users/s-funia/ops-local/archicratie/run-astro-localhost.sh + + + RunAtLoad + + + KeepAlive + + + WorkingDirectory + /Users/s-funia + + EnvironmentVariables + + HOME + /Users/s-funia + PATH + /opt/homebrew/opt/node@22/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + LANG + fr_FR.UTF-8 + LC_ALL + fr_FR.UTF-8 + + + StandardOutPath + /Users/s-funia/Library/Logs/archicratie-localhost-astro.out.log + + StandardErrorPath + /Users/s-funia/Library/Logs/archicratie-localhost-astro.err.log + + +``` + +--- + +## Installation / réinstallation des LaunchAgents + +### Vérifier les plists + +```bash +plutil -lint ~/Library/LaunchAgents/me.archicratie.localhost-sync.plist +plutil -lint ~/Library/LaunchAgents/me.archicratie.localhost-astro.plist +``` + +### Recharger proprement + +```bash +launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-sync.plist 2>/dev/null || true +launchctl bootout "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-astro.plist 2>/dev/null || true + +launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-sync.plist +launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/me.archicratie.localhost-astro.plist + +launchctl kickstart -k "gui/$(id -u)/me.archicratie.localhost-sync" +launchctl kickstart -k "gui/$(id -u)/me.archicratie.localhost-astro" +``` + +### Inspecter l’état + +```bash +launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,160p' +launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,160p' +``` + +État attendu : + +- pas d’erreur `Operation not permitted` ; +- pas d’erreur `EX_CONFIG` ; +- le LaunchAgent sync tourne périodiquement ; +- le LaunchAgent Astro peut être vu comme `running`, `spawn scheduled` ou `not running` selon le moment d’observation ; +- l’état réel de vérité reste le **doctor** et la **réponse HTTP sur 4321**. + +--- + +## Vérifications de bon fonctionnement + +### 1. Vérifier que le worktree suit bien `origin/main` + +```bash +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +``` + +Les deux SHA doivent être identiques. + +### 2. Vérifier la branche du worktree localhost + +```bash +git -C ~/ops-local/archicratie/localhost-worktree branch --show-current +``` + +Résultat attendu : + +```text +localhost-sync +``` + +### 3. Vérifier le dernier état sync + +```bash +cat ~/ops-local/archicratie/last-sync.env +``` + +Exemple attendu : + +```text +LAST_SYNC_AT="2026-03-16 20:29:43" +LAST_SYNC_SHA="a1bfbf4405d1342c635caec5b219c14b83b36d5e" +LAST_SYNC_STATUS="noop" +``` + +### 4. Vérifier les logs de sync + +```bash +tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +``` + +### 5. Vérifier les logs Astro + +```bash +tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +``` + +### 6. Vérifier qu’Astro écoute bien sur 4321 + +```bash +lsof -nP -iTCP:4321 -sTCP:LISTEN +``` + +### 7. Vérifier le processus Astro exact + +```bash +PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" +ps -p "$PID" -o pid=,command= +lsof -a -p "$PID" -d cwd +``` + +Attendu : + +- commande contenant `astro dev` +- cwd = `~/ops-local/archicratie/localhost-worktree` + +### 8. Vérifier le contenu servi + +Exemple : + +```bash +curl -s http://127.0.0.1:4321/archicrat-ia/prologue/ | grep -n "taxe Zucman" +``` + +Le texte renvoyé doit correspondre à la version attendue sur `main`. + +### 9. Vérifier globalement toute l’installation + +```bash +~/ops-local/archicratie/doctor-localhost.sh +``` + +Verdict attendu : + +```text +✅ aucun problème bloquant détecté +✅ aucun avertissement +``` + +--- + +## Interprétation des statuts + +### `status=updated` + +Le worktree localhost a été réaligné sur un nouveau SHA ou nettoyé, puis l’agent Astro a été relancé. + +### `status=noop` + +Le worktree localhost était déjà aligné et le serveur local tournait correctement. +Aucun changement de contenu n’était nécessaire. + +--- + +## Usage normal au quotidien + +### Cas A — travail produit / publié + +Quand on veut simplement consulter localement l’état réel de `main` : + +- on laisse tourner les LaunchAgents ; +- on consulte `http://127.0.0.1:4321`. + +Dans ce mode, le localhost doit être considéré comme : + +**un miroir local exécutable de `origin/main`**. + +### Cas B — développement de nouvelles fonctionnalités + +Quand on veut modifier du code, tester un comportement, créer une branche : + +```bash +cd /Volumes/FunIA/dev/archicratie-edition/site +git switch -c feat/ma-branche +npm run dev +``` + +Dans ce mode, on travaille dans le **repo canonique**, pas dans le worktree localhost. + +--- + +## Règle d’or + +Il existe désormais **deux usages distincts** : + +### 1. Voir ce qui est réellement sur `main` + +Utiliser : + +```text +http://127.0.0.1:4321 +``` + +qui sert depuis : + +```text +~/ops-local/archicratie/localhost-worktree +``` + +### 2. Développer / tester du neuf + +Utiliser : + +```text +/Volumes/FunIA/dev/archicratie-edition/site +``` + +avec branche locale, commandes manuelles, tests de dev. + +--- + +## Ce qu’il ne faut pas faire + +### Ne pas développer dans le worktree localhost + +Le worktree localhost est un miroir piloté. +Il peut être reset automatiquement. + +Donc : + +- pas de commits dedans ; +- pas de modifications de fond dedans ; +- pas de dev feature dedans. + +### Ne pas utiliser le repo canonique comme miroir auto-sync + +Sinon on mélange : + +- environnement de dev ; +- état publié ; +- serveur local permanent. + +### Ne pas conserver l’ancien chemin localhost comme référence + +Le chemin : + +```text +/Volumes/FunIA/dev/archicratie-localhost +``` + +n’est plus la référence opérationnelle. +Il est obsolète pour cette architecture. + +### Ne pas déplacer les scripts ops sur un volume externe + +Sinon `launchd` peut échouer avec : + +```text +Operation not permitted +``` + +--- + +## Procédure de redémarrage machine + +Après reboot, le comportement attendu est : + +1. les LaunchAgents se rechargent ; +2. le script d’auto-sync s’exécute ; +3. le worktree localhost est réaligné ; +4. Astro redémarre sur `127.0.0.1:4321`. + +### Vérification rapide après reboot + +```bash +launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,120p' +launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,120p' +tail -n 80 ~/ops-local/archicratie/logs/auto-sync-localhost.log +lsof -nP -iTCP:4321 -sTCP:LISTEN +``` + +--- + +## Procédure de secours manuelle + +### Forcer un resync + +```bash +~/ops-local/archicratie/auto-sync-localhost.sh +``` + +### Forcer un diagnostic complet + +```bash +~/ops-local/archicratie/doctor-localhost.sh +``` + +### Réinstaller tout le dispositif + +```bash +~/ops-local/archicratie/install-localhost-sync.sh +``` + +--- + +## Symptômes fréquents et diagnostic + +### Symptôme 1 — localhost ne montre pas les dernières modifs + +Vérifier : + +```bash +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +``` + +Si les SHA diffèrent : +- le sync n’a pas tourné ; +- ou le LaunchAgent sync ne s’exécute pas. + +### Symptôme 2 — SHA bon, mais contenu web pas à jour + +Vérifier : + +```bash +lsof -nP -iTCP:4321 -sTCP:LISTEN +PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" +ps -p "$PID" -o pid=,command= +lsof -a -p "$PID" -d cwd +``` + +Cause probable : +- Astro tourne depuis le mauvais dossier ; +- ou un ancien `astro dev` manuel tourne encore ailleurs. + +### Symptôme 3 — LaunchAgent présent, mais rien ne tourne + +Vérifier : + +```bash +tail -n 80 ~/Library/Logs/archicratie-localhost-sync.err.log +tail -n 80 ~/Library/Logs/archicratie-localhost-astro.err.log +tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +``` + +Causes possibles : +- mauvais PATH ; +- Node 22 absent ; +- script non exécutable ; +- erreur dans un plist ; +- ancien chemin encore référencé ; +- worktree localhost absent ; +- `node_modules` non installés dans le worktree. + +### Symptôme 4 — erreur `Operation not permitted` + +Cause probable : +- script ops ou agent lancé depuis un chemin sous `/Volumes/...`. + +Résolution : +- conserver les scripts sous `~/ops-local/archicratie`. + +### Symptôme 5 — erreur `EBADENGINE` + +Cause probable : +- Node 23 utilisé à la place de Node 22. + +Résolution : +- forcer PATH avec `node@22` dans les LaunchAgents et dans les scripts. + +### Symptôme 6 — erreur `EPERM` sur `astro.mjs` + +Cause probable : +- Astro essaie encore de démarrer depuis l’ancien emplacement localhost ; +- ou une incohérence persiste dans les chemins des scripts. + +Résolution : +- vérifier que **tous** les scripts pointent vers `~/ops-local/archicratie/localhost-worktree` ; +- vérifier que `doctor-localhost.sh` confirme le bon cwd ; +- réinstaller via `install-localhost-sync.sh`. + +--- + +## Commandes de contrôle essentielles + +### État Git + +```bash +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +git -C ~/ops-local/archicratie/localhost-worktree branch --show-current +``` + +### État LaunchAgents + +```bash +launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,160p' +launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,160p' +``` + +### État logs + +```bash +tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +tail -n 80 ~/Library/Logs/archicratie-localhost-sync.err.log +tail -n 80 ~/Library/Logs/archicratie-localhost-astro.err.log +``` + +### État serveur + +```bash +lsof -nP -iTCP:4321 -sTCP:LISTEN +PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" +ps -p "$PID" -o pid=,command= +lsof -a -p "$PID" -d cwd +curl -I -s http://127.0.0.1:4321/ | head -n 5 +``` + +### Vérification contenu + +```bash +curl -s http://127.0.0.1:4321/archicrat-ia/prologue/ | grep -n "taxe Zucman" +``` + +--- + +## Décision d’exploitation finale + +La politique retenue est la suivante : + +- **repo canonique** = espace de développement ; +- **worktree localhost** = miroir automatique de `main` ; +- **ops sous HOME** = scripts, logs, automation ; +- **LaunchAgent sync** = réalignement périodique ; +- **LaunchAgent astro** = exécution d’Astro ; +- **Astro local** = lancé uniquement depuis le worktree localhost. + +Cette séparation rend le dispositif plus : + +- lisible ; +- robuste ; +- opérable ; +- antifragile. + +--- + +## Résumé opératoire + +### Pour voir la vérité de `main` + +Ouvrir : + +```text +http://127.0.0.1:4321 +``` + +Le serveur doit provenir de : + +```text +~/ops-local/archicratie/localhost-worktree +``` + +### Pour développer + +Travailler dans : + +```text +/Volumes/FunIA/dev/archicratie-edition/site +``` + +avec tes commandes habituelles. + +### Pour réparer vite + +```bash +~/ops-local/archicratie/doctor-localhost.sh +~/ops-local/archicratie/auto-sync-localhost.sh +``` + +### Pour tout réinstaller proprement + +```bash +~/ops-local/archicratie/install-localhost-sync.sh +``` + +--- + +## Mémoire courte + +Si un jour plus rien n’est clair, repartir de ces six commandes : + +```bash +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,120p' +launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,120p' +lsof -nP -iTCP:4321 -sTCP:LISTEN +~/ops-local/archicratie/doctor-localhost.sh +``` + +Et lire : + +```bash +tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +``` + +--- + +## Statut actuel visé + +Quand tout fonctionne correctement : + +- `~/ops-local/archicratie/localhost-worktree` pointe sur le même SHA que `origin/main` ; +- `astro dev` écoute sur `127.0.0.1:4321` ; +- son cwd est `~/ops-local/archicratie/localhost-worktree` ; +- le contenu servi correspond au contenu mergé sur `main`. + +C’est l’état de référence à préserver. \ No newline at end of file diff --git a/docs/START-HERE.md b/docs/START-HERE.md index 6e4f949..003a256 100644 --- a/docs/START-HERE.md +++ b/docs/START-HERE.md @@ -1,51 +1,147 @@ -# START-HERE — Archicratie / Édition Web (v2) -> Onboarding + exploitation “nickel chrome” (DEV → Gitea → CI → Release → Blue/Green → Edge/SSO) +# START-HERE — Archicratie / Édition Web (v3) +> Onboarding + exploitation “nickel chrome” (DEV → Gitea → CI → Release → Blue/Green → Edge/SSO → localhost auto-sync) ## 0) TL;DR (la règle d’or) -- **Gitea = source canonique**. -- **main est protégé** : toute modification passe par **branche → PR → CI → merge**. -- **Le NAS n’est pas la source** : si un hotfix est fait sur NAS, on **backporte** via PR immédiatement. -- **Le site est statique Astro** : la prod sert du HTML (nginx), l’accès est contrôlé au niveau reverse-proxy (Traefik + Authelia). + +- **Gitea = source canonique**. +- **`main` est protégée** : toute modification passe par **branche → PR → CI → merge**. +- **Le NAS n’est pas la source** : si un hotfix est fait sur NAS, il doit être **backporté immédiatement** via PR. +- **Le site est statique Astro** : la prod sert du HTML via nginx ; l’accès est contrôlé au niveau reverse-proxy (Traefik + Authelia). +- **Le localhost automatique n’est pas le repo de dev** : il tourne depuis un **worktree dédié**, synchronisé sur `origin/main`. + +--- ## 1) Architecture mentale (ultra simple) -- **DEV (Mac Studio)** : édition + tests + commit + push -- **Gitea** : dépôt canon + PR + CI (CI.yaml) -- **NAS (DS220+)** : déploiement “blue/green” - - `web_blue` (staging upstream) → `127.0.0.1:8081` - - `web_green` (live upstream) → `127.0.0.1:8082` -- **Edge (Traefik)** : route les hosts + +- **DEV canonique (Mac Studio)** : édition, dev, tests, commits, pushes +- **Gitea** : dépôt canonique, PR, CI, workflows éditoriaux +- **NAS (DS220+)** : déploiement blue/green + - `web_blue` → staging upstream → `127.0.0.1:8081` + - `web_green` → live upstream → `127.0.0.1:8082` +- **Edge (Traefik)** : routage des hosts - `staging.archicratie...` → 8081 - `archicratie...` → 8082 - **Authelia** devant, via middleware `chain-auth@file` +- **Localhost auto-sync** + - un **repo canonique de développement** + - un **worktree localhost miroir de `origin/main`** + - un **agent de sync** + - un **agent Astro** + +--- ## 2) Répertoires & conventions (repo) + ### 2.1 Contenu canon (édition) -- `src/content/**` : contenu MD / MDX canon (Astro content collections) -- `src/pages/**` : routes Astro (index, [...slug], etc.) -- `src/components/**` : composants UI (SiteNav, TOC, SidePanel, etc.) -- `src/layouts/**` : layouts (EditionLayout, SiteLayout) + +- `src/content/**` : contenu MD / MDX canon +- `src/pages/**` : routes Astro +- `src/components/**` : composants UI +- `src/layouts/**` : layouts - `src/styles/**` : CSS global ### 2.2 Annotations (pré-Édition “tickets”) + - `src/annotations//.yml` - - Exemple : `src/annotations/archicrat-ia/prologue.yml` -- Objectif : stocker “Références / Médias / Commentaires” par page et par paragraphe (`p-...`). +- Exemple : + `src/annotations/archicrat-ia/prologue.yml` + +Objectif : +stocker “Références / Médias / Commentaires” par page et par paragraphe (`p-...`). ### 2.3 Scripts (tooling / build) -- `scripts/inject-anchor-aliases.mjs` : injection aliases dans dist -- `scripts/dedupe-ids-dist.mjs` : retire IDs dupliqués dans dist -- `scripts/build-para-index.mjs` : index paragraphes (postbuild / predev) -- `scripts/build-annotations-index.mjs` : index annotations (postbuild / predev) -- `scripts/check-anchors.mjs` : contrat stabilité d’ancres (CI) + +- `scripts/inject-anchor-aliases.mjs` : injection aliases dans `dist` +- `scripts/dedupe-ids-dist.mjs` : retrait IDs dupliqués +- `scripts/build-para-index.mjs` : index paragraphes +- `scripts/build-annotations-index.mjs` : index annotations +- `scripts/check-anchors.mjs` : contrat stabilité d’ancres - `scripts/check-annotations*.mjs` : sanity YAML + médias -> Important : les scripts sont **partie intégrante** de la stabilité (IDs/ancres/indexation). -> On évite “la magie” : tout est scripté + vérifié. +> Important : ces scripts ne sont pas accessoires. +> Ils font partie du contrat de stabilité éditoriale. -## 3) Workflow Git “pro” (main protégé) -### 3.1 Cycle standard (toute modif) -en bash : +--- +## 3) Les trois espaces à ne jamais confondre + +### 3.1 Repo canonique de développement + +```text +/Volumes/FunIA/dev/archicratie-edition/site +``` + +Usage : + +- développement normal +- branches de travail +- nouvelles fonctionnalités +- corrections manuelles +- commits +- pushes +- PR + +### 3.2 Worktree localhost miroir de `main` + +```text +/Users/s-funia/ops-local/archicratie/localhost-worktree +``` + +Branche attendue : + +```text +localhost-sync +``` + +Usage : + +- exécuter le localhost automatique +- refléter `origin/main` +- ne jamais servir d’espace de développement + +### 3.3 Ops local hors repo + +```text +/Users/s-funia/ops-local/archicratie +``` + +Usage : + +- scripts d’exploitation +- état +- logs +- automatisation `launchd` + +--- + +## 4) Pourquoi cette séparation existe + +Il ne faut pas utiliser le repo canonique de développement comme serveur localhost permanent. + +Sinon on mélange : + +- travail en cours +- commits non poussés +- essais temporaires +- état réellement publié sur `main` + +Le résultat devient ambigu. + +La séparation retenue est donc : + +- **repo canonique** = espace de développement +- **worktree localhost** = miroir exécutable de `origin/main` +- **ops local** = scripts et automatisation + +C’est cette séparation qui rend le système lisible, robuste et opérable. + +--- + +## 5) Workflow Git “pro” (main protégée) + +### 5.1 Cycle standard (toute modif) + +```bash git checkout main git pull --ff-only @@ -60,37 +156,48 @@ npm run test:anchors git add -A git commit -m "xxx: description claire" git push -u origin "$BR" +``` -### 3.2 PR vers main +### 5.2 PR vers `main` -Ouvrir PR dans Gitea +- ouvrir une PR dans Gitea +- attendre une CI verte +- merger +- laisser les workflows faire le reste -CI doit être verte +### 5.3 Cas spécial : hotfix prod (NAS) -Merge PR → main +On peut faire un hotfix d’urgence côté NAS si nécessaire. -### 3.3 Cas spécial : hotfix prod (NAS) +Mais l’état final doit toujours revenir dans Gitea : -On peut faire un hotfix “urgence” en prod/staging si nécessaire… +- branche +- PR +- CI +- merge -MAIS : l’état final doit revenir dans Gitea : branche → PR → CI → merge. +--- -## 4) Déploiement (NAS) — principe -### 4.1 Release pack +## 6) Déploiement (NAS) — principe -On génère un pack “reproductible” (source + config + scripts) puis on déploie. +### 6.1 Release pack -### 4.2 Blue/Green +On génère un pack reproductible, puis on déploie. -web_blue = staging upstream (8081) +### 6.2 Blue/Green -web_green = live upstream (8082) +- `web_blue` = staging (`8081`) +- `web_green` = live (`8082`) -Edge Traefik sélectionne quel host pointe vers quel upstream. +Le reverse-proxy choisit l’upstream selon le host demandé. -## 5) Check-list “≤ 10 commandes” (happy path complet) -### 5.1 DEV (Mac) +--- +## 7) Happy path complet + +### 7.1 DEV (Mac) + +```bash git checkout main && git pull --ff-only git checkout -b chore/my-change-$(date +%Y%m%d) @@ -99,55 +206,258 @@ rm -rf .astro node_modules/.vite dist npm run build npm run test:anchors npm run dev +``` -### 5.2 Push + PR +### 7.2 Push + PR +```bash git add -A git commit -m "chore: my change" git push -u origin chore/my-change-YYYYMMDD -# ouvrir PR dans Gitea +``` -### 5.3 Déploiement NAS (résumé) +Puis ouvrir la PR dans Gitea. -Voir docs/runbooks/DEPLOY-BLUE-GREEN.md. +### 7.3 Déploiement NAS -## 6) Problèmes “classiques” + diagnostic rapide -### 6.1 “Le staging ne ressemble pas au local” +Voir : -# Comparer upstream direct 8081 vs 8082 : +```text +docs/runbooks/DEPLOY-BLUE-GREEN.md +``` +--- + +## 8) Localhost auto-sync — ce qu’il faut retenir + +Le localhost automatique sert à voir **la vérité de `main`**, pas à développer du neuf. + +### 8.1 Scripts principaux + +#### Script de sync + +```text +~/ops-local/archicratie/auto-sync-localhost.sh +``` + +Rôle : + +- fetch `origin/main` +- réaligner le worktree localhost +- lancer `npm ci` si besoin +- redéclencher l’agent Astro si nécessaire + +#### Script Astro + +```text +~/ops-local/archicratie/run-astro-localhost.sh +``` + +Rôle : + +- lancer `astro dev` +- depuis le bon worktree +- avec le bon runtime Node +- sur `127.0.0.1:4321` + +> Oui : ce script est nécessaire. +> Il isole proprement le lancement du serveur Astro dans un contexte `launchd` stable. + +### 8.2 LaunchAgents + +#### Agent sync + +```text +~/Library/LaunchAgents/me.archicratie.localhost-sync.plist +``` + +#### Agent Astro + +```text +~/Library/LaunchAgents/me.archicratie.localhost-astro.plist +``` + +### 8.3 Document de référence + +Pour tout le détail d’exploitation du localhost automatique, lire : + +```text +docs/OPS-LOCALHOST-AUTO-SYNC.md +``` + +--- + +## 9) Règle d’or : il y a deux usages locaux distincts + +### 9.1 Voir ce qui est réellement sur `main` + +Utiliser : + +```text +http://127.0.0.1:4321 +``` + +Ce localhost doit être considéré comme : + +**un miroir local exécutable de `origin/main`** + +### 9.2 Développer / tester une nouvelle fonctionnalité + +Utiliser le repo canonique : + +```bash +cd /Volumes/FunIA/dev/archicratie-edition/site +npm run dev +``` + +Donc : + +- **localhost auto-sync** = vérité de `main` +- **localhost de dev manuel** = expérimentation en cours + +Il ne faut pas les confondre. + +--- + +## 10) Ce qu’il ne faut pas faire + +### 10.1 Ne pas développer dans le worktree localhost + +Le worktree localhost est piloté automatiquement. + +Il peut être : + +- réaligné +- nettoyé +- redémarré + +Donc : + +- pas de commits dedans +- pas de dev feature dedans +- pas d’expérimentation de fond dedans + +### 10.2 Ne pas utiliser le repo canonique comme miroir auto-sync + +Sinon on mélange : + +- espace de dev +- état publié +- serveur local permanent + +### 10.3 Ne pas remettre les scripts ops sur un volume externe + +Les scripts d’ops doivent rester sous `HOME`. + +Le fait de les mettre sous `/Volumes/...` a déjà provoqué des erreurs du type : + +```text +Operation not permitted +``` + +### 10.4 Ne pas supprimer `run-astro-localhost.sh` + +Ce script fait partie de l’architecture actuelle. +Le supprimer reviendrait à réintroduire le flou entre sync Git et exécution d’Astro. + +--- + +## 11) Commandes de contrôle essentielles + +### 11.1 État global + +```bash +~/ops-local/archicratie/doctor-localhost.sh +``` + +### 11.2 État Git + +```bash +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +git -C ~/ops-local/archicratie/localhost-worktree branch --show-current +``` + +### 11.3 État LaunchAgents + +```bash +launchctl print "gui/$(id -u)/me.archicratie.localhost-sync" | sed -n '1,160p' +launchctl print "gui/$(id -u)/me.archicratie.localhost-astro" | sed -n '1,160p' +``` + +### 11.4 État logs + +```bash +tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +tail -n 80 ~/Library/Logs/archicratie-localhost-sync.err.log +tail -n 80 ~/Library/Logs/archicratie-localhost-astro.err.log +``` + +### 11.5 État serveur + +```bash +lsof -nP -iTCP:4321 -sTCP:LISTEN +PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" +ps -p "$PID" -o pid=,command= +lsof -a -p "$PID" -d cwd +``` + +### 11.6 Vérification contenu + +```bash +curl -s http://127.0.0.1:4321/archicrat-ia/prologue/ | grep -n "taxe Zucman" +``` + +--- + +## 12) Problèmes classiques + diagnostic + +### 12.1 “Le staging ne ressemble pas au local” + +Comparer les upstream directs : + +```bash curl -sS http://127.0.0.1:8081/ | head -n 2 curl -sS http://127.0.0.1:8082/ | head -n 2 +``` -# Vérifier quel routeur edge répond (header diag) : +Vérifier le routeur edge : +```bash curl -sSI -H 'Host: staging.archicratie.trans-hands.synology.me' http://127.0.0.1:18080/ \ | grep -iE 'HTTP/|location:|x-archi-router' +``` -# Lire docs/runbooks/EDGE-TRAEFIK.md. +Voir : -### 6.2 Canonical incorrect (localhost en prod) +```text +docs/runbooks/EDGE-TRAEFIK.md +``` -Cause racine : site dans Astro = PUBLIC_SITE non injecté au build. +### 12.2 Canonical incorrect -Fix canonique : voir docs/runbooks/ENV-PUBLIC_SITE.md. +Cause probable : `PUBLIC_SITE` mal injecté au build. Test : +```bash curl -sS http://127.0.0.1:8082/ | grep -oE 'rel="canonical" href="[^"]+"' | head -1 +``` -### 6.3 Contrat “anchors” en échec après migration d’URL +Voir : -Quand on déplace des routes (ex: /archicratie/archicrat-ia/* → /archicrat-ia/*), le test d’ancres peut échouer même si les IDs n’ont pas changé, car les pages ont changé de chemin. +```text +docs/runbooks/ENV-PUBLIC_SITE.md +``` -# Procédure safe : +### 12.3 Contrat anchors en échec après migration d’URL -Backup baseline : +Procédure safe : +```bash cp -a tests/anchors-baseline.json /tmp/anchors-baseline.json.bak.$(date +%F-%H%M%S) -Mettre à jour les clés (chemins) sans toucher aux IDs : - node - <<'NODE' import fs from 'fs'; const p='tests/anchors-baseline.json'; @@ -161,16 +471,213 @@ fs.writeFileSync(p, JSON.stringify(out,null,2)+'\n'); console.log('updated keys:', Object.keys(j).length, '->', Object.keys(out).length); NODE -Re-run : - npm run test:anchors +``` -## 7) Ce que l’étape 9 doit faire (orientation) +### 12.4 “Le localhost auto-sync ne montre pas les dernières modifs” -Stabiliser le pipeline “tickets → YAML annotations” +Commande réflexe : -Formaliser la spec YAML + merge + anti-doublon (voir docs/EDITORIAL-ANNOTATIONS-SPEC.md) +```bash +~/ops-local/archicratie/doctor-localhost.sh +``` -Durcir l’onboarding (ce START-HERE + runbooks) +Puis : -Éviter les régressions par tests (anchors / annotations / smoke) \ No newline at end of file +```bash +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +``` + +Si les SHA diffèrent : +- le sync n’a pas tourné +- ou l’agent sync a un problème + +### 12.5 “Le SHA est bon mais le contenu web est faux” + +Vérifier quel Astro écoute réellement : + +```bash +lsof -nP -iTCP:4321 -sTCP:LISTEN +PID="$(lsof -tiTCP:4321 -sTCP:LISTEN | head -n 1)" +ps -p "$PID" -o pid=,command= +lsof -a -p "$PID" -d cwd +``` + +Attendu : +- commande contenant `astro dev` +- cwd = `~/ops-local/archicratie/localhost-worktree` + +### 12.6 Erreur `EBADENGINE` + +Cause probable : +- Node 23 utilisé au lieu de Node 22 + +Résolution : +- forcer `node@22` dans les scripts et les LaunchAgents + +### 12.7 Erreur `Operation not permitted` + +Cause probable : +- scripts d’ops placés sous `/Volumes/...` + +Résolution : +- garder les scripts sous : + +```text +~/ops-local/archicratie +``` + +### 12.8 Erreur `EPERM` sur `astro.mjs` + +Cause probable : +- ancien worktree sur volume externe +- ancien chemin résiduel +- Astro lancé depuis un mauvais emplacement + +Résolution : +- worktree localhost sous : + +```text +~/ops-local/archicratie/localhost-worktree +``` + +- scripts cohérents avec ce chemin +- réinstallation propre via : + +```bash +~/ops-local/archicratie/install-localhost-sync.sh +``` + +--- + +## 13) Redémarrage machine + +Après reboot, le comportement attendu est : + +1. le LaunchAgent sync se recharge +2. le LaunchAgent Astro se recharge +3. le worktree localhost est réaligné +4. Astro redémarre sur `127.0.0.1:4321` + +### Vérification rapide après reboot + +```bash +~/ops-local/archicratie/doctor-localhost.sh +``` + +Si nécessaire : + +```bash +~/ops-local/archicratie/install-localhost-sync.sh +``` + +--- + +## 14) Procédure de secours manuelle + +### Forcer un sync + +```bash +~/ops-local/archicratie/auto-sync-localhost.sh +``` + +### Réinstaller proprement le dispositif local + +```bash +~/ops-local/archicratie/install-localhost-sync.sh +``` + +### Diagnostic complet + +```bash +~/ops-local/archicratie/doctor-localhost.sh +``` + +--- + +## 15) Décision d’exploitation finale + +La politique retenue est la suivante : + +- **repo canonique** = espace de développement +- **worktree localhost** = miroir automatique de `main` +- **ops sous HOME** = scripts, logs, automation +- **LaunchAgent sync** = réalignement Git +- **LaunchAgent Astro** = exécution stable du serveur local +- **Astro local** = lancé uniquement depuis le worktree localhost + +Cette séparation rend le dispositif plus : + +- lisible +- robuste +- opérable +- antifragile + +--- + +## 16) Résumé opératoire + +### Pour voir la vérité de `main` + +Ouvrir : + +```text +http://127.0.0.1:4321 +``` + +Le serveur doit provenir de : + +```text +/Users/s-funia/ops-local/archicratie/localhost-worktree +``` + +### Pour développer + +Travailler dans : + +```text +/Volumes/FunIA/dev/archicratie-edition/site +``` + +avec les commandes habituelles. + +### Pour réparer vite + +```bash +~/ops-local/archicratie/doctor-localhost.sh +~/ops-local/archicratie/auto-sync-localhost.sh +``` + +--- + +## 17) Mémoire courte + +Si un jour plus rien n’est clair, repartir de ces commandes : + +```bash +~/ops-local/archicratie/doctor-localhost.sh +git -C ~/ops-local/archicratie/localhost-worktree rev-parse HEAD +git -C /Volumes/FunIA/dev/archicratie-edition/site ls-remote origin refs/heads/main +lsof -nP -iTCP:4321 -sTCP:LISTEN +``` + +Puis lire : + +```bash +tail -n 120 ~/ops-local/archicratie/logs/auto-sync-localhost.log +tail -n 120 ~/ops-local/archicratie/logs/astro-localhost.log +``` + +--- + +## 18) Statut actuel visé + +Quand tout fonctionne correctement : + +- le worktree localhost pointe sur le même SHA que `origin/main` +- `astro dev` écoute sur `127.0.0.1:4321` +- son cwd est `~/ops-local/archicratie/localhost-worktree` +- le contenu servi correspond au contenu mergé sur `main` + +C’est l’état de référence à préserver. \ No newline at end of file -- 2.49.1