feat: phase 2 — sessions export + rétention, init --template (closes #52 #53)

Axe 3 (#52) : templates embarqués dans le binaire (web, python, rust, cli)
- am init --template <stack> génère une config pré-remplie : groupe dev,
  profil par défaut, hooks projet (npm install / uv sync / cargo fetch)
- substitution {project} {dir} au rendu ; --template list pour lister
- fallback détection automatique de stack quand aucun template
- config générée validée (parse YAML + validate) par les tests

Axe 4 (#53) : am sessions export + rétention configurable
- am sessions --export <id> [--output <fichier>] : JSON complet et
  reproductible (métadonnées + commandes history/<id>.jsonl + extrait de
  log 4 Ko + rendu lisible 'readable'), compatible archivage manuel
- settings.sessions_retention_days (défaut 90) : purge au démarrage
  (silencieuse) et am sessions --retention <jours>
- purge limitée à l'index dérivé sessions.json — le journal d'événements
  primaire n'est jamais touché ; EventKind::Prune journalisé (visibilité
  am audit)
- sessions en cours (running) jamais purgées ; erreur claire si id inconnu

REPL : sessions --export/--retention/--output + init --template ; help
specs, tip cheat sheet, config.yaml, README, man pages régénérées.
Version 0.4.7, ROADMAP cochée, 276 tests verts.
This commit is contained in:
2026-08-18 10:08:20 -04:00
parent d9ffc34156
commit 6a6676fc5d
23 changed files with 561 additions and 71 deletions
+7 -1
View File
@@ -1519,6 +1519,9 @@ fn handle_line(
status: opt_value("--status"),
show: opt_value("--show"),
resume: opt_value("--resume"),
export: opt_value("--export"),
output: opt_value("--output"),
retention: opt_value("--retention").and_then(|v| v.parse().ok()),
},
"stats" => Command::Stats {
agent: rest.first().cloned(),
@@ -1557,7 +1560,10 @@ fn handle_line(
limit: opt_value("--limit").and_then(|v| v.parse().ok()).unwrap_or(100),
rerun: opt_value("--rerun").and_then(|v| v.parse().ok()),
},
"init" => Command::Init { force: flag("--force") },
"init" => Command::Init {
force: flag("--force"),
template: opt_value("--template"),
},
"search" => {
let words: Vec<String> = rest
.iter()