Skip to content

Commit 187c61c

Browse files
committed
fix(sync-regression): restore code-point-safe truncate + ignore node:test suites
Two regressions from the 2026-04-26 agent-core sync (PR #350): 1. lib/cross-platform/index.js::truncate lost its code-point-safe slicing (splitting surrogate pairs on emoji) and its non-positive maxLength special case. Restored [...text] spread + maxLength <= 0 early return. Regression tests in __tests__/cross-platform.test.js now pass. 2. jest.config.js testMatch picked up lib/binary/index.test.js which is a node:test suite (agent-core convention for co-located tests), and Jest failed with "must contain at least one test". Added /lib/binary/.*\.test\.js$ to testPathIgnorePatterns; run it via `node --test lib/binary/*.test.js` instead. Both fixes should be upstreamed to agent-core so every consumer gets them uniformly on next sync.
1 parent e12f90a commit 187c61c

2 files changed

Lines changed: 16 additions & 5 deletions

File tree

jest.config.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ module.exports = {
99
'/node_modules/',
1010
'/plugins/.*/lib/',
1111
'/.claude/worktrees/',
12-
'/worktrees/'
12+
'/worktrees/',
13+
// lib/binary/index.test.js is a node:test suite (co-located with the
14+
// module in agent-core convention). Jest's discovery picks it up and
15+
// fails with "must contain at least one test" because it has no
16+
// describe/it. Run it separately via `node --test lib/binary/*.test.js`.
17+
'/lib/binary/.*\\.test\\.js$'
1318
],
1419
modulePathIgnorePatterns: [
1520
'/.claude/worktrees/',

lib/cross-platform/index.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,15 +303,21 @@ function formatSection(title, content) {
303303
*/
304304

305305
/**
306-
* Truncate text to limit with ellipsis
306+
* Truncate text to limit with ellipsis.
307+
*
308+
* Slices on Unicode code points (not UTF-16 code units) so multi-byte
309+
* chars like emoji never end up as orphan surrogates. Non-positive
310+
* maxLength returns the original string unchanged.
307311
*
308312
* @param {string} text - Text to truncate
309-
* @param {number} maxLength - Maximum length
313+
* @param {number} maxLength - Maximum length (in code points)
310314
* @returns {string} Truncated text
311315
*/
312316
function truncate(text, maxLength) {
313-
if (text.length <= maxLength) return text;
314-
return text.substring(0, maxLength - 3) + '...';
317+
if (maxLength <= 0) return text;
318+
const codePoints = [...text];
319+
if (codePoints.length <= maxLength) return text;
320+
return codePoints.slice(0, maxLength - 3).join('') + '...';
315321
}
316322

317323
/**

0 commit comments

Comments
 (0)