From 2364e1ee7d900cacf8b5ab21914939758a824a36 Mon Sep 17 00:00:00 2001 From: ducoterra Date: Fri, 21 Aug 2026 18:18:47 -0400 Subject: [PATCH] feat(ui): onboarding suggestion chips with one-tap submit, keyboard access, and mobile scroll row --- .../04_story_honest_deflection.md | 0 .env.example | 1 + frontend/assets/app.js | 93 +++---- tests/e2e/test_honest_deflection.py | 15 +- tests/e2e/test_suggestion_chips.py | 232 ++++++++++++++++++ tests/integration/test_api.py | 31 ++- tests/unit/test_config.py | 29 +++ 7 files changed, 350 insertions(+), 51 deletions(-) rename .agent/phases/{todo => complete}/04_story_honest_deflection.md (100%) create mode 100644 tests/e2e/test_suggestion_chips.py diff --git a/.agent/phases/todo/04_story_honest_deflection.md b/.agent/phases/complete/04_story_honest_deflection.md similarity index 100% rename from .agent/phases/todo/04_story_honest_deflection.md rename to .agent/phases/complete/04_story_honest_deflection.md diff --git a/.env.example b/.env.example index d36065a..ff855c0 100644 --- a/.env.example +++ b/.env.example @@ -25,6 +25,7 @@ BOR_MAX_CONTEXT_CHARS=24000 # cap on total document text sent to the LLM BOR_CHUNK_TARGET_CHARS=2000 BOR_CHUNK_OVERLAP_CHARS=200 BOR_EMBED_BATCH_SIZE=16 +# BOR_SUGGESTIONS=["How is my Kubernetes cluster set up?"] # JSON list of onboarding chips # --- Debugging (0/1 — 1 enables attach-on-demand debugpy on port 5678) --- DEBUGPY=0 diff --git a/frontend/assets/app.js b/frontend/assets/app.js index 0a783d5..20695bf 100644 --- a/frontend/assets/app.js +++ b/frontend/assets/app.js @@ -1,13 +1,14 @@ /* Brain of Reese — chat shell. * - * Renders suggestions, shows KB health, and runs chat turns against - * POST /api/chat (SSE, PLAN §4): deltas render live into the Brain bubble, - * the done event appends source chips (and "Maybe try" chips when the - * turn was deflected — honesty gate, phase 04), errors surface as a red - * banner. The full feedback state machine lands with the loading-feedback - * story; this keeps the "never stale" contract: the button is busy for the - * whole turn and is always re-enabled at the end. - * All DOM ids match frontend/index.html. + * Renders suggestions (onboarding chips + "Maybe try" deflection chips — + * one shared .suggestion-chip component, renderChips below), shows KB + * health, and runs chat turns against POST /api/chat (SSE, PLAN §4): + * deltas render live into the Brain bubble, the done event appends source + * chips (and "Maybe try" chips when the turn was deflected — honesty gate, + * phase 04), errors surface as a red banner. The full feedback state + * machine lands with the loading-feedback story; this keeps the "never + * stale" contract: the button is busy for the whole turn and is always + * re-enabled at the end. All DOM ids match frontend/index.html. */ const messagesEl = document.querySelector("#messages"); @@ -99,27 +100,51 @@ function removeTyping() { document.querySelector("#typing-indicator")?.remove(); } -/* ---------- suggestions ---------- */ +/* ---------- suggestions (shared chip component, phase 05) ---------- + * + * One component, two homes: the onboarding row in the empty state and the + * "Maybe try" row under a deflected answer. The container must be + * role="list" with an accessible name ("Suggested questions" / "Maybe + * try"); each chip is a real