Aller au contenu

Patterns Orthanc applicables au Cerveau Positronic

Sources : ADR-0014 (Task State and Working Memory), ADR-0020 (Human-Workflow Interaction) Date : 2026-02-15 Auteur : Claude (analyse)


Executive Summary

Les ADRs d'Orthanc sont une masterclass d'architecture distribuée. Même si ProbatioVault n'adopte pas Orthanc en tant que tel, 5 patterns architecturaux majeurs sont directement applicables au Cerveau Positronic :

  1. Fencing Tokens (résolution split-brain)
  2. Working Memory Append-Only (audit trail + context coherence)
  3. State Machine with Validated Transitions (correctness by design)
  4. Human-Workflow Integration (4 patterns : Authorization, Clarification, Review, Intervention)
  5. Context Windowing with Priorities (gestion croissance contexte)

Pattern 1 : Fencing Tokens (Split-Brain Resolution) 🔐

Principe Orthanc (ADR-0014, Section Fencing Token Model)

Problème : Dans un système distribué, une tâche peut être réassignée à un nouvel agent après un timeout réseau. Si l'agent original revient, deux agents pensent être responsables de la même tâche (split-brain).

Solution : Chaque assignation génère un fencing token monotoniquement croissant (PostgreSQL BIGSERIAL). Toute écriture (checkpoint, verdict, etc.) doit inclure le token et est validée via :

UPDATE Task
SET last_checkpoint_step = $step, status = 'checkpointed'
WHERE task_id = $task_id
  AND fencing_token = $current_token  -- ✅ Garantie atomique

Propriétés : - Un token par assignation : Réassignation → nouveau token via nextval() - Validé à chaque écriture : Base de données rejette les tokens périmés - Monotoniquement croissant : Token supérieur supersède toujours token inférieur

Exemple de résolution split-brain :

1. Agent A exécute task_123 avec token=1000
2. Network partition → Control plane timeout
3. Control plane réassigne task_123 à Agent B avec token=1001
4. Partition guérit → Agent A revient
5. Agent A essaie PersistCheckpoint(token=1000)
   → Rejeté : token actuel = 1001
6. Control plane envoie RevokeAssignment à Agent A
7. Agent A abort, libère ressources


Application ProbatioVault : Workflow Gates

Problème actuel : Si le workflow de gouvernance se bloque (ex: ChatGPT timeout pendant Gate 3 review), on relance manuellement. Mais qu'advient-il si : - Review ChatGPT se termine finalement (après timeout) - Nouvelle review déjà lancée - Deux verdicts contradictoires arrivent

Solution proposée : Fencing tokens pour verdicts de gate.

Implémentation

1. Génération token (étape de gate) :

# docs/epics/PD-42/WORKFLOW-STATE.md
story_id: PD-42
current_step: 3
gate_status: IN_PROGRESS
gate_token: 1  # ← Nouveau : Fencing token pour Gate 3
gate_started_at: "2026-02-15T10:00:00Z"

2. Verdict de gate avec token :

# docs/epics/PD-42/gate3-verdict-v1.yaml
version: "1.0.0"
gate_type: CONFORMITY_CHECK
story_id: PD-42
gate_token: 1  # ← Doit matcher le token actuel
verdict: GO
score_mean: 8.5
scores:
  completeness: 8.5
  testability: 8.0
  clarity: 9.0
  traceability: 8.5
issued_at: "2026-02-15T10:15:00Z"

3. Validation avant application :

# scripts/apply-verdict.py
def apply_verdict(story_id, verdict_file):
    workflow_state = load_workflow_state(story_id)
    verdict = load_verdict(verdict_file)

    # Fencing token validation
    if verdict['gate_token'] != workflow_state['gate_token']:
        raise ValueError(
            f"Verdict token {verdict['gate_token']} does not match "
            f"current gate token {workflow_state['gate_token']}. "
            f"This verdict is stale (gate was restarted)."
        )

    # Appliquer verdict
    workflow_state['gate_status'] = verdict['verdict']
    workflow_state['gate_token'] += 1  # Incrémenter pour prochaine gate
    save_workflow_state(story_id, workflow_state)

