# ADR 013 — SDLC agentic distribué

- **Statut** : Proposé
- **Date** : 2026-09-15
- **Décideurs** : zot-lab / iASSET
- **Étend** : [ADR 001](./001-backlog-autonomy.md) · [ADR 002](./002-worktrees-fallback.md) · [ADR 003](./003-implement-hooks.md) · [ADR 004](./004-gitlab-runners.md) · [ADR 005](./005-tests-generate-ci.md) · [ADR 006](./006-security-scanners-ci.md) · [ADR 007](./007-spec-from-ticket.md) · [ADR 008](./008-asset-graph.md) · [ADR 009](./009-event-journal.md) · [ADR 010](./010-design-contracts.md) · [ADR 011](./011-ops-assets.md) · [ADR 012](./012-telemetry-intent.md)
- **Plan d’exécution** : [docs/roadmap-sdlc-agentic.md](../roadmap-sdlc-agentic.md)
- **Rejette** : Temporal / Kafka / bus maison maintenant · auto-merge · auto-prod · rewrite du runtime CLI

## Contexte

iASSET **0.4.0** a déjà la colonne vertébrale :

- dossier déclaratif `iasset/` (specs, agents, security, ops, telemetry, boundaries) ;
- bus GitLab via `iasset ci emit` / child pipeline ([ADR 004](./004-gitlab-runners.md)) ;
- gates déterministes (`validate`, reviews `mode: ci-deterministic`) ;
- HITL prod ([ADR 011](./011-ops-assets.md)) ;
- pas d’auto-merge ([ADR 001](./001-backlog-autonomy.md), [ADR 002](./002-worktrees-fallback.md)) ;
- journal JSONL ([ADR 009](./009-event-journal.md)) et boucle telemetry → Intent draft ([ADR 012](./012-telemetry-intent.md)).

Trois manques bloquent un vrai SDLC agentic **distribué** :

1. **DevOps** — plan de contrôle incomplet : tags runners, modes emit couverts par le smoke, orchestration déclarative encore locale (`orchestrate` hors mode CI).
2. **AI** — cognition multi-rôles : gate puis LLM (reviews hybrides), budgets réels, catalogue tools, agents planner / test-author, supervisor + run-id.
3. **Sécu** — identité / least privilege : `isExemptAgentWrite` trop large, secrets lisibles par agents, `api_key` inline toléré, scanners secrets+deps non obligatoires, `may_edit_with_gate` sans fail CI sans HITL.

Évoluer manifests + events + emit. **Ne pas** réécrire le runtime.

## Décision

### Principes non négociables

1. **GitLab orchestre, CLI mince** — pas Temporal, pas Kafka, pas de fleet dans le npm. Child pipeline = bus.
2. **Deterministic first, LLM second** — un job peut appeler un LLM seulement après (ou derrière) un gate / policy explicite.
3. **Pas d’auto-merge / pas d’auto-prod** — `require_human_on` et jobs prod `when: manual` restent la loi.
4. **Évoluer, ne pas rewrite** — schémas YAML, modes `IASSET_CI_MODE`, journal, gates ; pas de nouveau moteur d’orchestration dans `src/`.

### Architecture cible

```text
                    ┌─────────────────────────────┐
                    │  GitLab (bus + runners)     │
                    │  ci emit → child DAG needs  │
                    └──────────────┬──────────────┘
                                   │
         ┌─────────────────────────┼─────────────────────────┐
         ▼                         ▼                         ▼
   validate/gates            agent jobs                 ops / telemetry
   (déterministe)            (gate → LLM opt)           (HITL prod)
         │                         │                         │
         └─────────────┬───────────┴─────────────┬───────────┘
                       ▼                         ▼
              iasset/reports/              iasset/ (manifests)
              events.jsonl + hash          agents, security,
              scan-*, flow-*, …            orchestration/policy
```

```mermaid
flowchart LR
  MR[MR / trigger] --> Emit[ci emit]
  Emit --> Child[child pipeline]
  Child --> Val[validate + scans]
  Val --> Review[reviews hybrides]
  Review --> Flow[flow / orchestrate]
  Flow --> Ev[events.jsonl]
  Ev --> Graph[graph build]
  Flow --> Ops[ops promote]
  Ops -->|prod manual| HITL[humain]
  Tel[telemetry breach] -->|Intent draft| Spec[spec draft]
  Spec -.->|jamais auto-flow| Flow
```

Couches :

