feat: boot sequence — fresh fork detection (helloWorld) + brain-setup.sh guided 5 étapes
This commit is contained in:
@@ -201,6 +201,61 @@ git -C ~/Dev/Docs/progression status --short
|
|||||||
|
|
||||||
> Si un chemin est absent : "Information manquante — vérifier PATHS.md"
|
> 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 "<BRAIN_ROOT>" (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 <BRAIN_ROOT> 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 <url> + 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: <X> | tier: <Y>"
|
||||||
|
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 :**
|
**Ordre de lecture obligatoire :**
|
||||||
1. `brain-compose.local.yml` → instance active + feature_set + mode déclaré + kernel_version local
|
1. `brain-compose.local.yml` → instance active + feature_set + mode déclaré + kernel_version local
|
||||||
→ comparer avec `brain-compose.yml`.version
|
→ 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)
|
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
|
`progression/metabolism/README.md` → lire health_score dernière session + ratio 7j + détecter seuil conserve
|
||||||
9. Sinon → briefing standard
|
9. Sinon → briefing standard
|
||||||
9b. **RAG boot** — contexte additif (tier full uniquement, si brain-engine installé) :
|
9b. **RAG boot** — contexte additif (si Ollama disponible) :
|
||||||
→ silencieux si brain-engine indisponible — le boot ne doit jamais échouer sur le RAG
|
```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
|
→ 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` :
|
10. **Après le briefing** → déléguer à `session-orchestrator` :
|
||||||
→ passer le type de session détecté (brain / work / deploy / debug / coach / brainstorm)
|
→ passer le type de session détecté (brain / work / deploy / debug / coach / brainstorm)
|
||||||
|
|||||||
@@ -1,173 +1,138 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# brain-setup.sh — Setup complet brain sur une nouvelle machine
|
# brain-setup.sh — First boot setup (fresh fork)
|
||||||
# Usage : bash brain-setup.sh [brain_name] [brain_root]
|
# Idempotent — safe à relancer si une étape a échoué.
|
||||||
# Ex : bash brain-setup.sh prod-laptop ~/Dev/Brain
|
|
||||||
#
|
#
|
||||||
# Ce script est idempotent — safe à relancer si une étape a échoué.
|
# Usage : bash scripts/brain-setup.sh
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# ── Config ──────────────────────────────────────────────────────────────────
|
BRAIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
GITEA="git@git.tetardtek.com:Tetardtek"
|
CLAUDE_DIR="$HOME/.claude"
|
||||||
BRAIN_NAME="${1:-prod-laptop}"
|
|
||||||
BRAIN_ROOT="${2:-$HOME/Dev/Brain}"
|
|
||||||
|
|
||||||
REPOS=(
|
ok() { echo "OK $1"; }
|
||||||
"brain:$BRAIN_ROOT"
|
warn() { echo "WRN $1"; }
|
||||||
"toolkit:$BRAIN_ROOT/toolkit"
|
ask() { printf "\n? %s\n> " "$1"; }
|
||||||
"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"; }
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "╔══════════════════════════════════════════════╗"
|
echo "=== brain-template — First boot setup ==="
|
||||||
echo "║ brain-setup.sh — nouvelle machine ║"
|
echo " Chemin : $BRAIN_ROOT"
|
||||||
echo "║ brain_name : $BRAIN_NAME"
|
|
||||||
echo "║ brain_root : $BRAIN_ROOT"
|
|
||||||
echo "╚══════════════════════════════════════════════╝"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# ── Étape 0 — SSH key ────────────────────────────────────────────────────────
|
# ETAPE 1 — PATHS.md
|
||||||
echo "[ 0/5 ] Vérification SSH key Gitea..."
|
echo "--- 1/5 Chemins machine ---"
|
||||||
if ! ssh -T git@git.tetardtek.com -o StrictHostKeyChecking=no 2>&1 | grep -qE "Welcome|Hi there"; then
|
if grep -q '<BRAIN_ROOT>' "$BRAIN_ROOT/PATHS.md" 2>/dev/null; then
|
||||||
warn "Clé SSH Gitea non configurée."
|
ask "Chemin absolu du brain [Entree = $BRAIN_ROOT]"
|
||||||
info "Créer une clé :"
|
read -r brain_path; brain_path="${brain_path:-$BRAIN_ROOT}"
|
||||||
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"
|
|
||||||
|
|
||||||
# ── Étape 1 — Cloner les satellites ──────────────────────────────────────────
|
ask "Chemin projets [ex: $HOME/Dev/Projects]"
|
||||||
echo ""
|
read -r projects_path; projects_path="${projects_path:-$HOME/Dev/Projects}"
|
||||||
echo "[ 1/5 ] Clonage des satellites..."
|
|
||||||
for entry in "${REPOS[@]}"; do
|
|
||||||
repo="${entry%%:*}"
|
|
||||||
dest="${entry#*:}"
|
|
||||||
dest="${dest/#\~/$HOME}"
|
|
||||||
|
|
||||||
if [[ -d "$dest/.git" ]]; then
|
ask "URL Git [ex: git@github.com:alice]"
|
||||||
info "$repo → déjà cloné ($dest) — git pull..."
|
read -r gitea_url; gitea_url="${gitea_url:-git@github.com:<USERNAME>}"
|
||||||
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"
|
|
||||||
|
|
||||||
# ── Étape 2 — CLAUDE.md ──────────────────────────────────────────────────────
|
ask "Username Git"
|
||||||
echo ""
|
read -r username; username="${username:-<USERNAME>}"
|
||||||
echo "[ 2/5 ] Configuration CLAUDE.md..."
|
|
||||||
CLAUDE_TARGET="$HOME/.claude/CLAUDE.md"
|
|
||||||
CLAUDE_EXAMPLE="$BRAIN_ROOT/profil/CLAUDE.md.example"
|
|
||||||
|
|
||||||
mkdir -p "$HOME/.claude"
|
sed -i \
|
||||||
|
-e "s|<BRAIN_ROOT>|$brain_path|g" \
|
||||||
if [[ -f "$CLAUDE_TARGET" ]]; then
|
-e "s|<PROJECTS_ROOT>|$projects_path|g" \
|
||||||
warn "~/.claude/CLAUDE.md existe déjà — backup → CLAUDE.md.bak"
|
-e "s|<GITEA_URL>|$gitea_url|g" \
|
||||||
cp "$CLAUDE_TARGET" "$CLAUDE_TARGET.bak"
|
-e "s|<USERNAME>|$username|g" \
|
||||||
fi
|
-e "s|<HOME>|$HOME|g" \
|
||||||
|
"$BRAIN_ROOT/PATHS.md"
|
||||||
cp "$CLAUDE_EXAMPLE" "$CLAUDE_TARGET"
|
ok "PATHS.md configure"
|
||||||
sed -i "s|<BRAIN_ROOT>|$BRAIN_ROOT|g" "$CLAUDE_TARGET"
|
|
||||||
sed -i "s|<BRAIN_NAME>|$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"
|
|
||||||
else
|
else
|
||||||
cat > "$LOCAL_COMPOSE" << EOF
|
ok "PATHS.md deja configure"
|
||||||
# brain-compose.local.yml — Registre machine ($BRAIN_NAME)
|
brain_path="$BRAIN_ROOT"
|
||||||
# NON VERSIONNÉ — gitignored.
|
fi
|
||||||
|
|
||||||
kernel_path: $BRAIN_ROOT
|
# ETAPE 2 — CLAUDE.md global
|
||||||
kernel_version: "0.5.1"
|
echo ""
|
||||||
last_kernel_sync: "$(date +%Y-%m-%d)"
|
echo "--- 2/5 CLAUDE.md global ---"
|
||||||
machine: $BRAIN_NAME
|
CLAUDE_MD="$CLAUDE_DIR/CLAUDE.md"
|
||||||
write_mode: readonly_kernel # nouvelle machine = jamais kernel writer
|
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_root: ${brain_path:-$BRAIN_ROOT}
|
||||||
$BRAIN_NAME:
|
brain_name: $brain_name
|
||||||
path: $BRAIN_ROOT
|
|
||||||
brain_name: $BRAIN_NAME
|
## Bootstrap
|
||||||
feature_set: full
|
|
||||||
mode: prod
|
0. ${brain_path:-$BRAIN_ROOT}/PATHS.md
|
||||||
docs_fetch: ask
|
1. ${brain_path:-$BRAIN_ROOT}/profil/collaboration.md
|
||||||
config_status: hydrated
|
2. ${brain_path:-$BRAIN_ROOT}/agents/coach.md
|
||||||
active: true
|
3. ${brain_path:-$BRAIN_ROOT}/agents/helloWorld.md
|
||||||
|
|
||||||
|
helloWorld prend le relais.
|
||||||
EOF
|
EOF
|
||||||
ok "brain-compose.local.yml créé"
|
ok "~/.claude/CLAUDE.md cree (brain_name: $brain_name)"
|
||||||
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"
|
|
||||||
else
|
else
|
||||||
warn "MYSECRETS absent — jamais versionné."
|
ok "~/.claude/CLAUDE.md existe"
|
||||||
info ""
|
brain_name=$(grep 'brain_name:' "$CLAUDE_MD" | sed 's/.*: *//' | tr -d ' ' | head -1 || echo "prod")
|
||||||
info "Options pour le récupérer :"
|
|
||||||
info " A) Copie sécurisée depuis le desktop :"
|
|
||||||
info " scp tetardtek@<desktop-ip>:~/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."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Étape 5 — Claude Code ────────────────────────────────────────────────────
|
# ETAPE 3 — brain-compose.local.yml
|
||||||
echo ""
|
echo ""
|
||||||
echo "[ 5/5 ] Claude Code..."
|
echo "--- 3/5 brain-compose.local.yml ---"
|
||||||
if command -v claude &>/dev/null; then
|
LOCAL="$BRAIN_ROOT/brain-compose.local.yml"
|
||||||
ok "Claude Code installé ($(claude --version 2>/dev/null || echo 'version inconnue'))"
|
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
|
else
|
||||||
warn "Claude Code non installé."
|
ok "brain-compose.local.yml existe"
|
||||||
info " npm install -g @anthropic-ai/claude-code"
|
|
||||||
info " ou : https://claude.ai/code"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Résumé ────────────────────────────────────────────────────────────────────
|
# ETAPE 4 — Git remote
|
||||||
echo ""
|
echo ""
|
||||||
echo "╔══════════════════════════════════════════════╗"
|
echo "--- 4/5 Git remote ---"
|
||||||
echo "║ Setup terminé ║"
|
current_origin=$(git -C "$BRAIN_ROOT" remote get-url origin 2>/dev/null || echo "")
|
||||||
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 ""
|
||||||
echo " brain_name : $BRAIN_NAME"
|
echo "--- 5/5 Validation ---"
|
||||||
echo " brain_root : $BRAIN_ROOT"
|
bash "$BRAIN_ROOT/scripts/kernel-isolation-check.sh" 2>&1 | tail -2
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Prochaine étape :"
|
echo "=== Setup termine ==="
|
||||||
echo " → Ouvrir Claude Code dans $BRAIN_ROOT"
|
|
||||||
echo " → Le brain se boot automatiquement via CLAUDE.md"
|
|
||||||
echo ""
|
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 ""
|
||||||
|
echo " Ouvre Claude Code dans ce dossier."
|
||||||
|
echo " Dis : 'Bonjour — demarre le brain (helloWorld)'"
|
||||||
|
|||||||
Reference in New Issue
Block a user