From c3f98c5a296951968d17e3efe3114b1c73a1ecf5 Mon Sep 17 00:00:00 2001 From: Cadu Date: Thu, 7 May 2026 15:36:34 -0300 Subject: [PATCH 1/2] docs(projects): warn that Linear's API rejects emoji for --icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linear's GraphQL schema docstring claims project icons accept emoji or icon names, but the upstream server-side validator rejects emoji at runtime with a confusing INVALID_INPUT error. Update --icon help text on both `projects create` and `projects update` to recommend named icons (e.g. "Computer", "Database") and call out the schema/runtime mismatch so users — especially LLM consumers — don't get misled. Add regression tests that assert both help screens contain the warning. Closes #146 --- crates/lineark/src/commands/projects.rs | 4 +- crates/lineark/tests/offline.rs | 50 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/crates/lineark/src/commands/projects.rs b/crates/lineark/src/commands/projects.rs index 36cf632..dcc657e 100644 --- a/crates/lineark/src/commands/projects.rs +++ b/crates/lineark/src/commands/projects.rs @@ -75,7 +75,7 @@ pub enum ProjectsAction { /// Markdown content for the project. #[arg(long)] content: Option, - /// Project icon (emoji or icon name). + /// Project icon name (e.g., "Computer", "Database", "Cloud"). Linear's API rejects emoji despite the GraphQL schema docstring claiming otherwise. #[arg(long)] icon: Option, /// Project color (hex color code). @@ -131,7 +131,7 @@ pub enum ProjectsAction { /// Project status name or UUID. #[arg(long)] status: Option, - /// Project icon (emoji or icon name). + /// Project icon name (e.g., "Computer", "Database", "Cloud"). Linear's API rejects emoji despite the GraphQL schema docstring claiming otherwise. #[arg(long)] icon: Option, /// Project color (hex color code). diff --git a/crates/lineark/tests/offline.rs b/crates/lineark/tests/offline.rs index ef3f982..d415ad6 100644 --- a/crates/lineark/tests/offline.rs +++ b/crates/lineark/tests/offline.rs @@ -522,6 +522,56 @@ fn projects_create_help_shows_flags() { .stdout(predicate::str::contains("--color")); } +/// Regression test for #146: `--icon` help text must warn that emoji are +/// rejected by Linear's API, despite the GraphQL schema docstring claiming +/// otherwise. Without this warning, users (especially LLM consumers) follow +/// the schema-documented "emoji or icon name" wording and hit a confusing +/// `INVALID_INPUT` error from the upstream validator. +#[test] +fn projects_create_help_icon_warns_emoji_rejected() { + lineark() + .args(["projects", "create", "--help"]) + .assert() + .success() + .stdout(predicate::str::contains("Linear's API rejects emoji")) + .stdout(predicate::str::contains("Computer")); +} + +#[test] +fn projects_update_help_shows_flags() { + lineark() + .args(["projects", "update", "--help"]) + .assert() + .success() + .stdout(predicate::str::contains("--name")) + .stdout(predicate::str::contains("--description")) + .stdout(predicate::str::contains("--content")) + .stdout(predicate::str::contains("--lead")) + .stdout(predicate::str::contains("--clear-lead")) + .stdout(predicate::str::contains("--members")) + .stdout(predicate::str::contains("--team")) + .stdout(predicate::str::contains("--start-date")) + .stdout(predicate::str::contains("--clear-start-date")) + .stdout(predicate::str::contains("--target-date")) + .stdout(predicate::str::contains("--clear-target-date")) + .stdout(predicate::str::contains("--priority")) + .stdout(predicate::str::contains("--status")) + .stdout(predicate::str::contains("--icon")) + .stdout(predicate::str::contains("--color")) + .stdout(predicate::str::contains("--labels")); +} + +/// Regression test for #146 — same warning must appear on `update` help. +#[test] +fn projects_update_help_icon_warns_emoji_rejected() { + lineark() + .args(["projects", "update", "--help"]) + .assert() + .success() + .stdout(predicate::str::contains("Linear's API rejects emoji")) + .stdout(predicate::str::contains("Computer")); +} + #[test] fn projects_list_help_shows_led_by_me_flag() { lineark() From 4f03fc104b7a1da5ffcea766d7d460380d23d7b0 Mon Sep 17 00:00:00 2001 From: Cadu Date: Thu, 7 May 2026 16:30:14 -0300 Subject: [PATCH 2/2] docs(projects): document emoji shortcodes as a valid --icon format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up investigation found Linear's API does accept emoji — but only as colon-wrapped shortcodes (`:repeat:`, `:computer:`), not as raw unicode characters (🔁). Two formats work: - Emoji shortcodes: `:repeat:`, `:rocket:`, `:computer:` - Named icons: `Computer`, `Database` Update --icon help to call out both formats and explicitly warn that raw unicode emoji are rejected. Update regression tests to assert the new wording. --- crates/lineark/src/commands/projects.rs | 4 ++-- crates/lineark/tests/offline.rs | 28 ++++++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/crates/lineark/src/commands/projects.rs b/crates/lineark/src/commands/projects.rs index dcc657e..f625191 100644 --- a/crates/lineark/src/commands/projects.rs +++ b/crates/lineark/src/commands/projects.rs @@ -75,7 +75,7 @@ pub enum ProjectsAction { /// Markdown content for the project. #[arg(long)] content: Option, - /// Project icon name (e.g., "Computer", "Database", "Cloud"). Linear's API rejects emoji despite the GraphQL schema docstring claiming otherwise. + /// Project icon: an emoji shortcode like ":repeat:" (NOT raw unicode 🔁) or a Linear named icon like "Computer". Linear's API rejects raw unicode emoji. #[arg(long)] icon: Option, /// Project color (hex color code). @@ -131,7 +131,7 @@ pub enum ProjectsAction { /// Project status name or UUID. #[arg(long)] status: Option, - /// Project icon name (e.g., "Computer", "Database", "Cloud"). Linear's API rejects emoji despite the GraphQL schema docstring claiming otherwise. + /// Project icon: an emoji shortcode like ":repeat:" (NOT raw unicode 🔁) or a Linear named icon like "Computer". Linear's API rejects raw unicode emoji. #[arg(long)] icon: Option, /// Project color (hex color code). diff --git a/crates/lineark/tests/offline.rs b/crates/lineark/tests/offline.rs index d415ad6..cd6980e 100644 --- a/crates/lineark/tests/offline.rs +++ b/crates/lineark/tests/offline.rs @@ -522,19 +522,22 @@ fn projects_create_help_shows_flags() { .stdout(predicate::str::contains("--color")); } -/// Regression test for #146: `--icon` help text must warn that emoji are -/// rejected by Linear's API, despite the GraphQL schema docstring claiming -/// otherwise. Without this warning, users (especially LLM consumers) follow -/// the schema-documented "emoji or icon name" wording and hit a confusing -/// `INVALID_INPUT` error from the upstream validator. +/// Regression test for #146: `--icon` help text must document the two +/// formats Linear's API actually accepts — emoji *shortcodes* (`:repeat:`) +/// and named icons (`Computer`) — and warn that raw unicode emoji (`🔁`) +/// are rejected at runtime despite the GraphQL schema docstring claiming +/// otherwise. Without this, users (especially LLM consumers) reach for +/// raw unicode and hit a confusing `INVALID_INPUT` error from the +/// upstream validator. #[test] -fn projects_create_help_icon_warns_emoji_rejected() { +fn projects_create_help_icon_documents_accepted_formats() { lineark() .args(["projects", "create", "--help"]) .assert() .success() - .stdout(predicate::str::contains("Linear's API rejects emoji")) - .stdout(predicate::str::contains("Computer")); + .stdout(predicate::str::contains(":repeat:")) + .stdout(predicate::str::contains("Computer")) + .stdout(predicate::str::contains("rejects raw unicode emoji")); } #[test] @@ -561,15 +564,16 @@ fn projects_update_help_shows_flags() { .stdout(predicate::str::contains("--labels")); } -/// Regression test for #146 — same warning must appear on `update` help. +/// Regression test for #146 — same documentation must appear on `update` help. #[test] -fn projects_update_help_icon_warns_emoji_rejected() { +fn projects_update_help_icon_documents_accepted_formats() { lineark() .args(["projects", "update", "--help"]) .assert() .success() - .stdout(predicate::str::contains("Linear's API rejects emoji")) - .stdout(predicate::str::contains("Computer")); + .stdout(predicate::str::contains(":repeat:")) + .stdout(predicate::str::contains("Computer")) + .stdout(predicate::str::contains("rejects raw unicode emoji")); } #[test]