From b893f03a5031dd22db920b11f9b2b5b06a3ba064 Mon Sep 17 00:00:00 2001 From: ysyneu Date: Wed, 26 Aug 2026 08:22:13 -0700 Subject: [PATCH] fix(incident): clarify comment length cap unit and report actual count The 'incident comment' help said 'at most 1024 characters' without stating the unit, so scripts measuring with wc -c (bytes) over-trim compliant multibyte text. State that the limit counts Unicode characters (runes), not bytes, and point at wc -m. The over-cap error also said only 'must be at most 1024 characters'. It now reports the actual character count alongside the limit (e.g. 'content is 1025 characters, limit is 1024') so the caller knows how much to trim. The counting was already rune-based and matches the server-side check; only the message changed. --- internal/cli/command_test.go | 9 +++++++-- internal/cli/incident.go | 8 +++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/cli/command_test.go b/internal/cli/command_test.go index 9754dce..17e1058 100644 --- a/internal/cli/command_test.go +++ b/internal/cli/command_test.go @@ -443,6 +443,7 @@ func TestCommandIncidentLifecycleHelpDocumentsSafetyAndLookupHints(t *testing.T) want: []string{ "up to 100 incidents", "1024 characters", + "wc -m", }, }, } @@ -596,8 +597,12 @@ func TestCommandIncidentCommentRejectsOver1024Runes(t *testing.T) { if err == nil { t.Fatal("[incident-comment-too-long] expected an error, got nil") } - if !strings.Contains(err.Error(), "1024 characters") { - t.Fatalf("[incident-comment-too-long] unexpected error: %v", err) + // The error must name the actual character count and the limit, so whoever + // (or whatever) wrote the over-long comment knows how much to trim. + for _, want := range []string{"1025 characters", "limit is 1024"} { + if !strings.Contains(err.Error(), want) { + t.Fatalf("[incident-comment-too-long] error missing %q: %v", want, err) + } } } diff --git a/internal/cli/incident.go b/internal/cli/incident.go index 2cb7fbc..32f98fd 100644 --- a/internal/cli/incident.go +++ b/internal/cli/incident.go @@ -894,7 +894,9 @@ shell, so backticks, $(...), and quotes inside it reach the API exactly as written. Leading/trailing whitespace is trimmed before sending — matching how the server stores it, so a bash heredoc's trailing newline (the pattern this CLI's own skill card recommends) does not fail verification below. The -trimmed text must be non-empty and at most 1024 characters. Use --mute-reply +trimmed text must be non-empty and at most 1024 characters. The limit counts +characters (Unicode runes), not bytes, so multibyte text (e.g. Chinese) is not +penalized — measure with 'wc -m', not 'wc -c'. Use --mute-reply when the comment should not trigger webhook reply behavior. After writing, the command reads back every incident's timeline and verifies @@ -926,8 +928,8 @@ success.`, if comment == "" { return fmt.Errorf("--comment-file must not be empty") } - if len([]rune(comment)) > 1024 { - return fmt.Errorf("--comment-file content must be at most 1024 characters") + if n := len([]rune(comment)); n > 1024 { + return fmt.Errorf("--comment-file content is %d characters, limit is 1024", n) } return runCommand(cmd, args, func(ctx *RunContext) error {