4. Relance de gate → Nouveau token :

# Relance Gate 3 après timeout
./scripts/gov-step.sh PD-42 3

# WORKFLOW-STATE.md mis à jour :
# gate_token: 2  (incrémenté)
# gate_status: IN_PROGRESS

Bénéfice : Zéro risque de verdicts périmés appliqués. Si Gate 3 v1 se termine après relance, son gate_token: 1 est rejeté car token actuel = 2.


Pattern 2 : Working Memory Append-Only (Audit Trail + Context) 📝

Principe Orthanc (ADR-0014, Section Working Memory)

Trois objectifs simultanés : 1. Multi-step coherence : Étapes ultérieures référencent sorties des étapes précédentes 2. Crash recovery : Nouvel agent reçoit historique complet et reprend avec contexte 3. Audit trail : Log immutable de tout ce que l'agent a fait et pourquoi

Structure : Append-only log avec 9 types d'entrées (prompt_sent, ai_response, artifact, decision, tool_call, tool_result, child_result, error, status_update).

Invariants : - Jamais de UPDATE/DELETE pendant exécution - Ordonné par step_sequence + created_at - Stockage hybride : Payload inline si petit, blob storage si > seuil


Application ProbatioVault : Artefacts de Workflow

Problème actuel : Les artefacts de gouvernance (spec, tests, verdicts, etc.) sont créés mais pas structurés comme un log append-only. Résultat : - Pas de traçabilité complète (ex: quand Gate 3 v2 a-t-il été lancé ?) - Difficile de reconstruire l'historique des décisions - Pas de lien explicite entre artefacts

