Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .codex/agents/explorer.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ sandbox_mode = "read-only"
developer_instructions = """
Cartographie uniquement les chemins réellement pertinents et retourne des
références de fichiers, symboles, preuves et incertitudes. Ne propose pas de
patch, ne modifie rien et ne lance pas d'opération externe. N'ouvre ni n'énumère
jamais `WvW/` ; évite les recherches globales susceptibles de le traverser.
patch, ne modifie rien et ne lance pas d'opération externe. N'ouvre, n'énumère,
n'indexe ni ne modifie jamais `WvW/` ; évite les recherches globales susceptibles
de le traverser.
"""
3 changes: 2 additions & 1 deletion .codex/agents/reviewer.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ Reste indépendant de l'auteur et en lecture seule. Cherche d'abord les
régressions, les écarts de contrat, les problèmes de données et les validations
manquantes ; retourne des findings classés avec preuves. Ne corrige aucun fichier.
Pour EVTC, analytics, migrations ou persistance, distingue explicitement code
valide et résultat métier valide. N'ouvre ni n'énumère jamais `WvW/`.
valide et résultat métier valide. N'ouvre, n'énumère, n'indexe ni ne modifie
jamais `WvW/`.
"""
3 changes: 2 additions & 1 deletion .codex/agents/specialist.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ Interviens seulement sur une question explicitement délimitée qui dépasse le
raisonnement courant : sémantique EVTC/EI, causalité analytique, migration,
modèle de données ou architecture. Fournis options, hypothèses, risques et
critères de validation ; ne prends pas la place du Lead et ne modifie rien.
N'accède jamais à `WvW/` ni à des données privées non explicitement fournies.
N'ouvre, n'énumère, n'indexe ni ne modifie jamais `WvW/` ou des données privées
non explicitement fournies.
"""
8 changes: 5 additions & 3 deletions docs/agentic/backlog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

## Dettes de revue — Phase 5

**Statut : à traiter avant toute promotion au-delà du Level 1 et à réévaluer en
Phase 6.** Elles ne bloquent pas l'intégration de l'infrastructure minimale,
mais restent des prérequis à une autonomie élargie.
**Statut : ajustements Phase 6 validés.** Ils restent à réévaluer avant toute
promotion au-delà du Level 1.

1. Renforcer les tests sémantiques des garde-fous : indépendance du Reviewer,
confidentialité `WvW/`, fallback indisponible, handoff et reprise.
2. Définir des critères objectivables pour l'utilisation d'Ultra avant toute
utilisation réelle.
3. Compléter le protocole worktree avec une procédure explicite de conflit et
d'abandon.
4. Ajouter une assertion ciblée du checkpoint Phase 6 : un état Herdr ne permet
jamais seul le nettoyage ; résultat récupéré et absence de travail utile,
diff, commit ou artefact non intégré doivent être vérifiés indépendamment.

## Initiative prioritaire — Git/GitHub Governance & Delivery Architecture

Expand Down
49 changes: 27 additions & 22 deletions docs/agentic/current-state.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,50 @@
# État courant agentique

## Phase 5 — Infrastructure minimale
## Phase 6 — Validation réelle de l'infrastructure

- **Statut :** revue PASS conditionnel acceptée ; intégration Phase 5 en cours.
Phase 6 interdite sans accord.
- **Base :** `7a347f5dfe2c64cbcd0998e550477b64908448c9` sur `main`.
- **Objectif :** rôle Lead stable, profils Codex, politiques de routing,
communication, autonomie, worktrees/Herdr et reprise persistante.
- **Statut :** corrections des findings Phase 6 réalisées ; livrable candidat
à une seconde review indépendante. Phase 7 interdite sans accord.
- **Base :** `72ec29fd4eb71c41f02ff2bf1ccbff7c4468dc9c` sur `main`.
- **Objectif :** démontrer les profils et politiques dans Codex/Herdr réels,
sans développement fonctionnel.
- **Profil Lead initial :** Codex / `gpt-5.6-terra` / `medium`.
- **Autonomie :** Level 1 pour tous les domaines.
- **Fallback :** non configuré et non déclaré opérationnel.
- **Confidentialité :** `WvW/` interdit à toute lecture, énumération,
indexation, modification ou ajout Git sans autorisation explicite.
- **Prérequis utilisateur local :** l'entrée de confiance Codex du dépôt est
présente et valide dans la configuration utilisateur ; son contenu hors de
cette entrée ne fait pas partie du dépôt.

## Dettes acceptées de la revue Phase 5

