Skip to content

v1.20.7 — Draft Display Registry (ADR-085) + unified HITL pre-confirmation preview

Choose a tag to compare

@jgouviergmail jgouviergmail released this 17 May 00:35

Highlights

Single declarative source of truth for every DraftType's display. Replaces 4 disjoint legacy tables (DRAFT_TYPE_EMOJIS, DRAFT_SUCCESS_MESSAGES/DRAFT_CANCEL_MESSAGES, _DRAFT_RESULT_FIELD_CONFIG, hardcoded label-extraction chain) with one registry keyed by DraftType (apps/api/src/domains/agents/drafts/display.py), exhaustive over the 16 enum values. assert_registry_completeness() runs at lifespan startup and in a CI-parametrized test — a new DraftType without a registry entry either fails the boot or fails the PR.

Same registry also powers the pre-confirmation preview via a unified helper format_hitl_item_preview() consumed by both DraftCritiqueInteraction._generate_batch_critique (removed a ~100-line per-domain if/elif chain) and ForEachConfirmationInteraction._build_item_previews_section (with a new _steps_to_draft_type that maps FOR_EACH tool_name → canonical DraftType, falling back gracefully for non-draft domains like places/weather/routes).

What the user sees

Before (Supprime tous mes rappels × 3):

✅ 3/3
✅ Action exécutée avec succès
✅ Action exécutée avec succès
✅ Action exécutée avec succès

After:

🔔 ✅ 3 rappels supprimés
✅ **Faire les courses** — vendredi 16 mai 2026 à 14h00
✅ **Appeler Maman** — samedi 17 mai 2026 à 09h00
✅ **Rendez-vous médecin** — dimanche 18 mai 2026 à 11h00

And the pre-confirmation panel now renders consistently across both internal paths:

⚠️ **Confirmation de suppression**

**Éléments concernés :**
- 🔔 Rappel : Médecin - dimanche 17 mai 2026 à 19:00
- 🔔 Rappel : Ramonage - jeudi 21 mai 2026 à 19:00
- 🔔 Rappel : Alsace - vendredi 22 mai 2026 à 19:00

⚠️ Cette action est irréversible.

**Confirmes-tu cette suppression ?**

Every other draft type inherits the same shape automatically: 📅 Événement : Réunion équipe - lundi 20 mai 2026 à 10:00, 📧 Email : Confirmation rdv - jeudi 16 mai 2026 à 14:00, 👤 Contact : Marie Dupont, ✅ Tâche : Préparer démo - mardi 20 mai 2026 à 17:00.

Grammatical i18n across 6 languages

Two new tables encode noun forms (singular/plural + gender for fr/es/it) and past-participle forms (4 gender/number combinations for fr/es/it, invariant string for en/de/zh-CN); RESULT_HEADER_TEMPLATES handles Chinese's different word order (已删除 3 个提醒). Per-language pluralization rule: French treats 0 and 1 as singular; English/Spanish/German/Italian treat 1 as singular and everything else as plural; Chinese invariant. reminder_delete parity restored across DRAFT_SUCCESS_MESSAGES, DRAFT_CANCEL_MESSAGES, and _DESTRUCTIVE_CONFIRM_ACTION_TITLES in all 6 languages.

Tests

  • tests/unit/domains/agents/drafts/test_display_registry.py — ~30 parametrized cases on DraftType × 6 languages for the registry (completeness, i18n parity, plural-form rules, header composition snapshots).
  • tests/unit/domains/agents/drafts/test_hitl_item_preview.py — 119 cases including the regression guard on the duplicated-emoji bug, per-language noun capitalization, per-DraftType smoke (16 × 6 languages = 96 cases), nested field resolution.
  • tests/unit/domains/agents/drafts/test_for_each_draft_type_mapping.py — 25 cases on tool_name → draft_type resolution.
  • tests/unit/domains/agents/nodes/test_format_draft_execution_result.py — 19 cases covering batch/single/cancel/error per type + per-language header snapshots.

Architecture

ADR-085 — Draft Display Registry — full diagnostic story, decision rationale, alternatives considered, and consequences.

Backwards compat

  • HitlMessages.get_draft_emoji() unchanged (becomes a one-line wrapper over the registry — the three external callsites in draft_critique.py are untouched).
  • The legacy generic FOR_EACH fallback (item_date_connector) remains for non-draft domains (places/weather/routes/web_fetch/mcp).
  • All existing unit tests in tests/unit/domains/agents/ continue to pass without modification (4194 passed).

Files

  • 31 files changed, 2624 insertions(+), 299 deletions(-).
  • 7 new files: registry module + 4 test files + ADR + __init__.py.
  • Backend: Black + Ruff + MyPy strict + 4194 unit tests green.
  • Frontend: ESLint + tsc + 51 vitest cases green.
  • i18n parity: en ↔ fr/es/de/it/zh OK on all keys.

🤖 Generated with Claude Code