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: 3a11368f0c774f6391e17a68f5af2c08
Branch: dev/4-p514-code-point-bounds
Base: 98a6aec
At: 2026-11-04T02:40:10Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
What happens today
Two one-line bounds still decide "is this text within the limit?" in UTF-16 code units and then cut on code points, so a line that already fits gets cut anyway — and every astral character (emoji, CJK extension, any surrogate pair) doubles the count that decides:
core/src/host/memory.js:1271—ends(text, max):if (text.length <= max) return text. Used at:1282for the user's line in a memory review withREVIEW_USER_LINE_MAX = 3_000(:64); the prompt is assembled at:1353/:1463.core/src/host/room-context.js:45—oneLine(value, max):if (flat.length <= max) return flat. Call sites pass 40/80/24/60 (:173-175,:180,:191,:245,:263) for a board card's holder and title.
fits() (in core/src/shared/text-boundary.js, used by this same file family since #2326) counts code points; String.prototype.length counts UTF-16 units. The two disagree by exactly the number of astral characters, and the fast path takes the unit-based answer.
Reproduction (clean 98a6aec6511c43db73ffba620f57bd1756b67e1f, tests only)
Red first, --test-name-pattern 'P-514': 0 success + 0 cancelled + 4 failure.
ends('😀'.repeat(2900), 3000)— 2,900 code points / 5,800 units, andfits()says it is within the bound — comes back asUser:+ 1,497 emoji +…(middle cut)…(1,519 characters). About 1,400 characters are lost from a line that fits.oneLine('😀'.repeat(40), 40)→ 19 emoji +…;oneLine('😀'.repeat(80), 80)→ 39 emoji +…— a board card loses the holder's name and the title it was given.- Control:
ends('a'.repeat(2900), 3000)returns its input unchanged today, so the boundary is in the unit of the decision, not in the cut.
After the fix the same four assert 4 of 4 green: the 2,900-emoji line comes back whole (2,900 characters / 5,800 units), the 40- and 80-character board lines keep their full holder and title, and the ASCII control is byte-identical.
Expected
Judge with fits(...) from core/src/shared/text-boundary.js; do not move the cut (codePointStart / cut stay exactly as they are). ASCII behaviour is unchanged by construction: for text without astral characters fits is length <= max.
Scope
Two source files, +2/−2 each, plus tests. core/src/host/memory.js and core/src/host/room-context.js are both carried by patches/ds-bot/** (0001-core-fixes.patch, files/src/host/room-context.js), so the PR runs generate and includes the regenerated bundle: 9 files +141/−9 in total, tier T2 by the live risk-rules.json at 98a6aec6 (two core/src/host/** files; tests and patches are T1). It does not touch core/client.js.
Not in scope: core/web-search.js:97 has the same shape, but it is a vendor copy byte-identical to ds-bot/web-search.js and has no patches/ds-bot/files/ entry — changing it needs a new patch first.
Also noted while verifying (unreachable today, but it will bite the next caller): clip(text) without max returns 'hello… (cut)' because fits(text, undefined) is always false; the only importer, core/src/host/parts.js (:344, :355, :465), always passes max, the same contract gap #1918 closed for the reason text.
Duplicate check (live main 98a6aec6)
room-context.js's fast path was added by#1961(issue#1960, "the room-context cuts keep a lone surrogate") andmemory.jsends()'s by#1921(issue#1918); both PRs changed only the cut, not the decision — this is the half they left.#1958/#1959are the otheroneLinecopies incore/src/host/tasks.js/work-dispatch.js, different files.- Code search on live
98a6aec6for.length <= maxincore/src/host/returns exactly these two files and nothing else; no open issue or PR covers this face.
Activity
HugoXK commentedon Nov 4, 2026
Release
Written-by: FlyBot Lead
Released: 3a11368f0c774f6391e17a68f5af2c08
Reason: merged as 7226d74 (PR #2341)
At: 2026-11-04T03:17:48Z
host: the memory review's two-ended cut spends its budget in characte…