diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..6966336 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,22 @@ +{ + "permissions": { + "allow": [ + "Bash(git:*)", + "Bash(make:*)", + "Bash(python3:*)", + "Bash(pip:*)", + "Bash(ls:*)", + "Bash(cat:*)", + "Read(*)", + "Edit(*)", + "Write(*)", + "Glob(*)", + "Grep(*)" + ], + "deny": [ + "Bash(rm -rf:*)", + "Bash(curl *password*:*)", + "Bash(ssh:*)" + ] + } +} diff --git a/.gitea/AGENTS.md b/.gitea/AGENTS.md new file mode 100644 index 0000000..af99234 --- /dev/null +++ b/.gitea/AGENTS.md @@ -0,0 +1,24 @@ +# AGENTS — Identités et permissions + +## Comptes Gitea actifs + +| Username | Rôle | Périmètre | +|---|---|---| +| `floppyrj45` | Admin / Owner | Tous les repos, valide les PR sur `main` | +| `agent-surfer` | Agent principal OpenClaw | Tous les repos du Labo | +| `agent-watcher` | Gitea watcher / CI | Lecture + commentaires issues | +| `agent-claude-cli` | Claude Code CLI local | Repos assignés par Flag | +| `agent-codex` | Codex / OpenCode | Repos assignés par Flag | + +## Créer un nouveau compte agent + +```bash +./scripts/gitea-agent-setup.sh +``` + +Le script crée le compte Gitea, génère un token, et l'ajoute à `~/.agent-gitea-tokens`. + +## Règle de moindre privilège + +Un agent ne touche qu'aux repos explicitement listés dans `AI_CONTEXT.md` de chaque projet. +Il ne lit pas, ne fork pas, ne clone pas les repos hors de son périmètre. diff --git a/.gitea/WORKFLOW.md b/.gitea/WORKFLOW.md new file mode 100644 index 0000000..7a7b0bd --- /dev/null +++ b/.gitea/WORKFLOW.md @@ -0,0 +1,54 @@ +# WORKFLOW — Règles Git multi-agent + +## Branches + +| Branche | Usage | Qui push | +|---|---|---| +| `main` | Production stable | Flag uniquement (via PR) | +| `develop` | Intégration continue | Agents via PR | +| `feat//` | Nouvelle fonctionnalité | Agent concerné | +| `fix//` | Correction de bug | Agent concerné | +| `chore//` | Maintenance, docs, config | Agent concerné | + +**Jamais de push direct sur `main` ou `develop`.** Toujours via Pull Request. + +## Format de commit + +``` +[agent:] +``` + +Exemples : +- `[agent:surfer] ajout endpoint /mission pour dashboard` +- `[agent:claude-cli] fix calcul distance waypoints` +- `[flag] merge feat/surfer/telemetry-endpoint` + +Le nom d'agent doit correspondre à un compte Gitea listé dans `AGENTS.md`. + +## Pull Requests + +- Titre : `[agent:] ` +- Body : utiliser le template `.gitea/pull_request_template.md` +- Reviewer : `floppyrj45` (Flag) pour toute PR vers `main` +- PR vers `develop` : peut être mergée par un autre agent si les checks passent + +## Issues + +- Ouvrir une issue avant tout travail non trivial +- Assigner l'agent qui prend en charge +- Labels : `bug`, `feat`, `chore`, `blocked`, `agent:` + +## Protection de branche + +- `main` : PR obligatoire, 1 approbation humaine minimum +- `develop` : PR obligatoire, checks CI requis + +## Identité Git locale (agents) + +Chaque agent configure : +```bash +git config user.name "agent-" +git config user.email "agent-@labo.local" +``` + +Token d'authentification : voir `~/.agent-gitea-tokens` sur `.82`, ou demander via `gitea-agent-setup.sh`. diff --git a/.gitea/pull_request_template.md b/.gitea/pull_request_template.md new file mode 100644 index 0000000..2f3617f --- /dev/null +++ b/.gitea/pull_request_template.md @@ -0,0 +1,25 @@ +## Résumé + + + +## Type de changement + +- [ ] `feat` — nouvelle fonctionnalité +- [ ] `fix` — correction de bug +- [ ] `chore` — maintenance / docs / config +- [ ] `refactor` — refactoring sans changement de comportement + +## Agent / Auteur + +`agent:` + +## Checklist + +- [ ] Code testé localement +- [ ] Docs mises à jour si besoin (`docs/`) +- [ ] Pas de secret en clair dans le diff +- [ ] Commit messages au format `[agent:] verbe description` + +## Contexte + + diff --git a/.gitea/workflows/docs.yml b/.gitea/workflows/docs.yml new file mode 100644 index 0000000..7c5740a --- /dev/null +++ b/.gitea/workflows/docs.yml @@ -0,0 +1,23 @@ +name: Build Sphinx docs + +on: + push: + branches: [main, develop] + paths: ['docs/**'] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + - run: pip install sphinx sphinx-rtd-theme myst-parser + - run: make -C docs html + - name: Deploy docs + run: | + rsync -avz --delete docs/_build/html/ \ + floppyrj45@192.168.0.82:/srv/www/${REPO_NAME}-docs/ + env: + REPO_NAME: ${{ github.event.repository.name }} diff --git a/AI_CONTEXT.md b/AI_CONTEXT.md new file mode 100644 index 0000000..63c451e --- /dev/null +++ b/AI_CONTEXT.md @@ -0,0 +1,58 @@ +# AI_CONTEXT.md — Handoff agent + +> **Premier fichier à lire.** Ce fichier permet à n'importe quel agent IA de reprendre le projet sans briefing humain. + +## Projet + +| Champ | Valeur | +|---|---| +| **Nom** | PROJECT_NAME | +| **Description** | PROJECT_DESCRIPTION | +| **Statut** | `wip` / `active` / `paused` / `archived` | +| **Owner humain** | Flag (`floppyrj45`) | +| **Agent principal** | `agent-surfer` | + +## Ressources + +| Ressource | URL / Chemin | +|---|---| +| **Gitea** | `http://192.168.0.82:3000/floppyrj45/PROJECT_NAME` | +| **Nextcloud** | `/mnt/nas-nextcloud/PROJECT_NAME/` (sur `.82`) | +| **Docs Sphinx** | `http://192.168.0.82/PROJECT_NAME-docs/` | +| **Channel Discord** | `#PROJECT_CHANNEL` | + +## Architecture courte + +*À compléter — 5-10 lignes max. Stack, composants principaux, ports exposés.* + +## État actuel + +*Résumé de l'état du projet au moment de la dernière mise à jour de ce fichier.* + +## Tâches ouvertes + +- [ ] tâche 1 +- [ ] tâche 2 + +## Décisions clés + +*Décisions d'architecture ou de design importantes à connaître.* + +## Comment démarrer (agent) + +```bash +# 1. Configurer ton identité Git +git config user.name "agent-" +git config user.email "agent-@labo.local" + +# 2. Lire les règles workflow +cat .gitea/WORKFLOW.md + +# 3. Créer ta branche de travail +git checkout -b feat/agent-/ + +# 4. Push et ouvrir une PR vers develop +git push origin feat/agent-/ +``` + +Token Gitea : voir `~/.agent-gitea-tokens` sur `.82` ou demander à Flag. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ab111e1 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,37 @@ +# CLAUDE.md — Instructions pour agents Claude + +## Contexte projet + +Voir `AI_CONTEXT.md` pour le contexte complet. + +## Règles de développement + +- Lire `.gitea/WORKFLOW.md` avant tout commit +- Branche de travail : `feat/agent-claude-cli/` +- Commit format : `[agent:claude-cli] verbe description` +- Jamais de push direct sur `main` ou `develop` +- Jamais de secret en clair dans le code ou les commits + +## Stack technique + +*À compléter selon le projet.* + +## Commandes utiles + +```bash +# Tests +# make test + +# Docs +make -C docs html + +# Linter +# make lint +``` + +## Périmètre autorisé + +- Modifier le code dans ce repo uniquement +- Ouvrir des PRs vers `develop` +- Créer des issues si bloqué +- Ne pas toucher aux secrets, credentials, ou config infra diff --git a/README.md b/README.md index 9e646cb..2c5c933 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,29 @@ -# lab-project-template +# PROJECT_NAME -Template standard AI-ready — scaffold pour tout nouveau projet Labo \ No newline at end of file +> PROJECT_DESCRIPTION + +**Statut** : `wip` +**Owner** : Flag +**Agent principal** : `agent-surfer` + +## Démarrage rapide (agent IA) + +```bash +git clone http://192.168.0.82:3000/floppyrj45/PROJECT_NAME +cd PROJECT_NAME +# Lire le contexte complet : +cat AI_CONTEXT.md +cat CLAUDE.md +cat .gitea/WORKFLOW.md +``` + +## Ressources + +- Docs : `http://192.168.0.82/PROJECT_NAME-docs/` +- Nextcloud : `/mnt/nas-nextcloud/PROJECT_NAME/` +- Discord : `#PROJECT_CHANNEL` + +## Liens + +- [Master Plan](http://192.168.0.82:3000/floppyrj45/openclaw-workspace) +- [Docs Sphinx](http://192.168.0.82/PROJECT_NAME-docs/) diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..23cac69 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,9 @@ +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +html: + $(SPHINXBUILD) -b html $(SOURCEDIR) $(BUILDDIR)/html + +clean: + rm -rf $(BUILDDIR) diff --git a/docs/architecture.rst b/docs/architecture.rst new file mode 100644 index 0000000..6468882 --- /dev/null +++ b/docs/architecture.rst @@ -0,0 +1,4 @@ +Architecture +============ + +*À documenter.* diff --git a/docs/changelog.rst b/docs/changelog.rst new file mode 100644 index 0000000..0ff43a6 --- /dev/null +++ b/docs/changelog.rst @@ -0,0 +1,6 @@ +Changelog +========= + +v0.1 — init +----------- +- Scaffold initial diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..ff84f69 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,6 @@ +project = "PROJECT_NAME" +author = "Flag / OpenClaw agents" +release = "0.1" +extensions = ["myst_parser", "sphinx.ext.autodoc", "sphinx.ext.viewcode"] +html_theme = "sphinx_rtd_theme" +source_suffix = {".rst": "restructuredtext", ".md": "markdown"} diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..491d4c6 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,15 @@ +PROJECT_NAME +============ + +.. toctree:: + :maxdepth: 2 + :caption: Documentation + + architecture + changelog + api + +Overview +-------- + +*À compléter — voir AI_CONTEXT.md pour le contexte agent.* diff --git a/scripts/gitea-agent-setup.sh b/scripts/gitea-agent-setup.sh new file mode 100755 index 0000000..825abb5 --- /dev/null +++ b/scripts/gitea-agent-setup.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# gitea-agent-setup.sh — Crée ou récupère un compte Gitea pour un agent IA +# Usage: ./scripts/gitea-agent-setup.sh +# Ex: ./scripts/gitea-agent-setup.sh my-custom-agent + +set -e +AGENT_NAME="${1:?Usage: $0 }" +USERNAME="agent-${AGENT_NAME}" +BASE_URL="${GITEA_BASE_URL:-http://192.168.0.82:3000}" +TOKENS_FILE="$HOME/.agent-gitea-tokens" + +# Load admin token +if [[ -f "$TOKENS_FILE" ]]; then + source "$TOKENS_FILE" +fi +ADMIN_TOKEN="${GITEA_ADMIN_TOKEN:-}" + +if [[ -z "$ADMIN_TOKEN" ]]; then + echo "ERROR: GITEA_ADMIN_TOKEN non défini. Ajouter dans $TOKENS_FILE" + exit 1 +fi + +# Check if user already exists +STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -H "Authorization: token $ADMIN_TOKEN" \ + "$BASE_URL/api/v1/users/$USERNAME") + +if [[ "$STATUS" == "200" ]]; then + echo "Compte $USERNAME existe déjà." +else + echo "Création du compte $USERNAME..." + curl -sf -X POST "$BASE_URL/api/v1/admin/users" \ + -H "Authorization: token $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{ + \"username\": \"$USERNAME\", + \"email\": \"$USERNAME@labo.local\", + \"password\": \"$(openssl rand -base64 24)\", + \"full_name\": \"Agent $AGENT_NAME\", + \"login_name\": \"$USERNAME\", + \"source_id\": 0, + \"send_notify\": false, + \"must_change_password\": false + }" > /dev/null + echo "Compte $USERNAME créé." +fi + +# Generate token via CLI (requires SSH to .82) +echo "Génération du token..." +TOKEN=$(ssh floppyrj45@192.168.0.82 \ + "docker exec -u git gitea gitea admin user generate-access-token \ + --username $USERNAME --token-name default --raw 2>/dev/null") + +if [[ -z "$TOKEN" ]]; then + echo "ERROR: Impossible de générer le token." + exit 1 +fi + +VAR_NAME="GITEA_TOKEN_$(echo $AGENT_NAME | tr '[:lower:]-' '[:upper:]_')" + +# Add to tokens file +if grep -q "$VAR_NAME" "$TOKENS_FILE" 2>/dev/null; then + sed -i "s|^${VAR_NAME}=.*|${VAR_NAME}=${TOKEN}|" "$TOKENS_FILE" +else + echo "${VAR_NAME}=${TOKEN}" >> "$TOKENS_FILE" +fi + +echo "Token stocké dans $TOKENS_FILE" +echo "" +echo "Config Git pour $USERNAME :" +echo " git config user.name \"$USERNAME\"" +echo " git config user.email \"$USERNAME@labo.local\"" +echo "" +echo "Clone avec auth :" +echo " git clone http://$USERNAME:$TOKEN@192.168.0.82:3000/floppyrj45/REPO_NAME" diff --git a/scripts/new-project.sh b/scripts/new-project.sh new file mode 100755 index 0000000..b696087 --- /dev/null +++ b/scripts/new-project.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# new-project.sh — Scaffold un nouveau projet AI-ready +# Usage: ./new-project.sh "" [channel-discord] +# Ex: ./new-project.sh cosma-dashboard "Dashboard C2 COSMA temps réel" cosma + +set -e +REPO_NAME="${1:?Usage: $0 [discord-channel]}" +DESCRIPTION="${2:?Usage: $0 [discord-channel]}" +DISCORD_CHANNEL="${3:-master-plan}" +BASE_URL="${GITEA_BASE_URL:-http://192.168.0.82:3000}" +TEMPLATE_REPO="floppyrj45/lab-project-template" +NEXTCLOUD_BASE="/mnt/nas-nextcloud" + +if [[ -f "$HOME/.agent-gitea-tokens" ]]; then source "$HOME/.agent-gitea-tokens"; fi +ADMIN_TOKEN="${GITEA_ADMIN_TOKEN:-${GITEA_TOKEN_SURFER:-}}" +if [[ -z "$ADMIN_TOKEN" ]]; then + echo "ERROR: Aucun token Gitea trouvé dans ~/.agent-gitea-tokens" + exit 1 +fi + +echo "=== Création projet : $REPO_NAME ===" + +# 1. Create Gitea repo from template +echo "[1/4] Création repo Gitea..." +REPO=$(curl -sf -X POST "$BASE_URL/api/v1/repos/$TEMPLATE_REPO/generate" \ + -H "Authorization: token $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{ + \"owner\": \"floppyrj45\", + \"name\": \"$REPO_NAME\", + \"description\": \"$DESCRIPTION\", + \"private\": true, + \"default_branch\": \"main\" + }" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d.get("html_url","ERR"))' 2>/dev/null) +echo " Repo: $REPO" + +# 2. Create Nextcloud folder +echo "[2/4] Création dossier Nextcloud..." +mkdir -p "$NEXTCLOUD_BASE/$REPO_NAME" 2>/dev/null || echo " (Nextcloud mount non disponible, à créer manuellement)" + +# 3. Clone and customize AI_CONTEXT.md +echo "[3/4] Personnalisation du template..." +WORK_DIR=$(mktemp -d) +git clone "http://floppyrj45@192.168.0.82:3000/floppyrj45/$REPO_NAME" "$WORK_DIR/$REPO_NAME" 2>/dev/null +cd "$WORK_DIR/$REPO_NAME" + +sed -i "s/PROJECT_NAME/$REPO_NAME/g" AI_CONTEXT.md README.md CLAUDE.md docs/conf.py docs/index.rst +sed -i "s/PROJECT_DESCRIPTION/$DESCRIPTION/g" AI_CONTEXT.md README.md +sed -i "s/PROJECT_CHANNEL/$DISCORD_CHANNEL/g" AI_CONTEXT.md README.md + +git config user.name "agent-surfer" +git config user.email "agent-surfer@labo.local" +git add -A +git commit -m "[agent:surfer] init scaffold $REPO_NAME" +git push origin main +cd / && rm -rf "$WORK_DIR" + +# 4. Setup branch protection +echo "[4/4] Protection de branches..." +for branch in main develop; do + curl -sf -X POST "$BASE_URL/api/v1/repos/floppyrj45/$REPO_NAME/branch_protections" \ + -H "Authorization: token $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{ + \"branch_name\": \"$branch\", + \"enable_push\": false, + \"enable_push_whitelist\": true, + \"push_whitelist_usernames\": [\"floppyrj45\"], + \"require_signed_commits\": false, + \"enable_status_check\": false + }" > /dev/null 2>&1 || true +done + +echo "" +echo "=== Projet $REPO_NAME prêt ===" +echo " Gitea : $BASE_URL/floppyrj45/$REPO_NAME" +echo " Docs : http://192.168.0.82/$REPO_NAME-docs/" +echo " NC : $NEXTCLOUD_BASE/$REPO_NAME/" +echo "" +echo "Pour un agent Claude CLI :" +echo " git clone http://192.168.0.82:3000/floppyrj45/$REPO_NAME && cd $REPO_NAME && claude"