Skip to main content

G.O.A.L. Cascade CLI

CI

Framework Goal-Oriented Agentic Loop : cascade multi-agents pour produire des livrables de haute qualité avec transparence radicale des coûts, sécurité E2E et résilience provider.

État — version 0.4.0

La source de vérité du produit est la spécification d'implémentation V2. Les jalons S1 à S6 sont implémentés et testés (348 tests passent, 4 skip) :

  • S1 Fondations : cascade unique 4 rôles (producteur, critique, adversaire, arbitre), synthèse orientée objectif, artefacts immuables séparés, verdict JSON validé, borne stricte de 5 itérations.
  • S2 Multi-provider : anthropic, openai, google via Mirascope, plus mock, kimi-cli, kimi-code. Rate limit configurable, chaîne de fallback respectant la diversité de familles (Pilier 1).
  • S3 Qualité synthèse : détection de dérive cosinus (bge-m3) activée par défaut (configurable via drift_enabled = false), mode --no-synth, mesure de couverture synthèse vs sortie brute.
  • S4 LangGraph + budget : graphe d'états à 6 nœuds, checkpoints SQLite, kill switch budgétaire ([budget] TOML), goal resume.
  • S5 Cache + versioning : cache sémantique SQLite + embeddings, goal versions / goal diff / goal inspect.
  • S6 Multi-cascade + CI/CD : goal plan (LLM ou squelettique), goal cascade-run (exécuteur topologique), --enrich-frozen-specs (2e appel LLM via frozen_spec_gen.j2), hook CI/CD déterministe câblé dans la cascade unique.

Sécurité (audits A-F passés, voir Security) : pas de secrets dans les logs, traces en 0o700, .gitignore complet, hook déterministe avant LLM, STOP par défaut, diversité providers validée au démarrage.

Statut & Reste à faire

Fait dans la passe 0.4.0

  • Audit P1/P2/P3 prioritaire fermé (budget, run_id, RAG, redaction, drift, packaging, SSE, parser de verdict unique, traçabilité provider, auth constant-time, rate-limit dashboard).
  • Factory des providers déplacée hors cli.py (providers/factory.py) — cycle d'import cassé.
  • Typage cascade_graph.py complet (override mypy retiré).
  • --no-synth respecte la limite d'itérations (forced_stop).
  • langgraph-checkpoint-sqlite 3.1.1 (CVE PYSEC-2026-3636 corrigée).
  • CI reproduite localement en Python 3.11 : ruff, mypy, pytest, pip-audit verts.

Reste à faire (non bloquant pour 0.4.0)

  • 7 P1 restants de l'audit (sur 15) → Phase 2/3.
  • P1-13 : pas de test de crash/redémarrage mid-node réel (reprise checkpoint couverte, crash process non).
  • P2-7 : timeline.md réécrit intégralement à chaque refresh (dette O(n²)).
  • Publication PyPI + intégration Aegis /goal (Phase 2) — nécessitent credentials et accord.
  • Dégraissage de cli.py (~1600 lignes) — la factory providers est extraite, le découpage reste à poursuivre.

Quick start

# 1. Installation (mode dev)
uv sync --dev

# 2. Smoke test (aucune clé API requise)
uv run goal run --objective "Auditer un argument" --provider mock --variant A

# 3. Avec un vrai provider (installer l'extra llm)
uv pip install -e '.[llm]'
export ANTHROPIC_API_KEY=sk-ant-...
uv run goal run --objective "..." --provider anthropic

# 4. Multi-cascade
uv run goal plan spec.md --enrich-frozen-specs
uv run goal cascade-run plan.json

L'installation comme commande utilisateur est documentée plus bas.

Installation

Développement

uv sync --dev
uv run goal --help

Commande utilisateur (WSL)

uv tool install --force --editable /mnt/c/Users/eddie/ZCodeProject/goal-cascade-cli
goal --help

Extra llm (providers réels)

pip install 'goal-cascade[llm]'
# Ajoute : mirascope>=1.0, anthropic>=0.40, structlog>=24.0

Sans cet extra, seuls mock, kimi-cli, kimi-code sont disponibles.

Commandes principales

Commande Rôle
goal run --objective "..." Lance une cascade unique
goal plan spec.md Génère un plan multi-cascade depuis un spec
goal cascade-run plan.json Exécute toutes les cascades d'un plan
goal resume <run_id> Reprend un run interrompu (checkpoint SQLite)
goal status / list / inspect Consultation des runs
goal versions / diff Versioning et diff entre runs
goal rag-status / rag-sync Synchronisation RAG PostgreSQL
goal doctor [--config] Vérifie la configuration avant tout appel LLM

Options globales utiles :