| Couche | Rôle | Source de vérité |
|--------|------|------------------|
| Manifests | Intent, design, code, ops, telemetry, agents, security | `iasset/**/*.yaml` |
| Contrôle | DAG jobs, tags runners, modes emit, policy routes | `ci emit` + `orchestration/policy.yaml` (Phase B) |
| Cognition | implementer, reviews, planner, test-author | `iasset/agents/*` + drivers |
| Identité | boundaries, tool-policy, tokens least-privilege | `boundaries.yaml`, env CI, Phase B |
| Preuve | gates, scans, events, hash-chain | `iasset/reports/` |

### Pattern multi-turn : local vs distribué

| Boucle | Où | Latence typique | Usage |
|--------|-----|-----------------|-------|
| Multi-turn **cognitif** (plusieurs tours LLM) | Local : `flow` / `orchestrate` sur worktree | secondes | Exploration, implémentation itérative |
| Gates / reviews / preuves | Distribué : child pipeline GitLab | 45 s – plusieurs min | Async MR, audit, CI verte |

**Décision** : ne **pas** forcer chaque tour LLM via child pipeline. GitLab porte les gates et les jobs agent « one-shot » (review, flow step, scans). La boucle multi-turn rapide reste locale ; le bus GitLab reste le point de vérité pour la preuve et le HITL.

### Concurrence multi-agents (écritures)

Risque : `implementer` + `test-author` (ou jobs parallèles) commitent sur la **même** branche / MR → conflits, races, reviews flaky.

**Décision proposée** (à valider en implémentation, ticket **DEVOPS-04**) :

1. **Préférée** — **1 agent writer** par branche / MR ; les autres rôles en **read-only** (reports, comments) ou via artifacts CI.
2. **Alternative** — worktrees / branches par agent + **rebase orchestré** avant merge dans la branche MR (aligné [ADR 002](./002-worktrees-fallback.md)).
3. **Fallback** — sérialisation stricte des writes (mutex job / `resource_group` GitLab) sur une seule branche.

Pas de writes parallèles non coordonnés sur la même ref.

### Context pack (AI-10)

Composition formelle du pack passé aux agents (borné, journalisé avec `run-id`) :

| Inclus | Exclu |
|--------|--------|
| Graphe Assets pertinent ([ADR 008](./008-asset-graph.md)) | Dump repo entier |
| Bornes `boundaries.yaml` + tool-policy | Secrets / `.env` / clés |
| Artifacts / reports du run (`iasset/reports/…`) | Historique CI hors run-id |
| Spec / Intent / Design contrats ciblés | Contexte sémantique RAG non déclaré |

RAG / index sémantique = **opt-in consommateur**, hors core npm si possible. Objectif : éviter lost-in-the-middle et le surcoût tokens.

### Phase A — P0 (1–6 semaines) : harden + hybrid

Objectif : sécuriser le chemin agent existant et rendre le bus GitLab **prédictible** sans changer le modèle mental 0.4.0.

| Domaine | Décision |
|---------|----------|
| SEC | Restreindre `isExemptAgentWrite` ; deny-read secrets pour tools agent ; interdire `api_key` inline (env only) ; pin version `zot-iasset` côté consommateurs ; scanners `secrets` + `deps` **obligatoires** si policy projet active ; **anticiper** profil runner `agent-sandbox` (SEC-06) en fin A / début B |
| DEVOPS | Tags runners dans `ci emit` ; doc matrice secrets × kind ; smoke `emit` modes `event\|ops\|telemetry\|spec` ; stratégie concurrence writes (DEVOPS-04) |
| AI | Reviews hybrides (gate déterministe **puis** LLM optionnel) ; budgets token/round réels ; catalogue tools déclaratif ; **mini golden set** stub LLM en fin Phase A (AI-05) |
| DX | Parité local ↔ CI : `validate` / boundaries / gates mêmes codes d’erreur (DX-01) |

**Critères de succès Phase A**

- [ ] Un agent ne peut plus écrire hors allowlist sans passer par boundaries / exempts explicitement listés (SEC-01).
- [ ] Aucun secret fichier / `.env` / clé inline n’est lisible ou embarqué par le driver (SEC-02, SEC-03).
- [ ] `ci emit` pose des `tags:` runners ; smoke couvre les 4 modes event/ops/telemetry/spec (DEVOPS-01, DEVOPS-02).
- [ ] Review job : gate fail → job rouge **avant** tout appel LLM ; LLM ne peut pas « greenwasher » un gate rouge (AI-01).
- [ ] `iasset validate` / boundaries / gates en local produisent les **mêmes** codes / refus qu’en CI (DX-01).
- [ ] Mini golden set stub LLM : le CLI réagit correctement aux sorties agent (pas de drift silencieux) (AI-05).
- [ ] simple-crm (ou équivalent) : review + event E2E verts sur child pipeline.

