{"slug": "squelette-keep-ai-coding-agents-inside-the-scope-you-approved", "title": "Squelette – keep AI coding agents inside the scope you approved", "summary": "Squelette, a project-control layer that sits between humans and AI coding agents, ships at version 3.20.0 as a standard-library Python controller (scripts/project_control.py) that fails closed rather than advising when a rule is violated. The controller refuses writes outside a Work Item's authorized paths — its demo preflight on WI-001 exits 1 with BUSINESS_CHANGE_AUTHORIZATION and AUTHORIZED_PATHS failures after an agent touched modules/billing/invoice.py — and requires proof of reading governing documents plus evidence for every gate before DONE. Squelette targets long-running multi-agent projects where agents drift from approved scope, using one Git branch per Work Item and a commit hook installed outside the worktree.", "body_md": "**Governance and control for AI-assisted projects.**\nKeep the goal, the scope, the human authority and the evidence of completion explicit — even when several AI agents work on the project over weeks or months.\n\n*Who decides. Who does. What proves it's done.*\n\n[Version française ci-dessous ↓](#squelette--en-fran%C3%A7ais)\n\n```\nHuman\n  │  defines the goal, the scope, the decisions\n  ▼\nSQUELETTE — a controller inside the repository\n  ├── Project Charter and recorded human decisions\n  ├── Authorized Work Items, one branch each, explicit paths only\n  ├── Preflight: fail-closed checks before any write\n  ├── Proof of reading the governing documents\n  ├── Git provenance and a commit hook\n  └── Definition of Done: evidence for every applicable gate\n  ▼\nAI agents — ChatGPT · Claude · Codex · Gemini · others\n  ▼\nWork + evidence, both in Git\n```\n\nLong-running AI projects drift. An agent forgets a constraint, reinterprets a decision, edits files outside the intended scope, or declares the work complete without evidence — and nobody notices until much later.\n\nSquelette adds a project-control layer between the human and the agents. It is not a prompt: the rules are checks run by a small controller (`scripts/project_control.py`, standard-library Python, no service). When a rule is not met, the controller **refuses** — it does not advise.\n\n| Without a frame | With Squelette | \n|---|---|\n| \"Carry on with the project\" | A Work Item explicitly authorized by a recorded human decision | \n| Context lives in the chat | State lives in the repository, as records the controller audits | \n| Decisions mixed into conversations | Human decisions registered, with their scope, options and reasons | \n| The agent widens the scope as it goes | Authorized paths; the preflight and the commit hook refuse the rest | \n| \"The agent says it read the rules\" | Proof of reading: a digest of the governing documents, required to start | \n| \"It should work\" | Evidence required for every applicable gate before `DONE` | \n| Hard-to-explain changes | Git provenance: one branch per Work Item, explicit paths, no `git add -A` | \n| A new agent means a painful restart | `status` rebuilds the state from the records | \n| The agent picks how it talks to you | You choose the reporting style: technical, or plain language | \n| An agent wanders into another folder | Two distinct human confirmations, or the controller refuses the decision | \n\n`examples/hello-squelette/` replays a complete cycle in a temporary copy: initialization, one human decision, one authorized Work Item, one refused drift, one proven change. The block below is the controller's real output — regenerated by the demo and checked by the test suite, so the README cannot drift from the controller.\n\n``` bash\n$ python3 -B scripts/project_control.py status\nProject: Hello Squelette | NORMAL_MODE\nReporting to the Project Owner: plain (PLAIN) — what happened, what it changes, what he has to do\nLanguage: english (EN)\nBranch: work/wi-001-greeting | HEAD: <commit>\nChecks: PASS\nCommit gate: installed outside the worktree\nSkeleton: 3.20.0 | core aligned\nRoadmap view: absent — roadmap-view --write\nWork Items done: 1 | Blocked: 0\nWI-001 — Greeting module: IN_PROGRESS\n  Objective: Add greet(name) under modules/hello/ with its tests.\n  Branch: work/wi-001-greeting | Target: NOT_APPLICABLE\n  Missing checks: code, tests, integration\n  Authorities read: current\nNext action: Resume the Work Item in progress on its branch after preflight; complete its missing evidence.\n\n$ python3 -B scripts/project_control.py preflight WI-001\nPROJECT_CONTROL: FAIL\nREAD_ONLY: true\nCOMMAND: preflight\nWORK_ITEM_ID: WI-001\nBRANCH: work/wi-001-greeting\nHEAD: <commit>\n… 18 controls PASS …\nFAIL: BUSINESS_CHANGE_AUTHORIZATION — path outside Work Item authorization: modules/billing/invoice.py\n… 18 controls PASS …\nFAIL: AUTHORIZED_PATHS — path outside Work Item authorization: modules/billing/invoice.py\n… 3 controls PASS …\n[exit 1]\n\n$ python3 -B scripts/project_control.py status\nProject: Hello Squelette | NORMAL_MODE\nReporting to the Project Owner: plain (PLAIN) — what happened, what it changes, what he has to do\nLanguage: english (EN)\nBranch: main | HEAD: <commit>\nChecks: PASS\nCommit gate: installed outside the worktree\nSkeleton: 3.20.0 | core aligned\nRoadmap view: current\nWork Items done: 2 | Blocked: 0\nNext action: Project at rest; wait for an authorized objective.\n```\n\nThe whole cycle, step by step: [examples/hello-squelette/TRANSCRIPT.md](https://github.com/JyMinet/squelette/blob/main/examples/hello-squelette/TRANSCRIPT.md). The controller speaks the language the Project Owner chooses at initialization — French or English — for everything addressed to a human. Check names, report lines and refusal messages stay in English in both: they are identifiers, not prose.\n\n```\ngit clone https://github.com/JyMinet/squelette.git && cd squelette\npython3 -B examples/hello-squelette/demo.py     # replay the cycle in a temporary copy (macOS/Linux, Python 3, Git)\npython3 -B -m unittest discover -s tests        # the template's own checks\n```\n\nThen start your own project. Export the tracked tree — `git archive` carries every tracked file, including `.gitignore`, which a copy made by selecting the visible entries in a file manager leaves behind:\n\n```\nmkdir my-project\ngit -C squelette archive HEAD | tar -x -C my-project\ncd my-project && git init -b main\n```\n\nThen initialize a Git baseline, and give `FIRST_START.md` to your agent — Claude, Codex, ChatGPT, Gemini or any other. `AGENTS.md` (and `CLAUDE.md`, the entry point for Claude) tells it how to work. Watch it ask the questions, write the records, and stop where it must.\n\n- A lightweight governance framework for projects built with AI agents — software, documentation, data or automation — that never chooses your architecture for you.\n- A controller that checks and refuses, not a prompt that recommends: audit, preflight, closeout, `DONE` and the commit hook are executable.\n- Standard-library Python, no dependency, no service, no vendor: the same rules for every agent.\n- Not a project manager, not an orchestrator, not a way to make an agent smarter — a way to keep a project on course while agents work on it.\n\n*La documentation détaillée est en français, plus bas.*\n\n**Gouvernance et contrôle des projets menés avec des IA.**\nGarder explicites l'objectif, le périmètre, l'autorité humaine et la preuve de ce qui est fait — même quand plusieurs agents se relaient sur le projet pendant des semaines ou des mois.\n\n*Qui décide. Qui fait. Ce qui prouve que c'est fait.*\n\nUn projet mené longtemps avec des IA dérive : l'agent oublie une contrainte, réinterprète une décision, modifie des fichiers hors du périmètre prévu ou déclare le travail terminé sans preuve — et personne ne s'en aperçoit avant longtemps.\n\nSquelette ajoute une couche de contrôle de projet entre l'humain et les agents. Ce n'est pas un prompt : les règles sont des contrôles exécutés par un petit contrôleur (`scripts/project_control.py`, bibliothèque standard Python, aucun service). Quand une règle n'est pas respectée, le contrôleur **refuse** — il ne conseille pas.\n\n| Sans cadre | Avec Squelette | \n|---|---|\n| « Fais la suite du projet » | Un Work Item explicitement autorisé par une décision humaine enregistrée | \n| Le contexte vit dans la conversation | L'état vit dans le dépôt, sous forme de records que le contrôleur audite | \n| Décisions mélangées aux conversations | Décisions humaines enregistrées, avec leur périmètre, leurs options et leurs raisons | \n| L'agent élargit le périmètre en chemin | Chemins autorisés ; le preflight et le hook de commit refusent le reste | \n| « L'agent dit avoir lu les règles » | Preuve de lecture : une empreinte des documents d'autorité, exigée pour démarrer | \n| « Ça devrait fonctionner » | Preuves exigées pour chaque gate applicable avant `DONE` | \n| Changements difficiles à expliquer | Provenance Git : une branche par Work Item, chemins explicites, jamais de `git add -A` | \n| Nouvelle IA = reprise pénible | `status` reconstruit l'état depuis les records | \n| L'agent choisit comment il te parle | Tu choisis le style de retour : technique, ou langage courant | \n| Un agent s'aventure dans un autre dossier | Deux confirmations humaines distinctes, sinon le contrôleur refuse la décision | \n\n`examples/hello-squelette/` rejoue un cycle complet dans une copie temporaire : initialisation, une décision humaine, un Work Item autorisé, une dérive refusée, un changement prouvé. Le bloc de la section anglaise ci-dessus est la vraie sortie du contrôleur — régénérée par la démo et vérifiée par la suite de tests, pour que le README ne puisse pas s'écarter du contrôleur. Le cycle pas à pas : [examples/hello-squelette/TRANSCRIPT.md](https://github.com/JyMinet/squelette/blob/main/examples/hello-squelette/TRANSCRIPT.md).\n\n```\ngit clone https://github.com/JyMinet/squelette.git && cd squelette\npython3 -B examples/hello-squelette/demo.py     # rejoue le cycle dans une copie temporaire (macOS/Linux, Python 3, Git)\npython3 -B -m unittest discover -s tests        # les contrôles du squelette lui-même\n```\n\nPuis démarre ton propre projet. Exporte l'arbre suivi — `git archive` emporte tous les fichiers suivis, y compris `.gitignore`, qu'une copie faite en sélectionnant les entrées visibles d'un gestionnaire de fichiers laisse derrière elle :\n\n```\nmkdir mon-projet\ngit -C squelette archive HEAD | tar -x -C mon-projet\ncd mon-projet && git init -b main\n```\n\nPuis crée une baseline Git, et donne `FIRST_START.md` à ton agent — Claude, Codex, ChatGPT, Gemini ou un autre. `AGENTS.md` (et `CLAUDE.md`, point d'entrée pour Claude) lui dit comment travailler. Regarde-le poser les questions, écrire les records, et s'arrêter là où il doit.\n\n- Un cadre de gouvernance léger pour les projets menés avec des agents IA — logiciel, documentaire, data ou automatisation — qui ne choisit jamais l'architecture à ta place.\n- Un contrôleur qui vérifie et refuse, pas un prompt qui recommande : audit, preflight, closeout, `DONE` et hook de commit sont exécutables.\n- Python standard, aucune dépendance, aucun service, aucun fournisseur : les mêmes règles pour tous les agents.\n- Ni un gestionnaire de projet, ni un orchestrateur, ni un moyen de rendre un agent plus intelligent — un moyen de garder le cap d'un projet pendant que des agents y travaillent.\n\nDemandez à l’IA de lire `FIRST_START.md` et `AGENTS.md`, puis de résumer la situation avec :\n\n```\npython3 -B scripts/project_control.py status\n```\n\nCette commande ne modifie rien. Elle présente l’objectif connu, la branche et le commit courant, l’état du travail, les éléments manquants et la prochaine action. `--json` fournit les mêmes informations aux outils. Les informations absentes restent `UNKNOWN` ; une incohérence de contrôle est signalée et produit un code de sortie non nul.\n\n- **Nouvelle copie** : suivre[FIRST_START.md](https://github.com/JyMinet/squelette/blob/main/FIRST_START.md) . L’IA prépare le cadre, l’architecture minimale et le premier travail ; vous validez les choix structurants.\n- **Projet initialisé** : reprendre le Work Item autorisé, ou faire préparer un nouveau périmètre à autoriser. Un projet peut aussi rester au repos, sans chantier actif.\n\nL’IA entretient les records et leur synchronisation. Vous décidez de l’objectif, du périmètre et des choix qui engagent votre autorité ou un risque. Une autorisation déjà donnée couvre les étapes ordinaires nécessaires dans ce périmètre ; elle n’est pas redemandée à chaque commande.\n\nLe socle de gouvernance est obligatoire. Les capacités décisionnelles, le pack `runtime_proof/` et les patterns avancés restent optionnels et inactifs tant qu’un besoin explicite ne justifie pas leur adoption. [ADOPTION.md](https://github.com/JyMinet/squelette/blob/main/ADOPTION.md) guide ce choix.\n\nN’ajoutez pas de service, de document parallèle ou de nouvelle couche de suivi pour un besoin déjà couvert. La vue `status` est calculée depuis les records existants ; elle ne devient pas un registre supplémentaire à tenir.\n\nL’initialisation autorise seulement les fichiers de gouvernance prévus. Après sa clôture, le travail exige un Work Item autorisé, une branche dédiée et un preflight valide. Les règles opérationnelles sont dans [AGENTS.md](https://github.com/JyMinet/squelette/blob/main/AGENTS.md).\n\nLe core du squelette est versionné (`provenance/core-manifest.v1.json`) : `status` indique la version et tout écart local, et `template-upgrade` met à jour les fichiers core intacts d’un projet dérivé depuis une version plus récente du template, sans toucher aux records. Voir [Project Control](https://github.com/JyMinet/squelette/blob/main/project_control/README.md#version-du-squelette-et-mise-%C3%A0-jour-du-core).\n\n`DONE` exige les preuves applicables. Les rapports locaux sont contrôlés avec leurs références Git et leurs empreintes ; ils ne constituent pas une attestation indépendante de la réalité décrite. Une preuve en environnement contrôlé ne vaut pas vérification en production. Voir la [Definition of Done](https://github.com/JyMinet/squelette/blob/main/docs/governance/DEFINITION_OF_DONE.md).\n\n- [Project Control](https://github.com/JyMinet/squelette/blob/main/project_control/README.md) : commandes, cycle de travail et format des preuves.\n- [Charter](https://github.com/JyMinet/squelette/blob/main/docs/governance/PROJECT_CHARTER.md) : objectif, limites et autorité humaine.\n- [Roadmap](https://github.com/JyMinet/squelette/blob/main/docs/governance/ROADMAP.md) : travaux et état d’avancement.\n- [Vue ROADMAP](https://github.com/JyMinet/squelette/blob/main/docs/agent-governance/ROADMAP_VIEW.md) : l’avancement lisible par tous, généré par`roadmap-view --write` depuis les fichiers du dépôt (`docs/governance/ROADMAP_VIEW.md` et une page HTML), avec les[idées du Project Owner](https://github.com/JyMinet/squelette/blob/main/docs/governance/IDEAS.md) et ce qu’elles sont devenues.\n- [Décisions humaines](https://github.com/JyMinet/squelette/blob/main/docs/governance/HUMAN_DECISIONS.md) : choix structurants et raisons.\n- [Architecture](https://github.com/JyMinet/squelette/blob/main/docs/architecture/PROJECT_ARCHITECTURE_MAP.md) : responsabilités et frontières.\n\nPour une nouvelle copie, exporter l’arbre suivi sans `.git`, remote ni historique source, puis créer une baseline Git autonome avant FIRST_START. Aucun projet, domaine, Work Item ou décision humaine n’est préchargé.\n\nLes contrôles utilisent la bibliothèque standard Python et ne nécessitent aucun service externe. Pour vérifier le socle :\n\n```\npython3 -B scripts/project_control.py audit\npython3 -B -m unittest discover -s tests -v\n```\n\nUne gate de commit (`python3 -B scripts/project_control.py install-gate`, une fois par checkout et après chaque montée de version) rejoue l’audit avant chaque commit et protège la branche canonique : les règles Git ne reposent plus sur la seule discipline de l’agent. Elle s’installe hors de l’arbre de travail, là où aucun commit ne peut l’emporter.\n\n**Ce que l'adoption couvre, et ce qu'elle ne couvre pas.** Le squelette s'adopte sur un projet **déjà gouverné par une version antérieure** : c'est le cas prévu, outillé et vérifié. Greffer le squelette sur un dépôt qui n'a jamais été gouverné n'a pas de procédure publiée : le mode d'initialisation refuse tout code métier déjà présent sous `applications/`, `modules/` ou `shared/`, et aucun document ne dit quoi conserver, classer ou importer. C'est une limite connue, pas un oubli — la voie sera ouverte quand elle aura été cadrée et vérifiée.\n\n**Projet déjà initialisé avec une ancienne V3 :** aucune migration de records. Le projet déclare une baseline d’adoption (`legacy_baseline`, décision humaine) qui fige son historique, puis remplace son core par celui du template dans un Work Item dédié ; `template-upgrade` prend ensuite le relais pour les versions suivantes. Voir [Project Control](https://github.com/JyMinet/squelette/blob/main/project_control/README.md#compatibilit%C3%A9--baseline-dadoption).", "url": "https://wpnews.pro/news/squelette-keep-ai-coding-agents-inside-the-scope-you-approved", "canonical_source": "https://github.com/JyMinet/squelette", "published_at": "2026-09-24 12:02:26+00:00", "updated_at": "2026-09-24 12:30:24.147311+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-safety"], "entities": ["Squelette", "ChatGPT", "Claude", "Codex", "Gemini", "scripts/project_control.py"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/squelette-keep-ai-coding-agents-inside-the-scope-you-approved", "markdown": "https://wpnews.pro/news/squelette-keep-ai-coding-agents-inside-the-scope-you-approved.md", "text": "https://wpnews.pro/news/squelette-keep-ai-coding-agents-inside-the-scope-you-approved.txt", "jsonld": "https://wpnews.pro/news/squelette-keep-ai-coding-agents-inside-the-scope-you-approved.jsonld"}}