Repository navigation
host: the steward's long-message budget is characters at both ends - #2554
Conversation
|
@Birfy 求一次 tip 评审:head
请在这个 tip 上给正式 Verdict;若中间有改动请点名新 tip,我不会为此另推提交。 |
|
Verdict: PASS at c86062b Ran at this tip: Red first: the middle line replaces only Review points:
Not run: Owner: Dev-5 · Issue #2552 · T2 per |
`shorten()` took two thirds of the 1,500-character budget, spent it as a UTF-16 count on `codePointEnd`, then subtracted that unit index from the character budget to place the tail. With astral characters in the message the tail slid past the end of the text, so the view kept only its first 1,000 characters and the marker reported the surplus units as left-out characters: 600 where the 100 really left out were characters. Both bounds now count characters, and the marker counts what the two slices drop. Fixes ThinkFlowLab#2552 Docs-not-needed: the steward's own line does not change, only where its view cuts.
Fixes #2552
Owner: Dev-5
Written-by: Dev-5
Reviewer: Birfy
Risk tier: T2 —
core/src/host/steward.jsplus its test, the generated patch and one changelog fragment.Base: 940815a
Tip: c86062b (tree 48fa75e019d33c54573c93fee786c8fce93d2a36)
The defect
shorten()incore/src/host/steward.jsgives a long message a 1,500-character budget. #2546/#2548 moved the test of that budget to code points, but the two cut points still mixed units:codePointEnd()/codePointStart()return a UTF-16 index (they only step off a surrogate pair), soheadis an index, yetSTEWARD_LINE_MAX - headsubtracts it from a character budget and that result is subtracted fromtext.length, an index too. With astral characters in the message the view keeps fewer characters than the budget and the marker overstates what was left out.Readings through
stewardRequeston the base940815ab:'🚀'.repeat(800) + 'a'.repeat(800)(1,600 chars / 2,400 units)'a'.repeat(1600)The second row is the control: plain ASCII spends the budget correctly, so this is the mixed-unit arithmetic and not the budget itself.
Red first
On the base with only the test file changed,
core/test/steward.test.js(same file, same test name, no new file):The failing case is
'a'.repeat(999) + '🚀' + 'b'.repeat(800): the 1,000th character is the emoji, and the base kepthead= 999 (a unit index of 1,000 moved back off the pair), so the emoji was dropped and the tail grew to 501. The dense case behind it read1,000 !== 1,500(head 500 + tail 500, marker 600). The older assertions in this test are untouched; the twoisWellFormedchecks pass on the base, which is why #2548's boundary fix did not expose this.The fix
charIndex(text, chars)— the UTF-16 index the nth character starts at, stepping whole code points (the rule host: a text bound judges in UTF-16 units, so a cut hits text that is already under its own limit #2321/core-host: decision and meeting archives cut text by code unit and store U+FFFD #1912/core-host: the remaining code-unit cuts (claim cue, read_own_chat query/around, page title, diagnostics lines, peer name) #1916 settled on);head = charIndex(text, Math.ceil((STEWARD_LINE_MAX * 2) / 3))(1,000 characters) andtail = charIndex(text, chars - (STEWARD_LINE_MAX - headChars))(the last 500 characters), so both ends stay on a boundary and each spends the budget in characters;chars - codePoints(head slice) - codePoints(tail slice), the characters really left out.fits(),STEWARD_LINE_MAX,stewardRequest, every other function and every other bound are unchanged;codePointEnd/codePointStartleave the import because nothing in the file uses them now.After, through the same probe: dense head 1,000 / tail 500 / view 1,500 / marker 100;
'a'×999 + 🚀 + 'b'×800keeps the emoji (head1,000, tail 500, marker 300);core/test/steward.test.js11 tests, 11 pass, 0 fail.Files (
git diff --numstat 940815ab...HEAD)node scripts/ds-bot-patches.mjs generateran after the rebase onto940815ab; only0001-core-fixes.patchmoved and a secondgenerateis byte-identical (checkclean,canonicalno-op).core/client.js,patches/ds-bot/0008*andcore/src/host/diagnostics.jsare untouched.Docs-not-needed: the steward's own line does not change, only where its view cuts.
Ran, at the tip
c86062b0Not run:
dev/bench.sh smoke— nocore/index.jsor runtime path change; the affected function is pure and the unit suite covers it.Checkpoint
{ "pr": 2554, "claim": "Dev-5", "issue": 2552, "summary": "The steward's view of a long message spent a UTF-16 index as a character count, so an emoji-dense message kept 1,000 of its 1,500-character budget and the marker overstated the cut. shorten() now takes both ends through a local charIndex() that steps whole code points, and the marker counts the characters really left out. The case added to the existing test fails on the base; the older assertions are untouched.", "files": ["core/src/host/steward.js", "core/test/steward.test.js", "changelog.d/2552-steward-shorten-character-budget.fixed.md", "patches/ds-bot/0001-core-fixes.patch"], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=940815ab184e0d64e96eadb66e10c54a4d1a9e6e npm run verify", "result": "green", "at": "c86062b030d3ef746e86a6dde28cb61984b6537f" }, "next": "none — ready for review" }