fix: tolerate typo'd render-tag names in echo strip; warn on degenerate end_turn turns - #674
Merged
Merged
Conversation
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-674Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr674.tgz
npm install -g packageThis comment is automatically updated on each push. |
…te end_turn turns Follow-up to #644/#646: a model-emitted render-tag echo with a typo'd tag name (acpi/acip/apic-style variants of acp) bypassed every exact-spelling pattern in the tag-echo filter and passed through as the turn's entire visible text - a 43-char degenerate end_turn turn with zero tool calls that stalls the agent mid-orchestration until manually nudged (#673). - tag-echo-filter: all patterns now match acplike names (permutations of acp plus one inserted a/c/p/i char), still requiring a name boundary so legit text (acpi/acpi.h includes, caption, app, ACPI_DEVICE) is untouched; swallow-until-close scans loose close variants; add lifetime stats() for turn-level accounting - adapters (anthropic/openai/responses): warn [degenerate-turn] when a terminal turn ends with zero visible text and zero tool calls (thinking may be non-empty); responses RENDER_TAG_RE loosened to match - plugin passthrough pipes (openai chat / anthropic / responses): same degenerate-turn warn with per-field visible-text accounting (thinking and reasoning fields never count as visible) - tests: split-parity typo cases, gate engagement, safe-word survival, stats accounting, warning matrix, adapter e2e, pipe-level warn/no-warn
ranxianglei
force-pushed
the
2026-09-10_acip-tag-echo-tolerance
branch
from
September 10, 2026 10:16
d61fa2c to
da1ab44
Compare
This was referenced Sep 10, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes
#673 — follow-up to #644/#646 (v0.1.97 incident family): a model-emitted render-tag echo whose tag name is typo'd (an
acppermutation plus one stray char, e.g.acpi/acip) bypassed every exact-spelling pattern in the tag-echo filter. The 43-char fragment then became the turn's entire visible text:stop_reason=end_turn, zerotool_use, complete next-step plan sitting in the thinking block — the agent stalls mid-orchestration until manually nudged.What changed
Gap 1 — tolerant name matching (
src/loop/tag-echo-filter.ts)acpplus one inserteda/c/p/ichar (66 members, longest-first), built programmatically so the set stays auditable.acpi/acpi.h,<caption>,<app id="1">, uppercaseACPI_DEVICE, underscore triggers,a < b.stats()(inputChars/outputChars/dropped) so callers can do turn-level accounting across intermediate flushes.src/loop/adapter-responses.tsmodule-levelRENDER_TAG_REloosened to the same name set.Gap 2 — degenerate-turn detection (WARN only)
src/degenerate-turn.ts: pure predicate + message builder. Fires when a terminal turn ends with zero visible text AND zero tool calls (thinking may be non-empty — that is exactly the incident shape).anthropic→end_turn,openai→stop,responses→completed) and both plugin passthrough pipes (chat SSE covers OpenAI + Anthropic wires; Responses pipe). In the pipes, visible-text accounting counts onlycontent/textfields — thinking/reasoning never counts, matching the client-visible definition.[degenerate-turn]) immediately; auto-retry can land behind it as a follow-up.Tests
stats()accounting;degenerateTurnWarningmatrix.Pre-flight
npm run typecheckcleannpm test: 1279/1279 passnpm run buildclean (dist self-contained)