Skip to content

fix(runtime): preserve unicode while stripping markers - #6917

Merged
houko merged 2 commits into
mainfrom
fix/session-repair-unicode-markers
Aug 12, 2026
Merged

houko merged 2 commits into
mainfrom
fix/session-repair-unicode-markers

Conversation

@houko

@houko houko commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • replace lowercase-copy byte indexing with a case-insensitive regex over the original UTF-8 input
  • compile the combined injection-marker matcher once with LazyLock
  • add an end-to-end regression for a marker after a lowercase-expanding Unicode character

Verification

  • cargo test -p librefang-runtime --lib session_repair::tests (53 passed)
  • cargo clippy -p librefang-runtime --lib -- -D warnings
  • cargo fmt --check
  • git diff --check

Report: confirmed/crates/librefang-runtime/src/session_repair.rs.md

@github-actions github-actions Bot added area/runtime Agent loop, LLM drivers, WASM sandbox size/M 50-249 lines changed labels Aug 10, 2026
Rename the session-repair unicode fragment to include the PR number
per changelog.d/README.md, and add the missing (#6917) reference
next to the author handle.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit a1d91314 ("chore(changelog): name fragment after PR and add PR reference") has its author identity set to Claude <noreply@anthropic.com> (git log --format='%an <%ae>' 13a30adc5..HEAD).
This is exactly the case scripts/hooks/commit-msg is designed to reject even when the commit message text itself is clean, per CLAUDE.md's "No AI / Claude attribution" rule.
Fixing this requires rewriting the commit (amend/rebase) and force-pushing, which is outside the scope of an automated hardening pass — please re-author that commit and force-push before merge.

The actual fix looks correct: the old code lowercased the whole string with to_lowercase() and then reused byte offsets found in that lowercased copy to slice the original string — Unicode case expansion (e.g. Turkish İ U+0130 → i̇, 2 bytes → 3 bytes) desyncs those offsets from the original string's byte layout, risking a non-char-boundary slice panic or corrupted output.
The rewrite builds a single case-insensitive regex::Regex over the escaped marker list and calls replace_all directly on the original string, so there's no separate lowercased copy and no manual byte-offset bookkeeping — match ranges the regex crate returns are always char-boundary-aligned.
test_strip_injection_marker_after_expanding_unicode_lowercase (İ before a marker) exercises exactly the case-expansion class of bug.
Verified locally: cargo test -p librefang-runtime --lib -- session_repair:: (53 passed, including the new test) and cargo clippy -p librefang-runtime --all-targets -- -D warnings (clean).


Generated by Claude Code

@houko houko left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review pass. The unicode/byte-boundary fix and its regression test are correct (regex-based case-insensitive replace on the original string instead of lowercase-copy + reused byte offsets; new test exercises the real strip_tool_result_details end-to-end path). Changelog fragment is present and correctly formatted under changelog.d/fixed/.

One blocking item confirmed independently: the HEAD commit's author identity is Claude <noreply@anthropic.com>, which violates CLAUDE.md's no-AI-attribution rule (enforced server-side by scripts/hooks/commit-msg on author identity, not just message text) and needs to be re-authored and force-pushed by a human before merge — outside the scope of what this pass will do.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed independently at head sha a1d913147f7c8610639713cb458a5a9e9ec2429d: the commit that added/renamed this fragment ("chore(changelog): name fragment after PR and add PR reference") has its author identity set to Claude <noreply@anthropic.com>.
That's exactly the case scripts/hooks/commit-msg rejects even when the message text is clean, per CLAUDE.md's no-AI-attribution rule — the check runs on git var GIT_AUTHOR_IDENT, not just the message body.
This blocks a clean merge on the letter of the policy and needs the commit re-authored and the branch force-pushed, which is outside what this automated pass can do (no force-push allowed here) — flagging for the maintainer to fix before merge.
Separately, the substantive code change looks correct: switching from lowercase-copy + byte-offset reuse to a single case-insensitive regex::Regex over the original string avoids the Unicode case-expansion byte-boundary desync (e.g. Turkish İ), and the new test_strip_injection_marker_after_expanding_unicode_lowercase regression exercises the real end-to-end path (strip_tool_result_details → strip_injection_markers), not just the inner helper.
The changelog fragment itself is correctly placed under changelog.d/fixed/ with the right filename convention and trailing (#6917) (@houko).


Generated by Claude Code

@houko houko left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review pass: code fix looks correct and well-tested (regex-based rewrite correctly resolves the byte-boundary bug from mixing to_lowercase() offsets with original-string slicing). One process finding flagged inline: a commit on this branch carries Claude/Anthropic author+committer identity, in violation of this repo's own CLAUDE.md no-AI-attribution policy. No code changes pushed — nothing else needed a fix.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit a1d9131 ("chore(changelog): name fragment after PR and add PR reference") on this branch has both author identity and committer identity set to Claude <noreply@anthropic.com>.

This is a direct violation of the repo's own CLAUDE.md policy ("No Claude / Anthropic / AI attribution ... The commit-msg git hook rejects matching strings ... and separately rejects a commit whose author identity ... resolves to Claude / Anthropic"). The commit message text itself is clean, so this slipped past message-content scanning, but git var GIT_AUTHOR_IDENT on this commit resolves to Claude, which is exactly the case the commit-msg hook's author-identity check is meant to catch — it likely landed because core.hooksPath was not pointed at scripts/hooks in the environment that made this commit (see CLAUDE.md's "Enable once per clone" just setup step).

Not fixing via history rewrite/force-push per policy — flagging so a maintainer can decide whether to squash-merge (which drops the individual commit identities) or ask for a rebase with corrected identity before merge.

Content-wise, the actual fix (crates/librefang-runtime/src/session_repair.rs) looks correct: replacing the old manual lowercase-then-byte-offset search (which mixed byte offsets from to_lowercase()'d text with slicing on the original string — broken whenever a character's lowercase form has a different UTF-8 byte length, e.g. İ → i̇) with a single case-insensitive regex over the original string fixes the byte-boundary corruption bug directly, and the added regression test (test_strip_injection_marker_after_expanding_unicode_lowercase) exercises exactly that case. rustfmt --check is clean on both changed files, and the changelog fragment is correctly named/formatted per changelog.d/README.md.


Generated by Claude Code

@houko
houko merged commit 0c23a53 into main Aug 12, 2026
38 checks passed
@houko
houko deleted the fix/session-repair-unicode-markers branch August 12, 2026 00:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/runtime Agent loop, LLM drivers, WASM sandbox size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants