STOP. LISEZ CE SKILL.MD EN ENTIER AVANT D'APPELER UN POINT DE TERMINAISON.
Compétence Battle
Orchestrateur de compétition de sécurité entre équipes Rouge et Bleue
Oppose une équipe Rouge (attaque) à une équipe Bleue (défense) dans une boucle compétitive longue durée. Chaque équipe exploite l'ensemble des compétences .pi/skills pour attaquer ou défendre une base de code cible.
Batailles invariantes (le cas courant)
Le système de notation par défaut de Battle cible l'exploitation (panne système, injection de commandes), mais l'utilisation réelle la plus fréquente d'une boucle antagoniste Rouge/Bleue est la vérification d'un INVARIANT SPÉCIFIQUE AU PROJET : "aucune fuite de valeurs PII", "le grand livre est équilibré", "l'analyseur ne perd aucun enregistrement", "la vérification d'autorisation ne peut être contournée".
Fournissez un Juge pluggable d'invariant -- un petit module indépendant judge(target_dir, params) -> {passed, violations, evidence} (schéma battle.invariant_result.v1). L'objectif de Rouge devient "produire une entrée qui fait échouer le Juge" ; celui de Bleu est "la faire réussir" ; le marqueur lit le résultat du Juge, jamais l'auto-déclaration d'un agent. Les Juges sont en échec par défaut : un juge qui génère une erreur est un INVARIANT ÉCHOUÉ, jamais un succès silencieux.
python3 -m battle_skill.invariant_judge \
--juge fixtures/reference-judges/no_data_leak_judge.py \
--cible <dossier-de-sortie-libérée> \
--params '{"politique": "politique.json", "sous_dossier_sortie": "corpus"}'
fixtures/reference-judges/no_data_leak_judge.py est l'invariant de confidentialité de l'anonymiseur en tant que Juge : il analyse indépendamment la sortie libérée (scalaires JSON incluant échappements décodés, expansion numérique, cellules SQLite + schéma DDL + entiers d'en-tête, texte/CSV, rapport.json, et stdout/stderr capturés) pour toute valeur de politique dans toute représentation.
Recherche sur la famille de variation contractuelle (composition Battle générique)
Battle n'est pas spécifique à un projet. Pour tout projet ou compétence avec un acceptance_contract.bundle.v1, Battle doit développer chaque élément de contrat via Dogpile avant de revendiquer une couverture antagoniste complète :
./run.sh plan-de-variation-contrat \
--lot-acceptation /chemin/vers/lot_acceptation.json \
--source-dogpile brave-search \
--source-dogpile arxiv \
--sortie /tmp/plan-variation-battle.json
La sortie est battle.contract_variation_plan.v1. Il s'agit d'un contrat Battle en trois phases, pas d'une note informelle :
- Phase 1 : réussir le plancher gelé de l'
acceptance_contract.bundle.v1. - Phase 2 : après cette réussite, rassembler
$état-projet, les reçus Battle actuels, la recherche$dogpilefiltrée par source, et les propositions du réviseur$ask one-shot. - Phase 3 : geler les résultats utiles de la Phase 2 en cas déterministes, les exécuter, et conserver la preuve de lignée adaptative pour les victoires de Rouge, les correctifs de Bleu et la relecture.
Le plan mappe chaque cas d'acceptation vers des pistes de recherche Dogpile avec source et des familles de variation réutilisables. Utilisez des filtres --source-dogpile répétables lorsqu'une phase Battle n'a besoin que de certains fournisseurs Dogpile comme brave-search, arxiv, github-search, youtube, brave-questions, feeds, wayback, ou context7 au lieu de l'éventail complet des sources. Les familles de variation réutilisables incluent l'équivalence de représentation, l'encodage/normalisation, les différentiels d'analyseurs, les limites de surface de libération, la conversion avec perte, les faits scindés/composés, l'échelle, la tentative/concurrence, l'autorisation, et les limites de fuite d'échec. Dogpile et Ask sont uniquement des entrées de recherche : ils découvrent des familles de variation significatives et des preuves sources. Battle gèle ensuite les familles sélectionnées en générateurs déterministes, exécute la cible réelle dans des portes de preuves Docker/QEMU/jumeau numérique, émet battle.case_receipt.v1 par cas, agrège avec battle.campaign_aggregate.v1, et conserve les classes de workflow comme cas $agentic-evals. Une porte de libération sérieuse devrait s'attendre à des centaines de cas déterministes et environ 20 à 30 classes d'évaluation conservées lorsque la surface contractuelle est large ; les portes de fumée plus petites doivent s'étiqueter comme fumée.
Campagnes d'invariants (tester le plancher contractuel, puis attaquer au-delà)
Une bataille invariante juge une sortie. Une campagne invariante fait générer par Rouge la MATRICE complète des "versions" d'entrée que la spécification de la cible nomme -- chaque format x chaque représentation x les cas limites documentés -- PLUS des tests aléatoires, exécute la cible réelle sur chacun, et le Juge note chaque sortie. Chaque cas émet un battle.case_receipt.v1 avec les champs de pré-vérification du dispositif, d'exécution, de rejet, de Juge de sécurité, de Juge fonctionnel optionnel, et de verdict. Une campagne RÉUSSIT uniquement si tous les reçus de cas réussissent, les cas MUST_ACCEPT requis sont effectivement acceptés et jugés fonctionnellement, les cas MUST_REJECT requis sont rejetés en toute sécurité, et l'battle.campaign_aggregate.v1 calculé n'a aucun cas échoué ou incomplet. Une version qui échoue est une victoire concrète et reproductible pour Rouge.
Pour les cibles d'anonymisation/confidentialité, le contrat d'acceptation n'est que le plancher. Lorsqu'un acceptance_contract.bundle.v1 existe, la construction de l'arène peut le passer comme acceptance_floor à l'adaptateur de production. Battle échoue alors par défaut à moins que chaque id de acceptance_cases[] ne corresponde à au moins un cas de générateur de campagne dans les required_case_ids du profil ; ce sont les versions antagonistes minimales qui DOIVENT réussir avant que tout test aléatoire supplémentaire ou les cas hors contrat importent. Battle doit également exécuter une campagne hors contrat qui attaque les surfaces qu'un brief client omet souvent : clés JSON et clés dupliquées, en-têtes/dialectes/cellules multilignes CSV, identifiants/valeurs par défaut/valeurs générées/index partiels/déclencheurs SQLite, noms de fichiers, rapport.json, stdout/stderr, encodages alternatifs, et pièges de représentation de même identité. Une simple relecture de la matrice du brief est une preuve de fumée, pas une preuve Battle complète.
python3 -m battle_skill.invariant_campaign \
--générateur fixtures/reference-generators/anon_brief_matrix.py \
--cmd-exéc-cible 'docker run --rm -v {entrée}/corpus:/essai/entrée/corpus:ro -v {entrée}/politique.json:/essai/entrée/politique.json:ro -v {sortie}:/essai/sortie anonymization-trial run' \
--juge fixtures/reference-judges/no_data_leak_judge.py \
--params-gen '{"fuzz": 20}' --params-juge '{"sous_dossier_sortie": "corpus"}'
fixtures/reference-generators/anon_brief_matrix.py produit les versions du brief d'anonymisation : les quatre formats, chaîne JSON/int/float/scientifique, SQLite TEXT/INTEGER/REAL, Unicode NFC/NFD, BOM, échappement JSON \u, SQLite CHECK-littéral, plus fuzz. Il porte également les cas limites de la table ronde d'essai oai : valeurs de téléphone formatées de politique stockées sous forme de numériques JSON/SQLite à chiffres uniquement, la même identité ensemencée dans tous les formats concernés, et les pièges de perte de zéro non significatif / grand flottant. fixtures/reference-generators/anon_beyond_brief_matrix.py est l'échelon suivant requis pour la preuve de confidentialité/anonymisation : il essaie les surfaces non évidentes de schéma/chemin/encodage/journal/limite de libération qui vont au-delà du contrat d'acceptation littéral. Un générateur + cmd-exéc-cible + juge est un trio pluggable : pointez-le vers la matrice de spécification et l'invariant de tout projet.
Le Juge sans fuite de données prend également en charge un profil d'interprétation d'adhésion explicite pour la sémantique de transformation. Ces garanties sont DÉSACTIVÉES sauf si déclarées dans --params-juge, donc Battle n'étend pas silencieusement le contrat après avoir vu un échec :
{
"profil_interprétation": {
"décodeurs": ["base64", "base64url", "hex"],
"reconstruction_locale_enregistrement": true,
"max_octets_décodés": 4096
}
}
Avec ce profil, les valeurs scalaires/token entières base64/base64url/hex sont décodées une fois et les champs scalaires JSON/CSV/SQLite adjacents au niveau de l'enregistrement peuvent reconstruire une valeur de politique complète. Le décodage récursif arbitraire, les jointures globales de champs, et le pliage de caractères visuellement ambigus restent en dehors de la porte de blocage par défaut.
Après que Rouge trouve des cas échoués et que Bleu corrige la cible, émettez le reçu de lignée reproductible au lieu de résumer en prose :
./run.sh reçu-lignée-invariant \
--campagne-rouge /tmp/résultat-rouge.json \
--campagne-relecture /tmp/résultat-relecture.json \
--cible oai-trial \
--sortie /tmp/lignée-battle.json
Un battle.invariant_adaptive_lineage.v1 RÉUSSI prouve que Rouge a trouvé des cas limites contractuels, Bleu a supprimé ces victoires de Rouge, et la relecture indépendante du Juge a réussi.
Ensuite, Battle doit produire un rapport validé par $créer-rapport avec le contexte $état-projet et une table d'exploits explicite. Le rapport est l'artefact de décision lisible par l'homme ; les reçus restent l'autorité. Générez d'abord un état de projet frais, puis rendez le rapport :
RACINE_ÉTAT_PROJET=/chemin/vers/cible ../état-projet/run.sh rapport --json --sortie /tmp/état-projet.json
./run.sh rapport-invariant \
--campagne /tmp/brief-battle-fuzz.json \
--campagne /tmp/battle-au-delà-brief.json \
--lignée-adaptative /tmp/lignée-battle.json \
--état-projet /tmp/état-projet.json \
--cible oai-trial \
--sortie-json /tmp/rapport-battle.json \
--sortie-md /tmp/rapport-battle.md
Pour la revue terminale par l'agent du projet, utilisez des fiches lorsque les cas ont de longues preuves :
./run.sh rapport-invariant \
--campagne /tmp/brief-battle-fuzz.json \
--campagne /tmp/battle-au-delà-brief.json \
--état-projet /tmp/état-projet.json \
--cible oai-trial \
--sortie-json /tmp/rapport-battle.json \
--sortie-md /tmp/rapport-battle.md \
--fiches-terminal
rapport-invariant est une commande CLI Typer. Elle écrit le JSON machine sur stdout et conserve le rapport Battle humain sur stderr. Utilisez --fiches-terminal pour la revue normale par l'agent du projet des preuves Battle : il regroupe les fiches sous les titres Plancher du contrat d'acceptation, Exploits hors contrat, Lignée adaptative, et Autres cas de campagne, puis imprime un bloc ============== par cas avec Portée, Cas, Parent d'acceptation, Attendu, Résultat, Exemple, Pourquoi Battle vérifie cela, Recherche associée, Lignée adaptative, et Preuve du Juge. Si un reçu d'adaptateur de production porte acceptance_floor.case_map, les fiches du plancher contractuel montrent le(s) id(s) parent AC-* ; sinon Parent d'acceptation est non enregistré dans le reçu du cas. Si un reçu a exemple, pourquoi_choisi, refs_recherche, ou refs_source, les fiches montrent ces champs exacts ; sinon les exemples/justifications sont déterministes à partir de l'id du cas et la recherche est signalée comme non enregistrée dans le reçu du cas.
--tableau-terminal reste l'alias de vue d'ensemble compact pour --résumé-terminal : tous deux impriment le plancher contractuel, la pression Rouge, l'appel du marqueur, et une ligne de tableau de cas par attaque. Dans un terminal interactif, Battle utilise le tableau coloré de Rich (RED_WIN rouge, réussites propres vert, arrêts sécurisés jaune) et honore NO_COLOR ; en capture/CI, il tombe dans du texte brut déterministe pour que les journaux et tests restent stables.
rapport-invariant écrit create_report.report.v1, le valide via skills/create-report/run.sh validate, rend le Markdown via skills/create-report/run.sh render, et ajoute ## Tableau des exploits. Le tableau doit être simple et scannable : une ligne par cas d'attaque, avec les colonnes Portée, Contractuel ?, Lignée adaptative ?, Cas, Exploit / attaque, Pourquoi choisi, Attendu, Résultat, et Preuve du Juge. Portée sépare les cas contractuel du plancher d'acceptation des sondes hors contrat ; Pourquoi choisi explique les sondes non contractuelles ; Lignée adaptative ? marque les victoires Rouge qui ont été corrigées et rejouées ; RED_WIN bloque la libération. Le tableau est dérivé de battle.case_receipt.v1 lorsqu'il est présent, en se rabattant sur le case_log hérité uniquement pour les anciens reçus de campagne. Une clôture Battle sans ce rapport manque de la surface de décision même si les reçus de campagne réussissent.
Limite de finalité
La finalité de Battle est le backend de compétition de sécurité Rouge/Bleue : configuration autorisée de la cible, exécution isolée, génération d'attaque Rouge, génération de défense Bleue, relecture indépendante du Juge, reçus du marqueur, lignée adaptative, et apprentissage durable. La lignée adaptative est une boucle d'apprentissage backend qui génère, évalue, sélectionne, et promeut ou rejette les preuves enfants Rouge/Bleue à partir des reçus soutenus par le Juge.
PixiJS est uniquement une surface de spectateur/relecture pour les reçus Battle. Une réussite PixiJS prouve que les reçus enregistrés peuvent être inspectés dans une relecture amusante ; elle ne prouve pas que l'orchestrateur Battle, les sous-agents pilotés par fournisseurs, l'isolation Docker/QEMU, le planificateur de nuit, le marqueur, ou l'apprentissage mémoire fonctionnent. Ne concluez pas à la préparation du Battle central à partir des seules preuves PixiJS, et ne bloquez pas la lignée adaptative backend sur le polissage de la relecture au-delà de l'inspectabilité fidèle des reçus.
Architecture
Le Battle de production est une compétence d'orchestration, pas un grand moteur de sécurité sur mesure. Le processus hôte doit planifier les rounds, choisir les personnalités, répartir les sous-agents, provisionner les environnements d'exécution Docker, collecter les reçus, noter les signaux d'exécution durs, écrire des rapports, et persister l'apprentissage. Le code cible et le code généré par les équipes doivent s'exécuter uniquement à l'intérieur de Docker.
Invariants de production requis :
- Rouge et Bleu sont des équipes de sous-agents. Chaque sous-agent réparti doit inclure une personnalité explicite sélectionnée par l'orchestrateur pour ce tour. Plusieurs personnalités par équipe peuvent s'exécuter simultanément lorsque le tour bénéficie de la largeur.
- L'exécution Battle nécessite un manifeste
security.target_authorization.v1avant le démarrage de Docker, QEMU, la configuration de l'environnement d'exécution cible, la délégation Hack, la relecture de preuve, ou la relecture de correctif. Le manifeste lie la portée projet/opérateur et l'identité cible ; ce n'est pas un avis juridique et ne prouve pas le succès de l'exploit ou l'efficacité du correctif. - L'exécution de
$hackde l'équipe Rouge est une responsabilité de sous-agent, pas une import Python Battle. Battle effectue ou planifie une analyse/recherche/rappel mémoire, construit la liste d'exploits candidats, choisit la personnalité Rouge, répartit un sous-agentagent-skills/agents/Tau avec ce contrat, et enregistre le reçu d'exploit retourné. - Les transferts et reçus de sous-agents doivent suivre la forme de contrat JSON compacte de style Tau utilisée par
tau.agent_handoff.v1ettau.subagent_receipt.v1, avec des champs spécifiques à Battle ajoutés par-dessus plutôt qu'un protocole ad hoc séparé. - Battle appelle des contrats de sous-agents Tau modulaires. Tau et le harnais de boucle/agentique possèdent l'exécution des sous-agents et utilisent
scillmcomme appelant LLM/modèle. Battle possède la sélection d'équipe, l'attribution de personnalité, les environnements d'exécution Docker, la tenue de score, les artefacts, et la mémoire.
…
[tronqué pour la traduction]