[P0][SAFETY] Agentic crisis screen reads a key nothing writes since ff421d3 — multi-turn escalation detection is inert in the beta brain
#129
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A safety regression we introduced on 2026-08-05 is in the current beta brain. Filing immediately per our own rule that the safety layer is sacred.
What is broken
On the agentic path, the crisis screen's history-amplification half receives an empty string on every real conversation, so it always scores 0. Single-message crisis detection still works; escalation across a multi-message conversation does not.
Root cause — a key rename that missed one reader
ff421d3("history keeps its provenance and its session", 2026-08-05) correctly moved conversation history to a per-session key:chat.el:2559was not moved with it and still reads the old anonymous bucket:The desktop app always mints a session id (
DaemonClient.kt:706), sosession_idis never empty in practice, history is always written undersession_hist_<id>, andstate_get("conv_history")always returns"".The bitter part: the comment directly above that line documents this exact bug being fixed once already under issue #9 — "Old key caused history-amplification in safety_screen to always receive '' on agentic path." The fix was correct then; the rename re-broke it, and the comment now describes a repair that no longer holds.
Scope
soul.el:397usesconv_hist_key).ff421d3is an ancestor of the branch the shipped brain (8ec39278…) was built from — verified withgit merge-base --is-ancestor.What done looks like
chat.el:2559reads throughconv_hist_key(session_id)like every other consumer, plus a test that fails if any safety input is read from a key no producer writes. Suggested general rule — the same defect class produced three other findings in today's audit: any read of a state key that nothing writes should be a build-time error, not a silent empty string.Not exploited, not user-reported — found by a static sweep, verified by reading both sides.