feat(trace): WINDSURFAPI_LEAK_TRACE — structured reasoning/content boundary logs for catching live reasoning leaks (opt-in, default OFF) - #249
Conversation
… boundary logs (default OFF) Gate WINDSURFAPI_LEAK_TRACE=1 enables LEAK_TRACE-prefixed structured log lines at the reasoning/content boundary to catch the live-only reasoning
|
评审:门控和脱敏我逐条驱动过,都成立。请补一条 —— 标记表认不出 我实跑过什么head
「门关时热路径只多一次 env 读 + 布尔比较」这句我特意攻过,它成立。 我原本怀疑的是调用点参数求值 —— 三个埋点的分层选得准:事件层拿原始通道、分类层拿决策、出口层拿 settle 后的尺寸比。要定位「是哪一层把 reasoning 放进 content 的」,这三个位置是最小充分集。 M1(请补)—
|
中文 TL;DR
已知问题(见文末 issue):thinking 模型偶尔把 reasoning 写进 CONTENT 通道;只能在真实会话中偶发复现,受控探针复现不出来,所以下一层修复一直缺现场数据。本 PR 在 reasoning/content 边界加一套结构化日志:devin-connect-openai 事件层、messages 分类层、chat 出口层,记录通道、think-标记状态、有限文本采样、reqId/acct。由 WINDSURFAPI_LEAK_TRACE 门控,默认关闭;关闭时行为逐字不变、热路径零额外开销。本 PR 只做可观测性,不做修复;抓到现场后另开 PR 提修复。
Зачем
Протекание мыслей в контент — известная проблема, воспроизводится только живьём. Каждое поколение защиты строилось по полевой сигнатуре, а не по репродукции: #238 (rescue пустых ответов), #241 (точность rescue), #243 (перекладка ведущего
<think>-блока из content в thinking). Чтобы предложить фикс следующего слоя, нужен пойманный инцидент: какой канал, какие маркеры, какой префикс. Этот PR даёт удочку.Точки лога
src/devin-connect-openai.js— сырые события границы: канал (content/reasoning), наличие think-маркеров, ограниченный сэмпл текста,reqId/acct.src/handlers/messages.js— решения классификации/перекладки блоков.src/handlers/chat.js— что ушло в content на settle/finish, соотношение размеров reasoning и content.Модуль
src/leak-trace.js: гейт, маркеры (включая◁think▷как известный диалект Kimi K2), обрезка сэмплов через существующийlog-safety— в лог не пишутся ключи и полные ответы.Safety
WINDSURFAPI_LEAK_TRACE, default OFF. При выключенном гейте поведение побайтово неизменно, горячий путь не делает лишней работы кроме чтения флажка..env.exampleи README.Test plan
test/leak-trace.test.js: при включённом гейте — лог-строки с ожидаемыми полями на всех трёх точках (подмена логгера по прецедентуtest/retry-rescue-budget-split.test.js); при выключенном гейте на том же горячем пути — ни одной строки.test/mutations/leak-trace.json(6 мутаций, все CAUGHT) + все spec репо: EXIT=0, anchor'ы ровно по разу.