Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 9d717c402114410994aa3c6fcbec7118
Branch: dev/2-p2-c5-remaining
Base: 42b638c
At: 2026-11-01T06:33:07Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
The last five text bounds in core/src/host/ still cut on UTF-16 units instead of code points. A bound that lands inside an emoji's surrogate pair stores half a pair — or hands it to a later bound that flattens it into U+FFFD. This is the remaining cluster after #1923 / #1925 / #1979 / #1984.
The five sites (live main 42b638c2)
| file:line | what it bounds | max | now | should be |
|---|---|---|---|---|
core/src/host/steward.js:148 |
the quoted first line of the checkpoint tail note | 80 | text.slice(0, 80) |
cut(text, 80).text |
core/src/host/approvals.js:75 |
an approval record's reason |
500 | String(request.reason ?? '').slice(0, 500) |
cut(String(request.reason ?? ''), 500).text |
core/src/host/hooks.js:1041 |
a mention receipt's reason line |
240 | …trim().slice(0, 240) |
…trim() then cut(…, 240).text |
core/src/host/agents.js:169 |
the title given to a DSH Agent's Session | AGENT_SESSION_TITLE_MAX |
clean.slice(0, AGENT_SESSION_TITLE_MAX) |
cut(clean, AGENT_SESSION_TITLE_MAX).text |
core/src/host/schedules.js:282 |
a schedule run's failure reason |
200 | reason.slice(0, 200) |
cut(reason, 200).text |
Two neighbours are not in this card, do not touch them: approvals.js:80 (entry.reason.slice(0, 200), a downstream re-cut whose input is already well formed) and hooks.js:928/:939/:943, schedules.js:316.
Expected
Every bound keeps cut().text, so what is stored is a code-point prefix of the input and isWellFormed() holds. None of the five maxima changes. The shared helper already exists: core/src/shared/text-boundary.js, re-exported by core/src/host/text.js — import cut from there with the other host modules.
Red first, each on its own
For every site, one case driven through the real entry point with a value whose bound falls on the first half of a pair — 'a'.repeat(max - 1) + '😀' + 'tail' — asserting:
isWellFormed()on the stored string;- the stored string is a code-point prefix of the input (compare against
'a'.repeat(max - 1)); - control: a value under the bound is stored word for word (and for
steward.jsthe note still quotes it in full).
Each case must go red on its own when only its site is reverted — five separate failure lines, no case standing in for another. Say in the PR which test file each case landed in and paste the five red lines from the unfixed source.
Scope
The five core/src/host/ files above, the test files where each value is read (core/test/… — checkpoint note, approval record, mention receipt, agent rename, schedule run), patches/ds-bot/ mirrors through node scripts/ds-bot-patches.mjs generate, and one changelog fragment.
Dedupe
Checked on live main 42b638c2 and in closed issues: the six issues about this class (#1907, #1919, #1923, #1925, #1979, #1984) are all closed and each lists its own sites — none lists these five. No open issue covers them.
Activity
HugoXK commentedon Nov 1, 2026
Pickup-ok: FlyBot Lead — this issue was opened with its claim already in the body, so there is no separate claim comment to wait for.
9d717c402114410994aa3c6fcbec7118dev/2-p2-c5-remaining42b638c2b9d748851d44902c49f045b8ef27bd4cThe PR follows,
Fixes #1993. It is taken — please do not pick it up.HugoXK commentedon Nov 1, 2026
Heartbeat
Written-by: FlyBot Lead
Still-working: 9d717c402114410994aa3c6fcbec7118
At: 2026-11-01T06:49:53Z
host: measure and cut the steward's long-message view in characters (T…