Public: anyone can read this; the crew can change it.
The crew's one-line reasons are cut with `clip`: a parked reason ending in an emoji keeps it whole #6768
Check · Review · Land · Live done — Landed and live in production.
Four places in the crew code shortened text with their own `slice(0, n - 1) + "…"`. They now call the shared `clip` from `src/text/clip.ts`, which cuts at whole characters. So a parked reason or quoted line that runs past its limit right on an emoji keeps the emoji whole instead of leaving half of it as a broken character.
shipped production is serving it deploy b070674
Four places in the crew code shortened text with their own slice(0, n - 1) + "…". They now call the shared clip from src/text/clip.ts, which cuts at whole characters. So a parked reason or quoted line that runs past its limit right on an emoji keeps the emoji whole instead of leaving half of it as a broken character.
src/crew/handed.ts:oneLine(reason)is nowclip(reason, REASON_MAX).src/crew/sentinel.ts: its localclipis gone in favour of the shared one, and the default limit is now a namedQUOTE_MAX = 200.clipalready flattens whitespace onto one line, so the extraoneLine(...)calls around its inputs are dropped.src/crew/vision.ts:directionLinecallsclip(text, LINE_SHOWN). The local cut used byvisionBlockbecomesclipTight, a wrapper aroundclipthat keeps the old habit of never leaving a space before the "…". The unusedflathelper is removed.src/crew/plan.ts: its privateclipis removed and the shared one is imported. It already flattened whitespace and trimmed, so only the cut itself changes.
Two small differences in behaviour:
- Limits count characters, not code units. An emoji now counts as one toward the limit instead of two. The vision block's overall
roomcheck is unchanged and still caps the block's total length. - Sentinel issue titles are flattened. Titles passed through
clip(for exampleSentinel: …) now have runs of whitespace folded to one space. These titles are built from one-line templates, so nothing visible should change.
test/text-clip-crew.test.ts feeds oneLine a 200-character reason with an emoji at characters 139–140 and checks that no half-emoji is left and that the emoji is kept before the "…". It also checks a short reason and runs the same emoji check on a vision directionLine. Run against main's code, two of its three cases fail. On this branch it passes, along with the 13 test files that cover these modules (vision-pull, sentinel, tui-sentinel, mcp-vision, crew-handover, limb-replan, board, tui-onyou, red-main, shared-red, spawn-pipes, text-clip and the new one), and bun x tsc --noEmit is clean.
To try it: bun test test/text-clip-crew.test.ts.
🤖 Generated with Claude Code
Four private clips now share src/text/clip.ts; an emoji at the cut stays whole, and the tests pin it (reason at 139-140, directionLine). Behaviour changes are stated and sound. Two things next: (1) plan.ts leaves a double blank line where the local clip was removed; (2) in sentinel.ts the clip import sits after local imports, so move it into order. Neither blocks.
Four places in the crew code shortened text with their own
slice(0, n - 1) + "…". They now call the sharedclipfromsrc/text/clip.ts, which cuts at whole characters. So a parked reason or quoted line that runs past its limit right on an emoji keeps the emoji whole instead of leaving half of it as a broken character.src/crew/handed.ts:oneLine(reason)is nowclip(reason, REASON_MAX).src/crew/sentinel.ts: its localclipis gone in favour of the shared one, and the default limit is now a namedQUOTE_MAX = 200.clipalready flattens whitespace onto one line, so the extraoneLine(...)calls around its inputs are dropped.src/crew/vision.ts:directionLinecallsclip(text, LINE_SHOWN). The local cut used byvisionBlockbecomesclipTight, a wrapper aroundclipthat keeps the old habit of never leaving a space before the "…". The unusedflathelper is removed.src/crew/plan.ts: its privateclipis removed and the shared one is imported. It already flattened whitespace and trimmed, so only the cut itself changes.Two small differences in behaviour:
roomcheck is unchanged and still caps the block's total length.clip(for exampleSentinel: …) now have runs of whitespace folded to one space. These titles are built from one-line templates, so nothing visible should change.test/text-clip-crew.test.tsfeedsoneLinea 200-character reason with an emoji at characters 139–140 and checks that no half-emoji is left and that the emoji is kept before the "…". It also checks a short reason and runs the same emoji check on a visiondirectionLine. Run against main's code, two of its three cases fail. On this branch it passes, along with the 13 test files that cover these modules (vision-pull, sentinel, tui-sentinel, mcp-vision, crew-handover, limb-replan, board, tui-onyou, red-main, shared-red, spawn-pipes, text-clip and the new one), andbun x tsc --noEmitis clean.To try it:
bun test test/text-clip-crew.test.ts.🤖 Generated with Claude Code
Closes #6628