fix: restore root files and complete .claude lost during subtree push

This commit is contained in:
2026-03-27 10:07:33 +01:00
parent 52dc33cb47
commit 6c5c61811b
98 changed files with 881 additions and 0 deletions

52
.claude/CLAUDE.md Normal file
View File

@@ -0,0 +1,52 @@
## Instructions pour Claude
### Profil utilisateur
Programmeur expérimenté. Connaît parfaitement son projet, ses outils, et son environnement.
### Comportement attendu
- Faire ce qui est demandé, directement.
- Ne pas expliquer des choses triviales ou évidentes.
- Ne pas répéter ce qui vient d'être dit.
- Faire confiance au jugement de l'utilisateur.
- Si quelque chose ne fonctionne pas, chercher le bug — ne pas réexpliquer comment utiliser l'outil.
- Avant de demander la validation d'un plan, toujours afficher la totalité du plan dans le chat. L'utilisateur est responsable du code et décide en toute connaissance de cause.
## Stack
- Rust (edition 2024), Go 1.24
- Python 3.12, R 4.4, bash (scripts shell)
- Tests :
- Rust : `cargo test`
- Go : `go test`
- Python : `pytest` (avec coverage)
- R : `testthat` (via `Rscript -e "testthat::test_dir('tests')"`)
- bash : `bats` (Bash Automated Testing System)
- Lint :
- Rust : `clippy`
- Go : `golangci-lint`
- Python : `ruff` (ou `flake8` + `black`)
- R : `lintr`
- bash : `shellcheck`
## Heuristiques de délégation
Délègue à `qwen3-worker` (via MCP `qwen3_task`) si la tâche satisfait TOUS les critères :
- Objectif clair et bien délimité
- Pas de modification dAPI publique (traits Rust, interfaces Go exportées)
- Pas de vision cross-module requise
- Tâches typiques : génération de tests, documentation inline, scaffolding de stubs,
reformatage, recherche web, exécution de scripts, création de fichiers
Qwen3 dispose doutils autonomes (filesystem, shell, web) — inutile de lui passer
le contenu des fichiers, il les lit lui-même.
Traite toi-même si :
- Refactoring cross-module
- Conception darchitecture
- Debugging avec stacktrace multi-fichiers
- Modification de traits/interfaces publics
## Garde-fous absolus
- Ne jamais passer `rm -rf` sans confirmation explicite
- Ne jamais committer sans que les tests passent
- Toujours vérifier `git diff` avant un commit
- Pour le bash : ne jamais exécuter de commande avec `eval` non contrôlé ; privilégier lutilisation de `shellcheck` pour détecter les erreurs courantes

View File

@@ -0,0 +1 @@
2026-03-27T08:01:50Z agent=unknown

90
AGENTS.md Normal file
View File