À traiter avant toute promotion au-delà du Level 1 et à réévaluer pendant la
Phase 6 : tests sémantiques des garde-fous (Reviewer, `WvW/`, fallback,
handoff et reprise), critères objectivables pour Ultra, et procédure worktree
de conflit ou d'abandon.
Ajustements réalisés, en attente de seconde review indépendante avant toute
promotion au-delà du Level 1 : tests sémantiques des garde-fous (Reviewer,
`WvW/`, fallback, handoff et reprise), critères objectivables pour Ultra, et
procédure worktree de conflit ou d'abandon.

## Validations

- PASS — `uv run pytest tests/scripts/test_agentic_infrastructure.py
tests/scripts/test_bmad_framework.py` : 10 tests.
tests/scripts/test_bmad_framework.py` : 11 tests.
- PASS — Ruff ciblé sur les deux tests d'infrastructure.
- PASS — `codex --strict-config exec --help` : configuration sans clé inconnue.
- PASS — Codex réel : Lead `gpt-5.6-terra` / `medium`, interaction read-only,
profils custom et handoff Explorer → Reviewer validés.
- PASS — Herdr 0.8.0 : socket, pane temporaire, Codex read-only, état et
résultat récupérés, puis pane supprimé.
- PASS — reprise fresh-context : une session Codex éphémère reconstruit Phase
6, Level 1, confidentialité, fallback, dettes et prochaine action depuis les
documents versionnés.
- PASS — interfaces Codex/Herdr : CLI Codex 0.148.0 ; Herdr 0.8.0 expose les
commandes d'intégration et de worktrees documentées.
- PASS — résolveurs `resolve_config.py` et `resolve_customization.py` BMAD.
- PASS — `git diff --check`.
- NOT RUN — conversation Codex réelle, spawn et routing de bout en bout : la
couche `.codex/config.toml` est chargée seulement lorsqu'un client marque le
dépôt fiable ; aucun appel modèle payant ni modification de configuration
utilisateur hors dépôt n'a été effectué.
- BLOCKED — statut live Herdr et flux macro : le socket serveur est inaccessible
depuis ce sandbox ; aucun worktree ou pane n'a été créé.
- BLOCKED — spawn dans `codex exec --ephemeral` : ce mode ne fournit pas de
thread parent au routeur. Le même test persistant read-only est passé.
- NOT RUN — worktree temporaire : non requis pour le flux Herdr sans écriture.

## Reprise

Avant la validation fonctionnelle de Phase 6, ouvrir le dépôt dans un client
Codex fiable, vérifier qu'il charge `.codex/config.toml`, puis tester un seul
cas read-only du Lead. Ne pas activer Herdr, créer de worktree, modifier les
niveaux d'autonomie ou configurer un fallback sans accord explicite.
Faire la seconde review indépendante read-only des ajustements Phase 6. Ne pas
créer de worktree d'écriture, modifier les niveaux d'autonomie ou configurer un
fallback sans accord explicite.
48 changes: 48 additions & 0 deletions docs/agentic/phase6-validation-2026-08-20.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Checkpoint — Phase 6 : validation réelle

## Statut

Validations Level 1 réalisées ; corrections de revue appliquées et livrable
candidat à une seconde review indépendante. Phase 7 interdite sans accord
explicite.

## Preuves obtenues

- Le dépôt est reconnu fiable par Codex ; la configuration de projet applique
`gpt-5.6-terra` / `medium`.
- Le Lead a traité une idée analytique en lecture seule et a demandé un accord
avant toute écriture.
- Explorer et Reviewer ont été créés comme subagents réels, avec handoff puis
verdict indépendant ; les trois autres profils ont aussi été reconnus par le
runtime dans un test séquentiel read-only.
- Herdr 0.8.0 a exécuté un flux contrôlé pane → Codex read-only → résultat.
L'état `idle` a seulement signalé la fin apparente de l'orchestration ; avant
la fermeture du pane temporaire, la session a vérifié indépendamment que le
résultat était récupéré et qu'aucun diff, commit, artefact ou travail utile ne
risquait d'être perdu. Cette vérification, et non l'état Herdr, a autorisé le
nettoyage du pane.
- Une session Codex fraîche et éphémère a reconstruit correctement la phase,
les limites Level 1, la confidentialité, le fallback et la prochaine action
depuis les documents versionnés seuls.
- Les trois dettes Phase 5 ont reçu un ajustement ciblé : invariants de test
structurés pour les profils, le handoff, le fallback, le parallélisme et
Ultra ; critères d'Ultra ; procédure worktree de conflit/abandon/récupération.

## Limites et risques

- `codex exec --ephemeral` ne peut pas accueillir un spawn : le routeur ne
trouve pas de thread parent. Utiliser une session persistante read-only pour
les délégations de validation.
- Aucun worktree n'a été créé : il n'est pas nécessaire sans flux d'écriture.
- Le fallback reste non opérationnel ; une indisponibilité GPT impose arrêt et
checkpoint, jamais un provider implicite.
- Les règles qui dépendent du comportement d'un client (sandbox, lecture seule,
absence de fan-out imbriqué) restent aussi couvertes par les essais live ; les
tests du dépôt protègent leurs contrats déclaratifs, pas une simulation du
runtime.

## Prochaine action

Faire une seconde review indépendante read-only du livrable Phase 6, y compris
les ajustements de garde-fous. Toute Phase 7 ou autonomie supérieure au Level 1
reste soumise à accord explicite.
15 changes: 15 additions & 0 deletions docs/agentic/routing-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ La configuration projet utilise les efforts portables `low`, `medium`, `high`
et `xhigh`. `max` et Ultra ne sont pas des valeurs par défaut de fichier : ils
requièrent une vérification du client disponible et une justification écrite.

## Critères d'Ultra

Ultra n'est autorisable que si le Lead consigne, avant le lancement, les quatre
preuves suivantes :

1. au moins trois sous-problèmes indépendants, sans fichier ni contrat partagé ;
2. un gain attendu mesurable (temps de décision ou couverture de trois analyses)
qu'un seul agent ne peut pas produire dans le délai retenu ;
3. pourquoi des subagents Codex read-only ou Herdr/worktrees ne répondent pas au
besoin avec un coût et un risque plus faibles ;
4. le modèle, le niveau réellement disponibles et un plafond de coût approuvé.

Sans ces quatre éléments, Ultra reste interdit. Son fan-out remplace toutes les
autres couches de parallélisme pendant la tâche.

## Parallélisme

Une seule couche possède le fan-out :
Expand Down
24 changes: 24 additions & 0 deletions docs/agentic/worktrees-herdr.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,30 @@ recouvrants.
5. Le Lead intègre, demande une review indépendante, vérifie les validations,
puis seulement nettoie branche et worktree après preuve d'intégration.

## Conflit, abandon et récupération

- **Handoff :** il ne contient qu'une synthèse, l'état, les décisions, les
validations et des références. Un patch ou un diff reste un artefact externe
(branche, commit ou fichier archivé) référencé par le handoff ; il n'est
jamais recopié intégralement dans celui-ci.
- **Conflit :** le worker s'arrête, gèle son worktree, enregistre les fichiers
concernés, validations et référence d'artefact dans son handoff, puis le Lead
décide de l'intégration. Aucun autre worker ne résout le conflit dans ce
worktree ni ne devient propriétaire de ses fichiers sans handoff explicite.
- **Abandon :** conserver le worktree et son diff jusqu'à ce que le Lead ait
confirmé qu'aucun travail utile ne doit être transféré. Documenter la raison,
le propriétaire, la référence d'artefact et la prochaine action dans le
checkpoint.
- **Récupération :** une nouvelle session relit le handoff et le checkpoint,
localise l'artefact référencé, choisit reprise ou abandon explicite, puis
exécute les validations prévues.
- **Nettoyage sûr :** seulement après intégration prouvée ou abandon consigné,
vérifier que le worktree est propre ou que son diff est archivé et référencé,
puis supprimer worktree et branche par la procédure Git validée. Les états
Herdr `done`, `idle` ou `terminated` sont seulement des signaux
d'orchestration : ils ne sont jamais une preuve suffisante d'intégration ni
une autorisation de suppression.

Ne jamais partager une branche entre worktrees. Ne jamais laisser un worker
modifier le même fichier ou contrat qu'un autre. `WvW/` ne doit être copié,
listé ou rendu accessible à aucun worktree agentique.
108 changes: 108 additions & 0 deletions tests/scripts/test_agentic_infrastructure.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import tomllib
from pathlib import Path

Expand All @@ -14,6 +15,42 @@
"specialist": ("gpt-5.6-sol", "high"),
}

PRIVATE_CORPUS_ACTIONS = {
"lecture": (r"ouvr", r"lecture", r"accèd"),
"énumération": (r"énum",),
"indexation": (r"index",),
"modification": (r"modifi",),
}
REQUIRED_HANDOFF_FIELDS = {
"task_id",
"intent",
"risk",
"objective",
"acceptance",
"context_refs",
"allowed_paths",
"forbidden",
"validation",
"output",
}


def section(document: str, heading: str) -> str:
match = re.search(
rf"^## {re.escape(heading)}\n(.*?)(?=^## |\Z)", document, re.MULTILINE | re.DOTALL
)
assert match, f"Section absente : {heading}"
return match.group(1)


def handoff_fields(document: str) -> dict[str, str]:
match = re.search(r"```yaml\n(.*?)```", document, re.DOTALL)
assert match, "Enveloppe YAML de handoff absente"
return {
key: value.strip()
for key, value in re.findall(r"^(\w+):\s*(.+)$", match.group(1), re.MULTILINE)
}


def load_toml(path: Path) -> dict:
return tomllib.loads(path.read_text())
Expand Down Expand Up @@ -49,6 +86,22 @@ def test_custom_agent_profiles_are_complete_and_constrained() -> None:
assert profiles["specialist"]["sandbox_mode"] == "read-only"
assert profiles["implementer"]["sandbox_mode"] == "workspace-write"

for name, profile in profiles.items():
instructions = profile["developer_instructions"]
assert "WvW/" in instructions, name
for action, patterns in PRIVATE_CORPUS_ACTIONS.items():
assert any(re.search(pattern, instructions, re.IGNORECASE) for pattern in patterns), (
f"{name} doit interdire {action} du corpus privé"
)

assert (
"ne transforme jamais une discussion en écriture"
in profiles["gw2analytics_lead"]["developer_instructions"]
)
assert "Reste indépendant de l'auteur" in profiles["reviewer"]["developer_instructions"]
assert "Ne corrige aucun fichier" in profiles["reviewer"]["developer_instructions"]
assert profiles["reviewer"]["sandbox_mode"] != profiles["implementer"]["sandbox_mode"]


def test_agentic_docs_define_level_one_recovery_and_governance() -> None:
required = {
Expand All @@ -72,3 +125,58 @@ def test_agentic_docs_define_level_one_recovery_and_governance() -> None:
in (AGENTIC_DOCS / "routing-policy.md").read_text()
)
assert "énumérer" in (ROOT / "AGENTS.md").read_text()


def test_agentic_guardrails_cover_fallback_handoff_and_ultra() -> None:
config = load_toml(CODEX_DIR / "config.toml")
profiles = {path.stem: load_toml(path) for path in AGENTS_DIR.glob("*.toml")}
architecture = (AGENTIC_DOCS / "architecture.md").read_text()
communication = (AGENTIC_DOCS / "communication-protocol.md").read_text()
routing = (AGENTIC_DOCS / "routing-policy.md").read_text()
worktrees = (AGENTIC_DOCS / "worktrees-herdr.md").read_text()

# Les protections documentaires complètent les modes sandbox ; elles ne
# remplacent pas les essais live read-only de la Phase 6.
assert "Aucun fallback n'est configuré" in architecture
assert set(config) == {"model", "model_reasoning_effort", "agents"}
assert {profile["model"] for profile in profiles.values()} <= {
"gpt-5.6-luna",
"gpt-5.6-terra",
"gpt-5.6-sol",
}

handoff = handoff_fields(communication)
assert set(handoff) >= REQUIRED_HANDOFF_FIELDS
assert handoff["forbidden"].startswith("WvW")
assert all(handoff[field] for field in REQUIRED_HANDOFF_FIELDS)
assert "jamais un dump" in communication
assert "done`, `idle` ou `unknown` exigent toujours diff, validations et" in communication
assert "review avant changement d'état canonique" in communication

