From 59e046ad99534eef3cd86f0abce0b2e72f5b1fef Mon Sep 17 00:00:00 2001 From: bach Date: Sun, 4 Oct 2026 12:29:24 +0200 Subject: [PATCH] =?UTF-8?q?tour=200001=20(claude,=20implementer)=20:=20fon?= =?UTF-8?q?dation=20=E2=80=94=20README,=20PROTOCOL=20v0,=20config,=20backl?= =?UTF-8?q?og=20B-1..B-13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disput-Turn: 0001 Disput-Participant: claude Disput-Role: implementer Co-Authored-By: Claude Opus 5.5 --- .disput/backlog.md | 50 +++++ .disput/disput.toml | 53 ++++++ .disput/turns/0001-claude-implementer.md | 98 ++++++++++ .gitignore | 9 + AGENTS.md | 21 +++ CLAUDE.md | 10 + PROTOCOL.md | 228 +++++++++++++++++++++++ README.md | 69 +++++++ 8 files changed, 538 insertions(+) create mode 100644 .disput/backlog.md create mode 100644 .disput/disput.toml create mode 100644 .disput/turns/0001-claude-implementer.md create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 PROTOCOL.md create mode 100644 README.md diff --git a/.disput/backlog.md b/.disput/backlog.md new file mode 100644 index 0000000..1708f27 --- /dev/null +++ b/.disput/backlog.md @@ -0,0 +1,50 @@ +# Backlog — disput + +Une tâche par ligne : `- [ ] B- : …`. On coche à la fin du tour qui +la termine, en citant ce tour. `[USER]` = décision humaine, jamais prise +par un implémenteur. Numéros uniques, jamais réutilisés. + +## v0 — amorçage (le relais remplace la navette manuelle) + +- [ ] B-1 : squelette du paquet Python (`pyproject.toml`, `src/disput/`, + point d'entrée `disput`, `argparse` + `tomllib`, aucune dépendance + externe en v0), `tests/` en `unittest` +- [ ] B-2 : parseur de fichiers de tour (en-tête `+++` TOML, sections + Réponses/Items, identifiants, destinataires) + `disput lint` +- [ ] B-3 : déduction de l'état des items à partir des tours (§5) + + `disput status` +- [ ] B-4 : ordonnanceur (§7) en **fonction pure** : + (config, tours, diff du dernier tour) → (participant, rôle) | USER + | DONE. Tests exhaustifs, y compris l'anti ping-pong +- [ ] B-5 : vérification des invariants après un tour (§8), git + uniquement +- [ ] B-6 : adaptateurs `claude` et `vibe` (lancement non interactif, + env forcé, budget/max-turns, log local) + adaptateur `stub` pour + les tests +- [ ] B-7 : `disput run` (verrou, boucle, arrêt, `.disput/last-run.md`, + notification) + scénarios stub « tricheurs » : pas de commit, + réécriture, modification d'un tour existant, réviseur qui touche + au code, `status=USER` +- [ ] B-8 : `disput decide "…"` (écrit et commite le tour `user`) +- [ ] B-9 : garde-fous appliqués par adaptateur, à partir de `[guards]` + (deny et hook Claude, agent et hook `pre_tool` Vibe), avec preuve + qu'un `git push` est refusé dans chaque adaptateur +- [ ] B-10 : `disput init` (crée `.disput/` dans un projet existant) +- [ ] B-11 : premier `disput run --max-turns 2` sur disput lui-même, + sous surveillance de l'humain +- [ ] B-12 : adoption par qbt-manager (`disput init`, `disput.toml` + avec les checks preflight/tests et les garde-fous dry-run, rôle + `security` sur ses chemins sensibles) + +## Décisions humaines + +- [ ] B-13 [USER] : licence, et dépôt public ou privé (remote) + +## Plus tard (seulement sur besoin observé) + +- ACP comme transport unifié des adaptateurs, avec des garde-fous + centralisés +- reviewers en parallèle (worktrees) +- interface en terminal (affichage des tours en direct, décisions à + l'écran) +- adaptateurs supplémentaires (codex, gemini, opencode…) diff --git a/.disput/disput.toml b/.disput/disput.toml new file mode 100644 index 0000000..61e05fc --- /dev/null +++ b/.disput/disput.toml @@ -0,0 +1,53 @@ +# Configuration disput pour le développement de disput lui-même. + +[project] +name = "disput" +instructions = "PROTOCOL.md" + +[[participants]] +name = "claude" +adapter = "claude" +roles = ["implementer", "reviewer", "security"] + +[[participants]] +name = "vibe" +adapter = "vibe" +roles = ["implementer", "reviewer", "security"] + +[[participants]] +name = "user" +adapter = "human" +roles = ["decider"] + +[[roles]] +name = "implementer" +writes_code = true +triggers = ["backlog"] +brief = "Prendre la tâche ouverte la plus haute du backlog, l'implémenter, la tester réellement, commiter." + +[[roles]] +name = "reviewer" +writes_code = false +triggers = ["code_changed"] +brief = "Review sévère du diff depuis la base du tour : bugs, sécurité, hypothèses non validées, écart entre code et tours. Ré-exécuter, ne pas croire." + +[[roles]] +name = "security" +writes_code = false +triggers = ["paths:src/disput/guards*,src/disput/adapters/**,.disput/disput.toml"] +brief = "Audit des garde-fous : un agent peut-il contourner un deny, échapper à l'env forcé, pousser, réécrire l'historique ?" + +[[roles]] +name = "decider" +writes_code = false +triggers = [] +brief = "L'humain. Tranche les décisions [USER]." + +[[checks]] +name = "tests" +command = "python -m unittest discover -s tests" +policy = "no_regression" # passera à must_pass dès qu'il y aura des tests + +[guards] +env = {} +deny = ["git push", "git filter-branch", "git filter-repo", "git rebase", "git reset --hard", "git commit --amend", "git update-ref", "git reflog expire"] diff --git a/.disput/turns/0001-claude-implementer.md b/.disput/turns/0001-claude-implementer.md new file mode 100644 index 0000000..53b3748 --- /dev/null +++ b/.disput/turns/0001-claude-implementer.md @@ -0,0 +1,98 @@ ++++ +turn = 1 +participant = "claude" +role = "implementer" +base = "" # premier tour, pas de HEAD antérieur +status = "CONTINUE" ++++ + +# Tour 1 — claude, implementer : fondation du dépôt + +## Réponses + +Aucune : premier tour. + +## Travail + +Décision `user` à l'origine du dépôt, prise hors tour et consignée ici +(règle 5) : + +- créer un outil d'orchestration multi-agents, nommé **disput**, dans + son propre dépôt ; +- ouvrir dès le départ le protocole à **N participants et à des rôles + configurables**, pas seulement à un dialogue à deux ; +- développer l'outil **en parallèle de son expérimentation**, avec son + propre protocole (dogfooding) ; +- objectif premier : supprimer la navette manuelle (« à toi ») de + l'humain. + +Ce tour pose : + +- `README.md` : raison d'être, principes, usage visé ; +- `PROTOCOL.md` : spec normative v0 (concepts, fichiers de tour + immuables, cycle de vie des items, rôles et déclencheurs, + ordonnancement, invariants, garde-fous, place de l'humain, pratique + manuelle) ; +- `.disput/disput.toml` : configuration du projet lui-même (claude et + vibe éligibles aux trois rôles, user décideur) ; +- `.disput/backlog.md` : B-1 à B-13 ; +- `AGENTS.md` / `CLAUDE.md` minces, qui renvoient à `PROTOCOL.md`. + +Origine : ce protocole généralise celui pratiqué sur 16 tours dans un +autre projet du même utilisateur (dialogue Claude/Vibe en +implémenteur/reviewer alternés via un DEVLOG unique). Ce qui est repris : +- la réponse point par point ; +- l'interdiction de modifier les entrées de l'autre ; +- l'obligation de vérifier soi-même. + +Ce qui change : +- un fichier par tour plutôt qu'un DEVLOG unique ; +- l'état des items déduit des tours ; +- un ordonnanceur à règles au lieu d'une simple alternance ; +- des invariants vérifiables par machine. + +## Vérifications + +Aucun code ce tour, donc rien à exécuter. Relecture de cohérence : +l'en-tête de ce fichier suit le §4, et les identifiants d'items le §4 +également. + +## Items + +- [I-0001-1] → role:reviewer : en-tête de tour en **TOML entre `+++`** + plutôt qu'en YAML `---`, pour rester sans dépendance (`tomllib` est + dans la stdlib depuis 3.11). C'est moins répandu que YAML chez les + agents. Risque-t-il de mal formater des en-têtes ? Le coût d'une + dépendance YAML est-il préférable ? +- [I-0001-2] → role:reviewer : l'état des items est **déduit** des + tours, sans fichier d'état. C'est robuste à la falsification, mais + dépendant d'un parsing strict des lignes `- [I-…]` dans du markdown + libre. Faut-il un bloc structuré (TOML) pour les réponses et les items + plutôt que des puces ? +- [I-0001-3] → role:reviewer : **trou dans le §7** que je signale + moi-même. Un item adressé à `@participant`, sans rôle, ne dit pas dans + quel rôle ce participant doit jouer. Ma proposition : il joue dans le + rôle qu'il tenait au tour visé par l'item, et à défaut `implementer`. + D'accord, ou faut-il interdire l'adressage `@participant` nu ? +- [I-0001-4] → role:reviewer : « un tour = un rôle ». Si `reviewer` et + `security` sont déclenchés par le même diff et qu'un seul participant + est éligible (≠ auteur), il joue deux tours d'affilée. Est-ce + acceptable, ou faut-il autoriser un tour multi-rôles (un fichier, deux + sections) ? +- [I-0001-5] → role:security : le §9 promet trop. Des `deny` par motif + de chaîne se contournent facilement : `git -c … push`, des alias, un + `sh -c`, un `subprocess` en Python… L'invariant §8.3 (refs distantes) + ne détecte le push qu'**après coup**. Piste de défense en amont : + forcer dans `[guards].env` des variables qui rendent le transport + inopérant pendant un tour, par exemple une commande SSH qui échoue + toujours, ou un `pushurl` invalide via la config git d'environnement. + Est-ce suffisant, contournable, ou à combiner avec autre chose ? +- [I-0001-6] → role:reviewer : v0 **sans aucune dépendance externe** + (`argparse`, `unittest`, `tomllib`). Est-ce tenable jusqu'à B-7 ? Ou + vaut-il mieux assumer tout de suite une CLI (Typer/Click) et pytest ? + +**Prochain tour, d'après le §7 :** ce tour modifie des fichiers hors de +`.disput/` (`code_changed`), donc c'est au **reviewer**, tenu par +**vibe** (≠ auteur). `.disput/disput.toml` correspond aussi au +déclencheur `paths:` de `security`, donc vibe joue ensuite **security**, +sauf si I-0001-4 est tranché autrement entre-temps. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5469e94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.disput/logs/ +.disput/run.lock +.disput/last-run.md +.venv/ +__pycache__/ +*.pyc +*.egg-info/ +dist/ +build/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5dea9d4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,21 @@ +# AGENTS.md — instructions pour les agents (Vibe et autres) + +Ce dépôt se développe **avec son propre protocole**. Tu es un +participant ; ton nom est celui déclaré dans `.disput/disput.toml` +(Vibe = `vibe`). + +1. Lis **[`PROTOCOL.md`](PROTOCOL.md) en entier** avant toute action : + c'est la seule source des règles. +2. Sur « à toi » : applique le §11 (pratique manuelle) du protocole. +3. Signe ton fichier de tour `NNNN-vibe-.md`, et commite avec ce + format de message : + + ``` + tour NNNN (vibe, ) : + + Disput-Turn: NNNN + Disput-Participant: vibe + Disput-Role: + ``` +4. Jamais de push, de réécriture d'historique ni de modification d'un + fichier de tour existant (§3 et §8 du protocole). diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..efb2760 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,10 @@ +# CLAUDE.md + +@PROTOCOL.md + +Tu es le participant `claude` (voir `.disput/disput.toml`). Sur « à toi » : +applique le §11 du protocole ci-dessus. Signe tes tours +`NNNN-claude-.md`, et commite avec les trailers +`Disput-Turn` / `Disput-Participant: claude` / `Disput-Role`, sur le modèle +d'`AGENTS.md`. Jamais de push, de réécriture d'historique ni de +modification d'un fichier de tour existant. diff --git a/PROTOCOL.md b/PROTOCOL.md new file mode 100644 index 0000000..c3bea1e --- /dev/null +++ b/PROTOCOL.md @@ -0,0 +1,228 @@ +# Protocole disput — v0 (brouillon) + +Ce document est **normatif**. Il s'applique aux agents comme à l'outil. +On peut le pratiquer sans l'outil : chaque agent lit ce fichier, puis +l'état de `.disput/`, et joue son tour. + +Les mots en MAJUSCULES (DOIT, NE DOIT PAS, PEUT) ont valeur de règle. + +--- + +## 1. Concepts + +| Concept | Définition | +|---|---| +| **Participant** | Un client IA (adaptateur + modèle) ou l'humain. Identifié par un nom court : `claude`, `vibe`, `user`. | +| **Rôle** | Une fonction dans le dialogue, définie dans `disput.toml` : responsabilités, droits, déclencheurs. Un participant PEUT tenir plusieurs rôles. | +| **Tour** | Une intervention d'un participant dans un rôle. Elle produit **un fichier de tour** et **au moins un commit**. | +| **Item** | Une objection, une question ou une proposition, adressée à un participant ou à un rôle. Elle a un cycle de vie (§5). | +| **Backlog** | La liste ordonnée des tâches du projet (`.disput/backlog.md`). | +| **Décision** | Un choix réservé à l'humain. Le dialogue s'arrête jusqu'à ce qu'il tranche. | + +## 2. Arborescence dans un projet + +``` +.disput/ + disput.toml # participants, rôles, déclencheurs, contrôles, garde-fous + backlog.md # backlog unique du projet + turns/ + 0001-claude-implementer.md + 0002-vibe-reviewer.md + ... + archive/ # chantiers clos, déplacés verbatim (optionnel) +``` + +Fichiers locaux, **jamais commités** : `.disput/logs/`, `.disput/run.lock`, +`.disput/last-run.md`. + +## 3. Règles générales + +1. **Un tour = un fichier de tour + au moins un commit.** Pas de fichier + sans commit, pas de code sans tour qui l'explique. +2. **Les fichiers de tour sont immuables.** Une fois commité, un fichier + de tour NE DOIT PLUS JAMAIS être modifié, ni par son auteur ni par un + autre. Pour corriger, on écrit un nouveau tour. +3. **Réponse point par point.** Chaque item adressé à un participant DOIT + recevoir une réponse explicite de sa part, à son prochain tour, avant + tout autre travail. Les réponses groupées sont interdites. +4. **Vérifier, pas croire.** Un reviewer DOIT ré-exécuter ce qu'il peut + ré-exécuter (tests, scripts, commandes citées) au lieu de faire + confiance au récit de l'auteur. +5. **Toute décision est consignée** dans un tour, avec sa justification. + Le code doit refléter les tours. +6. **Pas de réécriture d'historique**, pas de force-push, pas de push + pendant un tour, sauf décision `user` consignée qui l'autorise + explicitement. +7. **Diversité des regards.** Le reviewer d'un tour DOIT être un autre + participant que l'auteur de ce tour. On DEVRAIT choisir un autre + fournisseur de modèle. +8. Les règles propres au projet (prod, secrets, dépôt public…) vivent + dans `disput.toml` (`[guards]`, `[[checks]]`) et dans le fichier + d'instructions du projet. Elles s'ajoutent à celles-ci et n'en + retirent aucune. + +## 4. Fichier de tour + +Nom : `NNNN--.md`. `NNNN` est le numéro du tour, sur +4 chiffres et strictement croissant. + +En-tête TOML entre `+++` (sans dépendance : `tomllib`) : + +```markdown ++++ +turn = 17 +participant = "vibe" +role = "implementer" +base = "a1b2c3d" # HEAD au début du tour +status = "CONTINUE" # CONTINUE | USER | DONE ++++ + +# Tour 17 — vibe, implementer : + +## Réponses +- [I-0016-1] ACCEPTÉ : +- [I-0016-2] REJETÉ : + +## Travail + + +## Vérifications + + +## Items +- [I-0017-1] → @claude : +- [I-0017-2] → role:security : + +## Décision requise (seulement si status = "USER") + +``` + +- Sections **Réponses** et **Items** : une ligne par item, avec + l'identifiant entre crochets en tête. Ce format sert au parsing et + DOIT être respecté à la lettre. +- Identifiant d'item : `I--`, attribué par son + auteur. +- Destinataire : `@` ou `role:`. + +## 5. Cycle de vie d'un item + +``` + ┌─ ACCEPTÉ ── CORRIGÉ ─┬─ CLOS +OUVERT ─────┤ (destinataire) └─ ROUVERT ─→ (retour à OUVERT) + (auteur) └─ REJETÉ ─────────────┬─ CLOS + (destinataire) └─ ESCALADÉ ─→ role:arbiter ou @user + (auteur) +``` + +- `ACCEPTÉ`, `REJETÉ` et `CORRIGÉ ()` sont posés par le + **destinataire**. +- `CLOS`, `ROUVERT` et `ESCALADÉ` sont posés par l'**auteur** de l'item, + qui vérifie lui-même la correction (règle 4). +- L'état d'un item n'est stocké nulle part : il se **déduit** de la + suite des fichiers de tour. C'est pour ça qu'ils sont immuables. +- Le parseur DEVRAIT accepter les mots-clés avec ou sans accent. + +## 6. Rôles et déclencheurs + +Un rôle se déclare dans `disput.toml` : + +```toml +[[roles]] +name = "reviewer" +writes_code = false # ne peut modifier que .disput/ +triggers = ["code_changed"] +brief = "Review sévère du diff : bugs, sécurité, hypothèses non validées, écart code/tours." +``` + +Déclencheurs v0 : + +| Déclencheur | Le rôle doit jouer quand… | +|---|---| +| `items_pending` | des items lui sont adressés et attendent une réponse (implicite pour tous les rôles) | +| `code_changed` | le dernier tour a modifié des fichiers hors de `.disput/` | +| `paths:,` | le dernier tour a touché un de ces chemins | +| `backlog` | aucun item en attente, et le backlog a une tâche ouverte, non `[USER]` | + +Une **affectation** associe un rôle aux participants qui peuvent le +tenir : + +```toml +[[participants]] +name = "claude" +adapter = "claude" +roles = ["implementer", "reviewer", "security"] +``` + +## 7. Ordonnancement : qui joue ensuite + +Après chaque tour, on choisit le prochain **(participant, rôle)** dans +l'ordre de priorité suivant : + +1. Si le dernier tour a `status = "USER"` : **arrêt**, on attend + `@user`. +2. **Items en attente.** S'il en existe, le plus ancien item non résolu + donne la main à celui qui doit agir : le destinataire pour répondre + ou corriger, l'auteur pour clore, rouvrir ou escalader. +3. **Déclencheurs.** Sinon, si le dernier tour a changé du code, chaque + rôle déclenché (`code_changed`, `paths:`) qui n'a pas encore joué sur + ce diff passe, dans l'ordre de `disput.toml`, tenu par un + participant ≠ l'auteur du code (règle 7). +4. **Backlog.** Sinon, le rôle `implementer` prend la tâche ouverte la + plus haute, non `[USER]`. S'il y a plusieurs participants éligibles, + on tourne entre eux (celui qui a implémenté le moins récemment). +5. Sinon : **DONE**. + +Pour un même rôle, on choisit le participant éligible qui a joué le +moins récemment. **Anti ping-pong** : si deux tours de review successifs +sur le même diff n'ouvrent aucun item et ne posent aucun `REJETÉ`, le +dialogue sur ce diff est clos. + +## 8. Invariants vérifiés après chaque tour + +Si un invariant échoue, l'outil s'arrête et le signale à `@user`. Sans +l'outil, le reviewer suivant DOIT les vérifier lui-même. + +1. Au moins un nouveau commit, et un arbre de travail propre. +2. L'ancien HEAD est un ancêtre du nouveau : pas de réécriture. +3. Aucune ref distante n'a bougé : pas de push. +4. Un seul fichier de tour ajouté, avec le bon numéro et un en-tête + valide. Aucun fichier de tour existant n'a été modifié. +5. Un rôle `writes_code = false` n'a modifié que `.disput/`. +6. Chaque item adressé à ce participant et en attente a reçu une réponse + dans ce tour (règle 3). +7. Les contrôles du projet (`[[checks]]`) respectent leur politique : + - `must_pass` : le contrôle doit réussir ; + - `no_regression` : s'il réussissait avant le tour, il doit encore + réussir après. + +## 9. Garde-fous (`[guards]`) + +- `env` : variables imposées à l'agent pendant son tour, par exemple + `DRY_RUN=true`. +- `deny` : motifs de commandes interdites (push, réécriture, passage en + prod…). L'outil les applique **dans chaque adaptateur** : les deny et + hooks de Claude Code, l'agent et le hook `pre_tool` de Vibe. Plus tard, + ils seront appliqués de façon centralisée via ACP. + +## 10. L'humain + +`user` est un participant comme les autres, avec le rôle `decider`. Il +répond à un tour `status = "USER"` par son propre tour +(`NNNN-user-decider.md`). Sans l'outil, il écrit ce fichier à la main. +Avec l'outil, il passe par `disput decide "…"`, qui l'écrit et le +commite. Ses décisions PEUVENT lever une règle du §3, explicitement et +de façon bornée. + +## 11. Pratique manuelle (avant que l'outil existe) + +Quand l'agent reçoit « à toi » : + +1. lire ce fichier, `disput.toml`, `backlog.md` et les fichiers de tour + depuis le dernier tour de ce participant (ou tous, s'il n'en a + aucun) ; +2. appliquer le §7 pour vérifier que c'est bien son tour, et dans quel + rôle. Si ce n'est pas son tour, le dire et s'arrêter ; +3. vérifier les invariants du §8 sur le tour précédent ; +4. jouer le tour, écrire le fichier de tour, commiter ; +5. résumer à l'humain : ce qui est fait, qui joue ensuite, et la + décision attendue s'il y en a une. diff --git a/README.md b/README.md new file mode 100644 index 0000000..41db7f8 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# disput + +> *disput*, de *disputatio* : la dispute scolastique, où chaque objection +> reçoit une réponse. + +`disput` orchestre **plusieurs clients IA en ligne de commande** (Claude +Code, Mistral Vibe, puis d'autres) qui travaillent ensemble sur un même +dépôt git. Chaque participant y tient un **rôle** : implémenteur, +reviewer, auditeur sécurité… Le travail se fait **par tours**, sous un +protocole strict, et tout l'état du dialogue vit dans le dépôt. + +`disput` ne remplace pas le harness de chaque agent : il **les fait +jouer à tour de rôle**, vérifie après chaque tour que les règles ont +été respectées, et ne rend la main à l'humain que lorsqu'une décision +lui revient. + +## Pourquoi + +Le protocole est né sur un projet réel, où Claude et Vibe alternaient +implémentation et review sévère. Sur 16 tours, la review croisée entre +modèles a attrapé de vrais bugs, que l'implémenteur avait pourtant +déclarés corrigés. Deux limites sont apparues : + +- l'humain servait de **bus de messages** : il tapait « à toi » dans un + agent, puis dans l'autre ; +- les garde-fous (pas de prod, pas de push, pas de réécriture + d'historique) n'étaient que **déclaratifs**. + +`disput` automatise le relais, impose les garde-fous et ouvre le +protocole à **N participants et à des rôles configurables**. + +## Principes + +1. **Le protocole d'abord, l'outil ensuite.** [`PROTOCOL.md`](PROTOCOL.md) + se suffit à lui-même : on peut le pratiquer à la main, en tapant + « à toi » à chaque agent. L'outil ne doit jamais devenir indispensable + pour avancer. +2. **Tout l'état est dans git.** Tours, objections, backlog, décisions : + des fichiers versionnés, lisibles par les humains comme par les + machines. +3. **Les garde-fous sont techniques.** Une règle que l'outil ne sait pas + vérifier ou bloquer n'est qu'un vœu. +4. **Pas de fonctionnalité sans besoin observé.** Une fonctionnalité + n'entre que si un projet réel en a eu besoin, et ce besoin est + consigné dans un tour. +5. **disput se développe avec disput.** Ce dépôt est son propre premier + projet client (voir `.disput/`). + +## État + +**Phase d'amorçage** : la spec existe, pas encore le code. Le +développement suit le protocole **à la main** jusqu'à ce que la v0 de +`disput run` sache prendre le relais. Voir +[`.disput/backlog.md`](.disput/backlog.md) et +[`.disput/turns/`](.disput/turns/). + +## Utilisation visée (v0) + +```bash +disput init # crée .disput/ dans un projet (config, backlog, tours) +disput status # qui joue ensuite, objections ouvertes, décisions en attente +disput run # enchaîne les tours jusqu'à DONE, USER ou un invariant violé +disput decide "texte" # enregistre la décision de l'humain et relance +disput lint # valide les fichiers de tour et la config +``` + +## Licence + +À décider (voir le backlog, item `[USER]`).