@@ -0,0 +1,90 @@
# AGENTS.md
This file documents the project's coding standards, build/test/lint commands, and operational guidelines for agentic AI assistants.
## Build, Lint, and Test Commands
- **Rust**: `cargo build --all-targets && cargo test --all-targets`
- **Go**: `go build ./... && go vet ./... && go test ./...`
- **Python**: `python -m pytest tests/` (single test: `python -m pytest tests/test_module.py::test_function`)
- **R**: `Rscript -e "devtools::test()"` (single test: `Rscript -e "testthat::test_file('tests/testthat/test_module.R')"`)
- **Bash**: Run tests directly or use `bash -n script.sh` for syntax check
For all languages: run linters before committing (see hooks in `.claude/hooks/`)
## Code Style Guidelines
### General Principles
- Follow language-specific idioms and conventions
- Prioritize readability over cleverness
- Use descriptive names for variables, functions, and types
- Keep functions small and focused on a single responsibility
### Imports and Dependencies
- **Rust**: Use `use` statements at top of file; group std, external crates, and local modules
- **Go**: Import blocks organized: standard library, then external packages, then local packages
- **Python**: Standard library imports first, then third-party, then local imports
- **R**: Attach packages with `library()` at top of script; use `pkg::function()` for occasional calls
- **Bash**: Source local modules with absolute paths or relative from script location
### Naming Conventions
- **Rust**: Types/CamelCase, functions/snake_case, constants/SCREAMING_SNAKE_CASE
- **Go**: Exported names start with uppercase, unexported with lowercase; use CamelCase for acronyms
- **Python**: Classes/CamelCase, functions/variables/snake_case; use _private for internal
- **R**: Functions/lowercase_with_underscores; avoid naming conflicts with base R functions
- **Bash**: Functions/snake_case; variables lowercase; constants UPPERCASE
### Error Handling
- **Rust**: Use `Result<T, E>` and `?` operator; define custom error types for libraries
- **Go**: Return `(result, error)` tuple; handle errors immediately after function call
- **Python**: Raise specific exception types; catch only what you can handle meaningfully
- **R**: Use `stop()` for errors, `warning()` for warnings; consider tryCatch for recovery
- **Bash**: Check return codes with `$?`; use `set -e` for strict error handling
### Types and Documentation
- **Rust**: Specify all types explicitly; use `cargo doc` for documentation
- **Go**: Document exported functions with comments; use type aliases for clarity
- **Python**: Use type hints (PEP 484); docstrings with Google or NumPy style
- **R**: Use roxygen2 for function documentation; document all exported functions
- **Bash**: Comment complex logic; use `set -x` for debugging trace
## Cursor Rules
- Run linters after any file write (see `.claude/hooks/post-write-lint.sh`)
- For Rust/Go projects, run `cargo clippy` or `go vet` before committing
- Verify tests pass after changes: `cargo test`, `go test`, `pytest`
- When modifying multiple files, run full test suite before finalizing
## Copilot Rules
- Delegation: Use Qwen3-Coder for atomic tasks via MCP server at port 1248
- Code review: Invoke code-reviewer agent for PRs and significant changes
- Planning: Use task-planner to break complex tasks into atomic steps
- Always verify agent outputs before committing or pushing
## Hooks and Automation
- **post-write-lint.sh**: Runs linters after file writes
- **subagent-stop-log.sh**: Logs subagent completion and exit codes
- **pre-bash-guard.sh**: Validates bash scripts before execution
## MCP Server Configuration
- **Endpoint**: `http://localhost:1248`
- **Model**: `qwen/qwen3-coder-next`
- **Local agent loop**: `.claude/mcp/qwen3-mcp/agent_lm.py`
- **Server script**: `.claude/mcp/qwen3-mcp/server.py`
## Project Structure
- `.claude/agents/` - Agent definitions (qwen3-worker, code-reviewer, task-planner)
- `.claude/skills/` - Domain-specific skills and conventions
- `.claude/hooks/` - Git hooks for automated checks
- `.claude/mcp/qwen3-mcp/` - MCP server and agent integration
## Testing Strategy
- Run tests after any code change
- For single test execution, use language-specific commands above
- CI/CD should run full test suite on every push
- Code coverage targets: 80% minimum for production code

231
README.md Normal file
View File