### Phase B — P1 (trimestre) : contrôle + identité + multi-rôles

| Domaine | Décision |
|---------|----------|
| DEVOPS | `ci emit --mode orchestrate` ; `events/routes.yaml` **ou** `orchestration/policy.yaml` ; consolidation `events.jsonl` en pipeline ; hash-chain journal |
| SEC | Identité agent + tool-policy + tokens least-privilege ; `may_edit_with_gate` → **fail CI** sans HITL explicite ; profil runner **agent-sandbox** (egress restreint, env masquées, scratch éphémère) si non livré en fin A (SEC-06) |
| AI | Supervisor + run-id / **context pack** (composition ci-dessus) ; agents `test-author` + `planner` |

**Critères de succès Phase B**

- [ ] Un backlog `depends_on` s’exécute via child pipeline `orchestrate` sans Temporal.
- [ ] Chaque job agent porte un `run-id` traçable dans `events.jsonl` (chaîne hashée).
- [ ] Context pack borné (graph + boundaries + reports) ; pas de dump repo.
- [ ] Diff dans `may_edit_with_gate` → job rouge tant qu’un humain n’a pas approuvé (variable / label / note).
- [ ] Tokens CI scoped par kind (review ≠ implement ≠ ops).
- [ ] Concurrence writes : 1 writer / branche ou rebase orchestré (DEVOPS-04).

### Phase C — P2 : isolation, evals, attestations

Pools runners isolés, quotas, evals agentiques **full** (AI-20, s’appuie sur le golden set AI-05), MCP iAsset **mince** (lecture manifests / reports, pas d’orchestration parallèle au CLI), SLSA-like sur artifacts. Bus externe (Kafka…) **seulement** si GitLab sature — hors décision aujourd’hui.

**Critères de succès Phase C** (indicatif)

- [ ] Quotas / isolation runner par kind prouvés sur un projet pilote (étend SEC-06 / DEVOPS-20).
- [ ] Suite d’evals agentiques rejouable hors LLM flaky (golden AI-05 + suite AI-20).
- [ ] Attestation minimale des artifacts `iasset/reports/` (hash + provenance pipeline).

### Non-goals / hors scope

- Auto-merge, auto-prod, auto-flow depuis telemetry ([ADR 012](./012-telemetry-intent.md)).
- Rewrite CLI, migration hors GitLab, GitHub Actions comme cible primaire.
- Temporal, Kafka, queue maison, « agent OS » dans le npm.
- Marketplace de plugins / scanners embarqués dans `zot-iasset` ([ADR 003](./003-implement-hooks.md), [ADR 006](./006-security-scanners-ci.md)).
- Client Datadog/Grafana dans le package ([ADR 012](./012-telemetry-intent.md)).
- Remplacer les gates déterministes par des jugements LLM.
- Forcer chaque tour multi-turn LLM via child pipeline (latence CI inadaptée).
- Sandbox OS / egress hermétique **dans** le filtre tools JS seul (SEC-01/02) — insuffisant ; le vrai confinement est runner-level (SEC-06), pas un non-goal du produit mais **hors Phase A tools-only**.
- RAG / index sémantique dans le core npm (opt-in consommateur uniquement).

### Backlog priorisé (IDs stables)

Détail tickets, dépendances, fichiers, AC, effort : [roadmap](../roadmap-sdlc-agentic.md).