Option Effet
--provider mock, kimi-cli, kimi-code, anthropic, openai, google
--config PATH Charger ~/.goal/config.toml (résout providers par rôle + budget + rate limit)
--variant A|B A = rédactionnel, B = technique
--no-synth Désactiver la synthèse orientée objectif (debug)
--enrich-frozen-specs 2e appel LLM pour enrichir les frozen specs (opt-in)

Note : --provider (singulier) vs --providers (pluriel selon spec)

La spec d'implémentation V2 mentionne --providers anthropic,openai,google (pluriel, liste séparée par virgules). Le flag implémenté est --provider au singulier — la cascade utilise un seul provider pour tous les rôles.

Pour mapper un provider différent par rôle (par exemple anthropic pour le producteur, openai pour le critique), utilisez le fichier de configuration TOML avec role_mapping :

[providers]
enabled = ["anthropic", "openai", "google"]
role_mapping = { producer = "anthropic", critic = "openai", adversary = "google", arbiter = "google" }

Voir la section Configuration TOML pour le schéma complet.

Note : les providers réels (anthropic, openai, google) nécessitent l'installation de l'extra llm :

uv pip install -e '.[llm]'
export ANTHROPIC_API_KEY=sk-ant-...
# puis utiliser --config ~/.goal/config.toml

Configuration TOML

Si ~/.goal/config.toml existe, goal run l'utilise pour résoudre les providers par rôle, le budget, le rate limit et le cache. Sinon, le mode CLI historique (--provider mock|kimi-cli|kimi-code) reste disponible.

[providers]
enabled = ["anthropic", "openai", "google"]
role_mapping = { producer = "anthropic", critic = "openai", adversary = "google", arbiter = "google" }
synthesizer = "anthropic"
require_diversity = false

[ratelimit]
max_retries = 3
initial_backoff_s = 1.0
backoff_multiplier = 2.0

[budget]
max_per_run_usd = 0.50
max_per_day_usd = 10.00
warn_at_percent = 80
hard_stop = true
runs_per_day_projection = 10

[cache]
provider = "exact"
enable_semantic = false
ttl_seconds = 3600

[logging]
level = "INFO"
format = "structlog"

Règles de validation :

  • Diversité : require_diversity = true refuse tout mode dégradé. La CLI refuse aussi de démarrer si tous les rôles résolvent vers la même famille de provider.
  • Rate limit : [ratelimit] (canonique) ou [rate_limit] (alias historique).
  • Secrets : ne JAMAIS mettre de clé API dans config.toml. Utiliser les variables d'environnement des SDKs (ANTHROPIC_API_KEY, etc.).

Sécurité

Le projet applique une grille de sécurité issue des audits A-F (cahier de tests tests/test_*_security.py) :

Audit Critère Implémentation
B1-B5 PromptLoader durci Pas de traversal (.., /), Jinja2 sandbox, PromptNotFoundError explicite, hiérarchie projet > user > package.
C1-C6 MultiCascadeExecutor Validation acyclicité, budget par module, arrêts propres, parallélisme contrôlé (synchrone v1), contrats vérifiés après chaque batch.
E1 Pas de secrets dans les logs redact_sensitive() masque Bearer, api_key, password, tokens avant toute persistance.
E2 Traces isolées ~/.goal/runs/<run_id>/ permissions 0o700 (garanti au démarrage du module).
E3 Cache sémantique local Path.home() / ".goal" / "semantic_cache.db" permissions 0o700.
E4 .gitignore complet .goal/runs/, .goal/semantic_cache.db, .goal/checkpoints.db, .goal/budget_daily.json.
F1 Pas de cache sémantique intra-cascade SemanticCache.lookup() jamais appelé dans CascadeExecutor ni Synthesizer.process().
F2 Historique brut jamais transmis Templates utilisent last_synthesis (mode normal), previous_output uniquement en --no-synth.
F3 Limite absolue 5 itérations max_iterations=5 enforced dans _run_loop.
F4 STOP par défaut _parse_verdict catch → verdict STOP automatique, jamais failed silencieux.
F5 Diversité providers validée CLI refuse de démarrer si tous les rôles → même famille (hors mock).

Le hook CI/CD déterministe (syntaxe Python/JSON, cicd_hook.py) est un contrôle qualité informatif, pas un contrôle de sécurité : un échec est tracé mais n'arrête pas la cascade.

Transparence des coûts

Chaque run produit <run_dir>/receipt.json :

  • total_cost_usd : somme des coûts de tous les appels LLM.
  • cache_hit_rate : cache_read_tokens / total_input_tokens.
  • projected_monthly_cost : projection basée sur runs_per_day_projection.
  • calls : liste complète des LLMCallRecord (input/output tokens, cost, latency).
  • final_verdict : STOP / CONTINUE / absent.
  • total_duration_s.