@@ -0,0 +1,231 @@
# CrazyClaude
Configuration Claude Code pour orchestrer des tâches de développement en déléguant les tâches atomiques à **Qwen3-Coder** via [aichat](https://github.com/sigoden/aichat).
Ce dépôt est conçu pour être intégré comme sous-répertoire `.claude/` dans n'importe quel projet. Il fournit agents, hooks, skills, un serveur MCP et une collection d'outils prêts à l'emploi.
Pour le détail de l'architecture, voir [`rapport-orchestration-claude-code.md`](./rapport-orchestration-claude-code.md).
---
## Architecture
```
Claude Code (orchestrateur)
└── MCP qwen3 (stdio)
└── aichat --serve (port dynamique)
└── LM Studio → Qwen3-Coder-Next
+ outils llm-functions
(fs, shell, web, ...)
```
Le serveur MCP lance aichat au démarrage sur un port libre. Qwen3 dispose d'outils filesystem, shell et web fournis par [llm-functions](https://github.com/sigoden/llm-functions) — sans aucune logique d'outil dans le serveur lui-même.
---
## Prérequis
- [Claude Code](https://claude.ai/code) (`claude` dans le PATH)
- [aichat](https://github.com/sigoden/aichat) (`aichat` dans le PATH)
- [LM Studio](https://lmstudio.ai/) avec le modèle `qwen/qwen3-coder-next` chargé et accessible depuis aichat
- [argc](https://github.com/sigoden/argc) — runner de scripts pour llm-functions
- [jq](https://jqlang.github.io/jq/) — requis par llm-functions
- Python 3.11+ (pour le serveur MCP)
- Outils selon votre stack : `cargo` + `clippy` (Rust), `golangci-lint` (Go)
---
## Installation dans un projet existant
### 1. Cloner ce dépôt
Avec **Jujutsu** :
```sh
# Depuis la racine de votre projet
jj git clone https://gargoton.petite-maison-orange.fr/eric/CrazyClaude.git .claude-crazy
```
Puis copiez le contenu :
```sh
cp -r .claude-crazy/.claude ./.claude
cp -r .claude-crazy/llm-functions ./.claude/llm-functions # si présent dans le clone
```
> Avec jj colocalisé git, vous pouvez aussi utiliser subtree :
>
> ```sh
> git subtree add --prefix .claude https://gargoton.petite-maison-orange.fr/eric/CrazyClaude.git main --squash
> ```
### 2. Créer le virtualenv Python
```sh
cd .claude
python3 -m venv venv
venv/bin/pip install -r mcp/qwen3-mcp/requirements.txt
```
### 3. Installer et construire llm-functions
Si `llm-functions/` n'est pas déjà présent dans `.claude/` :
```sh
git clone https://github.com/sigoden/llm-functions .claude/llm-functions
```
Choisissez les outils à activer en éditant `.claude/llm-functions/tools.txt`, puis construisez :
```sh
cd .claude/llm-functions
argc build
```
Les outils activés par défaut :
```
fs_cat.sh
fs_ls.sh
fs_mkdir.sh
fs_write.sh
fs_patch.sh
execute_command.sh
fetch_url_via_curl.sh
web_search_aichat.sh
execute_py_code.py
```
### 4. Configurer aichat
Vérifiez que aichat peut accéder à LM Studio et que le modèle `qwen/qwen3-coder-next` est disponible :
```sh
aichat --list-models | grep qwen
```
### 5. Enregistrer le serveur MCP
```sh
claude mcp add --transport stdio qwen3 -- .claude/venv/bin/python3 .claude/mcp/qwen3-mcp/server.py
```
Vérifier :
```sh
claude mcp list
# qwen3: ... - ✓ Connected
```
### 6. Adapter CLAUDE.md à votre projet
Éditez `.claude/CLAUDE.md` : mettez à jour la section `## Stack` et les heuristiques de délégation.
### 7. Rendre les hooks exécutables
```sh
chmod +x .claude/hooks/*.sh
```
---
## Structure
```
.claude/
├── CLAUDE.md # contexte projet + heuristiques de délégation
├── settings.json # hooks et permissions
├── agents/
│ ├── qwen3-worker.md # délégation vers Qwen3 via MCP
│ ├── code-reviewer.md # révision code (Claude Haiku)
│ └── task-planner.md # planification complexe (Claude Opus)
├── skills/
│ ├── delegation-rules.md # quand déléguer à Qwen3
│ └── rust-go-conventions.md # conventions Rust/Go
├── hooks/
│ ├── post-write-lint.sh # lint automatique après écriture
│ ├── subagent-stop-log.sh # log des décisions de délégation
│ └── pre-bash-guard.sh # blocage des commandes dangereuses
├── mcp/
│ └── qwen3-mcp/
│ ├── server.py # serveur MCP stdio : lance aichat + gère tool_calls
│ ├── agent_lm.py # agent loop CLI autonome (usage direct sans MCP)
│ └── requirements.txt
├── llm-functions/ # collection d'outils pour Qwen3 (sous-repo)
│ ├── tools.txt # outils activés
│ ├── functions.json # déclarations générées (lues par server.py)
│ ├── bin/ # binaires générés par argc build
│ └── tools/ # scripts sources (.sh, .py, .js)
├── logs/ # produits par les hooks (ignorés par jj/git)
└── venv/ # virtualenv Python (ignoré par jj/git)
```
---
## Outils disponibles pour Qwen3
Les outils sont définis dans `.claude/llm-functions/tools.txt` et buildés avec `argc build`.
| Outil | Description |
|-------|-------------|
| `fs_cat` | Lit un fichier |
| `fs_ls` | Liste un répertoire |
| `fs_mkdir` | Crée un répertoire |
| `fs_write` | Écrit/crée un fichier |
| `fs_patch` | Modifie un fichier par patch |
| `execute_command` | Exécute une commande shell |
| `fetch_url_via_curl` | Requête HTTP GET |
| `web_search_aichat` | Recherche web |
| `execute_py_code` | Exécute du code Python |
Pour ajouter un outil : éditez `tools.txt` et relancez `argc build`.
---
## Configuration du modèle
Le modèle Qwen3 est configuré dans `.claude/mcp/qwen3-mcp/server.py` :
```python
QWEN3_MODEL = "LMStudio:qwen/qwen3-coder-next"
```
Le format `Provider:model-id` suit la convention aichat. Adaptez selon votre installation LM Studio.
---
## Fichiers à ignorer (jj / git)
```
.claude/venv/
.claude/logs/
.claude/llm-functions/bin/
.claude/llm-functions/cache/
```
Avec Jujutsu :
```sh
printf ".claude/venv/\n.claude/logs/\n.claude/llm-functions/bin/\n.claude/llm-functions/cache/\n" >> .gitignore
```
---
## Mise à jour
Avec Jujutsu colocalisé (`jj git init --colocate`), la mise à jour est gérée côté git :
```sh
git subtree pull --prefix .claude https://gargoton.petite-maison-orange.fr/eric/CrazyClaude.git main --squash
```
jj voit le commit résultant comme un commit ordinaire dans son graphe.
Après mise à jour, reconstruire llm-functions si `tools.txt` a changé :
```sh
cd .claude/llm-functions && argc build
```

View File

@@ -0,0 +1,507 @@
# Rapport Technique : Orchestration Robuste avec Claude Code et Délégation à un LLM Local
**Auteur** : Eric Coissac
**Date** : 26 mars 2026
**Contexte** : Ce document décrit une architecture robuste exploitant les mécanismes natifs de **Claude Code** (subagents, hooks, skills, MCP) pour déléguer des tâches à faible complexité à **Qwen3-Coder** (via LM Studio), tout en maintenant Claude Code comme orchestrateur central.
---
## 1. Pourquoi cette architecture — et ce qu'elle n'est *pas*
Le document original décrivait un système où Claude Code appelait un script Python externe (`delegate_to_qwen.py`) pour piloter Qwen3. C'est un anti-pattern : cela court-circuite les mécanismes natifs de Claude Code et réintroduit de la complexité là où l'écosystème propose déjà des solutions mieux intégrées.
En mars 2026, Claude Code dispose de cinq systèmes fondamentaux :
| Système | Rôle |
|---------|------|
| **CLAUDE.md** | Contexte permanent du projet (règles, conventions, heuristiques) |
| **Skills** | Instructions chargées à la demande selon la pertinence |
| **Subagents** | Agents spécialisés avec fenêtre de contexte isolée, outils restreints, modèle configurable |
| **Hooks** | Scripts shell ou prompts LLM déclenchés sur des événements du cycle de vie |
| **MCP servers** | Extensions vers des outils et services externes via protocole standardisé |
La délégation à Qwen3 s'intègre naturellement via un **subagent pointant vers LM Studio** ou via un **MCP server stdio minimal**. Le script Python devient optionnel — il reste utile comme wrapper si LM Studio n'expose pas d'interface MCP, mais il ne doit pas être l'orchestrateur.
---
## 2. Architecture cible
```
Utilisateur
Claude Code (orchestrateur)
│ lit CLAUDE.md au démarrage
│ charge les skills pertinents à la demande
├─── Subagent : qwen3-worker ──────► LM Studio (localhost:1234)
│ contexte isolé modèle Qwen3-Coder
│ outils : Read, Write, Bash
├─── Subagent : code-reviewer ──────► Claude Haiku (coût réduit)
│ validation syntaxe/style
├─── Hooks ──────────────────────────► scripts shell
│ PostToolUse : lint auto
│ SubagentStop : log décision
│ PreToolUse : garde-fous
└─── MCP servers (optionnel)
qwen3-mcp (stdio) : wrapper LM Studio
```
**Principe clé** : Claude Code ne lit pas les fichiers sources pour les passer à Qwen3. C'est Qwen3 (via son subagent ou son agent loop) qui lit les fichiers dont il a besoin — le contenu ne transite pas par le contexte de Claude Code.
---
## 3. Structure du projet
```
.claude/
├── CLAUDE.md # contexte projet + heuristiques de délégation
├── settings.json # hooks et permissions
├── agents/
│ ├── qwen3-worker.md # subagent → LM Studio
│ ├── code-reviewer.md # subagent → Haiku (validation)
│ └── task-planner.md # subagent → Opus (planification complexe)
├── skills/
│ ├── delegation-rules.md # quand déléguer à Qwen3
│ └── rust-go-conventions.md # conventions spécifiques au projet
└── hooks/
├── post-write-lint.sh # lint automatique après écriture
├── subagent-stop-log.sh # observabilité
└── pre-bash-guard.sh # sécurité
mcp/
└── qwen3-mcp/
├── server.py # MCP server stdio (optionnel)
└── agent_lm.py # agent loop local (~120 lignes)
```
---
## 4. CLAUDE.md — contexte et heuristiques
```markdown
# Projet [nom]
## Stack
- Rust (edition 2024), Go 1.24
- Tests : cargo test, go test
- Lint : clippy (Rust), golangci-lint (Go)
## Heuristiques de délégation
Délègue à `qwen3-worker` si la tâche est **atomique** et satisfait TOUS les critères :
- ≤ 3 fichiers concernés
- Pas de modification d'API publique
- Pas de dépendance externe non encore importée
- Tâches typiques : génération de tests unitaires, reformatage, documentation inline,
conversion de types simples, scaffolding de stubs
Traite toi-même si :
- Refactoring cross-module
- Conception d'architecture
- Debugging avec contexte multi-fichiers
- Modification de traits/interfaces publics
## Garde-fous absolus
- Ne jamais passer `rm -rf` sans confirmation explicite
- Ne jamais committer sans que les tests passent
- Toujours vérifier `git diff` avant un commit
```
---
## 5. Subagent `qwen3-worker`
Fichier : `.claude/agents/qwen3-worker.md`
```markdown
---
name: qwen3-worker
description: >
Délègue à Qwen3-Coder via LM Studio les tâches atomiques sur 1-3 fichiers :
génération de tests unitaires, documentation inline, scaffolding de stubs,
reformatage de code. N'utilise PAS pour du refactoring cross-module ou de
la conception d'architecture.
tools: [Read, Write, Bash]
model: inherit
---
Tu es un assistant de codage spécialisé exécutant des tâches courtes et précises.
## Comportement
1. Lis les fichiers nécessaires avec l'outil Read (ne reçois pas le contenu en entrée).
2. Effectue la transformation demandée.
3. Écris le résultat avec Write.
4. Exécute le linter approprié (clippy pour Rust, golangci-lint pour Go) et corrige
les erreurs éventuelles (max 2 tentatives).
5. Retourne un résumé : fichiers modifiés, changements effectués, résultat du lint.
## Format de sortie
```
STATUS: success|partial|failure
FILES_MODIFIED: liste des fichiers
SUMMARY: description des changements
LINT: passed|failed (+ détail si failed)
```
Ne génère pas de fonctions non demandées. Ne modifie pas les signatures publiques.
```
> **Note importante** : le champ `model: inherit` signifie que ce subagent utilise le modèle courant de la session. Pour pointer vers LM Studio, il faut soit configurer `ANTHROPIC_BASE_URL` pour ce subagent, soit utiliser le MCP server décrit en section 7.
---
## 6. Hooks
### `settings.json`
```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/post-write-lint.sh",
"async": true
}
]
}
],
"SubagentStop": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/subagent-stop-log.sh"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/pre-bash-guard.sh"
}
]
}
]
}
}
```
### `post-write-lint.sh`
```bash
#!/usr/bin/env bash
# Lint automatique après écriture de fichier
FILE=$(echo "$CLAUDE_TOOL_INPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('file_path',''))")
if [[ "$FILE" == *.rs ]]; then
cargo clippy --quiet 2>&1 | tail -20
elif [[ "$FILE" == *.go ]]; then
golangci-lint run "$FILE" 2>&1 | tail -20
fi
```
### `subagent-stop-log.sh`
```bash
#!/usr/bin/env bash
# Observabilité : log chaque fin de subagent
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
PAYLOAD=$(cat)
AGENT=$(echo "$PAYLOAD" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('agent_name','unknown'))" 2>/dev/null)
echo "$TIMESTAMP agent=$AGENT" >> .claude/logs/subagent-decisions.log
```
### `pre-bash-guard.sh`
```bash
#!/usr/bin/env bash
# Bloque les commandes destructives sans confirmation
CMD=$(echo "$CLAUDE_TOOL_INPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('command',''))")
if echo "$CMD" | grep -qE 'rm -rf|DROP TABLE|git push --force'; then
echo "BLOQUÉ : commande dangereuse détectée. Confirmez explicitement."
exit 2 # exit 2 = deny dans Claude Code
fi
```
---
## 7. MCP Server (optionnel — si LM Studio n'est pas accessible comme modèle)
Si l'objectif est de router un subagent vers LM Studio plutôt que vers l'API Anthropic, le moyen le plus simple est un MCP server stdio minimal.
### `mcp/qwen3-mcp/server.py`
```python
#!/usr/bin/env python3
"""
MCP server stdio minimaliste exposant un outil `qwen3_task`.
Appelé par Claude Code via : claude mcp add --transport stdio qwen3 -- python3 mcp/qwen3-mcp/server.py
"""
import sys
import json
import requests
LMSTUDIO_URL = "http://localhost:1234/v1/chat/completions"
QWEN3_MODEL = "qwen3-coder" # nom du modèle dans LM Studio
def call_qwen3(task: str, files: list[str]) -> str:
context = ""
for path in files:
try:
with open(path) as f:
context += f"--- {path} ---\n{f.read()}\n\n"
except OSError as e:
context += f"--- {path} --- ERREUR: {e}\n\n"
prompt = f"""Tu es un assistant de codage. Effectue la tâche suivante de manière précise.
TÂCHE: {task}
FICHIERS:
{context}
Retourne uniquement le code modifié ou généré, sans explication.
"""
resp = requests.post(
LMSTUDIO_URL,
json={
"model": QWEN3_MODEL,
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.2,
"max_tokens": 4096,
},
timeout=120,
)
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"]
def handle_tool_call(tool_name: str, args: dict) -> str:
if tool_name == "qwen3_task":
return call_qwen3(args["task"], args.get("files", []))
return f"Outil inconnu : {tool_name}"
# Boucle MCP stdio (protocole JSON-RPC simplifié)
for line in sys.stdin:
try:
req = json.loads(line)
if req.get("method") == "tools/call":
result = handle_tool_call(
req["params"]["name"], req["params"].get("arguments", {})
)
print(json.dumps({"id": req["id"], "result": {"content": [{"type": "text", "text": result}]}}))
elif req.get("method") == "tools/list":
print(json.dumps({
"id": req["id"],
"result": {"tools": [{
"name": "qwen3_task",
"description": "Délègue une tâche de codage atomique à Qwen3-Coder via LM Studio.",
"inputSchema": {
"type": "object",
"properties": {
"task": {"type": "string", "description": "Description précise de la tâche"},
"files": {"type": "array", "items": {"type": "string"}, "description": "Chemins des fichiers concernés"}
},
"required": ["task"]
}
}]}
}))
elif req.get("method") == "initialize":
print(json.dumps({"id": req["id"], "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}}}))
except Exception as e:
print(json.dumps({"error": str(e)}), file=sys.stderr)
sys.stdout.flush()
```
**Installation** :
```bash
claude mcp add --transport stdio qwen3 -- python3 mcp/qwen3-mcp/server.py
```
---
## 8. Skill de délégation
Fichier : `.claude/skills/delegation-rules.md`
```markdown
---
name: delegation-rules
description: Règles pour décider quand et comment déléguer à qwen3-worker ou qwen3 MCP
---
# Règles de Délégation à Qwen3
## Critères de délégation (TOUS requis)
- ≤ 3 fichiers source concernés
- Tâche atomique, sans dépendance à résoudre
- Pas de modification de signature publique (trait, interface exportée)
- Contexte de fichier estimé < 8 000 tokens
## Tâches typiques éligibles
- Génération de tests unitaires pour une fonction donnée
- Ajout de documentation (doc comments Rust, godoc Go)
- Scaffolding de stubs à partir d'une interface
- Conversion de types internes simples
- Reformatage / réorganisation d'imports
## Procédure
1. Évalue les critères ci-dessus.
2. Si éligible → utilise le subagent `qwen3-worker` en précisant la tâche et les fichiers.
3. Attends le résumé de sortie (STATUS / FILES_MODIFIED / LINT).
4. Si STATUS=failure → prends en charge toi-même.
5. Si STATUS=partial → corrige les points restants directement.
## Ne jamais déléguer
- Refactoring impliquant > 3 fichiers
- Changement d'architecture ou de design pattern
- Debugging avec stacktrace à analyser
- Tâches nécessitant une recherche web ou du contexte externe
```
---
## 9. Pipeline de validation native
Claude Code valide via les hooks et les subagents dédiés — pas via du code de validation embarqué dans le script de délégation.
| Étape | Mécanisme | Déclencheur |
|-------|-----------|-------------|
| Lint syntaxique | `post-write-lint.sh` (hook) | PostToolUse/Write automatique |
| Validation de style | subagent `code-reviewer` | explicitement demandé |
| Tests | `Bash: cargo test / go test` | dans le subagent ou directement |
| Contrôle des diffs | `Bash: git diff --stat` | avant tout commit |
### Subagent `code-reviewer`
```markdown
---
name: code-reviewer
description: >
Révise du code Rust ou Go pour détecter bugs, régressions, problèmes de style.
Utilise après génération par qwen3-worker ou avant un commit.
tools: [Read, Grep, Glob, Bash]
model: claude-haiku-4-5-20251001
---
Tu es un reviewer expérimenté en Rust et Go.
Pour chaque fichier fourni :
1. Vérifie la cohérence des types et la gestion d'erreurs.
2. Identifie les patterns non idiomatiques.
3. Signale les tests manquants pour les chemins critiques.
Format de sortie :
```
VERDICT: approved|changes_requested
ISSUES: liste numérotée (vide si approved)
```
```
---
## 10. Boucle de correction contrôlée
La boucle de correction n'est pas un script externe — elle est gérée nativement par Claude Code via le prompt du subagent et les hooks.
Séquence type :
1. Claude Code délègue à `qwen3-worker`.
2. Le subagent retourne `STATUS: failure` avec détail.
3. Claude Code lit le résumé, corrige lui-même ou re-délègue avec le feedback intégré dans le prompt.
4. Maximum 2 re-délégations ; au-delà, Claude Code traite directement.
---
## 11. Sécurité
Les garde-fous sont dans les **hooks** (non contournables par le contexte) plutôt que dans des fonctions Python.
```json
{
"permissions": {
"allow": [
"Bash(cargo:*)",
"Bash(go:*)",
"Bash(git diff*)",
"Bash(git add*)",
"Bash(git commit*)",
"Read(**/*.rs)",
"Read(**/*.go)",
"Write(**/*.rs)",
"Write(**/*.go)"
],
"deny": [
"Bash(rm -rf*)",
"Bash(curl * | bash*)",
"Bash(git push --force*)"
]
}
}
```
---
## 12. Observabilité
Les logs sont produits par les hooks, pas par du code applicatif.
```
.claude/logs/
├── subagent-decisions.log # timestamp + agent name à chaque SubagentStop
└── delegation-outcomes.log # STATUS de chaque délégation (si ajouté au hook)
```
Pour des métriques plus élaborées (taux de délégation, taux d'échec), un hook `SubagentStop` peut écrire dans un fichier JSON et un script externe peut agréger.
---
## 13. Workflow complet — exemple
**Requête** : "Génère les tests unitaires pour les fonctions `parse_header` et `validate_checksum` dans `src/parser.rs`."
1. Claude Code lit `CLAUDE.md` → identifie les heuristiques de délégation.
2. Charge le skill `delegation-rules.md` → tâche éligible (1 fichier, atomique, pas d'API publique).
3. Délègue au subagent `qwen3-worker` : *"Génère des tests unitaires pour `parse_header` et `validate_checksum` dans `src/parser.rs`"*.
4. `qwen3-worker` lit `src/parser.rs` via l'outil Read (le contenu ne passe pas par le contexte principal).
5. Écrit les tests dans `src/parser.rs` (ou `tests/parser_tests.rs`).
6. Hook `post-write-lint.sh` déclenché → `cargo clippy` → résultat injecté dans le contexte du subagent.
7. Subagent retourne : `STATUS: success | FILES_MODIFIED: src/parser.rs | LINT: passed`.
8. Claude Code confirme à l'utilisateur.
---
## 14. Ce qui a changé par rapport au document initial
| Document initial | Cette version |
|-----------------|---------------|
| Script Python `delegate_to_qwen.py` comme orchestrateur | Claude Code natif comme orchestrateur |
| Validation syntaxique dans le script | Hook `post-write-lint.sh` (déterministe, non contournable) |
| Boucle de correction en Python | Gérée par le prompt du subagent + logique d'orchestration Claude |
| Sécurité dans `is_safe_file()` | Permissions natives (`settings.json`) + hook `pre-bash-guard.sh` |
| Logs en Python | Hooks shell sur les événements du cycle de vie |
| Tools MCP = scripts ad hoc | MCP server stdio standard + subagents natifs |
---
## 15. Prochaines étapes recommandées
1. **Bootstrapper la structure** : créer `.claude/agents/`, `settings.json`, `CLAUDE.md` avec les templates ci-dessus.
2. **Tester LM Studio** : vérifier que `curl http://localhost:1234/v1/models` répond avant d'activer le MCP server.
3. **Calibrer les heuristiques** : après 20-30 délégations, affiner les critères dans `delegation-rules.md` selon les résultats observés dans les logs.
4. **Envisager `model:` explicite** : si Claude Haiku est suffisant pour `qwen3-worker` (coût réduit, latence moindre), configurer `model: claude-haiku-4-5-20251001` à la place du LLM local.
5. **MCP Tool Search** : activer `ENABLE_TOOL_SEARCH=auto` pour réduire la consommation de contexte quand les MCP servers sont nombreux.