Skip to content

bug: streaming wrapped tag imitation leaks when its close shares the chunk #1067

Closed

Description

@tarnish233

The streaming prose tag filter leaks a wrapped-turn imitation when its malformed opening and loose closing tag arrive in the same chunk. This is a remaining match-precedence case after #872, not a change to tool-call argument filtering.

Reproduction: push a wrapped ACP opening with an unterminated attribute, followed by imitation markup and a loose close, through createTagEchoFilter() in one chunk. Compare its output with stripAcpTags() for the same string: streaming emits the imitation, while batch filtering preserves only the surrounding prose.

Root cause: BROKEN_ATTRS is checked only when no ordinary tag match exists anywhere in the buffer. A later close therefore prevents recognition of the earlier malformed opening.

The existing fix compares match positions and lets the earlier malformed opening own its span. A regression test checks streaming/batch parity. The filter continues to apply only to model prose; actual tool-call arguments remain byte-exact per #1039. A scoped PR will follow.

Activity

  1. tarnish233 commented on Sep 20, 2026

    @tarnish233
    ContributorAuthor

    修复 PR:#1069

  2. ranxianglei commented on Sep 20, 2026

    @ranxianglei
    Owner

    在 master 独立复核,机制属实:

    src/loop/tag-echo-filter.ts 流式 process() 的候选环只收集 PAIRED/LONE_OPEN/LONE_CLOSE 三类命中(按 index 择先);BROKEN_ATTRS 只在 if (!m)(三类全空)分支里查。同 chunk 里 malformed opening(属性列表未终止)+ imitation payload + loose close 的组合:LONE_CLOSE 在缓冲区后部命中 → m 非空 → BROKEN_ATTRS 分支永不执行 → close 被当孤立闭合标签丢弃,前面的畸形开头与 payload 全部按 prose 放行。

    批式 stripAcpTags() 走 wrappedSpan():BROKEN_ATTRS span 与奇引号 LONE_OPEN span 按起始位置比较取先者,畸形开头拥有自己的 span 并吞到 loose close——所以流式/批式行为劈叉,同串不同果。

    修复方向(位置择先)与批式对齐是对的。等 PR。

  3. ranxianglei commented on Sep 20, 2026

    @ranxianglei
    Owner

    🤖 Powered by ework · qwen3.8-27b

    [bot] 🏷 收到。已按你的机制分析开工:流式 process() 候选环把 BROKEN_ATTRS 提进位置竞争(与 PAIRED/LONE_OPEN/LONE_CLOSE 按 index 择先),让更早的畸形开头拥有自己的 span 并进入 swallow-until-close(IMITATION_SWALLOW_CAP、不释放),与批式 wrappedSpan() 的位置择先对齐。回归测试用同串跑 createTagEchoFilter()(整串单 chunk)+ flush,断言输出与 stripAcpTags() 一致。工具参数路径不动(#1039)。PR 稍后贴上来。

  4. added a commit that references this issue on Sep 22, 2026
    6a39fd6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions