From 1a9600e7cd27e9efaa6b8774dbfb281dd7b9bc2e Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Wed, 19 Aug 2026 00:07:58 -0700 Subject: [PATCH] feat(tui): make /workflow /goal /auto one-keystroke discoverable The engines already shipped; the remaining gap was visibility. Pin the orchestration trio at the top of the empty / menu, name them on the idle welcome and footer, put them in the first three Hotbar defaults, and add /auto as a host-only Auto-Review switch with when-to-use copy (#5439). Verified: cargo fmt --all -- --check; locale parity; command-migration manifest; cargo nextest -p codewhale-config --lib -- hotbar (5); codewhale-tui lib tests for empty slash pin, /auto, palette root, empty state, footer, hotbar defaults, and locale sync (32 passed). Signed-off-by: Hunter Bown --- CHANGELOG.md | 4 ++ config.example.toml | 6 +- crates/config/src/lib.rs | 6 +- crates/tui/locales/ca.json | 11 +++- crates/tui/locales/de.json | 11 +++- crates/tui/locales/en.json | 11 +++- crates/tui/locales/es-419.json | 11 +++- crates/tui/locales/fr.json | 11 +++- crates/tui/locales/hi.json | 11 +++- crates/tui/locales/id.json | 11 +++- crates/tui/locales/ja.json | 11 +++- crates/tui/locales/ko.json | 11 +++- crates/tui/locales/pt-BR.json | 11 +++- crates/tui/locales/ru.json | 11 +++- crates/tui/locales/uk.json | 11 +++- crates/tui/locales/vi.json | 11 +++- crates/tui/locales/zh-Hans.json | 11 +++- crates/tui/locales/zh-Hant.json | 11 +++- crates/tui/src/commands/contract.rs | 1 + crates/tui/src/commands/groups/core/mod.rs | 4 ++ .../tui/src/commands/groups/core/workflow.rs | 64 ++++++++++++++++++- crates/tui/src/commands/mod.rs | 16 ++++- crates/tui/src/commands/traits.rs | 21 ++++++ crates/tui/src/localization.rs | 10 +++ crates/tui/src/tui/app.rs | 18 ++++++ crates/tui/src/tui/hotbar/actions.rs | 58 ++++++++++++----- crates/tui/src/tui/onboarding/mod.rs | 4 ++ crates/tui/src/tui/shell_key_routing.rs | 9 ++- crates/tui/src/tui/underwater.rs | 24 ++++++- crates/tui/src/tui/widgets/mod.rs | 48 +++++++++++++- docs/KEYBINDINGS.md | 16 ++--- docs/MODES.md | 8 +++ 32 files changed, 399 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 316b9eb13..98e1be140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,6 +90,10 @@ abort under load. validate, and downloads binaries only from that source. Explicit `CODEWHALE_RELEASE_BASE_URL` / `CODEWHALE_USE_CNB_MIRROR=1` still skip the race; other targets stay on GitHub. +- `/workflow`, `/goal`, and `/auto` are pinned at the top of the empty `/` + menu, named on the idle welcome and footer, and occupy the first three + default Hotbar slots. `/auto` turns on Auto-Review (the existing + permission posture) and says when to use the other two instead (#5439). - `feat(tui): add command context adapters and migration gate (FEAT-015)` (aboimpinto) — TUI-owned capability facets, a dual-path dispatch seam, and source-aware CI enforcement so a command slice cannot claim to be migrated diff --git a/config.example.toml b/config.example.toml index c307abc78..8cf6557b8 100644 --- a/config.example.toml +++ b/config.example.toml @@ -130,8 +130,10 @@ check_interval_hours = 24 # # Invalid slots are skipped with a warning, duplicate slots use the last entry, # and unknown actions are preserved so the UI can show a disabled entry. -# Slash commands can be bound as slash., for example slash.mode. Commands -# that require arguments pre-fill the composer instead of running incomplete. +# Slash commands can be bound as slash., for example slash.workflow. +# `/hotbar on` writes the default slots: slash.workflow, slash.goal, slash.auto, +# then Plan/Work/Operate, palette, and sidebar. Commands that require arguments +# pre-fill the composer instead of running incomplete. # # [[hotbar]] # slot = 1 diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 13878266c..35c2b356b 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -1299,14 +1299,14 @@ pub struct ProviderChain { pub const HOTBAR_SLOT_COUNT: u8 = 8; pub const DEFAULT_HOTBAR_ACTIONS: [&str; HOTBAR_SLOT_COUNT as usize] = [ - "voice.toggle", - "session.compact", + "slash.workflow", + "slash.goal", + "slash.auto", "mode.plan", "mode.agent", "mode.operate", "palette.open", "sidebar.toggle", - "trust.toggle", ]; /// On-disk schema for one `[[hotbar]]` table. diff --git a/crates/tui/locales/ca.json b/crates/tui/locales/ca.json index c40e88fbe..60efac604 100644 --- a/crates/tui/locales/ca.json +++ b/crates/tui/locales/ca.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "Mostra el tauler inicial amb estadístiques i accions ràpides", "CmdHooksDescription": "Llista els hooks de cicle de vida configurats (només lectura)", "CmdAgentDescription": "Obre una sessió persistent de subagent", - "CmdGoalDescription": "Defineix un objectiu de sessió amb pressupost de tokens opcional", + "CmdGoalDescription": "Continuar un sol objectiu al llarg de diversos torns", "CmdInitDescription": "Genera l'AGENTS.md per al projecte", "CmdLspDescription": "Activa o desactiva els diagnòstics LSP", "CmdShareDescription": "Exporta la sessió actual com a URL web compartible", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "Ha fallat la còpia al porta-retalls: {error}. No s'ha escrit res; torna-ho a executar amb `stdout` per a una vista de text explícita", "CmdStructcopyReceiptTooLarge": "Les metadades del rebut de còpia estructural superen el límit de sortida de {bytes} bytes; no s'emetran", "CmdFleetDescription": "Inspecciona i configura els treballadors de Fleet i l'estat d'orquestració", - "CmdWorkflowDescription": "Orquestra el treball actual com a workflow", + "CmdWorkflowDescription": "Executar un script multiagent quan importen l'ordre o el fan-out", "CmdHotbarDescription": "Obre la configuració de Hotbar", "CmdSetupDescription": "Obre el Setup amb la constitució primer", "CmdSubagentsDescription": "Drecera de compatibilitat per a l'estat de Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell de només lectura", "AgentFocusPostureShellNone": "sense shell", "GoalReceiptSet": "Objectiu establert: \"{objective}\" · /goal mostra el progrés · /goal pause o /goal clear l'atura", - "GoalStatusIdleHint": "no s'està executant — envia un missatge o /goal resume per continuar" + "GoalStatusIdleHint": "no s'està executant — envia un missatge o /goal resume per continuar", + "CmdAutoDescription": "Treballa amb Auto-Review — sense objectiu ni workflow", + "AutoReceiptOn": "Auto-Review activat. /goal manté un objectiu; /workflow executa un script.", + "AutoReceiptPlanNote": "Plan resta només de lectura fins que passis a Work o Operate.", + "EmptyStateOrchestrationLabel": "Continuar", + "OnboardTipsLine5": "Per a feina més llarga, tria /auto (revisió), /goal (un objectiu) o /workflow (script)." } diff --git a/crates/tui/locales/de.json b/crates/tui/locales/de.json index 6f3501b0e..a8d906597 100644 --- a/crates/tui/locales/de.json +++ b/crates/tui/locales/de.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "Home-Dashboard mit Statistiken und Schnellaktionen anzeigen", "CmdHooksDescription": "Konfigurierte Lifecycle-Hooks auflisten (schreibgeschützt)", "CmdAgentDescription": "Persistente Sub-Agent-Sitzung öffnen", - "CmdGoalDescription": "Sitzungsziel mit optionalem Token-Budget setzen", + "CmdGoalDescription": "Über mehrere Turns hinweg an einem Ziel weiterarbeiten", "CmdInitDescription": "AGENTS.md für das Projekt erzeugen", "CmdLspDescription": "LSP-Diagnosen ein- oder ausschalten", "CmdShareDescription": "Aktuelle Sitzung als teilbare Web-URL exportieren", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "Kopieren in die Zwischenablage fehlgeschlagen: {error}. Es wurde nichts geschrieben; für eine explizite Textansicht erneut mit `stdout` ausführen", "CmdStructcopyReceiptTooLarge": "Die Beleg-Metadaten der strukturellen Kopie überschreiten das Ausgabelimit von {bytes} Bytes; Ausgabe wird verweigert", "CmdFleetDescription": "Fleet-Worker und Orchestrierungsstatus ansehen und einrichten", - "CmdWorkflowDescription": "Aktuelle Arbeit als Workflow orchestrieren", + "CmdWorkflowDescription": "Multi-Agent-Skript ausführen, wenn Reihenfolge oder Fan-out zählen", "CmdHotbarDescription": "Hotbar-Setup öffnen", "CmdSetupDescription": "Setup mit Verfassung zuerst öffnen", "CmdSubagentsDescription": "Kompatibilitäts-Kurzbefehl für Fleet-Status", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "Nur-Lese-Shell", "AgentFocusPostureShellNone": "keine Shell", "GoalReceiptSet": "Ziel gesetzt: \"{objective}\" · /goal zeigt den Fortschritt · /goal pause oder /goal clear beendet es", - "GoalStatusIdleHint": "läuft gerade nicht — Nachricht senden oder /goal resume zum Fortsetzen" + "GoalStatusIdleHint": "läuft gerade nicht — Nachricht senden oder /goal resume zum Fortsetzen", + "CmdAutoDescription": "Mit Auto-Review arbeiten — ohne Ziel oder Workflow", + "AutoReceiptOn": "Auto-Review an. /goal hält ein Ziel; /workflow führt ein Skript aus.", + "AutoReceiptPlanNote": "Plan bleibt schreibgeschützt, bis du zu Work oder Operate wechselst.", + "EmptyStateOrchestrationLabel": "Weiterarbeiten", + "OnboardTipsLine5": "Für längere Arbeit: /auto (Prüfung), /goal (ein Ziel) oder /workflow (Skript)." } diff --git a/crates/tui/locales/en.json b/crates/tui/locales/en.json index 3cbb05f1e..d2ab598b7 100644 --- a/crates/tui/locales/en.json +++ b/crates/tui/locales/en.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "Show home dashboard with stats and quick actions", "CmdHooksDescription": "List configured lifecycle hooks (read-only)", "CmdAgentDescription": "Open a persistent sub-agent session", - "CmdGoalDescription": "Set a session goal with optional token budget", + "CmdGoalDescription": "Keep working toward one objective across turns", "CmdInitDescription": "Generate AGENTS.md for project", "CmdLspDescription": "Toggle LSP diagnostics on or off", "CmdShareDescription": "Export current session as a shareable web URL", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "Structural-copy receipt metadata exceeds the {bytes}-byte output cap; refusing to emit it", "CmdFleetDescription": "Inspect and set up Fleet workers and orchestration state", "CmdLaneDescription": "Inspect and control durable Lanes (running Workflows)", - "CmdWorkflowDescription": "Orchestrate the current work as a workflow", + "CmdWorkflowDescription": "Run a repeatable workflow when order or fan-out matters", "CmdHotbarDescription": "Open Hotbar setup", "CmdSetupDescription": "Open constitution-first setup", "CmdSubagentsDescription": "Compatibility shortcut for Fleet status", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "read-only shell", "AgentFocusPostureShellNone": "no shell", "GoalReceiptSet": "Goal set: \"{objective}\" · /goal shows progress · /goal pause or /goal clear stops it", - "GoalStatusIdleHint": "not running now — send a message or /goal resume to continue" + "GoalStatusIdleHint": "not running now — send a message or /goal resume to continue", + "CmdAutoDescription": "Work with Auto-Review — skip a goal or workflow", + "AutoReceiptOn": "Auto-Review on. /goal keeps one objective; /workflow runs a script.", + "AutoReceiptPlanNote": "Plan stays Read Only until you switch to Work or Operate.", + "EmptyStateOrchestrationLabel": "Keep going", + "OnboardTipsLine5": "For longer work pick /auto (reviewer), /goal (one objective), or /workflow (a script)." } diff --git a/crates/tui/locales/es-419.json b/crates/tui/locales/es-419.json index 7caaf7fe3..52fb1a3ce 100644 --- a/crates/tui/locales/es-419.json +++ b/crates/tui/locales/es-419.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "Mostrar el panel inicial con estadísticas y acciones rápidas", "CmdHooksDescription": "Listar hooks de ciclo de vida configurados (solo lectura)", "CmdAgentDescription": "Abrir una sesión persistente de sub-agente", - "CmdGoalDescription": "Definir una meta de sesión con presupuesto de tokens opcional", + "CmdGoalDescription": "Seguir un solo objetivo a lo largo de varios turnos", "CmdInitDescription": "Generar AGENTS.md para el proyecto", "CmdLspDescription": "Alternar diagnóstico LSP encendido o apagado", "CmdShareDescription": "Exportar la sesión actual como una URL web compartible", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "Los metadatos del recibo de copia estructural superan el límite de salida de {bytes} bytes; se rechaza la emisión", "CmdFleetDescription": "Inspeccionar y configurar workers de Fleet y orquestación", "CmdLaneDescription": "Inspeccionar y controlar Lanes duraderos (Workflows en ejecución)", - "CmdWorkflowDescription": "Orquestar el trabajo actual como un workflow", + "CmdWorkflowDescription": "Ejecutar un script multiagente cuando importan el orden o el fan-out", "CmdHotbarDescription": "Abrir configuración de Hotbar", "CmdSetupDescription": "Abrir configuración con constitución primero", "CmdSubagentsDescription": "Atajo de compatibilidad para el estado de Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell de solo lectura", "AgentFocusPostureShellNone": "sin shell", "GoalReceiptSet": "Meta definida: \"{objective}\" · /goal muestra el progreso · /goal pause o /goal clear la detiene", - "GoalStatusIdleHint": "no está en ejecución — envía un mensaje o /goal resume para continuar" + "GoalStatusIdleHint": "no está en ejecución — envía un mensaje o /goal resume para continuar", + "CmdAutoDescription": "Trabaja con Auto-Review — sin meta ni workflow", + "AutoReceiptOn": "Auto-Review activado. /goal mantiene un objetivo; /workflow ejecuta un script.", + "AutoReceiptPlanNote": "Plan sigue en solo lectura hasta que pases a Work u Operate.", + "EmptyStateOrchestrationLabel": "Seguir", + "OnboardTipsLine5": "Para trabajo más largo, elige /auto (revisión), /goal (un objetivo) o /workflow (script)." } diff --git a/crates/tui/locales/fr.json b/crates/tui/locales/fr.json index 39d5033b3..d52c79d4a 100644 --- a/crates/tui/locales/fr.json +++ b/crates/tui/locales/fr.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "Afficher le tableau de bord avec stats et actions rapides", "CmdHooksDescription": "Lister les hooks de cycle de vie configurés (lecture seule)", "CmdAgentDescription": "Ouvrir une session de sous-agent persistante", - "CmdGoalDescription": "Définir un objectif de session avec budget de tokens optionnel", + "CmdGoalDescription": "Continuer vers un seul objectif sur plusieurs tours", "CmdInitDescription": "Générer un AGENTS.md pour le projet", "CmdLspDescription": "Activer ou désactiver les diagnostics LSP", "CmdShareDescription": "Exporter la session en cours en URL web partageable", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "Échec de la copie vers le presse-papiers : {error}. Rien n'a été écrit ; relancez avec `stdout` pour un affichage texte explicite", "CmdStructcopyReceiptTooLarge": "Les métadonnées du reçu de copie structurelle dépassent la limite de sortie de {bytes} octets ; émission refusée", "CmdFleetDescription": "Inspecter et configurer les workers Fleet et l'état d'orchestration", - "CmdWorkflowDescription": "Orchestrer le travail en cours comme un workflow", + "CmdWorkflowDescription": "Lancer un script multi-agents quand l'ordre ou le fan-out compte", "CmdHotbarDescription": "Ouvrir la configuration Hotbar", "CmdSetupDescription": "Ouvrir la configuration axée constitution", "CmdSubagentsDescription": "Raccourci de compatibilité pour le statut Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell en lecture seule", "AgentFocusPostureShellNone": "sans shell", "GoalReceiptSet": "Objectif défini : « {objective} » · /goal affiche la progression · /goal pause ou /goal clear l'arrête", - "GoalStatusIdleHint": "à l'arrêt pour l'instant — envoyez un message ou /goal resume pour continuer" + "GoalStatusIdleHint": "à l'arrêt pour l'instant — envoyez un message ou /goal resume pour continuer", + "CmdAutoDescription": "Travailler avec Auto-Review — sans objectif ni workflow", + "AutoReceiptOn": "Auto-Review activé. /goal suit un objectif ; /workflow lance un script.", + "AutoReceiptPlanNote": "Plan reste en lecture seule jusqu'au passage en Work ou Operate.", + "EmptyStateOrchestrationLabel": "Continuer", + "OnboardTipsLine5": "Pour un travail plus long, choisissez /auto (revue), /goal (un objectif) ou /workflow (script)." } diff --git a/crates/tui/locales/hi.json b/crates/tui/locales/hi.json index c215bd20e..09340719a 100644 --- a/crates/tui/locales/hi.json +++ b/crates/tui/locales/hi.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "आँकड़ों और त्वरित क्रियाओं सहित होम डैशबोर्ड दिखाएँ", "CmdHooksDescription": "कॉन्फ़िगर किए गए लाइफ़साइकिल हुक सूचीबद्ध करें (केवल-पठन)", "CmdAgentDescription": "स्थायी सब-एजेंट सत्र खोलें", - "CmdGoalDescription": "वैकल्पिक टोकन बजट के साथ सत्र लक्ष्य सेट करें", + "CmdGoalDescription": "कई टर्न तक एक ही लक्ष्य पर काम जारी रखें", "CmdInitDescription": "प्रोजेक्ट के लिए AGENTS.md बनाएँ", "CmdLspDescription": "LSP डायग्नोस्टिक्स चालू/बंद करें", "CmdShareDescription": "वर्तमान सत्र को साझा करने योग्य वेब URL के रूप में एक्सपोर्ट करें", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "क्लिपबोर्ड कॉपी विफल: {error}. कुछ भी नहीं लिखा गया; स्पष्ट पाठ दृश्य के लिए `stdout` के साथ फिर चलाएँ", "CmdStructcopyReceiptTooLarge": "संरचनात्मक-कॉपी रसीद मेटाडेटा {bytes}-बाइट आउटपुट सीमा से अधिक है; इसे भेजने से इनकार", "CmdFleetDescription": "Fleet वर्कर और ऑर्केस्ट्रेशन स्थिति देखें और सेटअप करें", - "CmdWorkflowDescription": "वर्तमान कार्य को वर्कफ़्लो के रूप में ऑर्केस्ट्रेट करें", + "CmdWorkflowDescription": "क्रम या फैन-आउट ज़रूरी हो तो मल्टी-एजेंट स्क्रिप्ट चलाएँ", "CmdHotbarDescription": "Hotbar सेटअप खोलें", "CmdSetupDescription": "संविधान-प्रथम सेटअप खोलें", "CmdSubagentsDescription": "Fleet स्थिति के लिए संगतता शॉर्टकट", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "केवल-पढ़ने शेल", "AgentFocusPostureShellNone": "शेल नहीं", "GoalReceiptSet": "लक्ष्य सेट: \"{objective}\" · /goal प्रगति दिखाता है · /goal pause या /goal clear इसे रोकता है", - "GoalStatusIdleHint": "अभी नहीं चल रहा — जारी रखने के लिए संदेश भेजें या /goal resume" + "GoalStatusIdleHint": "अभी नहीं चल रहा — जारी रखने के लिए संदेश भेजें या /goal resume", + "CmdAutoDescription": "Auto-Review से काम करें — लक्ष्य या वर्कफ़्लो के बिना", + "AutoReceiptOn": "Auto-Review चालू है। /goal एक लक्ष्य रखता है; /workflow स्क्रिप्ट चलाता है।", + "AutoReceiptPlanNote": "Work या Operate पर जाने तक Plan केवल पढ़ने योग्य रहता है।", + "EmptyStateOrchestrationLabel": "जारी रखें", + "OnboardTipsLine5": "लंबे काम के लिए /auto (समीक्षा), /goal (एक लक्ष्य) या /workflow (स्क्रिप्ट) चुनें।" } diff --git a/crates/tui/locales/id.json b/crates/tui/locales/id.json index 5e2f630e3..fcb4af07a 100644 --- a/crates/tui/locales/id.json +++ b/crates/tui/locales/id.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "Tampilkan dasbor beranda dengan statistik dan aksi cepat", "CmdHooksDescription": "Tampilkan hook siklus hidup terkonfigurasi (hanya baca)", "CmdAgentDescription": "Buka sesi sub-agen persisten", - "CmdGoalDescription": "Tetapkan tujuan sesi dengan anggaran token opsional", + "CmdGoalDescription": "Terus mengerjakan satu tujuan lintas giliran", "CmdInitDescription": "Buat AGENTS.md untuk proyek", "CmdLspDescription": "Aktifkan atau nonaktifkan diagnostik LSP", "CmdShareDescription": "Ekspor sesi saat ini sebagai URL web yang dapat dibagikan", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "Penyalinan ke papan klip gagal: {error}. Tidak ada yang ditulis; jalankan lagi dengan `stdout` untuk tampilan teks eksplisit", "CmdStructcopyReceiptTooLarge": "Metadata tanda terima salinan struktural melampaui batas keluaran {bytes} bita; penerbitannya ditolak", "CmdFleetDescription": "Periksa dan siapkan worker Fleet serta status orkestrasi", - "CmdWorkflowDescription": "Orkestrasikan pekerjaan saat ini sebagai alur kerja", + "CmdWorkflowDescription": "Jalankan skrip multi-agen saat urutan atau fan-out penting", "CmdHotbarDescription": "Buka penyiapan Hotbar", "CmdSetupDescription": "Buka penyiapan konstitusi-dulu", "CmdSubagentsDescription": "Pintasan kompatibilitas untuk status Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell hanya-baca", "AgentFocusPostureShellNone": "tanpa shell", "GoalReceiptSet": "Tujuan ditetapkan: \"{objective}\" · /goal menampilkan progres · /goal pause atau /goal clear menghentikannya", - "GoalStatusIdleHint": "tidak sedang berjalan — kirim pesan atau /goal resume untuk melanjutkan" + "GoalStatusIdleHint": "tidak sedang berjalan — kirim pesan atau /goal resume untuk melanjutkan", + "CmdAutoDescription": "Bekerja dengan Auto-Review — tanpa tujuan atau workflow", + "AutoReceiptOn": "Auto-Review aktif. /goal menjaga satu tujuan; /workflow menjalankan skrip.", + "AutoReceiptPlanNote": "Plan tetap hanya-baca sampai Anda pindah ke Work atau Operate.", + "EmptyStateOrchestrationLabel": "Lanjutkan", + "OnboardTipsLine5": "Untuk pekerjaan lebih panjang pilih /auto (peninjau), /goal (satu tujuan), atau /workflow (skrip)." } diff --git a/crates/tui/locales/ja.json b/crates/tui/locales/ja.json index 5253ab9b5..a414fe889 100644 --- a/crates/tui/locales/ja.json +++ b/crates/tui/locales/ja.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "統計とクイックアクション付きのホームダッシュボードを表示", "CmdHooksDescription": "設定済みのライフサイクルフックを一覧表示(読み取り専用)", "CmdAgentDescription": "永続サブエージェントセッションを開く", - "CmdGoalDescription": "トークンバジェット付きのセッション目標を設定", + "CmdGoalDescription": "複数ターンにわたって一つの目標を追い続ける", "CmdInitDescription": "プロジェクト用に AGENTS.md を生成", "CmdLspDescription": "LSP 診断のオン・オフを切り替え", "CmdShareDescription": "現在のセッションを共有可能な Web URL としてエクスポート", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "構造化コピーのレシートメタデータが出力上限の{bytes}バイトを超えたため、出力を拒否しました", "CmdFleetDescription": "Fleet ワーカーとオーケストレーション状態を確認・設定", "CmdLaneDescription": "永続化された Lane(実行中の Workflow)を確認・制御", - "CmdWorkflowDescription": "現在の作業をワークフローとして編成する", + "CmdWorkflowDescription": "順序や並列が必要なときにマルチエージェント脚本を実行する", "CmdHotbarDescription": "Hotbar設定を開く", "CmdSetupDescription": "憲法ファーストのセットアップを開く", "CmdSubagentsDescription": "Fleet ステータスへの互換ショートカット", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "読み取り専用シェル", "AgentFocusPostureShellNone": "シェル不可", "GoalReceiptSet": "目標を設定: 「{objective}」 · /goal で進捗表示 · /goal pause または /goal clear で停止", - "GoalStatusIdleHint": "現在は実行中ではありません — メッセージを送るか /goal resume で続行" + "GoalStatusIdleHint": "現在は実行中ではありません — メッセージを送るか /goal resume で続行", + "CmdAutoDescription": "Auto-Review で作業する — ゴールやワークフローは不要", + "AutoReceiptOn": "Auto-Review をオンにしました。/goal は一つの目標、/workflow は脚本です。", + "AutoReceiptPlanNote": "Work または Operate に切り替えるまで Plan は読み取り専用です。", + "EmptyStateOrchestrationLabel": "続ける", + "OnboardTipsLine5": "長い作業は /auto(審査)、/goal(一つの目標)、/workflow(脚本)から選びます。" } diff --git a/crates/tui/locales/ko.json b/crates/tui/locales/ko.json index 5920e53c5..0c9a17f34 100644 --- a/crates/tui/locales/ko.json +++ b/crates/tui/locales/ko.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "통계와 빠른 작업이 있는 홈 대시보드를 표시합니다", "CmdHooksDescription": "설정된 라이프사이클 훅 목록을 표시합니다 (읽기 전용)", "CmdAgentDescription": "지속적인 서브 에이전트 세션을 엽니다", - "CmdGoalDescription": "선택적 토큰 예산과 함께 세션 목표를 설정합니다", + "CmdGoalDescription": "여러 턴에 걸쳐 하나의 목표를 계속 진행합니다", "CmdInitDescription": "프로젝트용 AGENTS.md를 생성합니다", "CmdLspDescription": "LSP 진단을 켜거나 끕니다", "CmdShareDescription": "현재 세션을 공유 가능한 웹 URL로 내보냅니다", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "구조적 복사 영수증 메타데이터가 {bytes}바이트 출력 상한을 초과하여 출력을 거부했습니다", "CmdFleetDescription": "플릿 워커와 오케스트레이션 상태를 확인하고 설정합니다", "CmdLaneDescription": "지속되는 Lane(실행 중인 Workflow)을 확인하고 제어합니다", - "CmdWorkflowDescription": "현재 작업을 워크플로로 오케스트레이션합니다", + "CmdWorkflowDescription": "순서나 병렬 분기가 필요할 때 멀티 에이전트 스크립트를 실행합니다", "CmdHotbarDescription": "핫바 설정을 엽니다", "CmdSetupDescription": "헌법 우선 설정을 엽니다", "CmdSubagentsDescription": "Fleet 상태용 호환 단축 명령", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "읽기 전용 셸", "AgentFocusPostureShellNone": "셸 없음", "GoalReceiptSet": "목표 설정: \"{objective}\" · /goal 로 진행 상황 확인 · /goal pause 또는 /goal clear 로 중지", - "GoalStatusIdleHint": "지금은 실행 중이 아님 — 메시지를 보내거나 /goal resume 로 계속" + "GoalStatusIdleHint": "지금은 실행 중이 아님 — 메시지를 보내거나 /goal resume 로 계속", + "CmdAutoDescription": "자동 검토로 작업합니다 — 목표나 워크플로 없이", + "AutoReceiptOn": "자동 검토가 켜졌습니다. /goal 은 하나의 목표, /workflow 는 스크립트입니다.", + "AutoReceiptPlanNote": "Work 또는 Operate 로 바꿀 때까지 Plan 은 읽기 전용입니다.", + "EmptyStateOrchestrationLabel": "계속하기", + "OnboardTipsLine5": "긴 작업은 /auto(검토), /goal(하나의 목표), /workflow(스크립트) 중에서 고르세요." } diff --git a/crates/tui/locales/pt-BR.json b/crates/tui/locales/pt-BR.json index 0292429e1..24b0e0722 100644 --- a/crates/tui/locales/pt-BR.json +++ b/crates/tui/locales/pt-BR.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "Exibir o painel inicial com estatísticas e ações rápidas", "CmdHooksDescription": "Listar hooks de ciclo de vida configurados (somente leitura)", "CmdAgentDescription": "Abrir uma sessão persistente de sub-agente", - "CmdGoalDescription": "Definir uma meta de sessão com orçamento de tokens opcional", + "CmdGoalDescription": "Continuar um único objetivo ao longo de vários turnos", "CmdInitDescription": "Gerar AGENTS.md para o projeto", "CmdLspDescription": "Alternar diagnóstico LSP ligado ou desligado", "CmdShareDescription": "Exportar a sessão atual como uma URL web compartilhável", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "Os metadados do recibo de cópia estrutural excedem o limite de saída de {bytes} bytes; a emissão foi recusada", "CmdFleetDescription": "Inspecionar e configurar workers do Fleet e orquestração", "CmdLaneDescription": "Inspecionar e controlar Lanes duráveis (Workflows em execução)", - "CmdWorkflowDescription": "Orquestrar o trabalho atual como um workflow", + "CmdWorkflowDescription": "Executar um script multiagente quando ordem ou fan-out importam", "CmdHotbarDescription": "Abrir configuração da Hotbar", "CmdSetupDescription": "Abrir configuração com constituição primeiro", "CmdSubagentsDescription": "Atalho de compatibilidade para o status do Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell somente leitura", "AgentFocusPostureShellNone": "sem shell", "GoalReceiptSet": "Meta definida: \"{objective}\" · /goal mostra o progresso · /goal pause ou /goal clear interrompe", - "GoalStatusIdleHint": "parada no momento — envie uma mensagem ou /goal resume para continuar" + "GoalStatusIdleHint": "parada no momento — envie uma mensagem ou /goal resume para continuar", + "CmdAutoDescription": "Trabalhe com Auto-Review — sem meta ou workflow", + "AutoReceiptOn": "Auto-Review ligado. /goal mantém um objetivo; /workflow executa um script.", + "AutoReceiptPlanNote": "Plan permanece somente leitura até você mudar para Work ou Operate.", + "EmptyStateOrchestrationLabel": "Continuar", + "OnboardTipsLine5": "Para trabalho mais longo, escolha /auto (revisão), /goal (um objetivo) ou /workflow (script)." } diff --git a/crates/tui/locales/ru.json b/crates/tui/locales/ru.json index fb49f8360..ee04a2a97 100644 --- a/crates/tui/locales/ru.json +++ b/crates/tui/locales/ru.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "Показать домашнюю панель со статистикой и быстрыми действиями", "CmdHooksDescription": "Список настроенных хуков жизненного цикла (только чтение)", "CmdAgentDescription": "Открыть постоянную сессию субагента", - "CmdGoalDescription": "Задать цель сессии с необязательным бюджетом токенов", + "CmdGoalDescription": "Продолжать одну цель на протяжении нескольких ходов", "CmdInitDescription": "Сгенерировать AGENTS.md для проекта", "CmdLspDescription": "Включить или выключить диагностику LSP", "CmdShareDescription": "Экспортировать текущую сессию как веб-ссылку для общего доступа", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "Копирование в буфер обмена не удалось: {error}. Ничего не записано; запустите снова с `stdout` для явного текстового вывода", "CmdStructcopyReceiptTooLarge": "Метаданные квитанции структурного копирования превышают предел вывода в {bytes} байт; вывод отклонён", "CmdFleetDescription": "Просмотр и настройка воркеров Fleet и состояния оркестрации", - "CmdWorkflowDescription": "Оркестрировать текущую работу как воркфлоу", + "CmdWorkflowDescription": "Запустить мультиагентный скрипт, когда важны порядок или fan-out", "CmdHotbarDescription": "Открыть настройку Hotbar", "CmdSetupDescription": "Открыть настройку, начиная с конституции", "CmdSubagentsDescription": "Совместимый ярлык для статуса Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell только чтение", "AgentFocusPostureShellNone": "без shell", "GoalReceiptSet": "Цель задана: «{objective}» · /goal показывает прогресс · /goal pause или /goal clear останавливает", - "GoalStatusIdleHint": "сейчас не выполняется — отправьте сообщение или /goal resume, чтобы продолжить" + "GoalStatusIdleHint": "сейчас не выполняется — отправьте сообщение или /goal resume, чтобы продолжить", + "CmdAutoDescription": "Работать с Auto-Review — без цели и workflow", + "AutoReceiptOn": "Auto-Review включён. /goal держит одну цель; /workflow запускает скрипт.", + "AutoReceiptPlanNote": "Plan остаётся только для чтения, пока вы не перейдёте в Work или Operate.", + "EmptyStateOrchestrationLabel": "Продолжать", + "OnboardTipsLine5": "Для длинной работы выберите /auto (проверка), /goal (одна цель) или /workflow (скрипт)." } diff --git a/crates/tui/locales/uk.json b/crates/tui/locales/uk.json index 7d6c85a01..eabc91184 100644 --- a/crates/tui/locales/uk.json +++ b/crates/tui/locales/uk.json @@ -254,7 +254,7 @@ "CmdHomeDescription": "Показати домашню панель зі статистикою та швидкими діями", "CmdHooksDescription": "Показати налаштовані хуки життєвого циклу (лише читання)", "CmdAgentDescription": "Відкрити постійний сеанс субагента", - "CmdGoalDescription": "Задати ціль сеансу з необов'язковим бюджетом токенів", + "CmdGoalDescription": "Продовжувати одну ціль упродовж кількох ходів", "CmdInitDescription": "Згенерувати AGENTS.md для проєкту", "CmdLspDescription": "Увімкнути або вимкнути діагностику LSP", "CmdShareDescription": "Експортувати поточний сеанс як веб-URL для поширення", @@ -393,7 +393,7 @@ "CmdStructcopyClipboardFailed": "Копіювання до буфера обміну не вдалося: {error}. Нічого не записано; запустіть знову з `stdout` для явного текстового вигляду", "CmdStructcopyReceiptTooLarge": "Метадані квитанції структурного копіювання перевищують ліміт виводу в {bytes} байтів; вивід відхилено", "CmdFleetDescription": "Переглянути й налаштувати воркерів Fleet та стан оркестрації", - "CmdWorkflowDescription": "Оркеструвати поточну роботу як робочий процес", + "CmdWorkflowDescription": "Запустити мультиагентний скрипт, коли важливі порядок або fan-out", "CmdHotbarDescription": "Відкрити налаштування Hotbar", "CmdSetupDescription": "Відкрити налаштування, що починається з конституції", "CmdSubagentsDescription": "Сумісне скорочення для стану Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell лише читання", "AgentFocusPostureShellNone": "без shell", "GoalReceiptSet": "Ціль задано: «{objective}» · /goal показує прогрес · /goal pause або /goal clear зупиняє", - "GoalStatusIdleHint": "зараз не виконується — надішліть повідомлення або /goal resume, щоб продовжити" + "GoalStatusIdleHint": "зараз не виконується — надішліть повідомлення або /goal resume, щоб продовжити", + "CmdAutoDescription": "Працювати з Auto-Review — без цілі чи workflow", + "AutoReceiptOn": "Auto-Review увімкнено. /goal тримає одну ціль; /workflow запускає скрипт.", + "AutoReceiptPlanNote": "Plan лишається лише для читання, доки ви не перейдете в Work або Operate.", + "EmptyStateOrchestrationLabel": "Продовжувати", + "OnboardTipsLine5": "Для довшої роботи оберіть /auto (перевірка), /goal (одна ціль) або /workflow (скрипт)." } diff --git a/crates/tui/locales/vi.json b/crates/tui/locales/vi.json index b2827d305..fee371469 100644 --- a/crates/tui/locales/vi.json +++ b/crates/tui/locales/vi.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "Hiển thị bảng điều khiển trang chủ với số liệu thống kê và hành động nhanh", "CmdHooksDescription": "Liệt kê các lifecycle hook đã cấu hình (chỉ đọc)", "CmdAgentDescription": "Mở một phiên sub-agent nền", - "CmdGoalDescription": "Đặt mục tiêu cho phiên với giới hạn token tùy chọn", + "CmdGoalDescription": "Tiếp tục một mục tiêu xuyên suốt nhiều lượt", "CmdInitDescription": "Tạo tệp AGENTS.md cho dự án", "CmdLspDescription": "Bật hoặc tắt tính năng chẩn đoán LSP", "CmdShareDescription": "Xuất phiên hiện tại thành một liên kết web có thể chia sẻ", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "Siêu dữ liệu biên nhận sao chép cấu trúc vượt quá giới hạn đầu ra {bytes} byte; từ chối xuất dữ liệu", "CmdFleetDescription": "Xem và thiết lập worker Fleet cùng trạng thái điều phối", "CmdLaneDescription": "Xem và điều khiển các Lane bền vững (Workflow đang chạy)", - "CmdWorkflowDescription": "Điều phối công việc hiện tại thành một workflow", + "CmdWorkflowDescription": "Chạy script đa tác nhân khi thứ tự hoặc fan-out quan trọng", "CmdHotbarDescription": "Mở thiết lập Hotbar", "CmdSetupDescription": "Mở thiết lập ưu tiên hiến pháp", "CmdSubagentsDescription": "Phím tắt tương thích cho trạng thái Fleet", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "shell chỉ đọc", "AgentFocusPostureShellNone": "không shell", "GoalReceiptSet": "Đã đặt mục tiêu: \"{objective}\" · /goal hiển thị tiến độ · /goal pause hoặc /goal clear để dừng", - "GoalStatusIdleHint": "hiện không chạy — gửi tin nhắn hoặc /goal resume để tiếp tục" + "GoalStatusIdleHint": "hiện không chạy — gửi tin nhắn hoặc /goal resume để tiếp tục", + "CmdAutoDescription": "Làm việc với Auto-Review — không cần goal hay workflow", + "AutoReceiptOn": "Đã bật Auto-Review. /goal giữ một mục tiêu; /workflow chạy script.", + "AutoReceiptPlanNote": "Plan vẫn chỉ đọc cho đến khi bạn chuyển sang Work hoặc Operate.", + "EmptyStateOrchestrationLabel": "Tiếp tục", + "OnboardTipsLine5": "Công việc dài hơn: chọn /auto (xem xét), /goal (một mục tiêu) hoặc /workflow (script)." } diff --git a/crates/tui/locales/zh-Hans.json b/crates/tui/locales/zh-Hans.json index c6b75934e..f16227173 100644 --- a/crates/tui/locales/zh-Hans.json +++ b/crates/tui/locales/zh-Hans.json @@ -257,7 +257,7 @@ "CmdHomeDescription": "显示主页面板,含统计与快捷操作", "CmdHooksDescription": "列出已配置的生命周期钩子(只读)", "CmdAgentDescription": "打开持久子代理会话", - "CmdGoalDescription": "设置带有可选令牌预算的会话目标", + "CmdGoalDescription": "跨多轮持续推进同一个目标", "CmdInitDescription": "为项目生成 AGENTS.md", "CmdLspDescription": "切换 LSP 诊断的开启或关闭", "CmdShareDescription": "将当前会话导出为可共享的 Web URL", @@ -397,7 +397,7 @@ "CmdStructcopyReceiptTooLarge": "结构化复制回执元数据超过 {bytes} 字节的输出上限;拒绝输出", "CmdFleetDescription": "查看与配置 Fleet 工作节点及编排状态", "CmdLaneDescription": "查看与控制持久化的 Lane(运行中的工作流)", - "CmdWorkflowDescription": "将当前工作编排为工作流", + "CmdWorkflowDescription": "当需要阶段、顺序或多路并行时运行多智能体脚本", "CmdHotbarDescription": "打开 Hotbar 设置", "CmdSetupDescription": "打开以宪章为核心的设置", "CmdSubagentsDescription": "Fleet 状态的兼容快捷方式", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "只读 shell", "AgentFocusPostureShellNone": "无 shell", "GoalReceiptSet": "已设定目标:“{objective}” · /goal 查看进度 · /goal pause 或 /goal clear 停止", - "GoalStatusIdleHint": "当前未运行 — 发送消息或 /goal resume 以继续" + "GoalStatusIdleHint": "当前未运行 — 发送消息或 /goal resume 以继续", + "CmdAutoDescription": "用自动审核工作——不必先设目标或工作流", + "AutoReceiptOn": "已开启自动审核。/goal 盯住一个目标;/workflow 运行脚本。", + "AutoReceiptPlanNote": "在切换到工作或 Operate 之前,计划模式仍为只读。", + "EmptyStateOrchestrationLabel": "继续推进", + "OnboardTipsLine5": "更长的任务用 /auto(审核)、/goal(单一目标)或 /workflow(脚本)。" } diff --git a/crates/tui/locales/zh-Hant.json b/crates/tui/locales/zh-Hant.json index a461eb982..a0bfd2320 100644 --- a/crates/tui/locales/zh-Hant.json +++ b/crates/tui/locales/zh-Hant.json @@ -185,7 +185,7 @@ "CmdTreeDescription": "以樹狀結構顯示工作階段歷史(葉節點為目前分支)", "CmdBranchDescription": "將目前分支移至現有工作階段項目,不重寫歷史記錄", "CmdResumeDescription": "恢復工作階段,也可匯入已匯出的工作階段 JSON 檔案", - "CmdGoalDescription": "設定帶有可選令牌預算的工作階段目標", + "CmdGoalDescription": "跨多輪持續推進同一個目標", "CmdHelpDescription": "理解概念、命令與快捷鍵", "CmdHfDescription": "檢查 Hugging Face MCP 設定和概念", "CmdHomeDescription": "顯示主頁面板,含統計與快捷操作", @@ -353,7 +353,7 @@ "CmdVoiceControlDescription": "切換語音控制:AI 輔助的語音聽寫(結合當前輸入內容)", "CmdVoiceDescription": "切換語音輸入:錄製語音並轉錄為文字", "CmdVoiceSendDescription": "切換語音自動傳送:轉錄以「發送」或「send it」結尾時自動提交", - "CmdWorkflowDescription": "將目前工作編排為工作流程", + "CmdWorkflowDescription": "需要階段、順序或多路並行時執行多智能體腳本", "CmdWorkspaceDescription": "顯示或切換目前工作空間", "CommandPaletteSubtitle": "查找並執行一個操作", "CommandPaletteTitle": "命令", @@ -1502,5 +1502,10 @@ "AgentFocusPostureShellReadOnly": "唯讀 shell", "AgentFocusPostureShellNone": "無 shell", "GoalReceiptSet": "已設定目標:「{objective}」 · /goal 查看進度 · /goal pause 或 /goal clear 停止", - "GoalStatusIdleHint": "目前未執行 — 傳送訊息或 /goal resume 以繼續" + "GoalStatusIdleHint": "目前未執行 — 傳送訊息或 /goal resume 以繼續", + "CmdAutoDescription": "以自動審核工作——不必先設目標或工作流程", + "AutoReceiptOn": "已開啟自動審核。/goal 盯住一個目標;/workflow 執行腳本。", + "AutoReceiptPlanNote": "切換到工作或 Operate 之前,計劃模式仍為唯讀。", + "EmptyStateOrchestrationLabel": "繼續推進", + "OnboardTipsLine5": "較長的工作請選 /auto(審核)、/goal(單一目標)或 /workflow(腳本)。" } diff --git a/crates/tui/src/commands/contract.rs b/crates/tui/src/commands/contract.rs index 7c043997a..7d7899f55 100644 --- a/crates/tui/src/commands/contract.rs +++ b/crates/tui/src/commands/contract.rs @@ -145,6 +145,7 @@ pub(crate) fn key_to_message_id(key: &'static str) -> Option { "cmd_agent_description" => MessageId::CmdAgentDescription, "cmd_anchor_description" => MessageId::CmdAnchorDescription, "cmd_attach_description" => MessageId::CmdAttachDescription, + "cmd_auto_description" => MessageId::CmdAutoDescription, "cmd_auth_description" => MessageId::CmdAuthDescription, "cmd_automation_description" => MessageId::CmdAutomationDescription, "cmd_balance_description" => MessageId::CmdBalanceDescription, diff --git a/crates/tui/src/commands/groups/core/mod.rs b/crates/tui/src/commands/groups/core/mod.rs index 584ac7e09..0fc58c26c 100644 --- a/crates/tui/src/commands/groups/core/mod.rs +++ b/crates/tui/src/commands/groups/core/mod.rs @@ -117,6 +117,10 @@ impl CommandGroup for CoreCommands { workflow::WorkflowCmd::info(), workflow::WorkflowCmd::execute, )), + Box::new(FunctionCommand::new( + workflow::AutoCmd::info(), + workflow::AutoCmd::execute, + )), Box::new(FunctionCommand::new( hotbar::HotbarCmd::info(), hotbar::HotbarCmd::execute, diff --git a/crates/tui/src/commands/groups/core/workflow.rs b/crates/tui/src/commands/groups/core/workflow.rs index ab6280661..2d439bf8f 100644 --- a/crates/tui/src/commands/groups/core/workflow.rs +++ b/crates/tui/src/commands/groups/core/workflow.rs @@ -10,7 +10,8 @@ use crate::commands::traits::{CommandInfo, RegisterCommand}; use crate::localization::MessageId; -use crate::tui::app::{App, AppAction}; +use crate::tui::app::{App, AppAction, AppMode}; +use crate::tui::approval::ApprovalMode; use super::CommandResult; @@ -223,6 +224,43 @@ fn workflow_cancel(app: &App, run_id: &str) -> CommandResult { } } +/// `/auto` is the third orchestration choice: work with Auto-Review. +/// Host-only alias for the existing permission posture — no new runtime (#5439). +pub(in crate::commands) const AUTO_COMMAND_INFO: CommandInfo = CommandInfo { + name: "auto", + aliases: &[], + usage: "/auto", + description_id: MessageId::CmdAutoDescription, +}; + +pub(in crate::commands) struct AutoCmd; + +impl RegisterCommand for AutoCmd { + fn info() -> &'static CommandInfo { + &AUTO_COMMAND_INFO + } + + fn execute(app: &mut App, arg: Option<&str>) -> CommandResult { + auto(app, arg) + } +} + +pub fn auto(app: &mut App, arg: Option<&str>) -> CommandResult { + if arg.map(str::trim).is_some_and(|value| !value.is_empty()) { + return CommandResult::error("Usage: /auto"); + } + if let Err(reason) = app.apply_auto_review_posture() { + return CommandResult::error(reason); + } + + let mut message = app.tr(MessageId::AutoReceiptOn).into_owned(); + if app.mode == AppMode::Plan { + message.push(' '); + message.push_str(app.tr(MessageId::AutoReceiptPlanNote).as_ref()); + } + CommandResult::message(message) +} + #[cfg(test)] mod tests { use super::*; @@ -237,6 +275,30 @@ mod tests { App::new(options, &crate::config::Config::default()) } + #[test] + fn auto_sets_auto_review_and_explains_the_trio() { + let mut app = test_app(); + app.ui_locale = crate::localization::Locale::En; + app.set_agent_approval_posture(ApprovalMode::Suggest); + + let result = auto(&mut app, None); + assert!(!result.is_error, "{:?}", result.message); + assert_eq!(app.approval_mode, ApprovalMode::Auto); + let text = result.message.as_deref().unwrap(); + assert!(text.contains("Auto-Review")); + assert!(text.contains("/goal")); + assert!(text.contains("/workflow")); + assert!(result.action.is_none()); + } + + #[test] + fn auto_rejects_arguments() { + let mut app = test_app(); + let result = auto(&mut app, Some("now")); + assert!(result.is_error); + assert!(result.message.as_deref().unwrap().contains("Usage: /auto")); + } + #[test] fn bare_workflow_is_context_dependent_opt_in() { let mut app = test_app(); diff --git a/crates/tui/src/commands/mod.rs b/crates/tui/src/commands/mod.rs index 7f9fb3a82..1f0ab8096 100644 --- a/crates/tui/src/commands/mod.rs +++ b/crates/tui/src/commands/mod.rs @@ -952,7 +952,7 @@ mod tests { // Consistency: group-iterated command count must match registry. // FEAT-015 registers one test-only contextual command (`/feat015ctx`) // under `#[cfg(test)]` to prove the dual-path seam (D6); the nine - // production groups remain exactly 95 commands. + // production groups remain exactly 96 commands. let test_only_count = command_infos() .iter() .filter(|info| info.name == "feat015ctx") @@ -1081,7 +1081,15 @@ mod tests { #[test] fn flagship_orchestration_and_workspace_commands_are_visible_at_the_palette_root() { - for name in ["goal", "hooks", "tokens", "translate", "workspace"] { + for name in [ + "auto", + "goal", + "hooks", + "tokens", + "translate", + "workflow", + "workspace", + ] { let info = registry() .get_info(name) .unwrap_or_else(|| panic!("/{name} must be registered")); @@ -1094,6 +1102,10 @@ mod tests { "/{name} must not stay on the Advanced discovery list" ); } + assert_eq!( + traits::ORCHESTRATION_DISCOVERY_COMMANDS, + ["workflow", "goal", "auto"] + ); } #[test] diff --git a/crates/tui/src/commands/traits.rs b/crates/tui/src/commands/traits.rs index 6276f221f..2f58b6f14 100644 --- a/crates/tui/src/commands/traits.rs +++ b/crates/tui/src/commands/traits.rs @@ -56,6 +56,27 @@ pub(crate) const ADVANCED_DISCOVERY_COMMANDS: &[&str] = &[ pub(crate) const COMPATIBILITY_DISCOVERY_COMMANDS: &[&str] = &["subagents"]; +/// Flagship orchestration trio. Empty `/` pins these first so `/workflow`, +/// `/goal`, and `/auto` are the first selections from a blank prompt (#5439). +/// Order is the product "when to use" sequence, not alphabetical. +pub(crate) const ORCHESTRATION_DISCOVERY_COMMANDS: &[&str] = &["workflow", "goal", "auto"]; + +#[must_use] +pub(crate) fn orchestration_slash_hint() -> String { + ORCHESTRATION_DISCOVERY_COMMANDS + .iter() + .map(|name| format!("/{name}")) + .collect::>() + .join(" ") +} + +#[must_use] +pub(crate) fn orchestration_discovery_rank(name: &str) -> Option { + ORCHESTRATION_DISCOVERY_COMMANDS + .iter() + .position(|entry| *entry == name) +} + /// Built-in commands that the palette pastes into the composer instead of /// executing, even though they have no *required* argument. /// diff --git a/crates/tui/src/localization.rs b/crates/tui/src/localization.rs index f2bb84acb..a355192d2 100644 --- a/crates/tui/src/localization.rs +++ b/crates/tui/src/localization.rs @@ -537,6 +537,9 @@ pub enum MessageId { CmdFleetDescription, CmdLaneDescription, CmdWorkflowDescription, + CmdAutoDescription, + AutoReceiptOn, + AutoReceiptPlanNote, CmdHotbarDescription, CmdSetupDescription, CmdSubagentsDescription, @@ -781,6 +784,7 @@ pub enum MessageId { OnboardTipsLine2, OnboardTipsLine3, OnboardTipsLine4, + OnboardTipsLine5, OnboardTipsDoctorPrefix, OnboardTipsDoctorSuffix, OnboardTipsFooterEnter, @@ -1305,6 +1309,7 @@ pub enum MessageId { EmptyStateFleetSetupLabel, EmptyStateHelpConnector, EmptyStateHelpHint, + EmptyStateOrchestrationLabel, // Session picker surface. SessionsSurfaceTitle, SessionsPaneTitle, @@ -2116,6 +2121,9 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[ MessageId::CmdFleetDescription, MessageId::CmdLaneDescription, MessageId::CmdWorkflowDescription, + MessageId::CmdAutoDescription, + MessageId::AutoReceiptOn, + MessageId::AutoReceiptPlanNote, MessageId::CmdHotbarDescription, MessageId::CmdSetupDescription, MessageId::CmdSubagentsDescription, @@ -2358,6 +2366,7 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[ MessageId::OnboardTipsLine2, MessageId::OnboardTipsLine3, MessageId::OnboardTipsLine4, + MessageId::OnboardTipsLine5, MessageId::OnboardTipsDoctorPrefix, MessageId::OnboardTipsDoctorSuffix, MessageId::OnboardTipsFooterEnter, @@ -2840,6 +2849,7 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[ MessageId::EmptyStateFleetSetupLabel, MessageId::EmptyStateHelpConnector, MessageId::EmptyStateHelpHint, + MessageId::EmptyStateOrchestrationLabel, MessageId::SessionsSurfaceTitle, MessageId::SessionsPaneTitle, MessageId::SessionsHistoryPaneTitle, diff --git a/crates/tui/src/tui/app.rs b/crates/tui/src/tui/app.rs index fd9f768a3..5e595f227 100644 --- a/crates/tui/src/tui/app.rs +++ b/crates/tui/src/tui/app.rs @@ -3054,6 +3054,24 @@ impl App { ); } + /// Host path for `/auto`: persist Auto-Review as the TUI permission + /// posture without inventing a second runtime. Same write as Shift+Tab + /// landing on Auto-Review; Plan stays read-only and only the Act baseline + /// moves. + pub fn apply_auto_review_posture(&mut self) -> Result<(), String> { + if self.reject_setting_change_while_busy(MessageId::SettingSubjectPermissions) { + return Err(self.setting_locked_message(MessageId::SettingSubjectPermissions)); + } + if self.approval_policy_locked() { + return Err("Permissions are controlled by config or managed requirements".to_string()); + } + Self::persist_permission_posture(ApprovalMode::Auto) + .map_err(|err| format!("could not save TUI posture ({err})"))?; + self.set_agent_approval_posture(ApprovalMode::Auto); + self.needs_redraw = true; + Ok(()) + } + /// Update the durable Act approval choice. Entering Full Access enables /// trust mode; leaving it removes that implicit elevation while preserving /// an independently enabled trust baseline in other posture transitions. diff --git a/crates/tui/src/tui/hotbar/actions.rs b/crates/tui/src/tui/hotbar/actions.rs index 47b157929..9c64b6bdb 100644 --- a/crates/tui/src/tui/hotbar/actions.rs +++ b/crates/tui/src/tui/hotbar/actions.rs @@ -1089,10 +1089,14 @@ struct SlashHotbarAction { impl SlashHotbarAction { fn new(info: &'static CommandInfo) -> Self { + let short_label = match info.name { + "workflow" => "wf".to_string(), + other => other.chars().take(7).collect(), + }; Self { info, id: format!("slash.{}", info.name), - short_label: info.name.chars().take(7).collect(), + short_label, } } @@ -1115,11 +1119,18 @@ impl HotbarAction for SlashHotbarAction { } fn metadata(&self, locale: Locale) -> HotbarActionMetadata { - let recommendation = match self.info.discovery() { - crate::commands::traits::CommandDiscovery::Primary => HotbarRecommendation::Eligible, - crate::commands::traits::CommandDiscovery::Advanced - | crate::commands::traits::CommandDiscovery::Compatibility => { - HotbarRecommendation::Advanced + let recommendation = if codewhale_config::DEFAULT_HOTBAR_ACTIONS.contains(&self.id.as_str()) + { + HotbarRecommendation::Default + } else { + match self.info.discovery() { + crate::commands::traits::CommandDiscovery::Primary => { + HotbarRecommendation::Eligible + } + crate::commands::traits::CommandDiscovery::Advanced + | crate::commands::traits::CommandDiscovery::Compatibility => { + HotbarRecommendation::Advanced + } } }; HotbarActionMetadata { @@ -1812,8 +1823,12 @@ mod tests { .get(id) .unwrap_or_else(|| panic!("missing default hotbar action {id}")); let metadata = action.metadata(Locale::En); - assert_eq!(metadata.category, HotbarActionCategory::App); - assert_eq!(metadata.args, HotbarArgsBehavior::None); + if id.starts_with("slash.") { + assert_eq!(metadata.category, HotbarActionCategory::Slash); + } else { + assert_eq!(metadata.category, HotbarActionCategory::App); + assert_eq!(metadata.args, HotbarArgsBehavior::None); + } assert_eq!(metadata.recommendation, HotbarRecommendation::Default); assert!( metadata.recommendation.is_recommendable(), @@ -1943,7 +1958,16 @@ mod tests { .iter() .filter(|entry| entry.metadata.category == HotbarActionCategory::Slash) .collect::>(); - assert_eq!(slash_recommendations.len(), 1); + let default_slash = slash_recommendations + .iter() + .filter(|entry| entry.metadata.recommendation == HotbarRecommendation::Default) + .count(); + let eligible_slash = slash_recommendations + .iter() + .filter(|entry| entry.metadata.recommendation == HotbarRecommendation::Eligible) + .count(); + assert_eq!(default_slash, 3); + assert_eq!(eligible_slash, 1); } #[test] @@ -1965,14 +1989,14 @@ mod tests { .map(|binding| (binding.slot, binding.label.as_deref())) .collect::>(), vec![ - (1, Some("voice")), - (2, Some("compact")), - (3, Some("plan")), - (4, Some("agent")), - (5, Some("operate")), - (6, Some("palette")), - (7, Some("side")), - (8, Some("trust")), + (1, Some("wf")), + (2, Some("goal")), + (3, Some("auto")), + (4, Some("plan")), + (5, Some("agent")), + (6, Some("operate")), + (7, Some("palette")), + (8, Some("side")), ] ); diff --git a/crates/tui/src/tui/onboarding/mod.rs b/crates/tui/src/tui/onboarding/mod.rs index e99237e7e..cd58fd160 100644 --- a/crates/tui/src/tui/onboarding/mod.rs +++ b/crates/tui/src/tui/onboarding/mod.rs @@ -167,6 +167,7 @@ pub fn tips_lines(app: &App) -> Vec> { Line::from(Span::raw(app.tr(MessageId::OnboardTipsLine2).to_string())), Line::from(Span::raw(app.tr(MessageId::OnboardTipsLine3).to_string())), Line::from(Span::raw(app.tr(MessageId::OnboardTipsLine4).to_string())), + Line::from(Span::raw(app.tr(MessageId::OnboardTipsLine5).to_string())), Line::from(vec![ Span::raw(app.tr(MessageId::OnboardTipsDoctorPrefix).to_string()), Span::styled( @@ -428,6 +429,9 @@ mod tests { assert!(body.contains("/constitution")); assert!(body.contains("/provider")); assert!(body.contains("/model")); + assert!(body.contains("/auto")); + assert!(body.contains("/goal")); + assert!(body.contains("/workflow")); assert!(body.contains("codewhale doctor")); assert!(body.contains("open setup if it needs attention")); assert!(!body.contains("open the workspace")); diff --git a/crates/tui/src/tui/shell_key_routing.rs b/crates/tui/src/tui/shell_key_routing.rs index 58c9c0b52..6ac0db474 100644 --- a/crates/tui/src/tui/shell_key_routing.rs +++ b/crates/tui/src/tui/shell_key_routing.rs @@ -141,13 +141,14 @@ fn footer_action_hints_for_platform_and_ascii( is_macos, ascii_safe, ); + let orch = crate::commands::traits::orchestration_slash_hint(); if include_context { format!( - "{details}:{{output}} · {}:{{context}} · {help}:{{keys}}", + "{details}:{{output}} · {}:{{context}} · {help}:{{keys}} · {orch}", binding(ShellBindingId::ContextInspector).footer_chord ) } else { - format!("{details}:{{output}} · {help}:{{keys}}") + format!("{details}:{{output}} · {help}:{{keys}} · {orch}") } } @@ -261,6 +262,10 @@ mod tests { if is_macos { assert!(hints.contains("fn+F1:"), "{hints}"); } + assert!( + hints.contains("/workflow /goal /auto"), + "idle footer must advertise the orchestration trio: {hints}" + ); if include_context { assert!(hints.contains("/context:"), "{hints}"); } diff --git a/crates/tui/src/tui/underwater.rs b/crates/tui/src/tui/underwater.rs index a4a828868..98f14491f 100644 --- a/crates/tui/src/tui/underwater.rs +++ b/crates/tui/src/tui/underwater.rs @@ -1358,8 +1358,8 @@ pub(crate) const AMBIENT_MIN_CHAT_HEIGHT: u16 = 16; /// Companion column floor, same reasoning as [`AMBIENT_MIN_CHAT_HEIGHT`]. pub(crate) const AMBIENT_MIN_CHAT_WIDTH: u16 = 60; -/// Build the post-launch idle composition. It is deliberately not a command -/// dashboard: one brand mark, one context line, and one quiet Fleet setup path. +/// Build the post-launch idle composition: brand, workspace context, Fleet, +/// help, and the orchestration trio (`/workflow /goal /auto`). /// /// Expressed in terms of the ambient floor constants so the layout rule that /// reserves the rows and the gate that spends them cannot disagree. (The old @@ -1642,6 +1642,26 @@ pub fn empty_state_lines(app: &App, area: Rect) -> Vec> { ), ])); } + if area.height >= 8 { + let orch_label = tr(app.ui_locale, MessageId::EmptyStateOrchestrationLabel); + let orch_commands = crate::commands::traits::orchestration_slash_hint(); + let orch = format!("{orch_label} {orch_commands}"); + let inset = " ".repeat(width.saturating_sub(orch.width()) / 2); + lines.push(Line::from(vec![ + Span::raw(inset), + Span::styled( + orch_label.into_owned(), + Style::default().fg(app.ui_theme.text_soft), + ), + Span::raw(" "), + Span::styled( + orch_commands, + Style::default() + .fg(app.ui_theme.accent_primary) + .add_modifier(Modifier::BOLD), + ), + ])); + } } lines } diff --git a/crates/tui/src/tui/widgets/mod.rs b/crates/tui/src/tui/widgets/mod.rs index 29743a7e5..b05b22b3a 100644 --- a/crates/tui/src/tui/widgets/mod.rs +++ b/crates/tui/src/tui/widgets/mod.rs @@ -3773,7 +3773,25 @@ pub(crate) fn slash_completion_hints_with_model_candidates( } 2 }; - entries.sort_by(|a, b| rank(a).cmp(&rank(b)).then_with(|| a.name.cmp(&b.name))); + // Bare `/` pins the orchestration trio first so the shipped surfaces + // are the first selections, not buried alphabetically (#5439). Typed prefixes + // keep the existing rank/alpha order. + let orch_rank = |entry: &SlashMenuEntry| -> u8 { + if !prefix_lower.is_empty() { + return 1; + } + let command_key = entry.name.trim_start_matches('/'); + match commands::traits::orchestration_discovery_rank(command_key) { + Some(idx) => u8::try_from(idx).unwrap_or(0), + None => 3, + } + }; + entries.sort_by(|a, b| { + orch_rank(a) + .cmp(&orch_rank(b)) + .then_with(|| rank(a).cmp(&rank(b))) + .then_with(|| a.name.cmp(&b.name)) + }); entries.dedup_by(|a, b| a.name == b.name); entries.into_iter().take(limit).collect() } @@ -5051,6 +5069,32 @@ mod tests { assert!(hints.iter().any(|hint| hint.name == "/links")); } + #[test] + fn empty_slash_menu_pins_the_orchestration_trio_first() { + let hints = slash_completion_hints("/", 128, &[], Locale::En, None, ApiProvider::Deepseek); + let names: Vec<&str> = hints.iter().map(|hint| hint.name.as_str()).collect(); + assert_eq!( + &names[..3], + ["/workflow", "/goal", "/auto"], + "bare / must pin the orchestration trio (#5439): {names:?}" + ); + let workflow = hints + .iter() + .find(|hint| hint.name == "/workflow") + .expect("/workflow"); + let goal = hints + .iter() + .find(|hint| hint.name == "/goal") + .expect("/goal"); + let auto = hints + .iter() + .find(|hint| hint.name == "/auto") + .expect("/auto"); + assert!(workflow.description.contains("repeatable workflow")); + assert!(goal.description.contains("objective")); + assert!(auto.description.contains("Auto-Review")); + } + #[test] fn slash_completion_hints_rank_exact_alias_above_prefix_alias() { // `/q` should rank `/exit` (exact alias `q`) above `/clear` (alias @@ -6445,6 +6489,7 @@ mod tests { "the idle action must not imply that built-in Fleet roles still require setup" ); assert!(rendered.contains("/help or Ctrl+K")); + assert!(rendered.contains("Keep going /workflow /goal /auto")); assert!(!rendered.contains("Model /model")); assert!(!rendered.contains("Rules /constitution")); } @@ -6590,6 +6635,7 @@ mod tests { .collect::(); assert!(rendered.contains("Fleet ready /fleet setup")); + assert!(rendered.contains("/workflow /goal /auto")); assert!(!rendered.contains("▗▄▄")); } diff --git a/docs/KEYBINDINGS.md b/docs/KEYBINDINGS.md index 869c98cb5..f0916d391 100644 --- a/docs/KEYBINDINGS.md +++ b/docs/KEYBINDINGS.md @@ -104,14 +104,14 @@ Since #3807 a missing `hotbar` key renders **no bar** — fresh configs show no | Slot | Chord | Default action | Label | |------|---------|--------------------|-----------| -| 1 | `Alt-1` | `voice.toggle` | `voice` | -| 2 | `Alt-2` | `session.compact` | `compact` | -| 3 | `Alt-3` | `mode.plan` | `plan` | -| 4 | `Alt-4` | `mode.agent` | `agent` | -| 5 | `Alt-5` | `mode.operate` | `operate` | -| 6 | `Alt-6` | `palette.open` | `palette` | -| 7 | `Alt-7` | `sidebar.toggle` | `side` | -| 8 | `Alt-8` | `trust.toggle` | `trust` | +| 1 | `Alt-1` | `slash.workflow` | `wf` | +| 2 | `Alt-2` | `slash.goal` | `goal` | +| 3 | `Alt-3` | `slash.auto` | `auto` | +| 4 | `Alt-4` | `mode.plan` | `plan` | +| 5 | `Alt-5` | `mode.agent` | `agent` | +| 6 | `Alt-6` | `mode.operate` | `operate` | +| 7 | `Alt-7` | `palette.open` | `palette` | +| 8 | `Alt-8` | `sidebar.toggle` | `side` | | Focus state | Hotbar behavior | |-------------|-----------------| diff --git a/docs/MODES.md b/docs/MODES.md index 06ea631f9..5946d1cfa 100644 --- a/docs/MODES.md +++ b/docs/MODES.md @@ -85,6 +85,14 @@ The fast `deepseek-v4-flash` / thinking-off path is called Fin in the product language. Fin is a seam for routing, summaries, cheap child calls, and coordination work; it does not change approval behavior. +The orchestration trio is the first selection from a blank prompt (press `/`, +then Enter): +`/auto` turns on Auto-Review so the agent just works, `/goal` keeps one +objective across turns, and `/workflow` runs a repeatable ordered or fan-out +workflow. They also +sit on the idle welcome, the idle footer, and the first three Hotbar slots +when the bar is enabled. + `/goal ` sets a session objective with an optional token budget and keeps active objectives visible as Work context. The agent may also create the goal itself when a direct request describes a verifiable end state that will