feat(template): ADRs 018-035 — 14 décisions architecturales manquantes

Synchronise le template avec les décisions fondatrices 2025-2026 :
- 018 : migration Rust strangler fig toolkit
- 023 : Cortex/Cosmos product vision
- 025 : cortex composition operator
- 026 : IPC context packet access matrix
- 027 : ambient autonomy engine
- 028 : learning loop detect-iterate
- 029 : Cosmos frontend brain
- 030 : boot mode empirical validation
- 031 : distribution model
- 032 : execution mode vs workflow
- 033/033a : embedding language strategy + zone filter
- 034 : infra separation local/VPS/template
- 035 : session pilote mode (ADR-035)

Dépersonnalisation : keys/brain.<OWNER_DOMAIN>, deciders: [<owner>]
This commit is contained in:
2026-03-18 22:38:36 +01:00
parent 519b22809b
commit 8c95b70314
14 changed files with 1762 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
---
scope: kernel
name: 018-migration-rust-strangler-fig-toolkit
type: decision
context_tier: warm
---
# ADR-018 — Migration Rust : strangler fig + toolkit pattern
> Date : 2026-03-17
> Statut : actif
> Décidé par : brainstorm session brain
---
## Contexte
Le brain-engine actuel est en Python (FastAPI). Deux problèmes émergent à mesure que le modèle d'utilisation se précise :
1. **BSI sur git n'est pas viable** pour l'async multimodal — git est synchrone et lourd. Un vrai bus d'événements async requiert un backend capable de gérer des channels, du state en mémoire, et de la persistance légère.
2. **Cold start multi-plateforme** — le modèle d'utilisation cible (session pilote + sessions doc + CLI futur) implique de tourner sur laptop, VPS, et potentiellement d'autres machines. Une dépendance Python (venv, pip, uvicorn, FastAPI) est un frein.
Rust répond aux deux : binaire unique cross-platform, `tokio` pour l'async réel, performances natives.
---
## Décision
Migration **progressive** de brain-engine vers Rust via le pattern **strangler fig** :
1. Python brain-engine reste en prod pendant toute la migration
2. Un service Rust monte en parallèle sur un port distinct
3. Apache redirige les endpoints un par un vers Rust dès qu'ils sont stables
4. Quand Rust couvre ~80% des endpoints, Python est éteint
**Ordre de migration :**
```
Phase 1 — Fondations (forge les patterns toolkit)
/health → Axum hello world + config loading
/state → tokio + pm2 query + JSON response
Phase 2 — Core read-only
/agents → SQLite read + Layer 2 gate
/workflows → état dérivé
/focus → lecture fichier
Phase 3 — Write + auth
/brain/:path → write + tier enforcement
/tier → key validation
Phase 4 — RAG (dernière, la plus Python-dépendante)
/boot → embeddings → à évaluer selon maturité Rust ML
```
---
## Toolkit pattern — KPI stonks
Chaque endpoint extrait des **patterns réutilisables** qui s'appliquent aux suivants :
```rust
// Ces 4 patterns apparaissent sur chaque endpoint
// On les forge une fois sur /health + /state
1. Auth middleware x-api-key validation
2. _is_localhost() Layer 2 gate
3. JSON response helpers 200/401/403/404
4. Config struct env vars typed config
```
**Courbe de vélocité :**
```
Endpoint 1 (/health) → 2 jours (Rust + forge toolkit)
Endpoint 2 (/state) → 4h (patterns existent)
Endpoint 3+ → 30min (composition pure)
```
Le toolkit brain-rust devient lui-même distribuable — partie du kernel open.
---
## Stack cible
| Besoin | Crate |
|--------|-------|
| HTTP async | `axum` (tokio-based) |
| Async runtime | `tokio` |
| Sérialisation | `serde` + `serde_json` |
| SQLite | `rusqlite` ou `sqlx` |
| Config env | `dotenvy` |
| Process query (pm2) | `std::process::Command` + parse JSON |
---
## Alternatives considérées
| Option | Raison du rejet |
|--------|----------------|
| Rester Python | Cold start lourd, pas de binaire unique, bus async limité |
| Greenfield Rust | Big bang = risque, Python en prod = valeur certaine à ne pas perdre |
| Go | Rust = binaire plus léger, memory safety compile-time, "le pti crab fait de l'oeil" |
| Node.js | Déjà Python en prod, pas besoin d'ajouter un 3e runtime |
---
## Conséquences
**Positives :**
- Zéro downtime pendant la migration
- Apprentissage Rust progressif sur des vrais endpoints en prod
- Chaque iteration dégage un toolkit réutilisable
- Binaire unique → cold start trivial sur toute plateforme
- BSI v2 possible : vrai bus async (tokio channels + SQLite)
**Négatives / trade-offs assumés :**
- Deux services à maintenir pendant la transition
- Phase RAG (embeddings) : Rust ML moins mature que Python — décision reportée
- Temps d'apprentissage Rust non nul sur les premières itérations
---
## Références
- Fichiers concernés : `brain-engine/` (Python, à migrer), futur `brain-engine-rs/`
- ADR-015 : architecture L1/L2
- ADR-016 : BSI → now.md (le bus async justifie Rust)
- ADR-017 : brain_state Layer 2 (premier endpoint candidat Phase 1)
- Sessions où la décision a émergé : session brain 2026-03-17

View File

@@ -0,0 +1,82 @@
---
scope: kernel
name: 023-cortex-cosmos-product-vision
type: decision
context_tier: warm
status: vision
---
# ADR-023 — CORTEX + Cosmos — Vision produit et naming
> Date : 2026-03-17
> Statut : vision — implémentation au premier push public GitHub
> Décidé par : brainstorm navigate + coach (session 2026-03-17 ~23h)
---
## Naming évolution
| Actuel | Futur | Pourquoi |
|--------|-------|----------|
| brain | **CORTEX** | Plus précis — centre de traitement, pas l'organe. Kernel cognitif. |
| brain-ui | **Cosmos** | Interface orbitale — ce qui gravite autour de CORTEX |
| projets | **Satellites** | Naturels — pas des extensions, des orbites |
**Quand renommer :** au premier push public sur GitHub. Pas avant.
Tous les repos brain-* restent inchangés jusqu'à ce moment.
---
## Architecture produit
```
CORTEX — le kernel cognitif (OS distribué, forkable)
↑ expose
Cosmos — UI orbitale (chat, clés API, secrets, feature flags)
↑ orbite
Satellites — projets, outils, contextes personnels
```
---
## Vision Cosmos (UI)
Interface Rust accessible par les bons agents au bon moment :
- Onglet **Chat** — interface principale
- Onglet **Clés API** — gestion `brain-compose.local.yml`
- Onglet **Secrets** — accès contrôlé MYSECRETS par agents autorisés
- Onglet **Features**`user.featureEnh(coach=on, frigo=on, ...)`
`user.featureEnh()` = API de personnalisation cognitive.
Chaque user configure son CORTEX comme il configure son terminal.
PayByFeature s'exprime ici — activer/désactiver selon tier + préférences.
---
## Ce que le naming révèle
CORTEX n'est pas un renommage cosmétique. C'est la formalisation de ce qui
était senti avant d'être articulé :
- Brain = organe entier (trop large)
- CORTEX = centre de traitement = kernel (précis)
- Cosmos = l'espace où les satellites gravitent (scalable à l'infini)
Le nom s'est imposé par récursivité — en voyant émerger la structure,
pas en la décidant.
---
## Coexistence avec l'existant
CORTEX coexiste avec tout ce qui a été construit.
Les ADRs 001-022 restent valides — le naming change, l'architecture non.
brain-template → cortex-template au premier push public.
---
## Références
- ADR-022 (open-core distribution) — modèle de distribution CORTEX
- brain-ui (futur Cosmos) — UI orbitale
- `keys.<OWNER_DOMAIN>` — gate PayByFeature pour user.featureEnh()

