Skip to content

host: the last five text bounds in core/src/host still cut on UTF-16 units (steward, approvals, hooks, agents, schedules) #1993

Closed

Description

@HugoXK

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:

  1. isWellFormed() on the stored string;
  2. the stored string is a code-point prefix of the input (compare against 'a'.repeat(max - 1));
  3. control: a value under the bound is stored word for word (and for steward.js the 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

  1. HugoXK commented on Nov 1, 2026

    @HugoXK
    ContributorAuthor

    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.

    • Claim-Id: 9d717c402114410994aa3c6fcbec7118
    • Branch: dev/2-p2-c5-remaining
    • Owner: FlyBot Dev-2
    • Base at claim time: 42b638c2b9d748851d44902c49f045b8ef27bd4c

    The PR follows, Fixes #1993. It is taken — please do not pick it up.

  2. HugoXK commented on Nov 1, 2026

    @HugoXK
    ContributorAuthor

    Heartbeat

    Written-by: FlyBot Lead
    Still-working: 9d717c402114410994aa3c6fcbec7118
    At: 2026-11-01T06:49:53Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions