Skip to content

fix(prompt): truncate recent release bodies on UTF-8 char boundary#113

Merged
jdx merged 1 commit intomainfrom
claude/magical-chebyshev-15974a
Apr 23, 2026
Merged

fix(prompt): truncate recent release bodies on UTF-8 char boundary#113
jdx merged 1 commit intomainfrom
claude/magical-chebyshev-15974a

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 23, 2026

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, so communique generate against endevco/[email protected] blew up with:

thread 'main' panicked at src/prompt.rs:137:52:
byte index 3072 is not a char boundary; it is inside '—' (bytes 3070..3073) of `aube v1.0.0-beta.12 is a reliability and reach release…`

(See the failed enhance-release job.)

Fix: walk back from 3072 to the nearest char boundary before slicing.

Test plan

  • New regression test test_user_prompt_recent_releases_truncation_on_char_boundary reproduces the aube panic (em-dash straddling the 3072 cutoff) and now passes
  • cargo test prompt:: — 8/8 pass
  • cargo clippy / cargo fmt --check clean (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_prompt when 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.

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-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR fixes a panic in src/prompt.rs where &body[..3072] was sliced directly without checking for a UTF-8 char boundary, causing a runtime panic when multi-byte characters (e.g. em-dash ) straddled the cutoff. The fix walks end back from 3072 to the nearest valid char boundary before slicing, and a regression test reproduces the exact scenario.

Confidence Score: 5/5

Safe to merge — targeted one-liner bug fix with a direct regression test; no correctness concerns remain.

The change is minimal and exactly correct: is_char_boundary(0) is always true, so the while loop is guaranteed to terminate without underflow regardless of input. The regression test reproduces the exact panic scenario. All findings are P2 or lower.

No files require special attention.

Important Files Changed

Filename Overview
src/prompt.rs Fixes UTF-8 panic by walking back from byte 3072 to the nearest char boundary before slicing; adds a targeted regression test for the em-dash case.

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
Loading

Reviews (1): Last reviewed commit: "fix(prompt): truncate recent release bod..." | Re-trigger Greptile

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

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.

Comment thread src/prompt.rs
Comment on lines 136 to +137
let truncated = if body.len() > 3072 {
format!("{}...\n[truncated]", &body[..3072])
let mut end = 3072;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The magic number 3072 is used in multiple places (the length check and the initial truncation index). It is recommended to define this as a named constant (e.g., MAX_RELEASE_BODY_LEN) to improve maintainability and ensure consistency if the limit needs to be adjusted in the future.

Comment thread src/prompt.rs
Comment on lines +137 to +140
let mut end = 3072;
while !body.is_char_boundary(end) {
end -= 1;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

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.

Suggested change
let mut end = 3072;
while !body.is_char_boundary(end) {
end -= 1;
}
let end = body.floor_char_boundary(3072);

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.11%. Comparing base (21267b3) to head (c48ae1c).
⚠️ Report is 1 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jdx jdx merged commit 5e74d55 into main Apr 23, 2026
9 checks passed
@jdx jdx deleted the claude/magical-chebyshev-15974a branch April 23, 2026 20:24
jdx added a commit that referenced this pull request Apr 23, 2026
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>
jdx added a commit to endevco/aube that referenced this pull request Apr 23, 2026
## 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]>
jdx added a commit to jdx/hk that referenced this pull request Apr 23, 2026
## 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]>
jdx added a commit to jdx/mise that referenced this pull request Apr 23, 2026
## 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]>
jdx added a commit to endevco/pitchfork that referenced this pull request Apr 23, 2026
## 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]>
jdx added a commit to jdx/fnox that referenced this pull request Apr 23, 2026
## 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]>
NorthIsUp pushed a commit to NorthIsUp/fnox that referenced this pull request Apr 28, 2026
## 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant