From e40e22c949ec6775067a3309358878dddc406b7b Mon Sep 17 00:00:00 2001 From: Tetardtek Date: Sat, 21 Mar 2026 19:57:40 +0100 Subject: [PATCH] =?UTF-8?q?sync:=20kernel=20v0.8.0=20=E2=86=92=20template?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contexts/session-capital.yml | 45 +++++++++++++++++++++++ contexts/session-coach.yml | 2 +- contexts/session-deploy.yml | 46 +++++++++++++++++++++++ contexts/session-handoff.yml | 52 ++++++++++++++++++++++++++ contexts/session-infra.yml | 45 +++++++++++++++++++++++ contexts/session-urgence.yml | 45 +++++++++++++++++++++++ contexts/session-work.yml | 6 ++- docs/README.md | 1 + docs/agents.md | 32 ++++++++++++---- docs/architecture.md | 2 +- docs/getting-started.md | 71 ++++++++++++++++++++++-------------- docs/vue-free.md | 8 +++- docs/vue-tiers.md | 7 +++- scripts/sync-template.sh | 24 ++++++++++++ 14 files changed, 346 insertions(+), 40 deletions(-) create mode 100644 contexts/session-capital.yml create mode 100644 contexts/session-deploy.yml create mode 100644 contexts/session-handoff.yml create mode 100644 contexts/session-infra.yml create mode 100644 contexts/session-urgence.yml diff --git a/contexts/session-capital.yml b/contexts/session-capital.yml new file mode 100644 index 0000000..9c6f83b --- /dev/null +++ b/contexts/session-capital.yml @@ -0,0 +1,45 @@ +# session-capital.yml — Contexte BHP pour sessions capital professionnel +# Trigger : "brain boot mode capital" +# Focus : bilan, objectifs, CV, capital professionnel, progression long terme +# Cible : ~23% contexte max au boot + +session_type: capital +description: "Session capital — bilan, objectifs, CV, capital professionnel" +tier_required: featured # coach.md complet + capital-scribe = tier featured (RAG + progression) + +# L0 — Invariant (~5%) +L0: + - PATHS.md + - brain-compose.local.yml + - KERNEL.md + +# L1 — Session type (~18%) +L1: + - now.md # bridge session précédente + - agents/coach.md # coach complet — bilan et cap stratégique (pas boot-summary) + - profil/objectifs.md # objectifs actifs + prochaines étapes + - profil/capital.md # preuves CV, milestones, capital accumulé + - progression/README.md # état métabolique + ratio sessions + tendances + +# L2 — non applicable (capital = session introspective, pas de scope projet) +L2: + template: null + extras: [] + fallback: null + +# L3 — On demand +# progression/ détaillée, sessions passées, capital-scribe pour mise à jour capital.md +L3: + hint: "Charger à la demande : progression/ détaillée, sessions passées, capital-scribe" + +# --- Note capital --- +# capital-scribe actif automatiquement si modification capital.md détectée en session. +# Pas de projets/ en L2 — le coaching capital est orthogonal aux projets actifs. +# session-coach = réflexion stratégique ; session-capital = capital pro + CV + milestones. + +# --- Métriques cibles --- +context_target: + L0: "~5%" + L1: "~18%" + L2: "0%" + total_boot: "~23%" diff --git a/contexts/session-coach.yml b/contexts/session-coach.yml index 44874d4..72537d2 100644 --- a/contexts/session-coach.yml +++ b/contexts/session-coach.yml @@ -4,7 +4,7 @@ session_type: coach description: "Session coaching — progression, réflexion, cap stratégique, clarté" -tier_required: pro # coaching complet (coach.md 365 lignes) = feature pro +tier_required: featured # coaching complet (coach.md) = tier featured (RAG + progression) # L0 — Invariant (~5%) L0: diff --git a/contexts/session-deploy.yml b/contexts/session-deploy.yml new file mode 100644 index 0000000..6ed5bb3 --- /dev/null +++ b/contexts/session-deploy.yml @@ -0,0 +1,46 @@ +# session-deploy.yml — Contexte BHP pour sessions de déploiement +# Trigger : "brain boot mode deploy[/]" +# Cible : ~25% contexte max au boot + +session_type: deploy +description: "Session de déploiement — VPS, Docker, SSL, CI/CD, infra" +tier_required: pro # deploy = agents vps/ci-cd/monitoring (tous pro) + +# L0 — Invariant (~5%) +L0: + - PATHS.md + - brain-compose.local.yml + - KERNEL.md + +# L1 — Session type (~15%) +L1: + - now.md # état dernière session — ce qui a changé, ce qui est en attente + - focus.md # projets actifs — savoir quoi déployer + - agents/vps.md # VPS, Apache, Docker, SSL, vhost, certbot # tier: pro + - agents/ci-cd.md # pipelines, GitHub Actions, Gitea CI # tier: pro + - agents/monitoring.md # Kuma, alertes, logs post-déploiement # tier: pro + +# L2 — Project scope (~8%) — optionnel sur projet déclaré +L2: + template: "projets/{project}.md" + extras: + - "todo/{project}.md" + fallback: null + +# L3 — On demand +# Exemples : agents/security.md (audit pré-deploy), agents/mail.md (DNS/DKIM), +# agents/pm2.md, agents/migration.md, config spécifique +L3: + hint: "Charger à la demande : security pre-deploy, mail/DNS, pm2, migration schema" + +# --- Règle deploy --- +# agents/security.md NOT en L1 par défaut — deploy ≠ audit sécurité. +# Charger si audit pré-déploiement explicitement demandé (→ session-audit). +# agents/monitoring.md en L1 : toujours vérifier les alertes après deploy. + +# --- Métriques cibles --- +context_target: + L0: "~5%" + L1: "~12%" + L2: "~8%" + total_boot: "~25%" diff --git a/contexts/session-handoff.yml b/contexts/session-handoff.yml new file mode 100644 index 0000000..1d3e0df --- /dev/null +++ b/contexts/session-handoff.yml @@ -0,0 +1,52 @@ +# session-handoff.yml — Contexte BHP pour sessions HANDOFF +# Trigger : "brain boot mode HANDOFF[/]" +# Cible : ~15% contexte max au boot — minimum viable pour reprendre + +session_type: HANDOFF +description: "Reprise d'une session via handoff — contexte minimal + fichier handoff cible" +tier_required: free # handoff = protocole BSI de base — disponible pour tous + +# L0 — Invariant (~5%) +L0: + - PATHS.md + - brain-compose.local.yml + - KERNEL.md + +# L1 — Session type (~8%) — chirurgical : seulement ce qu'il faut pour reprendre +L1: + - BRAIN-INDEX.md # trouver le handoff actif + +# L2 — Handoff scope (~5%) — fichier handoff si déclaré dans le signal +# Signal : "HANDOFF/" → charger le fichier handoff directement +L2: + template: "handoffs/{handoff_id}.md" + extras: [] + fallback: + - handoffs/LATEST.md # si pas d'ID déclaré → dernier handoff + +# L3 — On demand +# Exemples : context complet projet, agents métier, focus.md +# Principe : le fichier handoff CONTIENT les pointeurs vers L3. +# La nouvelle session lit le handoff → décide elle-même quoi charger. +L3: + hint: "Lire le handoff d'abord. Il indique quoi charger en L3." + +# --- Règle HANDOFF --- +# Le handoff est la source de vérité pour la reprise. +# Ne pas charger focus.md, metabolism, agents au boot — le handoff décide. +# Après lecture du handoff → promouvoir le contexte nécessaire en L2 implicite. +# Le claim ouvert doit référencer le handoff : parent_satellite ou story_angle. + +# --- Format handoff attendu --- +# handoffs/.md doit contenir : +# - Contexte de la session précédente (état, décisions, bloquants) +# - Fichiers à charger (L3 → L2 pour cette session) +# - Todos ouverts prioritaires +# - Signal de session recommandé pour la suite + +# --- Métriques cibles --- +context_target: + L0: "~5%" + L1: "~5%" + L2: "~5%" + total_boot: "~15%" diff --git a/contexts/session-infra.yml b/contexts/session-infra.yml new file mode 100644 index 0000000..fc7ee9c --- /dev/null +++ b/contexts/session-infra.yml @@ -0,0 +1,45 @@ +# session-infra.yml — Contexte BHP pour sessions infrastructure +# Trigger : "brain boot mode infra" +# Focus : ops quotidien — monitoring, maintenance VPS, config, santé système +# Distinct de session-deploy (deploy = ship code ; infra = ops/health/maintenance) +# Cible : ~22% contexte max au boot + +session_type: infra +description: "Session infrastructure — ops quotidien, maintenance VPS, santé système" +tier_required: pro # vps, pm2, monitoring = agents pro + +# L0 — Invariant (~5%) +L0: + - PATHS.md + - brain-compose.local.yml + - KERNEL.md + +# L1 — Session type (~14%) +L1: + - now.md # bridge session précédente + - agents/coach-boot.md # présence légère — pas de bilan complet en infra + - agents/vps.md # VPS, Apache, Docker, SSL, vhost, certbot # tier: pro + - agents/pm2.md # process manager, restart, logs # tier: pro + - focus.md # projets actifs — contexte des services en cours + +# L2 — Project scope — optionnel si scope projet déclaré +L2: + template: "projets/{project}.md" + extras: [] + fallback: null + +# L3 — On demand +# agents/monitoring.md, agents/mail.md (DNS/DKIM), agents/ci-cd.md, agents/migration.md +L3: + hint: "Charger à la demande : monitoring, mail/DNS, ci-cd, migration schema, security pre-audit" + +# --- Distinction infra / deploy --- +# infra = état du système, maintenance, vérifications, config — pas de CI/CD au boot +# deploy = livraison code, CI/CD, releases, pipeline — agents/ci-cd.md en L1 + +# --- Métriques cibles --- +context_target: + L0: "~5%" + L1: "~14%" + L2: "~3%" + total_boot: "~22%" diff --git a/contexts/session-urgence.yml b/contexts/session-urgence.yml new file mode 100644 index 0000000..803feb5 --- /dev/null +++ b/contexts/session-urgence.yml @@ -0,0 +1,45 @@ +# session-urgence.yml — Contexte BHP pour sessions incident/urgence +# Trigger : "brain boot mode urgence" +# Focus : incident prod, production down, hotfix critique +# Mode conserve : automatique — cible context < 40% +# Cible : ~15% contexte max au boot (mode conserve) + +session_type: urgence +description: "Session urgence — incident prod, production down, hotfix critique" +tier_required: pro # vps, pm2, debug = agents pro + +# L0 — Invariant (~5%) +L0: + - PATHS.md + - brain-compose.local.yml + - KERNEL.md + +# L1 — Session type (~10%) — minimal, on va vite +# Coach absent : urgence avant bilan pédagogique — invocation explicite si besoin +L1: + - agents/vps.md # VPS, Apache — infra down # tier: pro + - agents/pm2.md # process manager, restart, logs # tier: pro + - agents/debug.md # diagnostic, crash, comportement inattendu + +# L2 — non applicable (urgence = focus immédiat, pas de scope projet) +L2: + template: null + extras: [] + fallback: null + +# L3 — On demand — déclenché après résolution +L3: + hint: "Après résolution : scribe (post-mortem), security (si faille), monitoring (état alertes)" + +# --- Règles urgence --- +conserve: auto # mode conserve activé automatiquement — cible context < 40% +coach: silent # coach silencieux sauf invocation explicite après résolution +# post-mortem : scribe déclenché sur signal "résolution confirmée" ou "c'est résolu" +# secrets-guardian : actif en passif — rotation clés si compromis suspects + +# --- Métriques cibles --- +context_target: + L0: "~5%" + L1: "~10%" + L2: "0%" + total_boot: "~15%" diff --git a/contexts/session-work.yml b/contexts/session-work.yml index f3372e2..7de05c5 100644 --- a/contexts/session-work.yml +++ b/contexts/session-work.yml @@ -16,10 +16,14 @@ L0: L1: - now.md # bridge session précédente - focus.md # focus actuel, todos prioritaires - - agents/coach.md # coach complet byTask — observe le projet en cours + - agents/coach-boot.md # coach boot-summary — observe le projet en cours (free) - agents/debug.md # bug, crash, comportement inattendu - metabolism/README.md # état métabolique, énergie session +# L1_featured — chargé si tier: featured+ — coach complet remplace coach-boot +L1_featured: + - agents/coach.md # coach complet byTask — observe le projet en cours + # L1_pro — Session type (~5%) — chargé uniquement si tier: pro déclaré # Pas de code-review ni security pour tier free — chargement explicite sur demande sinon L1_pro: diff --git a/docs/README.md b/docs/README.md index 4af1fa8..611ec03 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,7 @@ # docs/ — Documentation humaine > Guides lisibles sans contexte brain. Pour forks, onboarding, ou quand tu veux comprendre comment ca marche. +> L'histoire du projet → [story.tetardtek.com](https://story.tetardtek.com) --- diff --git a/docs/agents.md b/docs/agents.md index 336618d..726ce23 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -1,8 +1,12 @@ # Le brain en 30 secondes -Un brain, c'est un systeme de **specialistes IA** qui travaillent ensemble. Chaque specialiste (agent) fait une chose bien : debugger, reviewer du code, deployer, ecrire des tests. Tu n'en charges jamais plus de 5 a la fois — le brain sait lesquels activer selon ce que tu fais. +## Pourquoi un brain plutot que Claude seul ? -Tu forkes le brain, tu codes. Les agents se chargent automatiquement. +Claude est puissant. Mais a chaque session, il repart de zero. Tu re-expliques ton projet, ta stack, tes conventions. Tu repetes les memes consignes. Tu perds du contexte a chaque compaction. + +Le brain resout ca : **un systeme de specialistes IA qui persistent entre sessions.** Chaque specialiste (agent) fait une chose bien — debugger, reviewer du code, deployer, ecrire des tests. Ils connaissent tes regles, ta stack, tes decisions passees. Tu n'en charges jamais plus de 5 a la fois — le brain sait lesquels activer selon ce que tu fais. + +Tu forkes le brain, tu codes. Les agents se chargent automatiquement. Ton contexte survit aux sessions. --- @@ -10,25 +14,25 @@ Tu forkes le brain, tu codes. Les agents se chargent automatiquement. > 🟢 **free — Tu forkes, ca marche** > -> **14 agents + 8 systeme. 6 sessions.** Pas de cle API, pas de config. +> **17 agents + 9 systeme. 6 sessions.** Pas de cle API, pas de config. > -> Debug, brainstorm, scribes automatiques, protection secrets, creation d'agents custom. Le coach observe en arriere-plan. +> Debug, brainstorm, scribes automatiques, protection secrets, creation d'agents custom. 3 agents d'onboarding (guide, catalogist, pathfinder) pour t'orienter. Le coach observe en arriere-plan. > 🔵 **featured — Le brain te connait** > -> **18 agents + systeme. 8 sessions.** Le coach se reveille. +> **21 agents + systeme. 8 sessions.** Le coach se reveille. > > Bilans de session, objectifs concrets, progression tracee. Le brain se souvient de tes acquis entre sessions grace a la distillation RAG. > 🟠 **pro — L'atelier complet** > -> **40 agents + systeme. 12 sessions.** Tu ship en prod. +> **42 agents + systeme. 14 sessions.** Tu ship en prod. > > Code review (7 priorites), audit securite (8 priorites OWASP), tests automatises, 3 optimiseurs perf, deploy VPS + CI/CD + SSL, sessions urgence et infra. > 🟣 **full — Ton brain, tes regles** > -> **75 agents (tous). 15 sessions.** Tu es owner. +> **81 agents (tous). 15 sessions.** Tu es owner. > > Modification du kernel, copilotage long (mode pilote), supervision multi-phase (hypervisor), coach proactif qui anticipe. @@ -66,6 +70,11 @@ Charge les agents security et code-review **Ils ne chargent que l'essentiel.** Un agent de 200 lignes → ~25 lignes au boot. Le reste se charge quand tu en as besoin. +**Premier fork ? 3 agents t'orientent.** +- `guide` — presente le systeme, repond a "c'est quoi ce truc ?" +- `catalogist` — explore ce qui est disponible (agents, tiers, features) +- `pathfinder` — t'oriente vers la bonne session selon ce que tu veux faire + --- ## Explore les agents par famille @@ -80,10 +89,19 @@ Charge les agents security et code-review --- +## Pour aller plus loin + +**L'histoire du projet** — [story.tetardtek.com](https://story.tetardtek.com) raconte le pourquoi, le parcours, les decisions. Si tu veux comprendre la vision avant de fork. + +--- + ## Nouveautes | Date | Quoi de neuf | |------|-------------| +| 2026-03-21 | 3 agents onboarding (guide, catalogist, pathfinder) — le brain accueille les nouveaux | +| 2026-03-21 | Docs live — git pull = docs a jour, zero rebuild | +| 2026-03-21 | VPS scission — vitrine template publique separee du brain prod | | 2026-03-20 | Agents 87% plus legers au boot | | 2026-03-20 | Coach adaptatif — 5 comportements selon la session | | 2026-03-20 | Fermeture fiable — sequence deterministe | diff --git a/docs/architecture.md b/docs/architecture.md index 76ec48a..3c981cf 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -10,7 +10,7 @@ Le brain c'est 3 couches : **1. Le kernel** — l'identite - Les regles qui ne changent pas (KERNEL.md, constitution, PATHS.md) -- Les agents specialises (~75 fichiers .md) +- Les agents specialises (~81 fichiers .md) - Le profil de collaboration - Le brain-compose.yml (config, tiers, modes) diff --git a/docs/getting-started.md b/docs/getting-started.md index 45309d9..305c310 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,6 +1,7 @@ # Demarrer avec le brain — le vrai tuto > Du fork au premier `brain boot`. 10 minutes. +> Envie de comprendre le projet avant de fork ? → [story.tetardtek.com](https://story.tetardtek.com) --- @@ -55,7 +56,7 @@ bash setup.sh Le script fait tout automatiquement : 1. **Cree `brain-compose.local.yml`** — ta config machine (chemins auto-detectes) -2. **Cree les dossiers satellites** — todo/, progression/, toolkit/, reviews/, workspace/ ([pourquoi ?](satellites.md)) +2. **Cree les dossiers satellites** — todo/, progression/, toolkit/, reviews/, workspace/ 3. **Copie `profil/collaboration.md`** — regles de travail 4. **Build le dashboard** — `brain-ui/` (npm install + vite build) 5. **Init brain-engine** — cree l'environnement Python + brain.db @@ -98,45 +99,48 @@ Brain-engine c'est le serveur local qui fait tourner l'API, le dashboard, et la ### Demarrer ```bash +cd ~/Dev/Brain bash brain-engine/start.sh ``` -Brain-engine demarre en arriere-plan. Tu vois : +Tu vois : ``` -✅ brain-engine demarre (PID 12345) - Logs : tail -f brain-engine/brain-engine.log - Arreter : bash brain-engine/stop.sh +=== Lancement brain-engine sur port 7700 === + Health : http://localhost:7700/health + Dashboard : http://localhost:7700/ui/ ``` +> **Le terminal reste occupe** — brain-engine tourne au premier plan. Ouvre un autre terminal pour la suite. + ### Verifier -```bash -bash brain-engine/status.sh -``` - -Ou ouvre ton navigateur : `http://localhost:7700/ui/` +Ouvre ton navigateur : `http://localhost:7700/ui/` Tu vois le dashboard avec l'onglet Docs — c'est cette documentation. ### Arreter -```bash -bash brain-engine/stop.sh -``` - -### Mode debug (optionnel) - -Si tu veux voir les logs en direct dans le terminal : - -```bash -bash brain-engine/start.sh --foreground -``` - -`Ctrl+C` pour arreter. +Reviens dans le terminal ou brain-engine tourne et fais `Ctrl+C`. C'est tout. > Brain-engine n'est pas obligatoire pour utiliser le brain avec Claude Code. > C'est un bonus (dashboard, search, API). Tu peux faire `brain boot` sans. +### Lancer en arriere-plan (optionnel) + +Si tu ne veux pas bloquer un terminal : + +```bash +cd ~/Dev/Brain +nohup bash brain-engine/start.sh > /tmp/brain-engine.log 2>&1 & +echo $! > /tmp/brain-engine.pid +``` + +Pour l'arreter : + +```bash +kill $(cat /tmp/brain-engine.pid) +``` + --- ## Etape 6 — Premier brain boot @@ -220,11 +224,8 @@ claude ### Brain-engine tourne encore en fond, comment l'arreter ? -```bash -bash brain-engine/stop.sh -``` - -Pour verifier s'il tourne : `bash brain-engine/status.sh` +Si tu l'as lance au premier plan : `Ctrl+C` dans son terminal. +Si tu l'as lance en arriere-plan : `kill $(cat /tmp/brain-engine.pid)` En dernier recours : `pkill -f 'python3.*server.py'` ### Je vois "MYSECRETS absent" — c'est grave ? @@ -243,6 +244,20 @@ git fetch upstream git merge upstream/main ``` +### J'utilise Gitea self-hosted et git clone echoue ? + +Gitea en Docker ecoute souvent sur un port SSH non standard (2222 au lieu de 22). Ajoute dans `~/.ssh/config` : + +``` +Host git.example.com + HostName git.example.com + Port 2222 + User git + IdentityFile ~/.ssh/id_ed25519 +``` + +Puis ajoute la host key : `ssh-keyscan -p 2222 git.example.com >> ~/.ssh/known_hosts` + ### Ou est la documentation complete ? - Dashboard : `http://localhost:7700/ui/` → onglet Docs diff --git a/docs/vue-free.md b/docs/vue-free.md index 1b66471..9eb8e03 100644 --- a/docs/vue-free.md +++ b/docs/vue-free.md @@ -1,6 +1,6 @@ # 🟢 free — Ce que tu as -> 🟢 **14 agents invocables + 8 systeme. 6 sessions. Pas de cle, pas de config.** +> 🟢 **17 agents invocables + 9 systeme. 6 sessions. Pas de cle, pas de config.** --- @@ -36,6 +36,12 @@ - `pattern-scribe` — detection patterns recurrents - `time-anchor` — conscience temporelle, recontextualisation +**S'orienter** + +- `guide` — presentation du systeme, accueil fresh fork +- `catalogist` — exploration des registres (agents, tiers, features) +- `pathfinder` — routage intentionnel, oriente vers la bonne session + --- ## Agents systeme diff --git a/docs/vue-tiers.md b/docs/vue-tiers.md index 3301a8d..d852ea1 100644 --- a/docs/vue-tiers.md +++ b/docs/vue-tiers.md @@ -7,7 +7,7 @@ ## 🟢 free — Ce que tu as -> 🟢 **14 agents invocables + 8 systeme. 6 sessions.** +> 🟢 **17 agents invocables + 9 systeme. 6 sessions.** ### Sessions @@ -37,6 +37,11 @@ - `pattern-scribe` — detection patterns recurrents - `time-anchor` — conscience temporelle, recontextualisation +**S'orienter** +- `guide` — presentation du systeme, accueil fresh fork +- `catalogist` — exploration des registres (agents, tiers, features) +- `pathfinder` — routage intentionnel, oriente vers la bonne session + ### Agents systeme (tournent a chaque boot) - `helloWorld` — briefing, claim BSI diff --git a/scripts/sync-template.sh b/scripts/sync-template.sh index bbdabff..fe91b48 100755 --- a/scripts/sync-template.sh +++ b/scripts/sync-template.sh @@ -92,6 +92,30 @@ if [ -d "$BRAIN_ROOT/wiki" ]; then fi fi +# --- Docs --- +echo "" +echo "── docs/ ───────────────────────────────────────" +if [ -d "$BRAIN_ROOT/docs" ]; then + if [ -z "$DRY" ]; then + mkdir -p "$TEMPLATE_DIR/docs" + rsync -a --delete "$BRAIN_ROOT/docs/" "$TEMPLATE_DIR/docs/" + fi + doc_count=$(ls "$BRAIN_ROOT/docs/"*.md 2>/dev/null | wc -l | tr -d ' ') + echo " ✅ $doc_count docs" +fi + +# --- Contexts --- +echo "" +echo "── contexts/ ──────────────────────────────────" +if [ -d "$BRAIN_ROOT/contexts" ]; then + if [ -z "$DRY" ]; then + mkdir -p "$TEMPLATE_DIR/contexts" + rsync -a --delete "$BRAIN_ROOT/contexts/" "$TEMPLATE_DIR/contexts/" + fi + ctx_count=$(ls "$BRAIN_ROOT/contexts/"*.yml 2>/dev/null | wc -l | tr -d ' ') + echo " ✅ $ctx_count contexts" +fi + # --- Gitkeep --- [ -z "$DRY" ] && mkdir -p "$TEMPLATE_DIR/locks" && \ touch "$TEMPLATE_DIR/locks/.gitkeep"