1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! Remove narration from the final body that the step group already shows
//! (#1010).
//!
//! Since #943 per-step narration folds into the collapsible step group. The
//! final `response.content` carries the same narration, because it is
//! assistant text like any other, and nothing took it back out. The completion
//! path could not catch it: it compares the final body's HASH against one
//! intermediate's, which fires only when the model repeats a single
//! intermediate verbatim. A body that contains every note plus the answer
//! equals none of them, so nothing was suppressed and the whole turn's
//! commentary shipped ahead of the answer.
//!
//! Telegram does not have this problem because it normalizes whitespace before
//! comparing (`delivery.rs`, `norm`). Slack hashed raw bytes, so any formatting
//! drift missed. This module ports that normalization and extends it to the
//! shape Slack actually produces.
//!
//! ## Why matching cannot be done on paragraphs
//!
//! The narration and the final body are split at STREAM offsets, not at
//! paragraph boundaries, so the same sentence can be cut mid-word between them:
//!
//! ```text
//! group note : "You're right, and it's the s"
//! final body : "You're right, and it's the s\n\nharper version of the point."
//! ```
//!
//! Comparing paragraphs, or whole strings, or hashes, all fail here — no unit
//! on either side is equal to a unit on the other. Comparison therefore runs
//! over the sequence of NON-WHITESPACE characters, where the split is invisible
//! because whitespace is exactly what differs.
//!
//! Still structural: the group holds the exact strings it folded, and only
//! those are consumed, in the order they were folded. Nothing is inferred from
//! whether prose reads like narration, which is the constraint #928 and #1009
//! settled on.
/// Non-whitespace characters of `s`, each with its byte offset in `s`.
/// Drop the narration the step group already displays from the front of
/// `body`.
///
/// Consumes `folded` in order, advancing through `body` for as long as each
/// note matches. Stops at the first note that does not, so a body that
/// diverges partway keeps everything from the divergence onward. Returns
/// `body` unchanged when the first note does not match at all, which is the
/// case where the final is a fresh answer rather than a continuation.
pub
/// The narration strings a group has folded, in fold order, ready for
/// [`strip_folded_notes`].
pub