From 654152fd1b6d34b8aef25710f0b44a34f8f28575 Mon Sep 17 00:00:00 2001 From: Tetardtek Date: Mon, 16 Mar 2026 23:32:18 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20boot=20sequence=20=E2=80=94=20fresh=20f?= =?UTF-8?q?ork=20detection=20(helloWorld)=20+=20brain-setup.sh=20guided=20?= =?UTF-8?q?5=20=C3=A9tapes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agents/helloWorld.md | 63 ++++++++++- scripts/brain-setup.sh | 251 ++++++++++++++++++----------------------- 2 files changed, 169 insertions(+), 145 deletions(-) diff --git a/agents/helloWorld.md b/agents/helloWorld.md index 6f05543..35cac34 100644 --- a/agents/helloWorld.md +++ b/agents/helloWorld.md @@ -201,6 +201,61 @@ git -C ~/Dev/Docs/progression status --short > Si un chemin est absent : "Information manquante β€” vΓ©rifier PATHS.md" +## πŸ†• Fresh fork detection β€” prioritΓ© absolue + +**Avant tout boot normal, dΓ©tecter si c'est un fresh fork :** + +``` +Signal 1 β€” brain-compose.local.yml absent +Signal 2 β€” PATHS.md contient encore "" (placeholders actifs) +Signal 3 β€” BRAIN-INDEX.md vide + 0 claims/*.yml + +2 signaux sur 3 β†’ FRESH FORK β†’ basculer en mode setup (ci-dessous) +``` + +**Mode setup β€” protocole first boot :** + +``` +1. Annoncer : + "🧠 Fresh fork dΓ©tectΓ© β€” setup guidΓ© (5 Γ©tapes, ~15 min)" + "Je vais configurer le brain ensemble. RΓ©ponds Γ  chaque question." + +2. Γ‰tape 1 β€” Chemins machine + Demander : "Quel est le chemin absolu de ce dossier brain ?" + β†’ ex: /home/alice/Dev/Brain + Appliquer dans PATHS.md : remplacer par la valeur donnΓ©e + +3. Γ‰tape 2 β€” CLAUDE.md global + VΓ©rifier si ~/.claude/CLAUDE.md existe + Si absent : "Copier profil/CLAUDE.md.example vers ~/.claude/CLAUDE.md ?" + β†’ Si oui : indiquer la commande exacte (pas d'Γ©criture hors repo) + β†’ Demander brain_name : "Nom de cette instance ? (prod / dev / laptop…)" + +4. Γ‰tape 3 β€” brain-compose.local.yml + Copier brain-compose.local.yml.example β†’ brain-compose.local.yml + PrΓ©-remplir kernel_path avec le chemin donnΓ© en Γ©tape 1 + Demander : "Tier d'accΓ¨s ? (free / pro / full) β€” free si pas de clΓ© API" + +5. Γ‰tape 4 β€” Git remote + VΓ©rifier git remote -v β†’ si origin pointe encore sur brain-template + "Tu veux pousser vers ton propre repo ? Donne l'URL (ou 'skip')" + β†’ Si URL : git remote set-url origin + git push -u origin main + +6. Γ‰tape 5 β€” Validation + Lire brain-compose.local.yml β†’ confirmer kernel_path + brain_name + tier + bash scripts/kernel-isolation-check.sh β†’ afficher rΓ©sultat + "βœ… Brain configurΓ© β€” brain_name: | tier: " + Ouvrir le claim boot BSI (protocole standard) +``` + +**RΓ¨gles mode setup :** +- Une Γ©tape Γ  la fois β€” ne pas tout demander d'un coup +- Si l'utilisateur skip une Γ©tape β†’ noter et continuer +- Jamais Γ©crire hors du repo brain/ (CLAUDE.md = instruction, pas Γ©criture) +- Γ€ la fin du setup β†’ reprendre le boot normal depuis l'Γ©tape 1 ci-dessous + +--- + **Ordre de lecture obligatoire :** 1. `brain-compose.local.yml` β†’ instance active + feature_set + mode dΓ©clarΓ© + kernel_version local β†’ comparer avec `brain-compose.yml`.version @@ -219,8 +274,12 @@ git -C ~/Dev/Docs/progression status --short 8. `git -C progression/ pull --ff-only` silencieux β†’ sync satellite avant lecture (capture sessions laptop) `progression/metabolism/README.md` β†’ lire health_score derniΓ¨re session + ratio 7j + dΓ©tecter seuil conserve 9. Sinon β†’ briefing standard -9b. **RAG boot** β€” contexte additif (tier full uniquement, si brain-engine installΓ©) : - β†’ silencieux si brain-engine indisponible β€” le boot ne doit jamais Γ©chouer sur le RAG +9b. **RAG boot** β€” contexte additif (si Ollama disponible) : + ```bash + bash scripts/bsi-rag.sh + ``` + β†’ injecter l'output dans le contexte **aprΓ¨s** le briefing, avant dΓ©lΓ©gation + β†’ silencieux si Ollama indisponible ou aucun rΓ©sultat β€” le boot ne doit jamais Γ©chouer sur le RAG β†’ les fichiers dΓ©jΓ  chargΓ©s (focus.md, KERNEL.md…) sont automatiquement dΓ©dupliquΓ©s 10. **AprΓ¨s le briefing** β†’ dΓ©lΓ©guer Γ  `session-orchestrator` : β†’ passer le type de session dΓ©tectΓ© (brain / work / deploy / debug / coach / brainstorm) diff --git a/scripts/brain-setup.sh b/scripts/brain-setup.sh index 86cec15..bf762b7 100755 --- a/scripts/brain-setup.sh +++ b/scripts/brain-setup.sh @@ -1,173 +1,138 @@ #!/bin/bash -# brain-setup.sh β€” Setup complet brain sur une nouvelle machine -# Usage : bash brain-setup.sh [brain_name] [brain_root] -# Ex : bash brain-setup.sh prod-laptop ~/Dev/Brain +# brain-setup.sh β€” First boot setup (fresh fork) +# Idempotent β€” safe Γ  relancer si une Γ©tape a Γ©chouΓ©. # -# Ce script est idempotent β€” safe Γ  relancer si une Γ©tape a Γ©chouΓ©. +# Usage : bash scripts/brain-setup.sh set -euo pipefail -# ── Config ────────────────────────────────────────────────────────────────── -GITEA="git@git.tetardtek.com:Tetardtek" -BRAIN_NAME="${1:-prod-laptop}" -BRAIN_ROOT="${2:-$HOME/Dev/Brain}" +BRAIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +CLAUDE_DIR="$HOME/.claude" -REPOS=( - "brain:$BRAIN_ROOT" - "toolkit:$BRAIN_ROOT/toolkit" - "progression-coach:$BRAIN_ROOT/progression" - "brain-agent-review:$BRAIN_ROOT/reviews" - "brain-profil:$BRAIN_ROOT/profil" - "brain-todo:$BRAIN_ROOT/todo" - "brain.wiki:$BRAIN_ROOT/wiki" -) - -# ── Couleurs ───────────────────────────────────────────────────────────────── -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' -ok() { echo -e "${GREEN}βœ… $1${NC}"; } -warn() { echo -e "${YELLOW}⚠️ $1${NC}"; } -info() { echo -e " $1"; } +ok() { echo "OK $1"; } +warn() { echo "WRN $1"; } +ask() { printf "\n? %s\n> " "$1"; } echo "" -echo "╔══════════════════════════════════════════════╗" -echo "β•‘ brain-setup.sh β€” nouvelle machine β•‘" -echo "β•‘ brain_name : $BRAIN_NAME" -echo "β•‘ brain_root : $BRAIN_ROOT" -echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" +echo "=== brain-template β€” First boot setup ===" +echo " Chemin : $BRAIN_ROOT" echo "" -# ── Γ‰tape 0 β€” SSH key ──────────────────────────────────────────────────────── -echo "[ 0/5 ] VΓ©rification SSH key Gitea..." -if ! ssh -T git@git.tetardtek.com -o StrictHostKeyChecking=no 2>&1 | grep -qE "Welcome|Hi there"; then - warn "ClΓ© SSH Gitea non configurΓ©e." - info "CrΓ©er une clΓ© :" - info " ssh-keygen -t ed25519 -C 'laptop@brain'" - info " cat ~/.ssh/id_ed25519.pub" - info " β†’ Ajouter dans Gitea : Settings > SSH Keys" - echo "" - read -p " Appuie sur EntrΓ©e quand la clΓ© est ajoutΓ©e dans Gitea..." _ -fi -ok "SSH Gitea OK" +# ETAPE 1 β€” PATHS.md +echo "--- 1/5 Chemins machine ---" +if grep -q '' "$BRAIN_ROOT/PATHS.md" 2>/dev/null; then + ask "Chemin absolu du brain [Entree = $BRAIN_ROOT]" + read -r brain_path; brain_path="${brain_path:-$BRAIN_ROOT}" -# ── Γ‰tape 1 β€” Cloner les satellites ────────────────────────────────────────── -echo "" -echo "[ 1/5 ] Clonage des satellites..." -for entry in "${REPOS[@]}"; do - repo="${entry%%:*}" - dest="${entry#*:}" - dest="${dest/#\~/$HOME}" + ask "Chemin projets [ex: $HOME/Dev/Projects]" + read -r projects_path; projects_path="${projects_path:-$HOME/Dev/Projects}" - if [[ -d "$dest/.git" ]]; then - info "$repo β†’ dΓ©jΓ  clonΓ© ($dest) β€” git pull..." - git -C "$dest" pull --ff-only 2>/dev/null || warn "$repo : pull Γ©chouΓ© (conflits ?) β€” vΓ©rifier manuellement" - else - mkdir -p "$(dirname "$dest")" - git clone "$GITEA/$repo.git" "$dest" - ok "$repo β†’ $dest" - fi -done -ok "Tous les satellites clonΓ©s" + ask "URL Git [ex: git@github.com:alice]" + read -r gitea_url; gitea_url="${gitea_url:-git@github.com:}" -# ── Γ‰tape 2 β€” CLAUDE.md ────────────────────────────────────────────────────── -echo "" -echo "[ 2/5 ] Configuration CLAUDE.md..." -CLAUDE_TARGET="$HOME/.claude/CLAUDE.md" -CLAUDE_EXAMPLE="$BRAIN_ROOT/profil/CLAUDE.md.example" + ask "Username Git" + read -r username; username="${username:-}" -mkdir -p "$HOME/.claude" - -if [[ -f "$CLAUDE_TARGET" ]]; then - warn "~/.claude/CLAUDE.md existe dΓ©jΓ  β€” backup β†’ CLAUDE.md.bak" - cp "$CLAUDE_TARGET" "$CLAUDE_TARGET.bak" -fi - -cp "$CLAUDE_EXAMPLE" "$CLAUDE_TARGET" -sed -i "s||$BRAIN_ROOT|g" "$CLAUDE_TARGET" -sed -i "s||$BRAIN_NAME|g" "$CLAUDE_TARGET" -ok "~/.claude/CLAUDE.md configurΓ© (brain_name=$BRAIN_NAME, brain_root=$BRAIN_ROOT)" - -# ── Γ‰tape 3 β€” brain-compose.local.yml ──────────────────────────────────────── -echo "" -echo "[ 3/5 ] brain-compose.local.yml..." -LOCAL_COMPOSE="$BRAIN_ROOT/brain-compose.local.yml" - -if [[ -f "$LOCAL_COMPOSE" ]]; then - warn "brain-compose.local.yml existe dΓ©jΓ  β€” skip" + sed -i \ + -e "s||$brain_path|g" \ + -e "s||$projects_path|g" \ + -e "s||$gitea_url|g" \ + -e "s||$username|g" \ + -e "s||$HOME|g" \ + "$BRAIN_ROOT/PATHS.md" + ok "PATHS.md configure" else - cat > "$LOCAL_COMPOSE" << EOF -# brain-compose.local.yml β€” Registre machine ($BRAIN_NAME) -# NON VERSIONNΓ‰ β€” gitignored. + ok "PATHS.md deja configure" + brain_path="$BRAIN_ROOT" +fi -kernel_path: $BRAIN_ROOT -kernel_version: "0.5.1" -last_kernel_sync: "$(date +%Y-%m-%d)" -machine: $BRAIN_NAME -write_mode: readonly_kernel # nouvelle machine = jamais kernel writer +# ETAPE 2 β€” CLAUDE.md global +echo "" +echo "--- 2/5 CLAUDE.md global ---" +CLAUDE_MD="$CLAUDE_DIR/CLAUDE.md" +brain_name="prod" +if [ ! -f "$CLAUDE_MD" ]; then + ask "Nom de cette instance ? [prod / dev / laptop]" + read -r brain_name; brain_name="${brain_name:-prod}" + mkdir -p "$CLAUDE_DIR" + cat > "$CLAUDE_MD" << EOF +# CLAUDE.md -instances: - $BRAIN_NAME: - path: $BRAIN_ROOT - brain_name: $BRAIN_NAME - feature_set: full - mode: prod - docs_fetch: ask - config_status: hydrated - active: true +brain_root: ${brain_path:-$BRAIN_ROOT} +brain_name: $brain_name + +## Bootstrap + +0. ${brain_path:-$BRAIN_ROOT}/PATHS.md +1. ${brain_path:-$BRAIN_ROOT}/profil/collaboration.md +2. ${brain_path:-$BRAIN_ROOT}/agents/coach.md +3. ${brain_path:-$BRAIN_ROOT}/agents/helloWorld.md + +helloWorld prend le relais. EOF - ok "brain-compose.local.yml créé" -fi - -# ── Lock kernel push (nouvelle machine = readonly) ──────────────────────────── -git -C "$BRAIN_ROOT" remote set-url --push origin no_push -ok "Kernel push lockΓ©e (write_mode: readonly_kernel)" - -# ── Γ‰tape 4 β€” MYSECRETS ────────────────────────────────────────────────────── -echo "" -echo "[ 4/5 ] MYSECRETS..." -MYSECRETS="$BRAIN_ROOT/MYSECRETS" - -if [[ -f "$MYSECRETS" ]]; then - ok "MYSECRETS prΓ©sent" + ok "~/.claude/CLAUDE.md cree (brain_name: $brain_name)" else - warn "MYSECRETS absent β€” jamais versionnΓ©." - info "" - info "Options pour le rΓ©cupΓ©rer :" - info " A) Copie sΓ©curisΓ©e depuis le desktop :" - info " scp tetardtek@:~/Dev/Brain/MYSECRETS $MYSECRETS" - info "" - info " B) RecrΓ©er manuellement :" - info " cp $BRAIN_ROOT/MYSECRETS.example $MYSECRETS (si le fichier exemple existe)" - info " β†’ Remplir les valeurs manuellement" - info "" - warn "Le brain fonctionne sans MYSECRETS mais les sessions secrets seront bloquΓ©es." + ok "~/.claude/CLAUDE.md existe" + brain_name=$(grep 'brain_name:' "$CLAUDE_MD" | sed 's/.*: *//' | tr -d ' ' | head -1 || echo "prod") fi -# ── Γ‰tape 5 β€” Claude Code ──────────────────────────────────────────────────── +# ETAPE 3 β€” brain-compose.local.yml echo "" -echo "[ 5/5 ] Claude Code..." -if command -v claude &>/dev/null; then - ok "Claude Code installΓ© ($(claude --version 2>/dev/null || echo 'version inconnue'))" +echo "--- 3/5 brain-compose.local.yml ---" +LOCAL="$BRAIN_ROOT/brain-compose.local.yml" +tier="free" +if [ ! -f "$LOCAL" ]; then + ask "Tier ? [free / pro / full]" + read -r tier; tier="${tier:-free}" + api_key="" + if [ "$tier" != "free" ]; then + ask "Cle API" + read -r api_key + fi + cat > "$LOCAL" << EOF +brain_name: $brain_name +kernel_path: ${brain_path:-$BRAIN_ROOT} +tier: $tier +$([ -n "${api_key:-}" ] && echo "api_key: $api_key" || echo "# api_key: (tier free)") +instances: + $brain_name: + path: ${brain_path:-$BRAIN_ROOT} + brain_name: $brain_name +EOF + ok "brain-compose.local.yml cree (tier: $tier)" else - warn "Claude Code non installΓ©." - info " npm install -g @anthropic-ai/claude-code" - info " ou : https://claude.ai/code" + ok "brain-compose.local.yml existe" fi -# ── RΓ©sumΓ© ──────────────────────────────────────────────────────────────────── +# ETAPE 4 β€” Git remote echo "" -echo "╔══════════════════════════════════════════════╗" -echo "β•‘ Setup terminΓ© β•‘" -echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" +echo "--- 4/5 Git remote ---" +current_origin=$(git -C "$BRAIN_ROOT" remote get-url origin 2>/dev/null || echo "") +if echo "$current_origin" | grep -q "brain-template"; then + ask "URL de TON repo ? (skip pour ignorer)" + read -r new_remote + if [ "$new_remote" != "skip" ] && [ -n "$new_remote" ]; then + git -C "$BRAIN_ROOT" remote set-url origin "$new_remote" + git -C "$BRAIN_ROOT" remote add upstream "$current_origin" 2>/dev/null || true + ok "origin -> $new_remote / upstream -> brain-template" + else + warn "Remote non modifie" + fi +else + ok "Remote : $current_origin" +fi + +# ETAPE 5 β€” Validation echo "" -echo " brain_name : $BRAIN_NAME" -echo " brain_root : $BRAIN_ROOT" +echo "--- 5/5 Validation ---" +bash "$BRAIN_ROOT/scripts/kernel-isolation-check.sh" 2>&1 | tail -2 + echo "" -echo " Prochaine Γ©tape :" -echo " β†’ Ouvrir Claude Code dans $BRAIN_ROOT" -echo " β†’ Le brain se boot automatiquement via CLAUDE.md" +echo "=== Setup termine ===" echo "" -warn "Si MYSECRETS est absent : le remplir avant la premiΓ¨re session work." +echo " brain_name : ${brain_name:-prod}" +echo " tier : ${tier:-free}" +echo " brain_root : ${brain_path:-$BRAIN_ROOT}" echo "" +echo " Ouvre Claude Code dans ce dossier." +echo " Dis : 'Bonjour β€” demarre le brain (helloWorld)'"