View File

@@ -0,0 +1,145 @@
---
scope: kernel
name: ADR-025
title: "CORTEX — opérateur de composition × et frontière kernel/instance"
status: accepted
date: 2026-03-18
deciders: [<owner>]
---
# ADR-025 — CORTEX : opérateur de composition × et frontière kernel/instance
## Formule canonique
```
Cosmos = CORTEX( Brain(tier | featureFlags) × (satellites + BE + distillation + RAG + coach + BACT) )
```
| Composant | Ce que c'est | Vit où |
|-----------|-------------|--------|
| **CORTEX** | Kernel forkable — invariant, contractuel | `brain-template/` |
| **Brain(tier\|flags)** | CORTEX instancié — config user, gates | `brain-compose.yml` |
| **`×`** | Opérateur de composition — contrat entre CORTEX et ses services | `profil/routing.yml` (à définir) |
| **satellites** | Repos projets qui orbitent le brain | instance locale |
| **BE** | brain-engine — MCP, RAG, embed | VPS / local |
| **distillation** | Fine-tuning local sur contenu propre | instance locale |
| **RAG** | Recherche sémantique sur les fichiers brain | brain-engine |
| **coach** | Agent coach (speech + contextuel + BACT) | kernel + tier |
| **BACT** | Brain Accumulation & Context Transfer — progression long-terme | **instance-local uniquement** |
| **Cosmos** | UI — interface de configuration et d'expérience | brain-ui / SaaS |
---
## Règle BACT — non négociable
> **BACT est toujours instance-local. Il ne se distribue jamais dans un fork.**
Chaque owner construit son propre BACT depuis zéro.
Le BACT du propriétaire (l'owner) ne shippe pas dans brain-template.
Double bénéfice : vie privée préservée + fossé concurrentiel impossible à cloner.
---
## Cas d'usage — frontière par tier
### Owner (l'owner)
```
Cosmos = CORTEX(
Brain(tier=full, featureFlags=*)
× (satellites_perso + BE + distillation + RAG + coach[L2] + BACT[accumulé])
)
```
- BACT accumulé depuis le début — exclusif, non transférable
- Distillation activée sur tout
- Coach L2 — connaît l'historique complet
- Cosmos — routing configurable via UI
### fork(user × tier=free)
```
CORTEX_fork(
Brain(tier=free)
× (leurs_satellites + RAG[local] + coach_boot)
)
```
- Kernel identique — même protocoles, mêmes agents libres
- Distillation : logique présente dans le kernel, **activation bloquée**
- Coach-boot — speech protocol, zéro contexte accumulé
- BACT : commence à zéro, leur appartient, peut croître si tier upgrade
- Pas de Cosmos
### fork(user × tier=pro)
```
Cosmos_light = CORTEX_fork(
Brain(tier=pro)
× (leurs_satellites + BE + RAG + coach[full] + distillation[coach_only] + BACT[le leur])
)
```
- Coach full — speech + contexte session
- Distillation activée sur le coach uniquement
- BACT démarre vide, accumule leur progression
- Cosmos light — UI routing disponible
### fork(user × tier=full)
```
Cosmos = CORTEX_fork(
Brain(tier=full)
× (leurs_satellites + BE + distillation[tout] + RAG + coach[L2] + BACT[le leur])
)
```
- Distillation sur tout leur contenu
- Coach L2 alimenté par leur propre BACT
- Cosmos complet
---
## PCG appliqué à la distillation
Le modèle PCG (Protocol × Context × Gate) s'applique à chaque service :
```
Distillation (P) = la logique, l'algorithme → kernel, shippe dans tout fork
Distillation (C) = sur quoi elle s'applique → dépend du tier
Distillation (G) = peut-on l'activer → gated par tier
```
Principe : les free users reçoivent la **transparence** — ils voient la logique,
ils ne peuvent pas l'allumer. Open-source dans l'esprit, sustainable dans le modèle.
---
## L'opérateur × — pièce manquante
Le `×` est le composant le moins défini du système.
C'est lui qui transforme une liste de services en un système cohérent.
**Ce qu'il définit :**
- Qui peut spawner qui (routing inter-agents)
- Quel contexte passe d'un agent à l'autre (format du context packet)
- Quels signaux remontent et vers qui
- Comment Brain parle à ses satellites
**Où il vit :**
- Spec invariante (format) → kernel (`profil/ipc-spec.md` — à créer)
- Routing instance (qui parle à qui) → `profil/routing.yml`**éditable via Cosmos**
**Ce que Cosmos expose pour `×` :**
- Agent graph — éditeur visuel du routing
- Session builder — contexte par session
- Ambient layer — agents background on/off
- Pattern review — approve/reject apprentissage
---
## Ce que cet ADR ne définit pas encore
- Format exact du context packet (IPC spec) → ADR-026
- Ambient layer — agents background protocol → ADR-027
- Boucle d'apprentissage complète (detect → approve → update) → ADR-028
---
## Changelog
| Date | Note |
|------|------|
| 2026-03-18 | Création — formule canonique Cosmos, règle BACT, cas d'usage par tier, PCG sur distillation, opérateur × identifié comme pièce manquante |

View File

@@ -0,0 +1,148 @@
---
scope: kernel
name: ADR-026
title: "IPC — Context packet, signal vocabulary, access matrix inter-agents"
status: accepted
date: 2026-03-18
deciders: [<owner>]
---
# ADR-026 — IPC : context packet + signal vocabulary + access matrix
## Insight fondateur
> Le `×` de la formule Cosmos ne définit pas seulement le FORMAT de ce qui voyage —
> il définit **ce que chaque agent a le DROIT de recevoir selon le signal reçu**.
Le G du modèle PCG se précise ici :
```
P = comment l'agent se comporte internally
C = ce qu'il charge au boot (session-*.yml)
G = ce qu'il peut recevoir et émettre via × (access matrix)
```
Le Gate n'est pas seulement "quel tier débloque cet agent" —
c'est **le périmètre exact de sa communication inter-agents**.
---
## Le context packet — format kernel (invariant)
```yaml
packet:
from: agent_name # qui émet
to: agent_name | broadcast # destinataire
signal: SPAWN | RETURN | BLOCKED_ON | CHECKPOINT | HANDOFF | ESCALATE | ERROR
scope:
files: [] # fichiers concernés (chemins exacts)
zone: kernel | project | personal # zone BSI
payload:
context: {} # ce que l'émetteur a découvert
decision: null # décision prise (si applicable)
options: [] # options proposées (ESCALATE uniquement)
result: null # résultat retourné (RETURN uniquement)
return_to: agent_name # où renvoyer
session_id: string # claim BSI actif
```
**Règle d'or** : chaque signal ne remplit qu'un sous-ensemble du payload.
Un agent ne reçoit jamais plus que ce que son signal autorise.
---
## Signal vocabulary — complet et exhaustif
| Signal | Sens | Payload autorisé | Existait |
|--------|------|-----------------|---------|
| `SPAWN` | parent → enfant : démarre une tâche | scope + context initial | implicite ✗ |
| `RETURN` | enfant → parent : tâche terminée | result uniquement | implicite ✗ |
| `CHECKPOINT` | agent → BSI : état sauvegardé | context snapshot | ✓ |
| `HANDOFF` | session N → session N+1 : passage de relai | context + decision | ✓ |
| `BLOCKED_ON` | agent → pilote : bloqué techniquement | description blocage | ✓ |
| `ESCALATE` | agent → pilote : décision humaine requise | options de décision | ✗ nouveau |
| `ERROR` | agent → parent : échec non récupérable | error description | ✗ nouveau |
**Distinction BLOCKED_ON vs ESCALATE :**
- `BLOCKED_ON` = bloqué techniquement (fichier absent, permission manquante) → attente déblocage
- `ESCALATE` = ambiguïté de valeur (choix architectural, décision métier) → humain décide
---
## Access matrix — qui reçoit quoi
| Agent | Reçoit de | Envoie à | Zones autorisées | Signals autorisés |
|-------|-----------|----------|-----------------|-------------------|
| `orchestrator` | human, tout agent | tout agent | toutes | tous |
| `debug` | orchestrator, human | orchestrator | project + scope-only | SPAWN, RETURN, BLOCKED_ON |
| `security` | orchestrator, code-review | orchestrator | project | SPAWN, RETURN, ESCALATE |
| `coach` | human | human | personal + reference | ESCALATE, CHECKPOINT |
| `scribe` | orchestrator, human | orchestrator | selon scope déclaré | SPAWN, RETURN |
| `audit` | human | human | kernel (lecture) | RETURN, ESCALATE |
> Cette matrice est **extensible** — chaque agent déclare son access profile dans son frontmatter.
> Elle est **vérifiable** — l'opérateur × rejette tout packet qui viole la matrice.
---
## Signal → payload autorisé
Le signal contraint ce qui peut être packagé. Aucune exception.
```
SPAWN → scope.files + scope.zone + payload.context
RETURN → payload.result uniquement (jamais le contexte source)
BLOCKED_ON → payload.context (description blocage)
ESCALATE → payload.options (liste de choix, pas de contexte complet)
ERROR → payload.context (erreur uniquement)
CHECKPOINT → payload.context (snapshot complet, vers BSI uniquement)
HANDOFF → payload.context + payload.decision (vers session suivante uniquement)
```
**Pourquoi RETURN ne passe pas le contexte source :**
Évite les fuites — un agent enfant ne peut pas "rapporter" ce qu'il a vu
dans une zone hors de son scope de départ.
---
## Frontmatter agent — extension PCG
Chaque agent déclare son Gate IPC dans son frontmatter :
```yaml
brain:
# ... champs existants ...
ipc:
receives_from: [orchestrator, human] # qui peut lui SPAWN
sends_to: [orchestrator] # à qui il peut RETURN/ESCALATE
zone_access: [project] # zones autorisées en lecture
signals: [SPAWN, RETURN, BLOCKED_ON] # signals qu'il émet
```
---
## Deux faces de ×
```
× = context packet + signal vocabulary ← kernel, invariant (cet ADR)
+ routing table ← instance, configurable Cosmos
```
La routing table (qui parle à qui dans une instance donnée) est éditée via Cosmos UI.
Elle ne peut pas violer la access matrix du kernel — elle l'instancie.
---
## Ce que cet ADR ne définit pas
- Routing table format (`profil/routing.yml`) → à créer par instance
- Cosmos UI agent graph → produit
- Ambient layer signals → ADR-027
---
## Changelog
| Date | Note |
|------|------|
| 2026-03-18 | Création — context packet, signal vocabulary complet (ESCALATE + ERROR nouveaux), access matrix, PCG Gate précisé, frontmatter agent extension |

View File

@@ -0,0 +1,155 @@
---
scope: kernel
name: ADR-027
title: "Ambient layer — autonomy engine : workflows, signals, human-as-escalation-only"
status: accepted
date: 2026-03-18
deciders: [<owner>]
---
# ADR-027 — Ambient layer : autonomy engine
## Vision fondatrice
> Le brain exécute. L'humain décide uniquement ce qui est vraiment indécidable.
> Sur le long terme, le brain connaît l'infra, les préférences, les patterns —
> il agit seul sur le routine. L'humain est décisionnaire final, pas opérateur.
---
## Ce que l'ambient layer est
Extension du daemon Python existant (`ambient/daemon.py`) —
même pattern prouvé (conditions YAML → actions → notify),
étendu au domaine agent workflows.
```
Aujourd'hui : identity/*.yml → conditions → actions → notifie brain-ui
Demain : workflows/*.yml → signals IPC → spawn agents → RETURN → itère
```
L'ambient layer est un **event loop autonome** :
1. Évalue les workflow specs à chaque tick
2. Spawn les agents nécessaires (signal SPAWN, ADR-026)
3. Collecte les RETURN
4. Continue, ou ESCALATE si vraiment indécidable
5. Log tout pour la boucle d'apprentissage (ADR-028)
---
## Format workflow spec
```yaml
# workflows/deploy-batch.yml
workflow: deploy-batch
description: "Déployer N instances identiques"
for_each:
items: [instance-01, instance-02, ..., instance-10]
spawn: deploy
scope:
zone: project
files: [vps/configs/{{item}}.yml]
on_return:
success: → next_item
fail: → ESCALATE pilote
error: → ERROR + log + ESCALATE pilote
on_complete:
signal: RETURN
to: orchestrator
payload:
result: "{{success_count}}/{{total}} instances déployées"
on_escalate:
notify: [telegram, brain-ui]
wait: human_decision
```
---
## Règle humain-as-escalation-only
```
routine → ambient exécute seul
ambigu → ESCALATE → humain décide → ambient reprend
bloquant → BLOCKED_ON → humain débloque → ambient reprend
```
L'humain ne voit jamais les étapes techniques. Il voit :
- Le résultat final (tout s'est bien passé)
- L'ESCALATE (une décision est requise)
- Le résumé de progression si il le demande
---
## Connexion au daemon existant
Le daemon `ambient/daemon.py` ajoute un evaluator :
```
TriggerEngine.tick()
├── _eval_frigo() (existant — vie perso)
├── _eval_courses() (existant — vie perso)
├── _eval_budget() (existant — vie perso)
└── _eval_workflows() (nouveau — agent orchestration)
├── charge workflows/*.yml
├── évalue état courant
├── spawn agents via IPC (ADR-026)
└── collecte RETURN → feed learning loop (ADR-028)
```
---
## Données collectées par workflow run
Chaque exécution produit un run record :
```yaml
run:
workflow: deploy-batch
started_at: ISO8601
completed_at: ISO8601
steps:
- item: instance-01
agent: deploy
signal_out: SPAWN
signal_in: RETURN
result: success
duration_ms: 1240
- item: instance-02
...
escalations: 0
errors: 0
outcome: success
```
Ces records alimentent directement ADR-028 (boucle d'apprentissage).
---
## Vision long terme
> Le brain connaît le VPS. Il connaît les préférences. Il connaît les patterns d'erreur.
> Avec le temps, les ESCALATEs deviennent rares — le brain a appris quoi faire
> dans chaque situation déjà rencontrée.
Chaque run = un exemple d'entraînement.
Chaque ESCALATE résolu = une règle apprise.
Chaque ERROR récurrente = un pattern à corriger.
---
## Ce que cet ADR ne définit pas
- Format exact des run records persistés → à préciser à l'implémentation
- Fréquence tick workflow vs tick identity (peut être différente) → config
- Boucle d'apprentissage complète → ADR-028
---
## Changelog
| Date | Note |
|------|------|
| 2026-03-18 | Création — autonomy engine, workflow spec format, human-as-escalation-only, extension daemon existant, run records pour learning loop |

View File

@@ -0,0 +1,187 @@
---
scope: kernel
name: ADR-028
title: "Learning loop — detect → collect → propose → approve → update"
status: accepted
date: 2026-03-18
deciders: [<owner>]
---
# ADR-028 — Learning loop : detect → collect → propose → approve → update
## La boucle complète
```
ambient run → RETURN collecté → pattern-scribe détecte
pattern nouveau ?
oui ↓ non ↓
log pattern incrément compteur
seuil atteint ?
↓ oui
propose update (ADR / workflow / agent)
humain approve / reject
↓ approve
brain_write() → update
BACT enregistre la progression
```
---
## Ce qui ferme la boucle ouverte
Avant cet ADR :
- `pattern-scribe` détectait → loggait → **s'arrêtait**
- Humain devait lire le log et agir manuellement
Après cet ADR :
- `pattern-scribe` détecte → log → **propose** si seuil atteint
- Humain approuve ou rejette — le brain exécute
---
## Sources d'entrée de la boucle
| Source | Ce qu'elle apporte |
|--------|-------------------|
| `workspace/pattern-log.md` | Patterns inter-sessions détectés |
| `ambient/runs/*.yml` | Run records workflow (ADR-027) |
| BSI claims (fermés) | Historique décisions de session |
| `now.md` chain | Contexte bridge entre sessions |
---
## Seuils de déclenchement
```yaml
thresholds:
pattern_occurrences: 3 # même pattern 3x → propose correction
escalate_same_cause: 2 # même ESCALATE 2x → propose règle ambient
error_same_workflow: 2 # même ERROR 2x → propose fix workflow spec
bact_milestone: 10 # 10 cycles appris → coach L2 unlock signal
```
---
## Format de proposition
Quand le seuil est atteint, le brain génère une proposition :
```yaml
proposal:
id: prop-20260318-001
trigger: pattern_occurrences
pattern: "deploy instance-0x échoue si port 443 pas encore ouvert"
observed: 3x dans runs/deploy-batch-*.yml
proposes:
type: workflow_update
file: workflows/deploy-batch.yml
change: "ajouter step check-port-443 avant spawn deploy"
requires: human_approval
expires_at: ISO8601 # 72h — si pas de réponse → archive
```
---
## Approbation humaine
```
brain-ui → panneau "Proposals" → approve / reject / modify
Telegram → notification résumée → /approve prop-001 | /reject prop-001
Claude → en début de session → "1 proposition en attente — tu veux la voir ?"
```
**Règle** : jamais d'update automatique sans approbation.
L'autonomie croît par accumulation de confiance, pas par défaut.
---
## Connexion BACT
Chaque approbation humaine = un cycle d'apprentissage enregistré dans BACT :
```yaml
bact_entry:
date: ISO8601
type: workflow_improvement
pattern: "..."
approved_by: human
applied_to: workflows/deploy-batch.yml
outcome: null # rempli après le prochain run
```
Après le prochain run :
```yaml
outcome: success # le fix a fonctionné
# → confiance += 1 sur ce type de décision
```
Accumulation de confiance → certains patterns futurs peuvent passer
en auto-approve si confiance suffisante + pattern identique déjà résolu.
---
## La vision long terme capturée
> Chaque run = un exemple d'entraînement.
> Chaque ESCALATE résolu = une règle apprise.
> Chaque approbation = de la confiance accumulée dans BACT.
>
> Sur le long terme : le brain sait que tu as un VPS, qu'il tourne sur tel port,
> que tel pattern d'erreur se résout comme ça. Les ESCALATEs deviennent rares.
> Tu restes décisionnaire final — mais uniquement sur ce qui est vraiment nouveau.
---
## Bootstrap protocol — comment on arrive à l'autonomie
L'autonomie ne se déclare pas. Elle se gagne par itérations supervisées.
```
Itération 1 — ensemble
Humain + brain côte à côte sur le premier run.
Humain repère les gaps, le scope drift, les décisions mal calibrées.
Brain apprend la tolérance exacte — pas plus, pas moins.
Itération 2 — supervisée
Brain exécute. Humain observe sans intervenir sauf ESCALATE réel.
Validation que les corrections de l'itération 1 ont tenu.
Ajustements fins si nécessaire.
Itération 3+ — autonome
Brain tourne seul. Humain = décisionnaire final uniquement.
Les ESCALATEs sont rares — le brain a vu le pattern avant.
```
**Règle de passage** : on ne passe à l'itération suivante que si l'itération courante
n'a produit aucun scope drift non détecté. Un drift non détecté = retour à l'itération 1.
**Ce que "ensemble" signifie en pratique** :
- Humain lit les run records après chaque step
- Signale les écarts de scope immédiatement
- Approuve ou rejette chaque proposition générée
- Le brain ne "suppose" pas — il demande si ambigu
**Ce qui change à l'itération 3** :
- Le brain a un historique suffisant sur ce workflow précis
- Les propositions de ce type passent en auto-approve (confiance BACT)
- L'humain reçoit un résumé, pas une demande d'approbation step-by-step
---
## Ce que cet ADR ne définit pas
- Stockage BACT (format base, vecteurs, ou simple YAML) → à décider à l'implémentation
- Interface Cosmos "Proposals panel" → produit
- Seuil d'auto-approve (confiance suffisante) → à calibrer empiriquement
---
## Changelog
| Date | Note |
|------|------|
| 2026-03-18 | Création — boucle complète detect→propose→approve→update, seuils, format proposition, connexion BACT, vision long terme gravée |

View File

@@ -0,0 +1,166 @@
---
scope: kernel
name: ADR-029
title: "Cosmos — frontend du brain : séparabilité kernel/instance, vue owner vs fork"
status: accepted
date: 2026-03-18
deciders: [<owner>]
---
# ADR-029 — Cosmos : frontend du brain
## Principe fondateur
> Tu utilises le kernel. Tu ne vois pas ses internals.
> Comme Linux — l'utilisateur interagit avec le système,
> pas avec le code source du kernel.
Cosmos est le frontend de CORTEX. Il rend le brain configurable et visible
sans jamais exposer ce qui doit rester invariant.
---
## Ce que Cosmos EST
```
Cosmos = UI layer au-dessus de CORTEX
= l'interface entre l'humain et le brain
= éditeur de la partie configurable (×, sessions, gates, ambient)
≠ le kernel (jamais)
≠ accès fichier direct (jamais)
```
Toute écriture passe par `brain_write()` — jamais d'accès fichier direct.
Cosmos lit via MCP (`brain_boot`, `brain_search`, `brain_agents`).
Cosmos écrit via `brain_write()` uniquement.
---
## Séparabilité — la règle kernel/instance
**Ce que Cosmos expose :**
| Couche | Éditable | Visible |
|--------|----------|---------|
| Routing table `×` | ✓ instance | ✓ |
| Sessions (`session-*.yml`) | ✓ instance | ✓ |
| Feature gates (`brain-compose.yml`) | ✓ owner only | ✓ |
| Ambient workflows | ✓ instance | ✓ |
| Proposals learning loop | ✓ approve/reject | ✓ |
| Brain state (claims, now.md) | ✗ lecture seule | ✓ |
| Agents Protocol (`agents/*.md`) | ✗ | ✓ lecture seule |
| Kernel files (KERNEL.md, PATHS.md) | ✗ jamais | ✗ jamais |
**Règle absolue** : zone:kernel → invisible dans Cosmos.
L'utilisateur sait que le kernel existe. Il ne le voit pas. Il ne le touche pas.
---
## Vue owner vs vue fork
### Owner — vue complète
```
Agent graph 3D (ThreeJS)
├── Kernel layer → visible (agents kernel, routing kernel)
├── Project layer → visible + éditable
└── Personal layer → visible + éditable
Feature gates → brain-compose.yml éditable
BACT dashboard → progression accumulée, milestones
Distillation panel → activation / config
```
### Fork — vue instance
```
Agent graph 3D (ThreeJS)
├── "CORTEX core" → boîte noire (nom + version, pas d'internals)
└── Project layer → visible + éditable
Feature gates → lecture seule (tier affiché, pas éditable)
BACT dashboard → leur propre BACT uniquement
Distillation → visible si tier le permet, sinon locked
```
**La boîte noire** : le fork voit "CORTEX v0.9.0 — kernel" comme un bloc.
Il sait ce qu'il fait (les agents qu'il peut invoquer).
Il ne sait pas comment c'est construit à l'intérieur.
C'est le fossé concurrentiel rendu visible.
---
## Les panels Cosmos
### 1. Agent Graph (ThreeJS 3D)
Visualisation du routing table `×` (ADR-026).
Nœuds = agents. Arêtes = IPC connections.
Couleur par zone (kernel/project/personal).
Clic sur un agent → fiche PCG (Protocol lu depuis agents/*.md, Context, Gate).
**Owner** : graph complet. **Fork** : project layer + CORTEX core opaque.
### 2. Session Builder
Éditeur visuel des `session-*.yml`.
Drag & drop des fichiers L1. Mesure footprint en temps réel.
Alerte si > seuil défini dans `profil/session-footprint.md`.
### 3. Proposals Panel
Interface de la boucle d'apprentissage (ADR-028).
Liste des propositions générées par pattern-scribe + ambient.
Approve / Reject / Modify. Historique des décisions.
### 4. Ambient Board
État des workflows en cours (`workflows/*.yml`).
Statut par step (SPAWN envoyé, RETURN reçu, ESCALATE en attente).
Toggle on/off des agents ambient.
Visualisation des run records.
### 5. Brain State
Live : claims BSI ouverts, session active, now.md last update.
Lecture seule. Le cerveau en temps réel.
### 6. Feature Gates (owner only)
Éditeur `brain-compose.yml` — tier, coach_level, sessions disponibles.
Visualisation des agents unlockés par tier.
---
## Proactif local — angle produit (tier pro/full)
Le brain peut pousser des notifications sans que l'utilisateur soit dans Cosmos :
```
ollama (phi-3-mini) + ambient daemon → 0 token API
Morning briefing, workflow status, pattern alert → Telegram / Cosmos notif panel
GPU episodique — pas continu
```
C'est le brain hors du dev — accompagnement quotidien, zéro friction.
Disponible en tier pro/full. Infrastructure déjà posée (`ambient/daemon.py`).
---
## Ce que Cosmos ne fait JAMAIS
- Accès direct aux fichiers kernel
- Modification du Protocol d'un agent (`agents/*.md` contenu)
- Exposition des secrets / MYSECRETS
- Écriture BSI hors `brain_write()` contrôlé
- Affichage du BACT d'un autre utilisateur
---
## Stack pressenti
- **ThreeJS** — agent graph 3D
- **brain_write() MCP** — toutes les écritures
- **brain_boot() / brain_search()** — lecture contexte
- **WebSocket brain-engine** — live state (claims, ambient status)
---
## Changelog
| Date | Note |
|------|------|
| 2026-03-18 | Création — frontend CORTEX, séparabilité kernel/instance, boîte noire fork, vue owner vs fork ThreeJS, 6 panels, proactif local comme angle produit tier pro/full |

View File

@@ -0,0 +1,53 @@
---
scope: kernel
adr: 030
title: Validation empirique des boot modes — data first
status: pending-data
date: 2026-03-18
---
# ADR-030 — Validation empirique des boot modes
## Contexte
Session navigate 2026-03-18 : premier run réel de `session-navigate.yml` en conditions normales.
Résultat : cold start ressenti, gardes comportementaux absents, dérive d'exécution (satellites à l'aveugle, bypass PEP 668).
Le mode avait été conçu théoriquement et shipé avec confiance, sans simulation préalable.
Même pattern qu'ADR-028 décrit — itération 1 skippée.
## Décision provisoire
**ADR-030 est ouvert. Il n'est pas écrit.**
Il attend de la data empirique sur plusieurs boots réels avant d'être tranché.
## Ce qu'il faut tester
| Mode | Question clé |
|------|-------------|
| `navigate` | Cold start ressenti ? Gardes comportementaux actifs ? |
| `work` | Context familier ? Surcharge ou manque ? |
| `brain` | Trop lourd ? Juste ? |
| `sudo` (à définir) | Le feeling "je te retrouve" est-il là ? |
## Règle qui émerge (à valider par les tests)
> Avant de shipper un boot mode → simuler une session réelle dedans.
> Pas de confiance théorique. Forge sur du concret, pas du théorique.
## Hypothèse de travail
Le "mode sudo" n'est probablement pas un nouveau fichier de config.
C'est une garantie que le **contexte comportemental core** est toujours chargé,
peu importe la granularité du mode.
Contrat minimal à définir empiriquement : quels fichiers/règles ne peuvent jamais
être exclus, même à 10% de contexte ?
## Prochaines étapes
- [ ] Boot en mode `work` → observer + noter le ressenti
- [ ] Boot en mode `brain` → idem
- [ ] Boot standard (sans mode) → idem
- [ ] Agréger les observations → trancher ADR-030

View File

@@ -0,0 +1,39 @@
---
scope: kernel
id: ADR-031
title: Modèle de distribution brain — A court terme, B moyen/long terme
status: accepted
date: 2026-03-18
session: sess-20260318-1704-navigate
---
## Décision
Deux modèles de distribution validés, séquencés dans le temps.
**Modèle A — Self-hosted (court terme, maintenant)**
- Distribuer brain-template
- Les utilisateurs self-hostent leur brain-engine sur leur propre VPS
- Chacun embed ses propres fichiers → son propre brain.db → son propre MCP
- Coût infra pour Tetardtek : zéro supplémentaire
- Rôle Tetardtek : maintenir le kernel + distribuer le template
**Modèle B — Hébergé multi-tenant (moyen/long terme)**
- brain-store avec sharding par utilisateur (brain.db isolé par clé)
- brain_api_key (keys.<OWNER_DOMAIN>) = porte d'entrée facturation
- Tier enforcement + CATALOG déjà en place — infrastructure prête
- Trigger : premier utilisateur qui paie pour ne pas self-hoster
## Raison
Le Modèle B ne doit pas être construit avant d'avoir validé le Modèle A
sur de vrais utilisateurs. L'infra actuelle (VPS + brain-key-server + tier)
est déjà orientée Modèle B sans le savoir — c'est une progression naturelle.
Construire l'infra multi-tenant avant le premier client = sur-engineering garanti.
## Conséquence
- Ne pas implémenter brain-store sharding avant un use case concret
- Prioriser : kernel quality + template distributable + RAG VPS à jour
- Le fossé concurrentiel = brain.db accumulé dans le temps, pas le code

View File

@@ -0,0 +1,99 @@
---
scope: kernel
name: adr-032-execution-mode-vs-workflow
type: adr
context_tier: cold
---
# ADR-032 — Séparation workflow / mode d'exécution — fondation swarm-ready
> Date : 2026-03-18
> Statut : actif
> Décidé par : brainstorm coach + humain (sess-20260318-1808-agent-audit)
---
## Contexte
En préparant les premiers swarms d'agents, deux questions ont émergé :
- Où déclarer les contrats d'interface entre agents (input/output) ?
- Qu'est-ce que "swarm-ready" signifie concrètement ?
L'option A proposait de mettre le mode d'exécution dans le fichier workflow.
L'option B propose de séparer le QUOI (workflow) du COMMENT (mode d'exécution).
---
## Décision
Le **workflow** déclare QUOI faire (séquence de steps, agents, gates).
Le **mode d'exécution** déclare COMMENT l'humain est impliqué — propriété de la session, pas du workflow.
```yaml
# Dans la session (overlay)
workflow: superoauth-tier3
execution_mode: assisted # manual | assisted | swarm
```
Le même workflow peut être exécuté en mode manual, assisté ou swarm selon la confiance acquise.
Le workflow ne change pas — la confiance évolue.
---
## Les 3 modes d'exécution
| Mode | Humain | Condition |
|------|--------|-----------|
| `manual` | Lit chaque BSI claim, envoie à l'agent, valide avant next | Découverte — premier run d'un workflow |
| `assisted` | Brain orchestre + signale, humain a la vue de l'intérieur, intervient si besoin | Construction de confiance — le mode le plus formateur |
| `swarm` | Gate à l'entrée du workflow + validation du livrable final | Confiance acquise sur ce workflow |
Le mode `assisted` est le plus précieux cognitivement : l'humain voit ce que le brain voit, construit la confiance sur ce que le brain peut faire seul.
---
## Définition formelle de swarm-ready
Un workflow est **swarm-ready** quand :
1. Il a été exécuté en mode `manual` (découverte) ✅
2. Il a été exécuté en mode `assisted` (confiance construite) ✅
3. Les agents impliqués ont des périmètres validés en conditions réelles ✅
4. Le livrable final est structuré et consommable sans reformat humain ✅
`swarm-ready` est une déclaration de confiance sur un **workflow**, pas sur un agent isolé.
---
## Ce que ça implique
**Agents :** ne déclarent pas leur mode d'exécution. Restent atomiques.
**Workflows :** déclarent les steps, agents, gates. Ne déclarent pas le mode.
**Sessions :** overlayent le mode d'exécution sur le workflow.
**BACT :** recevra un pattern `agentic.yml` — template de workflow swarm-capable avec contrats I/O par step.
---
## Alternatives considérées
| Option | Raison du rejet |
|--------|----------------|
| Mode déclaré dans le workflow | Rigidifie — le même workflow ne pourrait pas évoluer de manual → swarm sans réécriture |
| Contrats I/O dans le fichier agent | Casse la granularité atomique — un agent utilisé dans 2 workflows différents aurait 2 "profils" |
| Nouveau répertoire `swarms/` | Doublon avec `workflows/` — la distinction est dans le mode, pas dans la structure |
---
## Conséquences
- `workflows/_template.yml` → à enrichir avec contrats I/O optionnels par step
- `contexts/session-*.yml` → à enrichir avec `execution_mode:` optionnel quand workflow déclaré
- Les workflows existants (`superoauth-tier3`, `brain-engine`, etc.) → rétrospectivement classés mode `manual` (découverte)
- `bact/patterns/agentic.yml` → à créer (pattern swarm workflow)
---
## Changelog
| Date | Changement |
|------|------------|
| 2026-03-18 | Création — brainstorm coach, décision structurante swarm-ready |

View File

@@ -0,0 +1,129 @@
---
scope: kernel
id: ADR-033
title: Stratégie embedding — multilinguisme et distribution brain-template
status: accepted
date: 2026-03-18
deciders: [human, coach]
tags: [embedding, distribution, multilingual, brain-template]
---
# ADR-033 — Stratégie embedding : multilinguisme et distribution brain-template
## Contexte
Le brain-engine embarque un pipeline d'embedding (chunks → vecteurs → UMAP → Cosmos).
Tout le contenu actuel est en FR. Brain-template (ADR-031) sera distribué à des utilisateurs
potentiellement non-FR.
Deux problèmes distincts ont émergé lors du brainstorm 2026-03-18 :
1. **Problème de distribution** : un utilisateur EN installe brain-template → peut-il avoir
un brain opérationnel dans sa langue ?
2. **Problème de collaboration** : deux instances brain (FR + EN) veulent co-travailler
sémantiquement → leurs espaces embedding sont-ils commensurables ?
---
## Options explorées
| Option | Description | Verdict |
|--------|-------------|---------|
| A — Modèle multilingue (multilingual-e5) | Un espace commun FR+EN+… | Upgrade path v2 |
| B — Modèles séparés par langue | Silos, pas de cross-lingual | ❌ Éliminé |
| C — Kernel traduit EN+FR en parallèle | Double maintenance garantie | ❌ Éliminé |
| D — Template structurel, contenu souverain | Chaque instance dans sa langue | ✅ Retenu v1 |
---
## Décision
### V1 — Option D : template structurel, instances souveraines
**brain-template distribue :**
- Schéma frontmatter (language-agnostic)
- Scripts bash/Python (language-agnostic)
- Workflow templates (structure)
- Agents `.md` en FR (langue du kernel owner)
**Chaque instance :**
- Forge ses agents dans sa langue dès le premier sprint
- Embarque son propre pipeline embedding avec le modèle de son choix
- Est sémantiquement souveraine — aucune dépendance au brain FR d'origine
**Un utilisateur EN installe brain-template :**
```
1. Clone le template (agents FR comme référence de structure)
2. Forge ses agents EN via recruiter (le FR est un exemple, pas une contrainte)
3. Son brain est 100% EN, embedding 100% EN, Cosmos 100% EN
4. Opérationnel — aucune rupture sémantique
```
**Ce qui ne change pas pour le brain FR owner :**
- Le brain existant n'est pas re-embeddé
- Le modèle embedding actuel reste en place
- Aucune action requise à la distribution du template
---
### V2 — Option A : upgrade multilingual (condition d'activation)
**Condition de déclenchement :**
> Première instance non-FR qui veut co-travailler sémantiquement avec le brain FR.
> Pas avant.
**Quand ce moment arrive :**
```
1. Migrer brain-engine vers multilingual-e5-large (ou équivalent)
2. Re-embedder tous les chunks existants (~30 min, opération batch)
3. Les deux instances partagent désormais un espace embedding commun
4. Cross-lingual search actif : query EN trouve contenu FR et vice-versa
```
**Ce que ça débloque :**
- Brain A (FR) et Brain B (EN) cherchent dans un espace commun
- Cosmos multi-instance : deux nébuleuses dans le même espace UMAP
- Collaboration sémantique sans perdre la souveraineté de chaque instance
---
## Zone filter — découplé (ADR-033a, sujet séparé)
La question du **zone filter** (quels contenus sont indexés selon leur zone) est indépendante
du choix de modèle. Elle sera traitée dans un brainstorm dédié.
Hypothèse de départ pour ADR-033a :
```
kernel → toujours indexé (open-core, vocabulaire partagé)
project → TTL basé sur l'activité du sprint
personal → jamais indexé (bact, collaboration, progression)
session → sélectif (checkpoint utile, contenu brut non)
```
---
## Conséquences
**Immédiat (V1) :**
- Brain-template peut être distribué sans changer l'infrastructure embedding actuelle
- Aucun re-embedding du brain FR owner requis
- Les utilisateurs non-FR sont pleinement autonomes dans leur langue
**Futur (V2) :**
- Migration multilingual-e5 planifiée — opération batch de ~30 min
- Déclenchée sur signal concret (premier besoin de collaboration cross-lingual)
- Pas d'over-engineering préventif
**Philosophie retenue :**
> Chaque brain est souverain dans sa langue. La collaboration sémantique est une
> option d'upgrade, pas un prérequis à la distribution.
---
## Références
- ADR-031 — Distribution model (brain-template)
- ADR-029 — Cosmos frontend brain
- `wiki/brain-engine.md` — pipeline embedding actuel
- `wiki/cosmos.md` — visualisation UMAP

View File

@@ -0,0 +1,161 @@
---
id: ADR-033a
title: Embedding zone filter — quoi indexer, quand, jusqu'à quand
status: accepted
date: 2026-03-18
deciders: [human, coach]
tags: [embedding, zone-filter, brain-engine, indexing]
scope: kernel
---
# ADR-033a — Embedding zone filter
## Contexte
Le brain-engine embède aujourd'hui tout le contenu sans filtre.
Dès que brain-template est distribué et que la confidentialité compte,
indexer aveuglément devient un problème :
- Du contenu personnel (bact, collaboration, progression) entre dans l'index
- Des sessions fermées depuis 6 mois restent dans le Cosmos
- Des claims BSI structurés polluent la recherche sémantique
Il faut une règle claire : **quoi** indexer, **quand** le retirer.
---
## Décision
### Règles zone par zone
| Contenu | Zone | Règle | Raison |
|---------|------|-------|--------|
| `agents/`, `contexts/`, `workflows/`, `KERNEL.md`, `wiki/` | kernel | **Toujours indexé** | Vocabulaire de base — haute valeur sémantique permanente |
| `toolkit/` | kernel/project | **Toujours indexé** | Patterns réutilisables — valeur inter-sprints |
| `profil/decisions/` (ADRs) | déclaré par fichier | **Selon `scope` frontmatter** | Certains ADRs sont kernel (archi brain), d'autres project (décision produit) |
| `projets/`, `handoffs/`, `workspace/<sprint>/` | project | **TTL 60 jours** depuis dernier git commit | Pertinent pendant le sprint, bruit ensuite |
| `now.md`, `checkpoint.md` | session | **Indexé tant qu'actif**, supprimé au close claim | Utile en cours de session, obsolète après |
| `claims/` | session | **Jamais** | Trop structuré, zéro valeur sémantique prose |
| `profil/bact/`, `profil/collaboration.md` | personal | **Jamais** | Privé — ne sort pas même dans le Cosmos owner |
| `progression/` | personal | **Jamais** | Journal personnel — hors embedding |
---
### Mécanisme de décision — hybride
```
Règle 1 — Répertoire (défaut)
agents/ → kernel → toujours
toolkit/ → kernel → toujours
wiki/ → kernel → toujours
projets/ → project → TTL
workspace/ → project → TTL
handoffs/ → project → TTL
claims/ → session → jamais
profil/bact/ → personal → jamais
progression/ → personal → jamais
Règle 2 — Frontmatter scope (override sur Règle 1)
scope: kernel → toujours indexé (même si dans profil/)
scope: project → TTL 60 jours
scope: personal → jamais
scope: session → indexé tant qu'actif
Règle 2 prend la main sur Règle 1 si scope est déclaré.
```
**Application concrète aux ADRs :**
```
profil/decisions/adr-003-scribe-pattern.md
scope: kernel → toujours indexé — archi brain permanente
profil/decisions/adr-008-superoauth-multitenant.md
scope: project → TTL — décision produit spécifique, pas archi brain
```
---
### TTL — Option A : git-based
```
TTL = date du dernier git commit sur le fichier + 60 jours
Si file.last_commit + 60j < today → retirer de l'index
→ ne pas supprimer le fichier
→ juste dé-indexer
Implémentation : brain-engine lit git log --follow -- <file>
compare la date au seuil
décision locale, aucun couplage externe
```
**Upgrade path BSI-based (non activé) :**
Si un jour le TTL git s'avère insuffisant (fichier non commité mais sprint actif),
le BSI peut fournir un signal d'activité. Déclenché sur besoin concret — pas avant.
Le BSI ne pilote pas l'embedding aujourd'hui : deux couches, deux responsabilités.
---
### Frontmatter ADR — champ scope obligatoire
À partir d'aujourd'hui, tout nouvel ADR déclare son scope :
```yaml
---
id: ADR-NNN
title: ...
status: accepted
date: YYYY-MM-DD
scope: kernel | project | personal
---
```
**Règle de classification ADR :**
```
scope: kernel → décision sur l'architecture du brain lui-même
(agents, protocoles, zones, embedding, distribution)
scope: project → décision sur un projet produit spécifique
(SuperOAuth, OriginsDigital, Cosmos features...)
```
**Patch ADRs existants (001-033a) :**
Opération batch — ajouter `scope: kernel | project` selon la règle ci-dessus.
Les ADRs 001-022 sont majoritairement kernel (fondations du brain).
Les ADRs 023-033 sont à classifier au cas par cas.
---
## Conséquences
**Immédiat :**
- brain-engine reçoit les règles de zone → filtre à implémenter
- Template ADR mis à jour (`scope` obligatoire)
- 33 ADRs existants à annoter (opération batch)
**Cosmos :**
- Nébuleuse plus propre — plus de bruit session/claims/personal
- Zones visuellement distinctes : kernel (dense, stable), project (dynamique, TTL), session (éphémère)
**Confidentialité :**
- Contenu personal ne sort jamais de l'index, même en mode debug
- Valide pour distribution brain-template : un utilisateur qui clone ne voit jamais le bact owner
---
## Ce qui n'est PAS décidé ici
- Taille des chunks (séparé — brain-engine config)
- Fréquence de re-indexing (séparé — cron brain-engine)
- Format du vecteur index (séparé — brain-engine schema)
- Multilinguisme embedding (ADR-033 — déjà acté)
---
## Références
- ADR-033 — Stratégie embedding multilinguisme (Option D + upgrade path A)
- ADR-005 — Zones typées + protection graduée
- ADR-022 — Modèle de distribution open-core
- `wiki/brain-engine.md` — pipeline embedding actuel
- `wiki/cosmos.md` — visualisation UMAP

View File

@@ -0,0 +1,142 @@
---
id: ADR-034
title: Séparation infra — local (owner) / VPS (brain-template)
status: accepted
date: 2026-03-18
deciders: [human, coach]
tags: [infra, distribution, brain-template, dev-loop, vps]
scope: kernel
---
# ADR-034 — Séparation infra : local (owner) / VPS (brain-template)
## Contexte
Jusqu'au 2026-03-18, le brain-ui local pointait sur le VPS (`brain.<OWNER_DOMAIN>`)
via le proxy Vite. Conséquences :
- En dev, le Cosmos montrait les embeddings du VPS — pas les changements locaux
- Le dev loop était cassé : modifier embed.py local → invisible en local
- Le VPS exposait le brain personnel du owner (ADRs privés, projets perso, bact)
- Un utilisateur qui visite le VPS voit le brain du owner, pas un produit
La distribution de brain-template (ADR-031) impose une séparation claire :
un utilisateur qui découvre le produit ne doit pas tomber sur le brain privé du créateur.
---
## Décision
### Deux instances, deux rôles
```
Local (prod-laptop)
→ brain owner, privé
→ brain-engine port 7700, BRAIN_TIER=owner
→ brain-ui Vite port 5173, proxy → localhost:7700
→ brain.db local (re-embed cron 6h + on-demand)
→ jamais exposé publiquement
VPS (brain.<OWNER_DOMAIN>)
→ brain-template, démo produit
→ ce que le monde voit en premier
→ kernel ouvert, agents de référence, zéro données owner
→ brain-engine + brain-ui déployés depuis brain-template
```
### Dev loop validé
```
1. Modifier le brain local (agents, embed, brain-ui)
2. Tester sur localhost:5173/ui/ → brain-engine local → brain.db local
3. Valider (dry-run, --stats, Cosmos local)
4. Commit + push
5. Déployer sur VPS uniquement si validé
```
Même principe que le swarm-ready gate (ADR-032) : au moins un run validé
en local avant de toucher le prod.
### Conséquences immédiates (2026-03-18)
- `vite.config.ts` proxy → `http://localhost:7700` + rewrite `/api → ''` + `ws: true`
- `scripts/dev-start.sh` — démarre brain-engine + Vite en un seul Ctrl+C
- `BRAIN_TIER=owner` en dev (pas de token requis, tier explicite)
- `numpy` + `umap-learn` installés localement (UMAP local opérationnel)
---
## Zone filter comme prérequis de distribution
ADR-033a est le fondement de sécurité qui rend cette séparation viable :
```
profil/bact/ → JAMAIS indexé → owner invisible au VPS
profil/decisions/ → scope kernel → archi partageable, décisions perso non
personal → JAMAIS → souveraineté par instance
```
Sans ADR-033a, exposer le brain-engine sur le VPS = exposer le bact owner.
Avec ADR-033a, chaque instance est souveraine sur son privé — le MCP est safe
par construction.
---
## Chemin vers brain-template sur VPS
```
1. ADR-033a live (zone filter) ✅ 2026-03-18
2. ADR-034 (séparation infra) ✅ 2026-03-18
3. Déployer brain-template sur VPS → prochaine étape
4. VPS = démo kernel propre → zéro données owner
5. brain-key-server valide les tiers → free / pro / owner par clé
```
---
## Note — Cosmos temps réel (future)
Deux modes d'embedding identifiés :
```
Mode actuel → cron 6h + on-demand (re-embed manuel) ← validé
Mode futur → file watcher (inotify) → re-embed sur write ← ADR-035 territory
```
Le temps réel est orthogonal à cette décision — déclenché sur besoin concret.
---
## Alternatives considérées
| Option | Raison du rejet |
|--------|----------------|
| Proxy Vite → VPS en dev | Dev loop cassé, Cosmos montre le VPS pas le local |
| Un seul brain sur VPS | Mélange données owner + produit — confidentialité rompue |
| brain-template = copie du brain owner | Expose données privées à la distribution |
---
## Conséquences
**Positives :**
- Dev loop complet local — chaque changement visible immédiatement
- VPS propre pour la démo — ce que le monde voit = le produit, pas le owner
- Confidentialité garantie par construction (ADR-033a)
- La boucle dev local → validate → VPS prod est celle qui sera documentée pour les futurs contributeurs
**Négatives / trade-offs assumés :**
- Deux environnements à maintenir (local + VPS)
- `scripts/dev-start.sh` requis pour démarrer l'env dev (acceptable)
- numpy/umap-learn à installer localement (one-time, documenté)
---
## Références
- ADR-031 — Distribution model brain-template
- ADR-033a — Embedding zone filter (prérequis sécurité)
- ADR-032 — Mode d'exécution (swarm-ready gate — même logique local→prod)
- `scripts/dev-start.sh` — démarrage env dev local
- `brain-ui/vite.config.ts` — proxy config dev
- Session 2026-03-18 — validation empirique complète du dev loop

View File

@@ -0,0 +1,126 @@
---
id: ADR-035
title: Mode Pilote — session longue durée, copilotage humain-brain
status: accepted
date: 2026-03-18
deciders: [human, coach]
tags: [session, mode, pilote, cognitif, collaboration]
scope: kernel
---
# ADR-035 — Mode Pilote
## Contexte
Quatre modes de session ont émergé dans le brain, mais seuls navigate, work et
swarm avaient une sémantique formelle. Le mode de collaboration le plus riche —
celui où humain et brain co-construisent sur la durée — restait implicite.
La session 2026-03-18 a été entièrement en mode pilote sans qu'il soit nommé :
zone filter, ADR-033/033a/034, Cosmos local, brain-template. Ce mode existait
dans la pratique avant d'exister dans le kernel.
---
## Décision
### Définition
```
Mode Pilote = session longue durée, contexte maximal, humain décide la direction
à chaque fork important. Brain est copilote actif — pas exécutant.
"On vole ensemble. Tu tiens le manche. Je gère les instruments."
```
### Propriétés
| Propriété | Valeur |
|-----------|--------|
| Durée | Illimitée — dure tant que l'énergie le permet |
| Contexte | FULL — tous les layers chargés |
| Initiative brain | Haute — propose, anticipe, signale |
| Gates humains | Sur les forks architecturaux et décisions irréversibles |
| Write mode | Autorisé partout selon la zone |
| Autonomie | Parallélisation possible (scripts + ADR en simultané) |
| Drift | Assumé et capturé — chaque insight est documenté immédiatement |
### Ce qui distingue Pilote des autres modes
```
Navigate → lecture, orientation, pas d'écriture
"Je veux comprendre l'état du brain"
Work → scope défini à l'avance, agent spécialisé, livrable attendu
"Je veux finir cette feature aujourd'hui"
Pilote → direction émergente, co-construction, documentation en temps réel
"On construit quelque chose ensemble, on verra où ça mène"
Swarm → autonome, humain ne voit que les blocages critiques
"Lance et reviens me voir si ça bloque"
```
### Quand utiliser Pilote
- Sessions de fondation (nouvelles décisions architecturales)
- Brainstorm → décision → implémentation → documentation dans la même session
- Quand la direction n'est pas encore claire au démarrage
- Quand la croissance cognitive est l'objectif autant que le livrable
### Comportement brain en mode Pilote
```
1. Propose l'ordre logique des étapes — l'humain valide ou réoriente
2. Signale les forks avant de s'engager ("Option A ou B ?")
3. Documente en temps réel (ADR, wiki, vocabulary) — pas en fin de session
4. Parallélise les tâches indépendantes sans demander permission
5. Stoppe et remonte tout blocage ou décision irréversible
6. Maintient le cap sur l'objectif même si la conversation dérive
```
### Activation
```yaml
# CLAUDE.md
brain boot mode pilote
# → charge contexts/session-pilote.yml
# → contexte FULL, identityShow: on, write: all zones
```
---
## Conséquences
**Pour le brain owner :**
- Un nom et une sémantique pour le mode de travail le plus productif
- La session 2026-03-18 en est la preuve empirique de référence
**Pour brain-template :**
- Distribué avec `session-pilote.yml` dans contexts/
- Le premier utilisateur comprend immédiatement quelle session ouvrir
pour co-construire son brain avec Claude
**Pour les swarms futurs :**
- Le mode Pilote est le prérequis naturel avant le swarm-ready gate :
on valide en Pilote, on automatise en Swarm
---
## Hiérarchie des modes (complète)
```
Navigate → orienter (lecture, fenêtre légère)
Work → livrer (scope défini, agent spécialisé)
Pilote → co-construire (direction émergente, contexte maximal)
Swarm → automatiser (autonome, humain en superviseur)
```
---
## Références
- ADR-032 — Mode d'exécution vs workflow (mode 1/2/3)
- ADR-030 — Validation empirique boot modes
- Session 2026-03-18 — référence empirique mode Pilote
- `contexts/session-pilote.yml` — contexte à créer