Document de pilotage des sprints d'amélioration. Statut global, journal, et checklist détaillée par sprint. À mettre à jour après chaque session de travail.
| ✓ | Sprint | Thème | Statut | Démarré | Terminé | Notes |
|---|---|---|---|---|---|---|
| ☑ | S0 | Bug Squash + Watch wiring | Terminé | 2026-04-08 | 2026-04-08 | Prérequis pour tout le reste |
| ☑ | S1 | Frictionless First Use | Terminé | 2026-04-08 | 2026-04-08 | Parallèle de S2 |
| ☑ | S2 | Mobile + A11y | Terminé | 2026-04-08 | 2026-04-08 | Parallèle de S1 |
| ☑ | S3 | Power User Velocity | Terminé | 2026-04-08 | 2026-04-08 | Le sprint "wow" |
| ☑ | S4 | Smarter Agent | Terminé | 2026-04-08 | 2026-04-08 | Réduit coût LLM |
| ☑ | S5 | Server Memory (SQLite) | Terminé | 2026-04-08 | 2026-04-08 | Parallèle de S6 |
| ☑ | S6 | Coverage Push | Terminé | 2026-04-08 | 2026-04-08 | 19 nouveaux tools, 73 au total |
| ☑ | S7 | Test Harness | Terminé | 2026-04-08 | 2026-04-08 | 111 tests (92 unit + 15 integration + 4 e2e), pytest vert |
| ☑ | S7+ | Robustness Pack | Terminé | 2026-04-08 | 2026-04-08 | +135 tests : agent loop, dispatch contract 73 tools, MCP smoke, endpoints HTTP complets, webhook entrant, WS cancel/confirm/rate-limit. 246 tests verts (3min38) |
| ☑ | S8 | Extension Polish | Terminé | 2026-07-22 | 2026-07-22 | Merge extension/ dans repo principal, sync live side panel, badge clear, embed natif ssc_ext, constants.js |
| ☑ | S9 | Pont extension ↔ app | Terminé | 2026-07-22 | 2026-07-22 | postMessage bridge, OAuth auto-fill, reload panel, prompts → side panel |
| ☑ | S10 | Sécurité & auth | Terminé | 2026-07-22 | 2026-07-22 | DOMPurify, auth_cookie/ws_token sur routes sensibles, tests session + watch |
| ☑ | S11 | Frontend modularisation | Terminé | 2026-07-22 | 2026-07-22 | Vite build, CSS/JS extraits, index.html 884 lignes, Playwright smoke |
| ☑ | S12 | Backend structure + CI | Terminé | 2026-07-22 | 2026-07-22 | Routers FastAPI modulaires, GitHub Actions CI, 408 unit tests verts |
| ☑ | S13 | Distribution | Terminé | 2026-07-22 | 2026-07-22 | manifest prod, ZIP build, permissions, store kit |
Légende statut : Non démarré / En cours / En revue / Terminé / Reporté
Cases : ☐ à faire · 🟡 en cours · ☑ terminé
gantt
title Roadmap des sprints
dateFormat X
axisFormat J%d
section Critique
S0 - Bug Squash :s0, 0, 2d
section Fluidité
S1 - First Use :s1, after s0, 4d
S2 - Mobile + A11y :s2, after s0, 4d
section Wow
S3 - Power Velocity :s3, after s1, 5d
section Cerveau
S4 - Smarter Agent :s4, after s3, 4d
section Produit
S5 - Server Memory :s5, after s4, 7d
S6 - Coverage Push :s6, after s4, 6d
section Qualité
S7 - Test Harness :s7, after s6, 2d
- Watch mode → Brancher dans S0 (scope minimal : bouton header + popover + toast)
- Cible utilisateur → Les deux (équipe interne + SaaS multi-tenant). S5 et S6 en parallèle après S4.
- Mobile → Parallèle de S1 (S1 et S2 démarrent en même temps, commits séparés)
- Budget LLM → Wow d'abord (S3 avant S4 — l'UX vend, l'optim suit)
- Persistance S5 → SQLite (zéro config, fichier unique, migration Postgres triviale plus tard)
Objectif : nettoyer la dette technique ET livrer le watch mode (différenciateur produit). Effort : 1–2 jours Risque : Très faible Statut : Terminé (2026-04-08)
-
loadConversation: appliquer copy/pin sur les bulles restaurées (parité avec live) - Pinned message : cliquer → scroll + highlight (
pin-flashanimation), clic-droit pour unpin -
Escapeferme aussi Settings et le Tour (cohérence avec shortcuts modal) -
switch_modelaccepteapi_keydans le body (avecneeds_keyflag dans la réponse 400) - Print CSS : corrigé sélecteurs (IDs au lieu de classes) + ajout des nouveaux modals/badges
- Suppression du code
tryAutoReconnectorphelin (déjà fait en session précédente)
- Bouton "Watch" dans le header (icône œil) + indicateur point pulsant vert quand actif
- Popover au clic : checkbox "Watch this sheet" + select intervalle (30s / 1min / 5min / 10min)
- Wire
startWatch()/stopWatch()→ envoi WS{type:"watch", enabled, interval}au backend existant - Toast notification + entrée tool dans le chat ("17:42 — 1 new row(s)")
- Persistance par sheet_id dans
localStorage(cléss_ctrl_watch_<sheetId>) - Restauration auto du watch state à la connexion WS et au switch de sheet
- Stop automatique du watch au switch de sheet et à la déconnexion
- Aucun code mort référencé (lint passe, JS sans erreurs console)
- Tous les modals/overlays se ferment avec
Esc - Switch de provider fonctionne avec une clé fournie au runtime
- Démo Watch : modifier une ligne dans Smartsheet → toast dans l'UI en <interval+5s
Objectif : un nouvel utilisateur arrive, comprend, connecte et envoie son 1er message en moins de 60 secondes, sans lire de doc. Effort : 3–4 jours Risque : Faible Statut : Terminé (2026-04-08)
- Empty state riche dans le chat : 4 cartes "Try this" cliquables avec icône/titre/description (auto-injectées par le welcome)
- Token validation live : badge "Looks valid" / "Too short" / "Looks malformed" temps réel + skeleton pendant l'appel
/api/validate-token - Erreurs contextuelles : helper
friendlyTokenError()mappant 401/403/429/5xx/network → titre + hint clair - Tour v2 : skip-able (toast confirmant), "Replay onboarding tour" dans Settings, +2 étapes (input + watch mode), persistance via
ss_ctrl_tour_done - Welcome dynamique : analyse heuristique sheet (statut/date/owner/numérique) → 4 cartes adaptatives + hints (sheet vide / large / wide)
- Reconnect 1-clic : banner persistant après échec des retries WS, bouton "Reconnect" réutilisant
sessionIdsans reload - First-message hint : pulse subtil 3× sur les try-cards après 10s d'inactivité (annulé dès première frappe), respecte
prefers-reduced-motion
- Démo : un user lambda + un token valide → conversation utile en <60s, montre en main.
- Welcome message change selon le contenu de la sheet.
Objectif : utilisable au téléphone et au clavier seul. Aujourd'hui le mobile est cassé. Effort : 3–4 jours Risque : Faible Statut : Terminé (2026-04-08)
- Bottom sheet drawer sur mobile pour history (backdrop cliquable, animation
drawerUp, fermeture via toggle/backdrop) - Header collapsable sur mobile : burger
#btn-burger(visible <900px),mobile-menu-open→flex-wrapqui empile les boutons secondaires, masqué tant que non connecté - Modal a11y pass :
role="dialog",aria-modal="true",aria-labelledby, focus trap (trapFocus/releaseFocus), retour focus au déclencheur,Escapedéjà câblé -
aria-labelsur tous les boutons icônes (mic, send, stop, copy, pin, watch, settings, history, shortcuts, export, burger) +aria-hidden="true"sur les<svg> -
prefers-reduced-motion: media query globale (background, typing, watch dot, pin flash, toast, screen transitions, tour, drawer) - Skeletons activés :
validate-skeletonpendant/api/validate-token(3 lignes shimmer) - Contrast pass WCAG AA :
--text-secondary#8B95B0→#A1ADCC,--text-muted#5A6480→#7E8AA8,tour-highlightplus contrasté
- Tout le flow (connect → chat → settings → history) fonctionne sur un viewport 375px.
- Lighthouse a11y score ≥ 90.
- Navigation full-keyboard de bout en bout testée.
Objectif : transformer les utilisateurs power en évangélistes. Le sprint "wow". Effort : 4–5 jours Risque : Modéré (nouvelles features) Statut : Terminé (2026-04-08)
- Slash commands :
/summarize,/find,/formula,/chart,/analyze,/template,/help,/clearavec autocomplete (↑↓⏎/Tab/Esc), filtre live, expansion serveur-side,/help&/clearpurement client - Drag & drop CSV : overlay full-page (drag enter/leave/drop), parser CSV/TSV maison (gestion quotes), preview modal (10 premières lignes, nom éditable, meta lignes/colonnes), endpoint
POST /api/csv-to-sheet(création sheet + add_rows par batch de 250, max 5000), switch automatique vers la nouvelle sheet - TTS sortie voix : bouton speaker sur chaque message assistant (live, streaming, history),
speechSynthesisnatif, détection FR/EN heuristique, voix locale-matchée, animation pulse pendant lecture, stop via clic ou Esc, cleanup au disconnect, respecteprefers-reduced-motion - Templates / Saved Prompts : storage
localStorage(ss_ctrl_templates_v1), section dédiée dans Settings, éditeur modal CRUD, placeholders{{var}}avecprompt()interactif, intégration/template <name>, validation nom (alphanum +-_.) - Diff view destructive : backend
_compute_diff()(fetch row-by-row état actuel pourupdate_rows/delete_rows/add_rows), payloadconfirm_action.diffenrichi, frontend rendu différencié par kind (table cellulaire avec strike+→ pour update, pills pour delete/add), variantdangerpour delete, fallback raw args si diff indisponible - Inline sparklines :
addSparklinesIn()post-render markdown, détection colonnes ≥70% numériques (parsing locale-aware €$%, virgule/point), SVG natif (path + dot final, vert ↑/orange ↓),<tfoot>avec mini meta (▲▼ min·avg·max)
- ✅ Démo : 8 slash commands fonctionnent avec autocomplete fluide.
- ✅ Drag d'un CSV → preview puis confirmation → nouvelle sheet créée dans Smartsheet.
- ✅ TTS lit les réponses en français/anglais selon la locale.
- ✅ Templates éditables/dupliquables avec variables.
- ✅ Confirm cards montrent before/after avec diff visuel par cellule.
- ✅ Tables numériques affichent sparklines + min/avg/max automatiquement.
Objectif : agent plus rapide, moins cher, plus fiable. Invisible mais énorme effet. Effort : 3–4 jours Risque : Modéré (touche au prompt + flux LLM) Statut : Terminé (2026-04-08)
- Tool subsetting par intent :
select_tools_for_message()(backend/tools.py) — keyword classifier,_CORE_TOOLStoujours inclus, intent additif (read/write/columns/rows/analysis/image/cross_sheet/structural/automation/webhook). Intégré dansagent.run()avant chaquechat_stream. - Sampling intelligent
analyze_sheet/detect_issues:_sample_rows()(head N + middle random + tail N) au-delà de 1000 lignes ;sampling_inforetourné au LLM ; règle système "annoncer l'échantillon". - Cache
get_sheet(page_size=0)TTL 30s par sheet_id ; invalidation auto surdelete_sheet/rename_sheet/add_column/update_column/delete_column;cache_stats()exposé via/api/usage. - Plan visible : règle système "≥3 actions → plan numéroté avant exécution".
- Citations row/column : prompt enrichi —
row #<rowNumber> (<primary value>)et[Column Name]. - Retry sur tool call malformé :
_safe_parse_args()(llm_router.py) →__parse_error__/__raw__;agent.run()injecte untool_resultd'erreur pour que le LLM corrige son call. - Clarifying questions : règle système "si ambigu, pose une question précise avant d'agir".
- Métriques tokens :
LLMRouter.usage(input_tokens/output_tokens/calls/by_model/last_call), endpointGET /api/usage, panneau "Usage & performance" dans Settings (avec hit-rate cache).
- Token count moyen par turn divisé par 2 sur sheets larges (mesurer avant/après).
- Aucune erreur 500 sur tool call malformé pendant 1h de tests.
- Plan visible pour toute requête multi-étapes (vérifier sur 5 cas).
Objectif : sortir du localStorage. Fondation pour passer d'outil démo à produit installable en équipe. Effort : 5–7 jours Risque : Élevé (nouvelle DB, auth, migration) Statut : Terminé (2026-04-08)
- DB SQLite (
backend/db.py, fichierdata/smartsheet_ctrl.sqlite, WAL, FK ON,asyncio.to_thread) — tablesusers,auth_sessions,conversations,messages,favorites,audit_log,webhook_events; init lazy viainit_db()au lifespan. - Auth minimaliste :
upsert_user()(hash SHA-256 du token Smartsheet),create_auth_session()(cookie tokensecrets.token_urlsafe, TTL 30j),get_user_by_cookie();db_user_idinjecté dans la session HTTP. - Conversation sync multi-device : endpoints
POST /api/conversations/save,GET /api/conversations,GET /api/conversations/{id},POST /api/conversations/delete; persistance auto user/assistant viarun_agent_safe+send_event; frontendregisterActiveConversation()au start/switch. - Audit log destructives :
confirm_callback→ssdb.log_audit(status=approved/rejected); endpointGET /api/audit?sheet_id=; modal "Audit log" dans Settings (timestamp, tool, sheet, status colorisé). - Inbound webhooks :
POST /api/smartsheet-webhook(verification challenge + persistance event) ;GET /api/webhook-events?since=; polling frontend toutes les 15s →showToast(). - Export full account (RGPD) :
ssdb.export_user_data()+ endpointGET /api/export(JSON dump : user, conversations+messages, favorites, audit_log) ; bouton "Download my data" dans Settings. - Migration localStorage → DB :
maybeMigrateLocalHistory()au premier login (flagssctrl_migrated_v1) →POST /api/conversations/migrate(bulk import 50 dernières conversations).
- Connexion depuis un 2e device → même historique disponible.
- Toute action destructive apparaît dans l'audit log.
- Webhook test : créer une ligne dans Smartsheet → toast dans l'UI <5s.
Objectif : "tout ce que tu fais à la main dans Smartsheet, l'agent peut le faire". Effort : 4–6 jours Risque : Faible (additif, pas de refacto) Statut : Terminé (2026-04-08)
- Attachments — URL + binaire :
attach_url_to_sheet,attach_url_to_row,list_row_attachments,delete_attachment(+upload_file_to_sheet/upload_file_to_rowcôté client pour bytes binaires si fournis par le frontend). - Forms read :
list_sheet_forms— tente l'endpoint non documentéGET /sheets/{id}/forms, fallback transparent qui retourne le permalink de la sheet et explique la limitation API publique. - Webhook update :
update_webhook(webhook_id, enabled?, name?, events?, callback_url?)— enable/disable et reconfiguration in-place sans delete + recreate. - Automation rules :
get_automation,update_automation(enabled/name/action),delete_automation. Note : Smartsheet n'expose PAS la création via API — explicite dans le prompt et la description du tool. - Proofs (Premium) :
list_row_proofsetcreate_row_proof_from_urlavec détection 403/404 → message "Premium feature non disponible". - Update requests :
list_update_requests,create_update_request(sendTo emails, rowIds, columnIds optionnels, subject/message, ccMe),delete_update_request. - Workspace sharing :
list_workspace_shares,share_workspace,update_workspace_share,delete_workspace_share(cascade sur toutes les sheets du workspace). - Cell linking :
create_cell_link(target..., source...)— link live one-way, distinct des cross-sheet refs (qui sont ingrédients de formules). - System prompt MAJ : section "PLATFORM FEATURES" enrichie (proofs, update requests, attachments URL, cell linking vs cross-sheet, webhook update, automation API limitation).
- Intent map MAJ (
tools.py) : 5 nouveaux intents (attachment,automation,proof,update_request,form) + keywords FR/EN,shareétendu pour workspace,webhookinclutupdate_webhook. - DESTRUCTIVE_TOOLS étendu : 13 nouveaux tools écrits ajoutés (delete_attachment, delete_automation, update_automation, create/delete_update_request, share_workspace + update/delete, create_cell_link, update_webhook, attach_url_to_sheet/row, create_row_proof_from_url) → confirmation utilisateur obligatoire.
- Documentation README mise à jour : compteur 53 → 73 tools, 12 → 16 catégories, nouvelles sections (Forms, Update Requests, Proofs, Workspace Sharing, Automations) avec tableaux des tools.
- ✅ Démo possible : "joins ce lien Drive à la ligne 12" →
attach_url_to_rowavec confirmation. - ✅ Démo possible : "désactive la règle automation X" →
update_automation(enabled=false)avec confirmation. - ✅ Démo possible : "envoie un update request à alice@x.com pour les lignes 5–10" →
create_update_requestavec confirmation. - ✅ Démo possible : "partage le workspace Marketing avec bob@x.com en EDITOR" →
share_workspace. - ✅ Tools count cohérent :
tools.py(73) ↔ README (73) ↔ ROADMAP (73).
Objectif : un filet de sécurité complet, exécutable d'une commande, qui couvre les trois niveaux (logique pure, contrats Smartsheet réels, flow utilisateur de bout en bout).
-
requirements-dev.txt(pytest, pytest-asyncio, pytest-cov) +pytest.ini(markersunit/integration/e2e/live_llm, asyncio_mode=auto). -
tests/conftest.py: fixtures partagées (tmp_dbqui isole SQLite,smartsheet_token/sheet_idskippables,stub_llm_providerpour zéro coût LLM en e2e). -
tests/unit/(92 tests) :test_rate_limit.py,test_llm_router.py,test_tools.py,test_smartsheet_client.py(mock httpx transport),test_db.py(DB temp),test_agent.py. -
tests/integration/(15 tests) :test_smartsheet_live.py(lectures réelles + lifecycle create→write→delete tolérant aux restrictions de tier),test_app_endpoints.py(TestClientFastAPI : health, providers, env-status, validate-token, session validation). -
tests/e2e/(4 tests) :test_websocket_flow.py— POST session réel + connexion WS + message + streaming + suggestions, plus rejets d'auth (mauvais ws_token, session inconnue). -
tests/README.md: matrice des couches, comment lancer, isolation DB, gating environnement. - README projet : section "Running the test suite" + arborescence mise à jour.
- ✅
pytest -q→ 111 passed (en ~40s, machine dev). - ✅ Aucun test ne pollue
data/smartsheet_ctrl.sqlite(fixturetmp_db+ isolation e2e). - ✅ Aucun test ne consomme de tokens OpenAI/Anthropic (LLM stubbé en e2e).
- ✅ Tests integration/e2e skippent proprement si
SMARTSHEET_TOKENouSHEET_IDabsents. - ✅ Lifecycle write réel testé (create_sheet via workspace ou home, add/update/delete rows, delete_sheet) avec cleanup garanti dans
finally. - ✅ Auth WebSocket validée (bon token → succès, mauvais token → erreur, session inconnue → erreur).
Objectif : combler les trous de la suite initiale en allant chercher les zones où un bug ferait vraiment mal — la boucle de tool-calling de l'agent, la cohérence dispatch ↔ TOOL_DEFINITIONS, tous les endpoints HTTP, l'inbound webhook, et les scénarios WebSocket avancés (cancel, confirm, rate-limit).
-
tests/unit/test_agent_loop.py(8 tests) : boucleAgent.run()avecchat_streamscripté — dispatch tool non-destructif, confirm approve, confirm reject (vérifie queexecute_tooln'est PAS appelé), recovery__parse_error__(INVALID_JSON tool_result injecté), événementimage(__is_image__), événementchart(__is_chart__), guardrailMAX_TOOL_ROUNDS(final response forcé). -
tests/unit/test_tools_dispatch.py(80 tests) : contrat OpenAI — chaque entrée deTOOL_DEFINITIONSaname/description/parameters.type==object, tous lesrequiredexistent dansproperties, chaque property a untype/enum/anyOf, pas de doublon de nom. Paramétré sur les 73 tools : chaque dispatch sans crash via un_AsyncAutoMockqui intercepte n'importe quelle méthode du client. Cohérence intent map ↔ tools. -
tests/unit/test_app_helpers.py(12 tests) :_friendly_errormappe correctement 401/403/404/timeout/quota/rate-limit, fallback générique, n'expose jamais de secret dans le message._detect_available_providersfiltre les clés vides/whitespace. -
tests/unit/test_mcp_smoke.py(4 tests) : module importe, registremcp.list_tools()≥ 50, chaque tool a name+description, pas de doublon. -
tests/integration/test_app_endpoints_full.py(26 tests) : tous les endpoints HTTP non couverts par S7 — usage, disconnect (idempotent + session inconnue), favorites lifecycle complet, conversations CRUD + migration localStorage (rejet roles invalides + contenu vide), audit, export RGPD, switch-model (intra-provider + provider inconnu + session invalide), pin-sheet, webhook-events polling, csv-to-sheet (validation 400 + lifecycle réel avec cleanup tolérant), inbound webhook (challenge handshake + payload réel + fan-out par session + persistance anonyme si aucune session match), generate-title (snippet vide + session invalide), quick-connect (uses .env + 400 si token absent). -
tests/e2e/test_websocket_advanced.py(5 tests) : cancel mid-stream (slow_stream qui trickle 10 chunks à 200ms, client envoie{type:cancel}, serveur émet{type:cancelled}), confirm tool destructif sur WS (LLM scripté émetdelete_rows, vérification queexecute_toolest appelé aprèsconfirm), reject tool destructif sur WS (vérification queexecute_tooln'est PAS appelé), rate-limit WS (monkeypatchcheck_limitstrict, message "Slow down" garanti), conversation multi-tour dans la même connexion WS (echo stream).
- ✅
pytest -q→ 246 passed in 3min38 (machine dev). - ✅ Couverture pratique : agent loop, dispatch contract pour les 73 tools, MCP server, tous les endpoints HTTP, webhook entrant complet, scénarios WebSocket avancés.
- ✅ Aucun test ne consomme d'OpenAI (stub
chat_stream) ni ne pollue la DB de prod (tmp_dbpartout). - ✅ Tests integration et e2e skippent proprement si
.envincomplet. - ✅ Test csv-to-sheet et webhook entrant tolérants aux limitations de tier Smartsheet (skip gracieux + cleanup garanti).
- ✅
tests/README.mdmis à jour avec compteurs par layer et matrice de couverture.
Objectif : découper le monolithe backend/app.py en modules testables, corriger les collisions d'imports, et verrouiller la qualité avec une CI GitHub Actions.
-
backend/core/—state.py(sessions, watchers, auth),helpers.py(errors, providers, API keys) -
backend/services/session.py— bootstrap session, welcome dynamique, sheet context -
backend/routes/— routers : health, sessions, persistence, webhooks, admin, misc, pages -
backend/ws/chat.py— WebSocket handler + watcher loop -
backend/app.py— entry point ~95 lignes (lifespan, mounts, re-exports test-compat) - Fix collision
sessionsrouter ↔ dict in-memory (aliassessions_routes) - Fix shadowing
create_sessionroute ↔ service (bootstrap_session) -
.github/workflows/ci.yml— unit + integration + e2e + frontend build + functional runners -
tests/integration/test_functional_runners.py— gate scriptstests/functional/*.py -
pytest tests/unit -q→ 408 passed
- ✅ Backend modulaire sans régression fonctionnelle
- ✅ Suite unitaire verte (408 tests)
- ✅ CI prête pour push/PR (integration/e2e skip sans secrets Smartsheet)
- ✅
tests/README.mdcompteurs à jour
Objectif : préparer la publication Chrome Web Store — manifest prod, packaging automatisé, permissions justifiées.
-
manifest.dev.json/manifest.prod.json— dev (localhost host) vs store (Smartsheet + optional localhost) -
permissions.js— demandeoptional_host_permissionsquand l’utilisateur change l’origine Controller -
extension/scripts/build_store_package.py— ZIP Store dansdist/; option--controller-originpour HTTPS prod -
tests/unit/test_extension_manifest.py— validation manifests + build ZIP - CI job
extension— tests manifest + build ZIP -
extension/store/— listing, privacy policy, guide soumission (Phase D kit) - Soumission manuelle — compte développeur Chrome, screenshots, URL privacy HTTPS, upload ZIP
- ✅
python extension/scripts/build_store_package.pyproduit un ZIP valide - ✅ Manifest prod :
host_permissionslimité à Smartsheet ; localhost en optional - ✅ Tests unit extension verts ; CI job extension
- ☐ Publication Store (action manuelle utilisateur)
Format : date — sprint — ce qui a été fait — bloqueurs.
| Date | Sprint | Action | Bloqueurs |
|---|---|---|---|
| 2026-04-08 | — | Roadmap créée | — |
| 2026-04-08 | — | Décisions de cadrage arrêtées (5/5) | — |
| 2026-04-08 | S0 | Sprint 0 démarré : bug squash + watch mode wiring | — |
| 2026-04-08 | S0 | Sprint 0 terminé : 11/11 items livrés, 0 erreur lint | — |
| 2026-04-08 | S1+S2 | Sprints 1 & 2 démarrés en parallèle (a11y + premier usage) | — |
| 2026-04-08 | S2 | prefers-reduced-motion, aria-label complets, modal a11y (focus trap), bottom-sheet drawer mobile, skeletons validate-token, contrast WCAG AA, header collapsable burger |
— |
| 2026-04-08 | S1 | Empty state try-cards, token validation live + erreurs contextuelles, reconnect 1-clic, tour v2 (replay + skip), welcome dynamique heuristique, first-message hint | — |
| 2026-04-08 | S1+S2 | Sprints 1 & 2 terminés : 14/14 items livrés, 0 erreur lint | — |
| 2026-04-08 | S3 | Sprint 3 démarré : ordre attaqué tout-en-un (slash → templates → diff → sparklines → CSV → TTS) | — |
| 2026-04-08 | S3 | Slash commands (8 cmds, autocomplete ↑↓⏎/Tab/Esc), Templates CRUD avec {{var}}, Diff view backend _compute_diff + UI before/after par cellule |
— |
| 2026-04-08 | S3 | Sparklines SVG inline (parsing locale-aware, ▲▼ min/avg/max), Drag&drop CSV (parser maison, preview modal, endpoint /api/csv-to-sheet batché 250×), TTS (speechSynthesis, détection FR/EN, animation pulse, Esc-stop) |
— |
| 2026-04-08 | S3 | Sprint 3 terminé : 6/6 items livrés, 0 erreur lint, ROADMAP mise à jour | — |
| 2026-04-08 | S4+S5 | Sprints 4 & 5 démarrés en parallèle (agent smarter + persistance serveur) | — |
| 2026-04-08 | S4 | Cache schema TTL 30s (invalidation auto), sampling head/middle/tail, tool subsetting par intent (keywords), _safe_parse_args + retry tool call, prompt enrichi (citations, clarifying, plan ≥3 étapes, sampling notice), métriques tokens (LLMRouter.usage + /api/usage + UI Settings) |
_compute_diff absent → audit before/after=None (à enrichir au S6) |
| 2026-04-08 | S5 | backend/db.py (SQLite WAL, 7 tables), upsert user + cookie session 30j, persistance auto messages, audit log destructives + modal UI, inbound webhooks + polling toast 15s, export RGPD JSON, migration localStorage → DB au login |
— |
| 2026-04-08 | S4+S5 | Sprints 4 & 5 terminés : 8/8 + 7/7 items livrés, 0 erreur lint, ROADMAP mise à jour | — |
| 2026-04-08 | S6 | Sprint 6 démarré : Coverage Push (cible "tout ce que l'UI fait, l'agent peut le faire") | — |
| 2026-04-08 | S6 | Client : attach_url_to_sheet/row, upload_file_to_sheet/row (binary), delete_attachment, list_row_attachments, list_sheet_forms (avec fallback permalink), update_webhook (in-place), get/update/delete_automation, list_row_proofs + create_row_proof_from_url (Premium-aware), list/create/delete_update_request, list/share/update/delete_workspace_share, create_cell_link (one-way live link) |
API Smartsheet ne permet PAS la création d'automation rules ni l'exposition documentée des forms — clarifié dans prompt + tool descriptions |
| 2026-04-08 | S6 | tools.py : 19 nouveaux _t(...) + dispatch, intent map enrichie (5 nouveaux intents, keywords FR/EN), DESTRUCTIVE_TOOLS étendu (+13). Prompt système : section PLATFORM FEATURES réécrite (proofs, update requests, attachments URL, cell linking vs cross-sheet). README : compteur 53 → 73 tools (16 catégories) avec nouvelles sections |
— |
| 2026-04-08 | S6 | Sprint 6 terminé : 8/8 fonctionnalités Smartsheet couvertes + 3/3 items doc, 0 erreur lint, ROADMAP mise à jour | — |
| 2026-04-08 | S7 | Sprint 7 démarré : test harness sur les trois étages (unit, integration, e2e) | — |
| 2026-04-08 | S7 | tests/ créé : pytest.ini (markers + asyncio_mode=auto), requirements-dev.txt (pytest, pytest-asyncio, pytest-cov), conftest.py (env loader, tmp_db, stub_llm_provider, fixtures sample_columns/rows). |
— |
| 2026-04-08 | S7 | Unit (92 tests) : rate_limit (TokenBucket refill/wait, SessionRateLimiter isolation), llm_router (_safe_parse_args, usage cumulatif par modèle, validation provider), tools (intents FR/EN, chart generator, integrity check map↔TOOL_DEFINITIONS), smartsheet_client (mock httpx transport : retry 429/5xx, schema cache hit/miss/expire, mapping colonnes, CSV ids), db (CRUD users/sessions/conversations/favorites/audit/webhooks + isolation cross-user), agent (DESTRUCTIVE_TOOLS, suggestions, prune, truncate, prompt build) |
— |
| 2026-04-08 | S7 | Integration (15 tests) : Smartsheet API live (get_current_user, list_sheets, summary, pagination, cache hits, search, workspaces, shares, lifecycle create→add→update→delete tolérant 403/404), FastAPI HTTP (/health, /api/providers, /api/env-status, /api/validate-token, /api/session validation) |
API POST /sheets exige containerType selon tier → fallback workspace, sinon skip clean |
| 2026-04-08 | S7 | E2E (4 tests) : flow WebSocket complet (POST /api/session réel → connect /ws/{sid}?token=… → message → stream_delta + stream_end + suggestions extraites), authentification WS (bad token rejeté, session inconnue rejetée), lifespan + DB temp, LLM stubbé (zéro coût OpenAI). |
record_webhook_event exige webhook_id (signature corrigée), suggestions extraites uniquement si [SUGGESTIONS] en début de ligne (stub ajusté) |
| 2026-04-08 | S7 | Sprint 7 terminé : pytest -q → 111 passed in ~40s, 0 erreur lint, README mis à jour (section Tests + arborescence), tests/README.md détaillé. |
— |
| 2026-04-08 | S7+ | Robustness Pack démarré : couverture des trous critiques (boucle agent avec tool calls, contrat dispatch, endpoints HTTP non testés, webhook entrant, scénarios WS avancés, MCP smoke). | — |
| 2026-04-08 | S7+ | Unit (+92) : test_agent_loop.py (8 tests — dispatch tool, confirm approve/reject, parse-error recovery, MAX_TOOL_ROUNDS, événements image/chart), test_tools_dispatch.py (80 tests — schema validity, 73 tools dispatchent sans crash, intent map cohérent), test_app_helpers.py (12 tests — _friendly_error mapping HTTP, anti-leak secrets, _detect_available_providers), test_mcp_smoke.py (4 tests — import, 52 MCP tools enregistrés, noms uniques). |
— |
| 2026-04-08 | S7+ | Integration (+26) : test_app_endpoints_full.py couvre /api/usage, /api/disconnect (idempotent), /api/favorites/* (lifecycle complet + idempotence), /api/conversations/* (save/list/get/delete + migration localStorage avec rejet roles invalides/contenu vide), /api/audit, /api/export (RGPD), /api/switch-model (intra-provider + provider inconnu), /api/pin-sheet, /api/webhook-events, /api/csv-to-sheet (validation + cycle complet avec cleanup tolérant), /api/smartsheet-webhook (challenge + payload réel + fan-out par session + persistance anonyme), /api/generate-title, /api/quick-connect. |
/api/usage retourne 400 (pas 200) sur session inconnue → expectation corrigée. |
| 2026-04-08 | S7+ | E2E (+5) : test_websocket_advanced.py — cancel mid-stream (slow_stream + {type:cancel} → {type:cancelled}), confirm/reject de tool destructif via WS (delete_rows scriptée, vérification que execute_tool est ou n'est PAS appelé), rate-limit WS (monkeypatch check_limit → message "Slow down" attendu), conversation multi-tour dans la même connexion (echo stream). |
— |
| 2026-04-08 | S7+ | Robustness Pack terminé : pytest -q → 246 passed in 3min38, 0 régression, 0 erreur lint, tests/README.md mis à jour (compteurs par layer + couverture exhaustive). Couverture pratique : agent loop, dispatch contract, MCP smoke, tous les endpoints HTTP, webhook entrant, scénarios WS avancés. |
— |
| 2026-07-22 | S13 | Sprint 13 terminé : manifest.prod.json, build ZIP (build_store_package.py), permissions.js, tests manifest, CI extension, kit store/. Soumission CWS reste manuelle. |
— |
| 2026-07-22 | S12 | Sprint 12 terminé : backend découpé (core/services/routes/ws), collision sessions corrigée, CI GitHub Actions, 408 unit tests verts, gate functional runners. |
— |
| 2026-07-22 | S11 | Sprint 11 terminé : pipeline Vite (frontend/package.json), CSS → src/styles/main.css, JS → src/legacy/app.js + src/main.js, build frontend/dist/, backend sert dist si présent, Playwright smoke (2 tests). index.html réduit de ~7800 → 884 lignes. |
— |
| 2026-07-22 | S10 | Sprint 10 terminé : DOMPurify sur rendu Markdown, _resolve_session() (ws_token / auth_cookie), routes sensibles protégées (disconnect, export, audit, migrate, delete, csv), tests unit test_session_auth + test_watch_mode. |
— |
- Avant chaque session : relire le statut global et le sprint en cours.
- Pendant : cocher les items au fur et à mesure.
- À la fin : ajouter une ligne au journal de bord, mettre à jour le statut global.
- Avant un nouveau sprint : valider les critères d'acceptation du précédent.
Ce fichier est maintenu manuellement par l'agent IA et l'utilisateur ensemble. Aucune dépendance externe. Aucun outil de tracking requis.