Repository navigation
fix(cli): preserve shaping joiners in human-readable results - #76
rudycelekli wants to merge 1 commit into
Conversation
Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. Reviewed October 6, 2026, 3:35 AM ET / 07:35 UTC. ClawSweeper reviewWhat this changesThe CLI preserves Unicode shaping joiners in human-readable results while continuing to strip them from diagnostics, with regression tests and a changelog entry. Merge readiness✅ Ready for maintainer review This PR remains necessary: current main and v0.4.11 still remove shaping joiners. The focused patch preserves the diagnostic boundary, and the supplied compiled-CLI transcript demonstrates the corrected behavior. No blocking defect was found. Priority: P2 Review scores
Verification
How this fits togethergoplaces maps Google Places responses into names, addresses, and other result fields. The CLI renders those fields as human-readable terminal text or JSON and separately sanitizes errors. flowchart TD
A[Places HTTP response] --> B[Typed result mapping]
B --> C[CLI output choice]
C --> D[Human text sanitizer]
C --> E[JSON output]
D --> F[Terminal results]
G[Parser and API errors] --> H[Strict diagnostic sanitizer]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Preserve legitimate shaping characters in displayed results while retaining strict diagnostic filtering and unchanged JSON contracts. Do we have a high-confidence way to reproduce the issue? Yes: main's shared human sanitizer unconditionally removes Cf characters, including both joiners. The supplied baseline CLI transcript confirms the resulting corruption; this reviewer did not execute it. Is this the best way to solve the issue? Yes: a two-character exception for human output plus a separate strict diagnostic path is a narrow repair that preserves existing security and JSON behavior. AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning medium; reviewed against 9883e1044f50. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
Problem
Human result rendering removes every Unicode Cf character. That changes emoji sequences such as
👩🔬into👩🔬and drops ZWNJ used in Persian shaping from names and addresses. The JSON output retains the original text, so human and machine consumers receive different names.Change and security boundary
Preserve only ZWNJ U+200C and ZWJ U+200D in human-readable result text. The Unicode Standard's Arabic/Persian discussion describes the shaping role of these characters; its implementation guidance also describes ZWJ's role in emoji sequences.
Keep parser/error diagnostics on the existing strict sanitizer, removing all Cf including joiners. ESC, C0/C1 controls, bidi controls, and every other Cf remain removed in human results as well. JSON output is unchanged. This preserves the diagnostic security boundary introduced in #53 and the bidi protection introduced in
47e9e25, while avoiding legitimate result-text corruption. This is display text handling, not a general anti-confusable or identifier-validation guarantee.Verification
9883e1044f504a19ab440e9c909dbf1c5d9c1a1fbefore the fix.09b976240cfac03dc867133619d4c141d4b2b285passedgo build ./...,go test ./...,go test -race ./...,make coverage(92.4%, required90%), andmake lint-checkwith the pinned golangci-lint v2.13.2.AI assistance was used for implementation and verification. The source patch received separate review before publication.
Inspectable compiled CLI transcript
Compiled with
go build -o goplaces-after ./cmd/goplacesfrom09b976240cfac03dc867133619d4c141d4b2b285. Updated binary SHA-256:5bd935dc38ccad65f44c5c3412b5a54cecb5cf82ac91769a225949b2c766ac47.<owned-local-base>replaces the process-owned ephemeral loopback endpoint; the keyowned-local-testis synthetic. The fixture returnsdisplayName.textandformattedAddresscontaining👩🔬 میخواهم, plus adversarial RLO/LRI/ZWSP/BOM/ESC/BEL controls in the name. Error-control requests return HTTP400 with those format controls in their JSON error body. This proves exact code-point preservation, not rendering support in every terminal font.