fix(prompt): truncate recent release bodies on UTF-8 char boundary#113
fix(prompt): truncate recent release bodies on UTF-8 char boundary#113
Conversation
Slicing `&body[..3072]` panics when byte 3072 falls inside a multi-byte UTF-8 character — e.g. the em-dash `—` (3 bytes), which aube's own release-notes style uses heavily. This crashed `communique generate` against endevco/aube v1.0.0 with: byte index 3072 is not a char boundary; it is inside '—' (bytes 3070..3073) Walk back to the nearest char boundary before slicing. Adds a regression test that reproduces the aube panic. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Greptile SummaryThis PR fixes a panic in Confidence Score: 5/5Safe to merge — targeted one-liner bug fix with a direct regression test; no correctness concerns remain. The change is minimal and exactly correct: No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A{body.len gt 3072} -->|No| B[Use body as-is]
A -->|Yes| C[mut end = 3072]
C --> D{is_char_boundary end}
D -->|No| E[end -= 1]
E --> D
D -->|Yes| F[slice body to end]
F --> G[format truncated string]
B --> H[Push to section]
G --> H
Reviews (1): Last reviewed commit: "fix(prompt): truncate recent release bod..." | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review
This pull request fixes a potential panic during release body truncation by ensuring the slice occurs at a valid UTF-8 character boundary. It also introduces a regression test to verify this behavior. Review feedback suggests defining the truncation limit as a named constant and using the idiomatic floor_char_boundary method for better readability.
| let truncated = if body.len() > 3072 { | ||
| format!("{}...\n[truncated]", &body[..3072]) | ||
| let mut end = 3072; |
There was a problem hiding this comment.
| let mut end = 3072; | ||
| while !body.is_char_boundary(end) { | ||
| end -= 1; | ||
| } |
There was a problem hiding this comment.
If the project is using Rust 1.76 or later, this manual loop can be replaced with the more idiomatic str::floor_char_boundary method, which more clearly expresses the intent of finding the nearest valid UTF-8 boundary.
| let mut end = 3072; | |
| while !body.is_char_boundary(end) { | |
| end -= 1; | |
| } | |
| let end = body.floor_char_boundary(3072); |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #113 +/- ##
==========================================
+ Coverage 94.08% 94.11% +0.03%
==========================================
Files 26 26
Lines 4055 4076 +21
Branches 4055 4076 +21
==========================================
+ Hits 3815 3836 +21
Misses 155 155
Partials 85 85 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
A small patch release that fixes a panic when generating notes against releases with multi-byte characters in their bodies, and picks up a security fix in `rustls-webpki`. ## Fixed - **Don't panic on multi-byte chars in style-reference bodies** — `communique generate` truncates each recent release body to 3072 bytes to keep the prompt small, but previously sliced `&body[..3072]` directly. If byte 3072 fell inside a multi-byte UTF-8 character (common with em-dashes, which are 3 bytes), the command would panic with `byte index 3072 is not a char boundary`. The truncation now walks back to the nearest char boundary before slicing, with a regression test covering the case. ([#113](#113)) (@jdx) ## Security - **`rustls-webpki` bumped to 0.103.13** — Addresses [RUSTSEC-2026-0104](https://rustsec.org/advisories/RUSTSEC-2026-0104), a reachable panic in certificate revocation list parsing. Lockfile-only change. ([#107](#107)) (@jdx) ## Docs - Added a dismissible cross-site announcement banner and an en.dev footer to the documentation site, with follow-up polish (contrast, centering, z-index), smarter caching, and `ResizeObserver`-based height syncing so VitePress's nav offset stays correct on resize. ([#109](#109), [#110](#110), [#111](#111), [#112](#112)) (@jdx) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary Refreshes `mise.lock`'s `communique` entry from 1.0.2 → 1.0.3 so enhance-release picks up the UTF-8 char-boundary fix from [jdx/communique#113](jdx/communique#113). The prior truncation sliced release bodies at byte 3072 with no regard for UTF-8 char boundaries, which [crashed](https://github.com/endevco/aube/actions/runs/24854719507/job/72767529235) enhance-release for [aube v1.0.0](https://github.com/endevco/aube/releases/tag/v1.0.0) because one of the recent-release style samples had an em-dash `—` straddling the cutoff. ## Test plan - [x] Refreshed URLs, checksums, and asset IDs for all 6 platforms in the existing `[[tools.communique]]` block - [ ] CI green on the enhance-release job for the next tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: lockfile-only dependency bump updating download URLs/checksums/asset IDs, with no runtime code changes. > > **Overview** > Bumps the pinned `communique` tool in `mise.lock` from **1.0.2 → 1.0.3**, updating the associated per-platform download URLs, checksums, and GitHub asset IDs. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit d78a7d4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary Refreshes the `communique` entry in `mise.lock` from its prior pin to 1.0.3 so enhance-release picks up the UTF-8 char-boundary fix from [jdx/communique#113](jdx/communique#113). The prior truncation sliced release bodies at byte 3072 with no regard for UTF-8 char boundaries, which [crashed](https://github.com/endevco/aube/actions/runs/24854719507/job/72767529235) enhance-release for [aube v1.0.0](https://github.com/endevco/aube/releases/tag/v1.0.0) because one of the recent-release style samples had an em-dash `—` straddling the cutoff. ## Test plan - [x] Refreshed URLs, checksums, and asset IDs for all platforms in the existing `[[tools.communique]]` block - [ ] CI green on the release-enhancement job for the next tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: this only updates the pinned `communique` binary in `mise.lock` (version/URLs/checksums/asset IDs) with no application code changes. > > **Overview** > Updates `mise.lock` to pin `github:jdx/communique` from `1.0.1` to `1.0.3`, refreshing the download URLs, SHA256 checksums, and GitHub asset IDs across all supported platforms. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 77d34b9. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary Refreshes the `communique` entry in `mise.lock` from its prior pin to 1.0.3 so enhance-release picks up the UTF-8 char-boundary fix from [jdx/communique#113](jdx/communique#113). The prior truncation sliced release bodies at byte 3072 with no regard for UTF-8 char boundaries, which [crashed](https://github.com/endevco/aube/actions/runs/24854719507/job/72767529235) enhance-release for [aube v1.0.0](https://github.com/endevco/aube/releases/tag/v1.0.0) because one of the recent-release style samples had an em-dash `—` straddling the cutoff. ## Test plan - [x] Refreshed URLs, checksums, and asset IDs for all platforms in the existing `[[tools.communique]]` block - [ ] CI green on the release-enhancement job for the next tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: updates a pinned CLI tool version in `mise.lock` with refreshed platform URLs/checksums; impact should be limited to tooling/release automation behavior. > > **Overview** > Bumps the pinned `communique` tool in `mise.lock` from `1.0.2` to `1.0.3`, updating the associated per-platform download URLs, asset IDs, and checksums so the repo uses the newer release across Linux/macOS/Windows artifacts. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7e6c824. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary Refreshes the `communique` entry in `mise.lock` from its prior pin to 1.0.3 so enhance-release picks up the UTF-8 char-boundary fix from [jdx/communique#113](jdx/communique#113). The prior truncation sliced release bodies at byte 3072 with no regard for UTF-8 char boundaries, which [crashed](https://github.com/endevco/aube/actions/runs/24854719507/job/72767529235) enhance-release for [aube v1.0.0](https://github.com/endevco/aube/releases/tag/v1.0.0) because one of the recent-release style samples had an em-dash `—` straddling the cutoff. ## Test plan - [x] Refreshed URLs, checksums, and asset IDs for all platforms in the existing `[[tools.communique]]` block - [ ] CI green on the release-enhancement job for the next tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: updates a pinned dev tool binary in `mise.lock` only, with refreshed download URLs/checksums and no application logic changes. > > **Overview** > Bumps the `communique` tool pin in `mise.lock` from `1.0.1` to `1.0.3`, updating the associated per-platform asset URLs, API asset IDs, and SHA256 checksums. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6974e86. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary Refreshes the `communique` entry in `mise.lock` from its prior pin to 1.0.3 so enhance-release picks up the UTF-8 char-boundary fix from [jdx/communique#113](jdx/communique#113). The prior truncation sliced release bodies at byte 3072 with no regard for UTF-8 char boundaries, which [crashed](https://github.com/endevco/aube/actions/runs/24854719507/job/72767529235) enhance-release for [aube v1.0.0](https://github.com/endevco/aube/releases/tag/v1.0.0) because one of the recent-release style samples had an em-dash `—` straddling the cutoff. ## Test plan - [x] Refreshed URLs, checksums, and asset IDs for all platforms in the existing `[[tools.communique]]` block - [ ] CI green on the release-enhancement job for the next tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk dependency lockfile update only; main impact is CI/tooling behavior changes from the new `communique` release. > > **Overview** > Bumps the pinned `communique` version in `mise.lock` from `1.0.1` to `1.0.3`. > > Updates the corresponding per-platform download URLs, asset IDs, and SHA256 checksums so `mise` installs the new release across Linux/macOS/Windows. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5b12e96. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
## Summary Refreshes the `communique` entry in `mise.lock` from its prior pin to 1.0.3 so enhance-release picks up the UTF-8 char-boundary fix from [jdx/communique#113](jdx/communique#113). The prior truncation sliced release bodies at byte 3072 with no regard for UTF-8 char boundaries, which [crashed](https://github.com/endevco/aube/actions/runs/24854719507/job/72767529235) enhance-release for [aube v1.0.0](https://github.com/endevco/aube/releases/tag/v1.0.0) because one of the recent-release style samples had an em-dash `—` straddling the cutoff. ## Test plan - [x] Refreshed URLs, checksums, and asset IDs for all platforms in the existing `[[tools.communique]]` block - [ ] CI green on the release-enhancement job for the next tag 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk dependency lockfile update only; main impact is CI/tooling behavior changes from the new `communique` release. > > **Overview** > Bumps the pinned `communique` version in `mise.lock` from `1.0.1` to `1.0.3`. > > Updates the corresponding per-platform download URLs, asset IDs, and SHA256 checksums so `mise` installs the new release across Linux/macOS/Windows. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5b12e96. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Summary
src/prompt.rs's style-reference truncation sliced&body[..3072]directly, which panics whenever byte 3072 falls inside a multi-byte UTF-8 character. aube's release-notes style uses the em-dash—(3 bytes) heavily, socommunique generateagainst endevco/[email protected] blew up with:(See the failed enhance-release job.)
Fix: walk back from 3072 to the nearest char boundary before slicing.
Test plan
test_user_prompt_recent_releases_truncation_on_char_boundaryreproduces the aube panic (em-dash straddling the 3072 cutoff) and now passescargo test prompt::— 8/8 passcargo clippy/cargo fmt --checkclean (pre-commit hooks passed on push)🤖 Generated with Claude Code
Note
Low Risk
Low risk: change is limited to prompt-string truncation logic and adds a regression test; main risk is only in edge-case formatting of truncated output.
Overview
Fixes a panic in
user_promptwhen truncating "recent release" bodies by ensuring the 3072-byte cutoff is adjusted backward to a valid UTF-8 character boundary before slicing.Adds a regression test covering the multi-byte character boundary case to prevent future crashes during style-reference generation.
Reviewed by Cursor Bugbot for commit c48ae1c. Bugbot is set up for automated code reviews on this repo. Configure here.