Skip to content

fix(chatqna): withhold digit/bracket partial sentinels in stream (real prod fix)

Jérôme Revillard requested to merge worktree-fix-sentinel-stream-leak2 into main

!177 (merged) was incomplete — prod still leaks

After !177 (merged), el-salvador (deployed image 8f646aac, fix confirmed present) still leaked [[CONF:100]] to users and self_confidence was never captured (confidence fell back to retrieval).

Root cause (confirmed on deployed code)

!177 (merged) only withheld the FULL [[CONF: literal prefix. But the sentinel is a variable pattern [[CONF:<digits>]]. Tested directly on the deployed container:

_streaming_marker_tail_len("x[[CONF:")    = 7   # !177 fix works (full literal)
_streaming_marker_tail_len("x[[CONF:100") = 0   # NOT withheld -> leaks

When the tokenizer splits at a digit boundary ([[CONF:100 + ]]) or a single closing bracket ([[CONF:80] + ]), that partial is not a prefix of the literal [[CONF:, so the fixed-marker tail check misses it → leaks + value lost.

The marker-tail mechanism withholds prefixes of a FIXED literal; it cannot cover a variable sentinel's digit/bracket partials.

Fix

Withhold any trailing in-progress sentinel via _SELF_CONF_PARTIAL_RE, broadened to allow ] (disallow [): \s*\[\[CONF:[^\[]*$. Applied in the streaming loop (not only the flush), combined with the marker-tail via max().

Proof (parametrized regression)

test_streaming_sentinel_never_leaks_any_chunk_boundary covers ALL chunk boundaries: complete, mid-prefix, full-prefix, after-digit, after-all-digits, after-one-bracket. Verified: 3 of 6 FAIL on !177 (merged) code (the digit/bracket cases leak, exact prod symptom [[CONF:80]), all 6 PASS with this fix.

chatqna suite green (138), ruff clean.

Merge request reports

Loading