| ID | Titre court | Phase |
|----|-------------|-------|
| SEC-01 | Restreindre `isExemptAgentWrite` | A |
| SEC-02 | Deny-read secrets (tools agent) | A |
| SEC-03 | Interdire `api_key` inline | A |
| SEC-04 | Pin `zot-iasset` + scanners secrets/deps obligatoires | A |
| SEC-05 | Matrice secrets × kind (doc + checks) | A |
| SEC-06 | Profil runner `agent-sandbox` (egress / env / scratch) | A fin / B |
| SEC-10 | Identité agent + tool-policy + tokens LP | B |
| SEC-11 | `may_edit_with_gate` → fail CI sans HITL | B |
| DEVOPS-01 | Tags runners dans `ci emit` | A |
| DEVOPS-02 | Smoke emit modes event/ops/telemetry/spec | A |
| DEVOPS-03 | Doc secrets runners / variables par mode | A |
| DEVOPS-04 | Concurrence writes multi-agents (1 writer / rebase) | A fin / B |
| DEVOPS-10 | `ci emit --mode orchestrate` | B |
| DEVOPS-11 | `orchestration/policy.yaml` (routes events) | B |
| DEVOPS-12 | Consolidation events.jsonl + hash-chain | B |
| DEVOPS-20 | Pools runners isolés + quotas | C |
| AI-01 | Reviews hybrides (gate puis LLM) | A |
| AI-02 | Budgets réels (tokens / rounds) | A |
| AI-03 | Catalogue tools déclaratif | A |
| AI-05 | Mini golden set stub LLM (early evals) | A (fin) |
| AI-10 | Supervisor + run-id / context pack | B |
| AI-11 | Agents `test-author` + `planner` | B |
| AI-20 | Evals agentiques full + MCP iAsset mince | C (réf. AI-05) |
| DX-01 | Parité local ↔ CI (validate / boundaries / gates) | A |
| E2E-01 | simple-crm review + event E2E | A (cette semaine) |

## Conséquences

### Positives

- Une seule ADR de **direction** ; les ADR 001–012 restent les contrats locaux.
- Roadmap exécutable (Antigravity) avec IDs stables, sans ambiguïté de phase.
- Alignement explicite : GitLab = bus, CLI = cadre, humain = merge/prod.
- Séparation claire multi-turn local vs gates distribués → UX cognitive sans surcharger CI.
- Context pack borné + golden set early → moins de drift et de lost-in-the-middle.

### Négatives / risques

- Phase A augmente la friction agent (moins d’exempts, plus de secrets CI) — voulu.
- Reviews hybrides coûtent tokens et flakiness : le gate reste le verdict dur.
- Phase B touche policy / identité : risque de churn schémas — versionner et smoke avant merge.
- **Latence boucle feedback CI** (45 s – plusieurs min) : acceptable pour reviews async ; **inadaptée** au multi-turn cognitif rapide. Mitigation : pattern local vs distribué (ci-dessus) — ne pas router chaque tour LLM en child pipeline.
- **Conflits concurrence** : jobs agents parallèles sur même branche/MR. Mitigation : DEVOPS-04 (1 writer, ou worktrees + rebase, ou sérialisation).
- **Sandboxing tools JS (SEC-01/02) contournable** via shell / hooks / `postinstall`. Mitigation : SEC-06 profil runner `agent-sandbox` (fin A / début B) ; isolation pools complète en Phase C (DEVOPS-20).
- Symétrie local/CI absente aujourd’hui → faux verts locaux / faux rouges CI. Mitigation : DX-01.

### Suite immédiate (cette semaine)

Ordre strict (feedback Antigravity) : **SEC-01 → SEC-02 → SEC-03 → DEVOPS-01 + DEVOPS-03 → DEVOPS-02 → AI-01 (cadrage) → DX-01 → AI-05 (golden stub) → E2E-01**.  
Ensuite reste Phase A : **SEC-04 → SEC-05 → AI-02 → AI-03 → DEVOPS-04 → SEC-06** (SEC-06 peut glisser début B). Voir roadmap.

## Feedback Antigravity — amendements (2026-09-15)

Revue Antigravity : **valide** l’ADR (pragmatisme GitLab-as-bus, deterministic first, HITL, auditabilité). Statut ADR reste **Proposé** jusqu’à formalisation humaine.

| # | Retour | Intégration |
|---|--------|-------------|
| A1 | Latence CI vs multi-turn rapide | Consequences + section « Pattern multi-turn local vs distribué » |
| A2 | Conflits concurrence multi-agents | Décision proposée + ticket **DEVOPS-04** |
| B1 | Sandbox hermétique (tools JS contournables) | Consequences ; non-goals tools-only ; ticket **SEC-06** (SEC-04 déjà = pin/scanners) |
| B2 | Symétrie local ↔ distribué | Ticket **DX-01** Phase A |
| B3 | Evals plus tôt | Ticket **AI-05** fin Phase A ; AI-20 Phase C référence AI-05 (AI-02 reste budgets) |
| B4 | Context packing / RAG | Section ADR + enrichissement **AI-10** ; RAG opt-in hors core |

Accepté sans changer les principes non négociables ni les IDs SEC-01..05 / AI-01..03 / DEVOPS-01..03 / E2E-01 existants.