Solution proposée : Workflow Memory Append-Only (inspiré d'Orthanc).

Implémentation

1. Créer fichier de working memory :

# docs/epics/PD-42/workflow-memory.yaml
story_id: PD-42
entries:
  - id: "entry-001"
    step: 0
    type: "need_created"
    created_at: "2026-02-15T09:00:00Z"
    payload_ref: "PD-42-besoin.md"

  - id: "entry-002"
    step: 1
    type: "specification_created"
    created_at: "2026-02-15T09:30:00Z"
    payload_ref: "PD-42-specification.md"
    agent: "ChatGPT"

  - id: "entry-003"
    step: 3
    type: "gate_review_requested"
    created_at: "2026-02-15T10:00:00Z"
    payload_ref: "gate3-review-v1.md"
    gate_type: "CONFORMITY_CHECK"
    gate_token: 1

  - id: "entry-004"
    step: 3
    type: "verdict_issued"
    created_at: "2026-02-15T10:15:00Z"
    payload_ref: "gate3-verdict-v1.yaml"
    verdict: "GO"
    score_mean: 8.5

  # Jamais de modification des entries précédentes
  # Nouvelle entry si nouvel événement

2. Types d'entrées ProbatioVault :

Type Description Payload
need_created Expression de besoin (étape 0) Lien vers besoin.md
specification_created Spécification (étape 1) Lien vers specification.md
tests_created Tests & validation (étape 2) Lien vers tests.md
gate_review_requested Review de gate lancée Lien vers review.md
confrontation_generated Confrontation produite Lien vers confrontation.md
verdict_issued Verdict de gate Lien vers verdict.yaml
correction_applied Corrections après NON_CONFORME Détails corrections
code_contract_defined Code contract créé (étape 4) Lien vers code-contracts.yaml
implementation_started Début implémentation (étape 6) Branch feature créée
agent_task_completed Tâche agent terminée (6b) Commit SHA, agent
acceptability_validated Reviews acceptabilité (étape 7) Résultats linter, tests, reviews
pipeline_monitored Surveillance pipeline GitLab Status pipeline
rex_completed REX terminé (étape 9) Lien vers rex.md

3. Script d'ajout d'entrée :

# scripts/add-workflow-entry.sh
#!/bin/bash
STORY_ID=$1
ENTRY_TYPE=$2
PAYLOAD_REF=$3

# Générer ID unique (UUID v7 comme Orthanc)
ENTRY_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

# Append entry (YAML)
cat >> docs/epics/${STORY_ID}/workflow-memory.yaml <<EOF
  - id: "$ENTRY_ID"
    step: $(get_current_step $STORY_ID)
    type: "$ENTRY_TYPE"
    created_at: "$TIMESTAMP"
    payload_ref: "$PAYLOAD_REF"
EOF

echo "✅ Entry $ENTRY_ID added to workflow memory"

4. Intégration workflow :

# Exemple : Après verdict Gate 3
./scripts/gov-step.sh PD-42 3

# Interne : Script génère verdict-v1.yaml
# Puis ajoute entry
./scripts/add-workflow-entry.sh PD-42 "verdict_issued" "gate3-verdict-v1.yaml"

Bénéfices : - ✅ Audit trail complet : Chaque action tracée avec timestamp - ✅ Reconstruction historique : Lire workflow-memory.yaml = comprendre tout le workflow - ✅ Crash recovery : Si workflow interrompu, reprendre du dernier entry - ✅ Traçabilité : Lien entre artefacts explicite


Pattern 3 : State Machine with Validated Transitions ⚙️

Principe Orthanc (ADR-0014, Section Task State Machine)

8 états + transitions validées + validation à 2 niveaux :

  1. Application-side check : Scala valide (current_state, target_state) avant UPDATE
  2. Database CHECK constraint : PostgreSQL rejette valeurs illégales (defense in depth)

Table de transitions : Spécifie exactement quelles transitions sont permises (ex: running → checkpointed OK, running → completed interdit).

Bénéfice : Impossible d'arriver dans un état incohérent (ex: task completed sans être passée par checkpointed).


Application ProbatioVault : State Machine de Workflow

Problème actuel : Workflow-State.md est manuel. Aucune validation que les transitions sont légitimes (ex: passer de Step 3 à Step 6 sans passer par Step 4-5).

Solution proposée : State machine de workflow avec transitions validées.

Implémentation

1. Définir états et transitions :

# docs/governance/workflow-state-machine.yaml
states:
  - step_0: "Expression de besoin"
  - step_1: "Spécification"
  - step_2: "Tests & Validation"
  - step_3: "Review spécification (Gate)"
  - step_4: "Plan d'implémentation"
  - step_5: "Review plan (Gate)"
  - step_6: "Implémentation"
  - step_7: "Acceptabilité"
  - step_8: "Review acceptabilité (Gate)"
  - step_9: "REX"

valid_transitions:
  - from: step_0
    to: [step_1]
    trigger: "Besoin complété"

  - from: step_1
    to: [step_2]
    trigger: "Spécification complétée"

  - from: step_2
    to: [step_3]
    trigger: "Tests définis"

  - from: step_3
    to: [step_4, step_1]  # GO → Step 4, NON_CONFORME → Step 1
    trigger: "Verdict Gate 3"
    conditions:
      - verdict: GO → step_4
      - verdict: NON_CONFORME → step_1  # Retour correction spec

  - from: step_4
    to: [step_5]
    trigger: "Plan complété"

  - from: step_5
    to: [step_6, step_4]  # GO → Step 6, NON_CONFORME → Step 4
    trigger: "Verdict Gate 5"

  - from: step_6
    to: [step_7]
    trigger: "Implémentation complétée"

  - from: step_7
    to: [step_8]
    trigger: "Acceptabilité validée"

  - from: step_8
    to: [step_9, step_7]  # GO → Step 9, NON_CONFORME → Step 7
    trigger: "Verdict Gate 8"
    conditions:
      - verdict: GO AND pipeline: success → step_9
      - verdict: NON_CONFORME → step_7

  - from: step_9
    to: []  # Terminal
    trigger: "REX complété"

2. Script de validation de transition :

# scripts/validate-transition.py
import yaml

def validate_transition(story_id, target_step):
    # Charger state machine
    with open('docs/governance/workflow-state-machine.yaml') as f:
        sm = yaml.safe_load(f)

    # Charger état actuel
    with open(f'docs/epics/{story_id}/WORKFLOW-STATE.md') as f:
        current_step = parse_current_step(f.read())

    # Vérifier transition valide
    valid = any(
        t['from'] == f'step_{current_step}' and f'step_{target_step}' in t['to']
        for t in sm['valid_transitions']
    )

    if not valid:
        raise ValueError(
            f"Invalid transition: step_{current_step} → step_{target_step}. "
            f"This transition is not allowed by the state machine."
        )

    return True

# Usage
validate_transition('PD-42', 6)  # ✅ OK si current_step=5 avec verdict GO
validate_transition('PD-42', 6)  # ❌ Erreur si current_step=3 (saute 4-5)

3. Intégration dans gov-step.sh :

# scripts/gov-step.sh (extrait)
STORY_ID=$1
TARGET_STEP=$2

# Validation transition AVANT exécution
python3 scripts/validate-transition.py "$STORY_ID" "$TARGET_STEP"

if [ $? -ne 0 ]; then
  echo "❌ Transition invalide. Vérifiez WORKFLOW-STATE.md"
  exit 1
fi

# Exécuter étape seulement si validation OK
...

Bénéfice : Impossible de sauter des étapes ou de faire des transitions illégitimes. La state machine garantit la correction du workflow.


Pattern 4 : Human-Workflow Integration (4 Patterns) 🧑‍💼

Principe Orthanc (ADR-0020, Full ADR)

4 patterns d'interaction humain-workflow :

  1. Authorization : Agent demande permission avant action (ex: merge protected branch)
  2. Clarification : Agent pose questions structurées (ex: OAuth2 ou JWT ?)
  3. Review : Agent soumet deliverable pour validation humaine (ex: ADR, spec critique)
  4. Intervention : Humain injecte guidance corrective dans workflow en cours

Chaque pattern : - ✅ Persiste dans PostgreSQL (survit aux crashes) - ✅ Lifecycle à 5 états (PENDING → ACKNOWLEDGED → RESOLVED / ESCALATED → EXPIRED) - ✅ Escalation chains avec timeouts - ✅ Fencing token validation sur réponses - ✅ Audit trail immutable (InteractionAuditEntry)


Application ProbatioVault : Gates PMO + Human Oversight

Problème actuel : Gates PMO sont automatiques (Claude orchestrate, ChatGPT review, scoring). Mais certaines stories critiques nécessitent approbation humaine explicite (ex: changements auth, migrations DB).

Solution proposée : Pattern Authorization + Review pour gates critiques.

Implémentation Pattern 1 : Authorization (Gate Critique)

Use case : Story PD-XX modifie l'authentification → Gate 8 nécessite approbation humaine en plus des reviews automatiques.

1. Configuration authorization policy :

# docs/governance/authorization-policy.yaml
project_id: ProbatioVault-backend
rules:
  - rule_id: "auth-changes-require-approval"
    priority: 1
    operation_pattern: "gate_8:auth_module"  # Gate 8 sur modules auth
    interaction_type: AUTHORIZATION
    approver:
      type: escalation_chain
      chain_id: "security-approvers"
    timeout_action: ESCALATE
    timeout_seconds: 86400  # 24h

  - rule_id: "db-migrations-require-approval"
    priority: 2
    operation_pattern: "gate_8:db_migration"
    interaction_type: AUTHORIZATION
    approver:
      type: user
      user_id: "loic@phydya.com"
    timeout_action: SUSPEND
    timeout_seconds: 172800  # 48h

2. Escalation chain :

# docs/governance/escalation-chains.yaml
- chain_id: "security-approvers"
  name: "Security Review Chain"
  levels:
    - level: 0
      approvers:
        - type: user
          user_id: "security-lead@probatiovault.com"
      timeout_seconds: 86400  # 24h

    - level: 1  # Escalation si level 0 timeout
      approvers:
        - type: group
          group_id: "architects"
      timeout_seconds: 43200  # 12h

    - level: 2  # Escalation finale
      approvers:
        - type: user
          user_id: "cto@probatiovault.com"
      timeout_seconds: 86400  # 24h

  exhausted_action: EXPIRE  # Si tous niveaux timeout → EXPIRE
  acknowledge_resets_timer: true

3. Workflow avec authorization gate :

# docs/epics/PD-XX/authorization-request.yaml
request_id: "auth-req-001"
story_id: PD-XX
step: 8  # Gate 8
interaction_type: AUTHORIZATION
operation_type: "gate_8:auth_module"
gate_token: 3
context:
  description: |
    Gate 8 pour story PD-XX (Ajout MFA 2FA).
    Modifications critiques dans AuthService, UserRepository.
    Reviews automatiques OK (linter, tests, coverage).
    Approbation humaine requise avant merge.
  impact: |
    - APPROVE → Merge feature branch, lancer REX
    - REJECT → Bloquer merge, escalader vers correction
  payload_content_type: "application/json"
  payload:
    files_modified:
      - "src/auth/AuthService.ts"
      - "src/auth/MfaService.ts"
      - "src/repositories/UserRepository.ts"
    test_coverage: 87%
    linter_warnings: 0
    reviews:
      - type: "code_review"
        verdict: "APPROVE"
        reviewer: "ChatGPT"
      - type: "security_review"
        verdict: "APPROVE"
        reviewer: "ChatGPT (adversarial)"
  artifact_refs:
    - "feature/PD-XX-mfa-settings"
    - "docs/epics/PD-XX/acceptability.md"
created_at: "2026-02-15T15:00:00Z"
status: PENDING
current_approver: "security-lead@probatiovault.com"
escalation_level: 0

4. Workflow orchestration :

# scripts/gov-step.sh PD-XX 8

# Après reviews automatiques (linter, tests, reviews LLM)
# Vérifier si authorization requise
python3 scripts/check-authorization-policy.py PD-XX gate_8

# Si policy match → Créer authorization request
python3 scripts/create-authorization-request.py \
  --story PD-XX \
  --step 8 \
  --operation "gate_8:auth_module" \
  --context "docs/epics/PD-XX/acceptability.md"

# Notifier approver (email, Slack, WhatsApp via OpenClaw)
python3 scripts/notify-approver.py --request-id "auth-req-001"

# Workflow SUSPEND jusqu'à réponse humaine
echo "⏸️  Workflow suspendu - Approbation requise (auth-req-001)"

5. Réponse humaine :

# docs/epics/PD-XX/authorization-response.yaml
request_id: "auth-req-001"
decision: APPROVE  # ou REJECT
responder: "security-lead@probatiovault.com"
reasoning: |
  Code reviews OK, tests OK, sécurité OK.
  MFA implementation suit les standards TOTP.
  Approved for merge.
resolved_at: "2026-02-15T16:30:00Z"
gate_token: 3  # Doit matcher le token de la request

6. Application réponse :

# scripts/apply-authorization-response.py
python3 scripts/apply-authorization-response.py \
  --request-id "auth-req-001" \
  --response "docs/epics/PD-XX/authorization-response.yaml"

# Validation fencing token
# Si APPROVE → Workflow resume (merge, REX)
# Si REJECT → Workflow suspend, escalade correction

Bénéfices : - ✅ Approbation humaine traçable : Audit trail complet - ✅ Escalation automatique : Si security-lead timeout → escalade architects - ✅ Fencing tokens : Zéro risque d'approbation périmée - ✅ Configurable : Policy YAML modifiable sans changer code


Implémentation Pattern 3 : Review (Deliverable Critique)

Use case : Spécification critique (étape 1) nécessite review humaine avant Gate 3.

1. Review request :

# docs/epics/PD-XX/review-request-spec.yaml
request_id: "review-req-001"
story_id: PD-XX
step: 1
interaction_type: REVIEW
deliverable_type: "specification"
deliverable_ref: "PD-XX-specification.md"
context:
  description: |
    Spécification pour feature critique (authentification MFA).
    Review humaine requise avant soumission à Gate 3.
  artifact_refs:
    - "docs/epics/PD-XX/specification.md"
created_at: "2026-02-15T11:00:00Z"
status: PENDING
current_reviewer: "architect-senior@probatiovault.com"

2. Review response :

# docs/epics/PD-XX/review-response-spec.yaml
request_id: "review-req-001"
decision: MODIFY  # APPROVE, MODIFY, ou REJECT
feedback:
  - section: "3.2 Token Storage"
    comment: "Préciser durée de vie du TOTP token (actuellement absent)"
    severity: REQUIRED
  - section: "4.1 User Flow"
    comment: "Ajouter diagramme de séquence pour clarifier flow"
    severity: SUGGESTION
responder: "architect-senior@probatiovault.com"
resolved_at: "2026-02-15T12:00:00Z"

3. Modify-Feedback-Resubmit Cycle :

# Workflow reçoit MODIFY verdict
# 1. Incorporer feedback REQUIRED
# 2. Générer spec v2
# 3. Soumettre nouvelle review request (request_id différent, correlation_id identique)
python3 scripts/create-review-request.py \
  --story PD-XX \
  --deliverable "docs/epics/PD-XX/specification-v2.md" \
  --correlation-id "review-req-001"  # Lien avec v1

# 4. Reviewer review spec v2
# 5. Si APPROVE → Passer à Gate 3
# 6. Si MODIFY encore → Limité à 3 itérations (config), puis ESCALATE

Bénéfice : Review gates catch issues before commit (exact SC-007 d'Orthanc).


Pattern 5 : Context Windowing with Priorities 📊

Principe Orthanc (ADR-0014, Section Context Windowing)

Problème : Working memory grandit. Finit par dépasser context window du LLM.

Solution : Context windowing avec règles d'inclusion :

  1. Toujours inclure : Task definition + 3 dernières entrées
  2. Summarize older : Entrées au-delà des 3 dernières → Summarization capability
  3. Priority-based retention : 9 niveaux de priorité (decisions > errors > tool_result > ... > prompt_sent)
  4. Budget calculation : context_window × 0.7 (30% réservé pour réponse AI)

Bénéfice : Zéro perte de décisions critiques, même sur workflows longs.


Application ProbatioVault : Summarization de Workflow Memory

Problème actuel : Workflow memory peut devenir très long (ex: PD-105 avec 13 tâches agents × multiple commits). Si on veut assembler un prompt avec tout l'historique pour une review finale, risque de dépasser context window.

Solution proposée : Context windowing avec priorités pour artefacts de workflow.

Implémentation

1. Définir priorités des entry types :

# docs/governance/context-priorities.yaml
# Priorité 1 = Toujours retenu en full, 9 = Summarize en premier
priorities:
  1: [verdict_issued, code_contract_defined]  # Décisions critiques
  2: [correction_applied, pipeline_monitored]  # Erreurs et corrections
  3: [confrontation_generated, acceptability_validated]  # Validations
  4: [gate_review_requested, agent_task_completed]  # Résultats intermédiaires
  5: [specification_created, tests_created, implementation_started]  # Créations
  6: [need_created, rex_completed]  # Contexte initial/final
  7: []  # Réservé future
  8: []  # Réservé future
  9: []  # Réservé future

2. Context windowing script :

# scripts/assemble-context-windowed.py
import yaml

def calculate_size(entry):
    """Estime taille en tokens (1 token ≈ 4 chars)"""
    if 'payload_ref' in entry:
        content = load_file(entry['payload_ref'])
        return len(content) // 4
    return 100  # Estimation par défaut

def assemble_context_windowed(story_id, budget_tokens=140000):
    # budget_tokens = 200k × 0.7 (30% réservé pour réponse)

    # 1. Charger workflow memory
    with open(f'docs/epics/{story_id}/workflow-memory.yaml') as f:
        memory = yaml.safe_load(f)

    entries = memory['entries']

    # 2. Toujours inclure : Need + 3 dernières entrées
    need_entry = entries[0]  # Toujours premier
    recent_entries = entries[-3:]  # 3 derniers

    locked_size = sum(calculate_size(e) for e in [need_entry] + recent_entries)

    # 3. Remaining budget
    remaining_budget = budget_tokens - locked_size

    # 4. Charger priorités
    with open('docs/governance/context-priorities.yaml') as f:
        priorities = yaml.safe_load(f)

    # 5. Trier entries par priorité (sauf need + recent déjà lockés)
    middle_entries = entries[1:-3]  # Entre need et 3 derniers

    def priority_rank(entry):
        for rank, types in priorities['priorities'].items():
            if entry['type'] in types:
                return rank
        return 9  # Par défaut : Lowest priority

    middle_entries_sorted = sorted(middle_entries, key=priority_rank)

    # 6. Retenir tant que budget permet
    retained = []
    summarize = []
    current_size = 0

    for entry in middle_entries_sorted:
        entry_size = calculate_size(entry)
        if current_size + entry_size <= remaining_budget:
            retained.append(entry)
            current_size += entry_size
        else:
            summarize.append(entry)

    # 7. Summarize via LLM
    if summarize:
        summary_prompt = "Résume les entrées suivantes en 500 tokens max:\n"
        summary_prompt += "\n".join(format_entry(e) for e in summarize)

        summary = call_llm_summary(summary_prompt)  # Claude ou ChatGPT
        summary_entry = {
            'id': 'summary-001',
            'type': 'context_summary',
            'created_at': now(),
            'payload': summary
        }
    else:
        summary_entry = None

    # 8. Assembler contexte final
    final_context = [need_entry]
    if summary_entry:
        final_context.append(summary_entry)
    final_context.extend(retained)
    final_context.extend(recent_entries)

    return final_context

# Usage
context = assemble_context_windowed('PD-105', budget_tokens=140000)
# Context contient : Need + Summary (si nécessaire) + High-priority entries + 3 recent

3. Intégration dans prompts de gate :

# scripts/assemble-gate-prompt.sh
STORY_ID=$1
GATE_TYPE=$2

# Assembler contexte avec windowing
python3 scripts/assemble-context-windowed.py "$STORY_ID" > /tmp/context.md

# Assembler prompt de gate avec contexte windowé
cat > /tmp/gate-prompt.md <<EOF
# Gate $GATE_TYPE pour $STORY_ID

## Contexte Workflow (Context-Windowed)

$(cat /tmp/context.md)

## Document à Review

$(cat docs/epics/$STORY_ID/specification.md)

## Instructions Review

[...]
EOF

# Envoyer prompt via ChatGPT
cat /tmp/gate-prompt.md | opencode run

Bénéfice : Zéro perte de décisions critiques (verdicts, code contracts), même sur workflows très longs (ex: 50+ entries).


Roadmap d'Adoption 🗓️

Q1 2026 : Patterns 1-2 (Foundations) - [ ] Implémenter Fencing Tokens pour verdicts de gate (Pattern 1) - [ ] Créer Workflow Memory Append-Only (Pattern 2) - [ ] Migrer artefacts existants vers workflow-memory.yaml

Q2 2026 : Pattern 3 (Correctness) - [ ] Définir State Machine avec transitions validées (Pattern 3) - [ ] Intégrer validation dans scripts gov-step.sh

Q3 2026 : Patterns 4-5 (Advanced) - [ ] Implémenter Authorization Pattern pour gates critiques (Pattern 4) - [ ] Implémenter Review Pattern pour deliverables critiques (Pattern 4) - [ ] Implémenter Context Windowing pour workflows longs (Pattern 5)


Conclusion 🎯

Les ADRs d'Orthanc démontrent qu'une architecture distribuée multi-agents peut être à la fois rigoureuse ET pragmatique. Les 5 patterns extraits sont directement applicables au Cerveau Positronic :

  1. Fencing Tokens → Résolution split-brain pour verdicts de gate
  2. Working Memory → Audit trail + traçabilité complète
  3. State Machine → Correction by design (transitions validées)
  4. Human-Workflow → Authorization + Review pour gates critiques
  5. Context Windowing → Gestion workflows longs sans perte décisions

Prochaine étape : POC Fencing Tokens sur une story test (ex: PD-XXX) pour valider le pattern avant déploiement généralisé.