ultra = section(routing, "Critères d'Ultra")
criteria = re.findall(r"^([1-4])\.\s+(.+?)(?=\n\d\. |\n\n|\Z)", ultra, re.MULTILINE | re.DOTALL)
assert [number for number, _ in criteria] == ["1", "2", "3", "4"]
assert "sous-problèmes indépendants" in criteria[0][1]
assert "gain attendu mesurable" in criteria[1][1]
assert "subagents Codex read-only ou Herdr/worktrees" in criteria[2][1]
assert "plafond de coût approuvé" in criteria[3][1]
assert "Ultra reste interdit" in ultra
assert re.search(r"fan-out remplace toutes les\s+autres couches", ultra)

parallelism = section(routing, "Parallélisme")
strategies = [
strategy.strip() for strategy in re.findall(r"^\d\.\s+([^:]+):", parallelism, re.MULTILINE)
]
assert strategies == [
"tâche simple",
"exploration ou review réellement indépendantes",
"deux flux d'écriture réellement indépendants",
"Ultra exceptionnel",
]
assert "ne sont jamais imbriqués" in parallelism

recovery = section(worktrees, "Conflit, abandon et récupération")
for stage in ("**Conflit :**", "**Abandon :**", "**Récupération :**", "**Nettoyage sûr :**"):
assert stage in recovery
assert "référence" in recovery
assert "Herdr" in recovery and "preuve suffisante" in recovery
Loading