feat(p10): archivage automatique des sessions terminées (rétention configurable)

- DB: migration #10 (sessions.archived_at + index), helpers archive/unarchive/archiveExpired (soft-archive, jamais de DELETE)
- core/retention-settings.ts: session_retention_days (défaut 30, 0=jamais, 1-3650) + session_purge_days (off)
- core/session-archive.ts: scheduler start/stop/sweep (calqué DiscoveryService), câblé dans runDaemon
- pty-manager.list({includeArchived}) + SessionSummary.archived + emitHistoricalUpdate
- routes: GET /sessions?includeArchived, POST/DELETE /sessions/:id/archive, POST /sessions/archive-now
- protocole additif: message WS session_archived (relayé par la gateway, abonnés 'sessions')
- settings: retentionDays/purgeDays exposés et validés dans PATCH /settings
- web: store sessions (showArchived + archive/unarchive), SessionsListView (toggle/badge/actions), SettingsView (slider rétention), i18n EN+FR
- tests: retention-settings + session-archive (vitest) + settings-routes étendu ; acceptance-p10.mjs (sweep, event WS, resume d'une session archivée → 201, rétention=0)
This commit is contained in:
2026-06-27 13:31:28 +02:00
parent be43911dc0
commit c8dd539571
22 changed files with 818 additions and 42 deletions

View File

@@ -47,6 +47,11 @@ export default {
hideDiscovered: 'Hide external history',
showHidden: 'Show hidden',
hideHidden: 'Hide hidden',
archive: 'Archive',
unarchive: 'Unarchive',
archivedBadge: 'archived',
showArchived: 'Show archived',
hideArchived: 'Hide archived',
clients: 'no client | 1 client | {n} clients',
exitCode: 'exit code {code}',
statusLabel: {
@@ -342,6 +347,8 @@ export default {
sessionHidden: 'Session hidden',
sessionUnhidden: 'Session shown',
sessionsHidden: 'no session hidden | 1 session hidden | {n} sessions hidden',
sessionArchived: 'Session archived',
sessionUnarchived: 'Session unarchived',
repoAdded: 'Repository added',
repoRemoved: 'Repository removed',
worktreeCreated: 'Worktree created',
@@ -413,6 +420,11 @@ export default {
removeRoot: 'Remove',
scanInterval: 'Re-scan interval (minutes)',
scanIntervalHint: '0 disables periodic scanning. Changes apply on the next daemon restart.',
// Sessions (rétention / archivage auto)
sessions: 'Sessions',
sessionsHint: 'Finished sessions older than the retention window are automatically archived (hidden from the list by default). Nothing is deleted — archived sessions stay resumable and forkable.',
retentionDays: 'Auto-archive after (days)',
retentionDaysHint: '0 never archives. Archived sessions are hidden by default; toggle "Show archived" in the sessions list to see them.',
// Claude CLI
claudeCli: 'Claude CLI',
claudeCliHint: 'Where Arboretum finds the `claude` binary and its data. Handy when the daemon runs as a service with a minimal PATH that does not include ~/.local/bin.',

View File

@@ -49,6 +49,11 @@ const fr: typeof en = {
hideDiscovered: 'Masquer lhistorique externe',
showHidden: 'Afficher les masquées',
hideHidden: 'Masquer les masquées',
archive: 'Archiver',
unarchive: 'Désarchiver',
archivedBadge: 'archivée',
showArchived: 'Afficher les archivées',
hideArchived: 'Masquer les archivées',
clients: 'aucun client | 1 client | {n} clients',
exitCode: 'code de sortie {code}',
statusLabel: {
@@ -345,6 +350,8 @@ const fr: typeof en = {
sessionHidden: 'Session masquée',
sessionUnhidden: 'Session réaffichée',
sessionsHidden: 'aucune session masquée | 1 session masquée | {n} sessions masquées',
sessionArchived: 'Session archivée',
sessionUnarchived: 'Session désarchivée',
repoAdded: 'Dépôt ajouté',
repoRemoved: 'Dépôt retiré',
worktreeCreated: 'Worktree créé',
@@ -416,6 +423,11 @@ const fr: typeof en = {
removeRoot: 'Retirer',
scanInterval: 'Intervalle de re-scan (minutes)',
scanIntervalHint: '0 désactive le scan périodique. Les changements prennent effet au prochain redémarrage du daemon.',
// Sessions (rétention / archivage auto)
sessions: 'Sessions',
sessionsHint: 'Les sessions terminées plus anciennes que la fenêtre de rétention sont archivées automatiquement (masquées de la liste par défaut). Rien nest supprimé — une session archivée reste reprenable et forkable.',
retentionDays: 'Auto-archiver après (jours)',
retentionDaysHint: '0 narchive jamais. Les sessions archivées sont masquées par défaut ; activez « Afficher les archivées » dans la liste pour les voir.',
// Claude CLI
claudeCli: 'CLI Claude',
claudeCliHint: 'Où Arboretum trouve le binaire `claude` et ses données. Utile quand le daemon tourne en service avec un PATH minimal qui ninclut pas ~/.local/bin.',