From 47e91ee84b304831462df4638bfe034db9f00268 Mon Sep 17 00:00:00 2001 From: Andy <> Date: Tue, 28 Apr 2026 19:03:46 +0900 Subject: [PATCH] fix: handle clarify review edge cases --- static/messages.js | 2 +- static/style.css | 2 +- tests/test_sprint30.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/static/messages.js b/static/messages.js index 7bb3f2d2..ffa65a48 100644 --- a/static/messages.js +++ b/static/messages.js @@ -1010,7 +1010,7 @@ function attachLiveStream(activeSid, streamId, uploaded=[], options={}){ source.close(); delete INFLIGHT[activeSid];clearInflight();clearInflightState(activeSid);stopApprovalPolling();stopClarifyPolling(); if(!_approvalSessionId||_approvalSessionId===activeSid) hideApprovalCard(true); - if(!_clarifySessionId||_clarifySessionId===activeSid) hideClarifyCard(true, 'terminal'); + if(!_clarifySessionId||_clarifySessionId===activeSid) hideClarifyCard(true, 'cancelled'); if(S.session&&S.session.session_id===activeSid){ S.activeStreamId=null; } diff --git a/static/style.css b/static/style.css index ccda1f4a..e2dd9c75 100644 --- a/static/style.css +++ b/static/style.css @@ -473,7 +473,7 @@ .clarify-inner{background:var(--surface);backdrop-filter:blur(8px);border:1px solid var(--accent-bg-strong);border-radius:12px;padding:12px 14px 36px;box-shadow:0 1px 0 rgba(255,255,255,.02) inset;} .clarify-header{display:flex;align-items:center;gap:8px;margin-bottom:10px;font-size:12px;font-weight:700;color:var(--blue);letter-spacing:.01em;} .clarify-countdown{margin-left:auto;min-width:42px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums;font-weight:700;} - .clarify-countdown.urgent{color:var(--error);} + .clarify-countdown.urgent{color:var(--error);box-shadow:inset 0 -2px 0 var(--error);border-radius:2px;} .clarify-question{font-size:14px;color:var(--text);line-height:1.7;white-space:pre-wrap;margin-bottom:12px;} .clarify-choices{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;} .clarify-choice{display:flex;align-items:flex-start;gap:10px;width:100%;padding:11px 14px;border-radius:12px;font-size:13px;font-weight:600;border:1px solid var(--accent-bg-strong);background:var(--accent-bg);color:var(--accent-text);cursor:pointer;transition:all .15s;white-space:normal;text-align:left;box-shadow:0 1px 0 rgba(255,255,255,.03) inset;} diff --git a/tests/test_sprint30.py b/tests/test_sprint30.py index ca84aec0..60d3ec1f 100644 --- a/tests/test_sprint30.py +++ b/tests/test_sprint30.py @@ -518,6 +518,9 @@ class TestClarifyCardTimerLogic: def _get_html(self): return pathlib.Path(__file__).parent.parent / 'static' / 'index.html' + def _get_css(self): + return pathlib.Path(__file__).parent.parent / 'static' / 'style.css' + def test_clarify_min_visible_ms_constant_present(self): src = self._get_js().read_text() assert 'CLARIFY_MIN_VISIBLE_MS' in src @@ -568,6 +571,34 @@ class TestClarifyCardTimerLogic: assert "$('msg')" in src, \ 'clarify timeout should keep the typed draft visible in the composer' + def test_clarify_draft_appends_to_existing_composer_text(self): + src = self._get_js().read_text() + m = re.search(r'function _stashClarifyDraft.*?(?=\nfunction |\nasync function |\Z)', + src, re.DOTALL) + assert m, '_stashClarifyDraft function not found' + body = m.group(0) + assert 'current.replace(/\\s+$/, "")' in body, \ + 'preserved clarify drafts must append after existing composer text instead of replacing it' + assert '\\n\\n${draft}' in body, \ + 'preserved clarify drafts should be separated from existing composer text' + + def test_cancel_stream_does_not_preserve_clarify_draft(self): + src = self._get_js().read_text() + m = re.search(r"source\.addEventListener\('cancel'.*?\n \}\);", + src, re.DOTALL) + assert m, 'cancel event handler not found' + body = m.group(0) + assert "hideClarifyCard(true, 'cancelled')" in body, \ + 'explicit stream cancel must not use the timeout/terminal draft preservation path' + + def test_clarify_urgent_countdown_has_non_color_cue(self): + css = self._get_css().read_text() + m = re.search(r'\.clarify-countdown\.urgent\{([^}]*)\}', css) + assert m, 'urgent clarify countdown style missing' + body = m.group(1) + assert any(prop in body for prop in ('box-shadow', 'outline', 'border', 'text-decoration')), \ + 'urgent countdown styling must include a non-color visual cue' + def test_respond_clarify_calls_hide_with_force(self): src = self._get_js().read_text() import re