Kill switch budgétaire

Quand hard_stop=true et que le coût courant dépasse max_per_run_usd (ou le cumul journalier dépasse max_per_day_usd), la cascade s'arrête avec statut budget_exceeded. Le reçu final est conservé. Le cumul quotidien est dans <GOAL_HOME>/budget_daily.json (permissions 0o600).

Traçabilité permanente

Chaque run est conservé sous ~/.goal/runs/<run_id>/ (permissions 0o700). Le dossier contient :

  • events.jsonl : événements append-only horodatés et numérotés.
  • prompt_<iteration>_<role>.txt : chaque prompt envoyé.
  • iteration_<n>.txt et synthesis_<n>.json : résultats bruts.
  • state.json et final_output.md : état et livrable.
  • timeline.md : manifeste humain pour le RAG.
  • rag-status.json : reçu observable d'indexation + embedding.
  • receipt.json : transparence des coûts.

RAG PostgreSQL et embeddings

À chaque run, timeline.md est indexé dans la catégorie PostgreSQL goal-cascade. Les embeddings sont demandés en direct à Ollama sur ia-general (http://10.0.0.223:11434) — exception volontaire : l'embedding ne passe pas par l'IAQ Router. Modèle : bge-m3:latest (dimension 1024).

goal rag-status <run_id>
goal rag-sync <run_id>

Statuts possibles : pending, indexing, indexed_pending_embedding, embedded, failed. Une indisponibilité d'ia-general reste enregistrée et n'est jamais transformée en faux succès.

Variables d'environnement :

Variable Défaut Description
OLLAMA_HOST http://10.0.0.223:11434 URL Ollama de ia-general
OLLAMA_EMBED_URL $OLLAMA_HOST/api/embed Endpoint embeddings
OLLAMA_EMBED_MODEL bge-m3:latest Modèle

Tests

# Suite complète (348 tests, 4 skip)
uv run pytest -p no:cacheprovider -q

# Tests d'intégration avec un vrai provider LLM
GOAL_RUN_INTEGRATION=1 \
GOAL_INTEGRATION_PROVIDER=anthropic \
ANTHROPIC_API_KEY=sk-ant-... \
uv run pytest -p no:cacheprovider tests/integration/test_real_provider_smoke.py -v

Le smoke test vrai provider est skip par défaut pour éviter les coûts accidentels en CI.

Exemples

# Mock local (zéro coût, zéro dépendance)
uv run goal run --objective "Auditer un argument" --variant A --provider mock

# Kimi CLI non interactif (sessions jetables)
uv run goal run --objective "Auditer un argument" --variant A \
  --provider kimi-cli --synthesizer-model "moonshot/kimi-k2-0711-preview"

# Vrai provider avec config TOML
uv run goal run --objective "Refactor ce module" --variant B --config ~/.goal/config.toml

# Multi-cascade avec enrichissement LLM
uv run goal plan spec.md --enrich-frozen-specs --output plan.json
uv run goal cascade-run plan.json

Licence

MIT — voir LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

goal_cascade-0.4.0.tar.gz (196.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

goal_cascade-0.4.0-py3-none-any.whl (151.7 kB view details)

Uploaded Python 3

File details

Details for the file goal_cascade-0.4.0.tar.gz.

File metadata

  • Download URL: goal_cascade-0.4.0.tar.gz
  • Upload date:
  • Size: 196.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for goal_cascade-0.4.0.tar.gz
Algorithm Hash digest
SHA256 6e0b860ccc2db7859b09e934b2daea882e9751f966cbde7ff32f7dd6ca97332a
MD5 910644231c9246da09ae3627323442e1
BLAKE2b-256 ecb0a63cd49874c368b19ae63e47a674b321b76ef846f51138ed6856e4470502

See more details on using hashes here.

Provenance

The following attestation bundles were made for goal_cascade-0.4.0.tar.gz:

Publisher: release.yml on ploteddie-bit/goal-cascade-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file goal_cascade-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: goal_cascade-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 151.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for goal_cascade-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cbcaebda74e75cd198f9118c84e4d090ebc07f8587b58e8b7545ab727b795bec
MD5 8c36b4c1ae45334737ffdb2f4348c0f2
BLAKE2b-256 8f608dbb3894a897fc8598c3c1fdd8c996b514461157c4533ac1085382e13e58

See more details on using hashes here.

Provenance

The following attestation bundles were made for goal_cascade-0.4.0-py3-none-any.whl:

Publisher: release.yml on ploteddie-bit/goal-cascade-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page