claude-failover/WORK_IN_PROGRESS.md
Ubuntu 3e20085204 feat(phase2-E): multi-provider routing via secutools delegation
Adds optional delegation of agent-queue tasks to the SecuAAS secutools
AI platform (GPU / Gemini / Claude API) instead of dispatching to a
local Claude Code tmux session. Per-task opt-in via YAML frontmatter
fields preferred_ai, allow_delegation, complexity_hint — absence keeps
the Phase 1 behaviour exactly (zero breaking change).

Go side:
- internal/secutools: HTTP client with exponential-backoff retries
  (SubmitJob/GetJob/WaitForResult), DecideProvider map adapter for CLI
  use, table tests.
- internal/router: struct-typed Decide() with strict precedence
  (needs_claude_code > preferred_ai=claude-code > allow_delegation=false
  > preferred_ai > fail-safe local on unknown).
- internal/delegation: Manager submits jobs, writes .md.delegated
  markers for on-restart recovery, runs a periodic reaper that moves
  completed jobs into done/ with provider/cost footer and failed jobs
  into failed/.
- internal/dispatcher: WithDelegation() opt-in, routeTask hook before
  findFreeSession, skips .md.delegated in assignNextTask.
- internal/api: /api/delegated/status (active jobs + counters),
  /watchdog/status extended with delegation counters.
- cmd/ccl-delegate: small CLI exposing submit/get/result/decide so the
  bash dispatcher can call the same contract without duplicating logic.
- cmd/claude-failover: delegation wired opt-in via SECUTOOLS_API_KEY.

Tests:
- 29+ new unit tests across router, secutools, delegation, dispatcher,
  api packages. go test -race -count=1 clean.
- tests/phase2-E-integration.sh: bash end-to-end against a Python
  stdlib mock HTTP server, exercising the dev-management scripts.

Forward-compat with watchdog (Phase 1 B1 already ignores
state=delegated_to_secutools) so delegated tasks aren't flagged stale.
2026-04-17 02:17:19 +00:00

5 KiB

Travaux en Cours - claude-failover

Dernière mise à jour

2026-04-17 02:20:00

Version Actuelle

0.4.0 — Phase 2 chantier E livré (multi-provider routing + bash wiring).

Demande en cours

Aucune demande active. Branche feat/phase2-E-multi-provider-routing prête à push (en attente de validation utilisateur).

Phase 2 / Chantier E — Statut

  • router (decide tree + 8 tests)
  • secutools client (HTTP + 5 tests + 2 retry tests)
  • secutools/routing.go DecideProvider(map) + 14 table tests
  • delegation manager (submit + reaper + LoadFromDisk + 7 tests)
  • dispatcher integration (routeTask + dispatchProject branch + 5 tests)
  • API endpoints /api/delegated/status + /watchdog/status enrichi
  • main.go opt-in via SECUTOOLS_API_KEY
  • cmd/ccl-delegate CLI Go pour bash wrapper
  • tests/phase2-E-integration.sh bout-en-bout avec mock Python
  • tests -race clean
  • smoke test E2E avec vraie API secutools (à faire après push)
  • dashboard MCP Secuaas:orchestrator consommer /api/delegated/status

Demande Précédente

Phase 1 / Chantier A — Failover robuste (spec dans ccl-platform/phases/phase1/A-failover.md). Rendre le failover compte1 ↔ compte2 déterministe en intégrant dans le code les fixes manuels (symlinks partagés), en ajoutant un registre UUID fiable, et en durcissant tmux send-keys.

Branche : feat/phase1-A-failover-robust.

Sous-tâches Chantier A

  • A1 — internal/symlinks/shared.go (+ tests) — v0.3.5
  • A2 — lifecycle/manager.go : ValidateAll au startup
  • A3 — switcher/account_switcher.go : EnsureForAccount post-flip
  • A4 — internal/registry/uuid_registry.go (+ tests)
  • A5 — internal/tmux/send.go avec retry exponentiel (+ tests)
  • A6 — Capture UUID 200 → 500 lignes
  • A7 — scripts/test-failover.sh dans ccl-platform + scripts associés

Étapes Complétées

  • v0.2.1 — Cooldown post-swap + log forensique (trigger_session, pattern, snippet)
  • v0.2.2 — Confirmation 2-polls pour les hits sans reset time
  • v0.2.3 — Veto 5xx (api_error / overloaded_error / internal server error) et retrait du pattern générique "rate limit" (remplacé par rate_limit_error)
  • Documentation : docs/architecture.md §2.2.1 "False-positive protection"
  • Tests unitaires exhaustifs (14 cas pour isQuotaExhausted dont les 3 veto 5xx)
  • Déploiement prod : /usr/local/bin/claude-failover + service redémarré
  • Push sur Forgejo origin/main (commits 7c5f838 et 62e98cb)

Prochaines Étapes

  • préserver les sessions dédiées lors d'un swap légitime — fait en v0.3.0 via saveDedicatedUUIDs + relaunchDedicatedSessions.
  • Optionnel : telegram alert quand SwapRequested est émis pour que l'opérateur soit au courant sans lire les logs. Le notifier.Telegram existe déjà — il suffit de câbler.
  • Optionnel : exposer /quota/status via internal/api avec les champs last_swap_at, suspected_hit_at, cooldown_remaining pour le dashboard.

Contexte Important

  • Symptôme en prod (2026-04-15) : daemon faisait des swaps compte1↔compte2 en boucle (intervalle descendant à 1 min), tuant les sessions interactives ccl-1 et ccl-2 en permanence. reset="" sur tous les events.
  • Cause racine identifiée via le log forensique v0.2.1 : les 500 d'Anthropic contenaient le texte "rate limit" dans leur payload. Snippet capturé : API Error: 500 {"type":"error","error":{"type":"api_error",...}}. Le monitor les confondait avec de vrais 429.
  • Config reactivate_cooldown: "5m" existait déjà dans config.yaml mais n'était consommée que par le dispatcher — pas par le monitor. v0.2.1 a branché le monitor dessus.
  • Comptes disponibles : compte1 (Claude Max), compte2 (Claude Team). Symlink actuel : ~/.claude → .claude-compte2.
  • Sessions tmux gérées : pool autonome ccl-auto-* (min=2, max=10) + dédiées ccl-1-conformvault, ccl-2-scanyze.

Fichiers Modifiés (cette série de fixes)

  • internal/quota/monitor.go — quotaPatterns, serverErrorPatterns, suspectedHitAt, cooldown
  • internal/quota/monitor_test.go — 14 sous-tests isQuotaExhausted + 3 tests poll
  • internal/state/state.go — LastSwapAt/From/To + RecordSwap + LastSwapInfo
  • internal/switcher/account_switcher.go — appel state.RecordSwap() après swap
  • docs/architecture.md — §2.2.1 False-positive protection
  • VERSION.md — changelog 0.2.1 → 0.2.3

Bugs Connus

  • Sessions dédiées tuées lors d'un swap légitime : comportement documenté et voulu (respawn sur le nouveau compte), mais coupe brutalement le travail interactif en cours. Voir Prochaines Étapes.

Historique des Demandes (Récentes)

Date Version Demande Status
2026-04-15 0.2.1 Casser le ping-pong + logs forensiques Terminé
2026-04-15 0.2.2 Confirmation 2-polls pour absorber les flashes Terminé
2026-04-15 0.2.3 Veto 5xx + patterns stricts (root cause) Terminé