Bind Dream QA tip to user answer

#19
docs/smoke/2026-06-09-user-tone-polish-smoke.md CHANGED
@@ -72,8 +72,65 @@ has_zh_title=True
72
 
73
  ## Hugging Face Space Sync
74
 
75
- Pending.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  ## Public User-View Review
78
 
79
- Pending.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  ## Hugging Face Space Sync
74
 
75
+ Initial HF PR:
76
+
77
+ ```text
78
+ discussion=18
79
+ title=Polish Dream QA user tone
80
+ refs/pr/18=64306abd58defe5ed57402a1f8ef93a92b88d00f
81
+ status=merged
82
+ space/main=79a74147ba4b179c8376823668f0f6aeb531fb36
83
+ ```
84
+
85
+ Public config after PR #18:
86
+
87
+ ```text
88
+ title=Dream QA
89
+ version=4.44.1
90
+ mode=blocks
91
+ component_count=72
92
+ ```
93
 
94
  ## Public User-View Review
95
 
96
+ Initial public review after PR #18:
97
+
98
+ ```text
99
+ first_screen_has_advanced=True
100
+ first_screen_has_runtime_settings=False
101
+ first_screen_has_model_routes=False
102
+ question=When you think about the floor 14 and the elevator, is there one real thing today that you want to make easier to start?
103
+ question_has_chinese_leakage=False
104
+ ```
105
+
106
+ The final card improved the Tiny action, but the primary Today Tip still drifted toward generic elevator grounding instead of the user's overdue-email answer. Follow-up fix: answer-aware Today Tip polish now binds email/message answers to the primary suggestion as well as the Tiny action.
107
+
108
+ Follow-up local action smoke:
109
+
110
+ ```text
111
+ status=tip
112
+ has_overdue_email=True
113
+ has_first_sentence=True
114
+ has_immediately=False
115
+ has_chinese_leakage=False
116
+ ```
117
+
118
+ Follow-up commands:
119
+
120
+ ```text
121
+ .venv/bin/python -m pytest tests/test_ui_actions.py tests/test_today_tip_quality_eval.py -q
122
+ .venv/bin/python scripts/evaluate_today_tip_quality.py
123
+ .venv/bin/python -m pytest -q
124
+ git diff --check
125
+ ```
126
+
127
+ Observed:
128
+
129
+ ```text
130
+ 11 passed, 2 warnings
131
+ {"case_count": 11, "failures": {}, "passes": true}
132
+ 95 passed, 2 warnings
133
+ git diff --check clean
134
+ ```
135
+
136
+ Final HF follow-up: Pending.
dream_customs/pipeline.py CHANGED
@@ -298,6 +298,20 @@ def _answer_based_tiny_action(answers: str, language: str = "en") -> str:
298
  return ""
299
 
300
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  def _anchor_in_text(text: str, anchors: List[str]) -> bool:
302
  clean = (text or "").lower()
303
  for anchor in anchors:
@@ -583,7 +597,13 @@ def _polish_today_tip(card: TodayTipCard, intake: DreamIntake, answers: str = ""
583
  if not polished.interpretation.strip() or not _anchor_in_text(polished.interpretation, anchors):
584
  polished.interpretation = _fallback_interpretation(intake, language)
585
  generic_tip_markers = ["drink water", "hydrate", "多休息", "保持积极", "take a walk"]
 
586
  if (
 
 
 
 
 
587
  not polished.today_tip.strip()
588
  or any(marker in polished.today_tip.lower() for marker in generic_tip_markers)
589
  or not _anchor_in_text(polished.today_tip, anchors)
 
298
  return ""
299
 
300
 
301
+ def _answer_based_today_tip(answers: str, anchor: str, language: str = "en") -> str:
302
+ lowered = (answers or "").lower()
303
+ if _is_zh(language):
304
+ if "邮件" in lowered or "email" in lowered:
305
+ return f"今天把「{anchor}」当成允许慢慢开始的按钮:只打开那封邮件,先写第一句话。"
306
+ return ""
307
+ if "email" in lowered or "message" in lowered:
308
+ return (
309
+ f"For today, treat the {anchor} as permission to start gently: "
310
+ "open the overdue email and write only the first sentence."
311
+ )
312
+ return ""
313
+
314
+
315
  def _anchor_in_text(text: str, anchors: List[str]) -> bool:
316
  clean = (text or "").lower()
317
  for anchor in anchors:
 
597
  if not polished.interpretation.strip() or not _anchor_in_text(polished.interpretation, anchors):
598
  polished.interpretation = _fallback_interpretation(intake, language)
599
  generic_tip_markers = ["drink water", "hydrate", "多休息", "保持积极", "take a walk"]
600
+ answer_tip = _answer_based_today_tip(answers, anchors[0], language)
601
  if (
602
+ answer_tip
603
+ and ("email" in (answers or "").lower() or "邮件" in (answers or "").lower())
604
+ ):
605
+ polished.today_tip = answer_tip
606
+ elif (
607
  not polished.today_tip.strip()
608
  or any(marker in polished.today_tip.lower() for marker in generic_tip_markers)
609
  or not _anchor_in_text(polished.today_tip, anchors)
tests/test_ui_actions.py CHANGED
@@ -157,3 +157,6 @@ def test_english_today_tip_has_no_chinese_anchor_leakage():
157
 
158
  for leaked in ["数字", "电梯", "按钮", "楼层", "融化"]:
159
  assert leaked not in combined
 
 
 
 
157
 
158
  for leaked in ["数字", "电梯", "按钮", "楼层", "融化"]:
159
  assert leaked not in combined
160
+ assert "overdue email" in combined.lower()
161
+ assert "first sentence" in combined.lower()
162
+ assert "immediately" not in combined.lower()