feat(linear): full label parity with Trello — dropdown + create-label UX#1121
Merged
zbigniewsobiecki merged 1 commit intodevfrom Apr 16, 2026
Merged
feat(linear): full label parity with Trello — dropdown + create-label UX#1121zbigniewsobiecki merged 1 commit intodevfrom
zbigniewsobiecki merged 1 commit intodevfrom
Conversation
The Linear PM wizard stored label mappings as free-text names, but
Linear's issueUpdate.labelIds rejects names and requires UUIDs — so the
cascade-processing / cascade-processed / cascade-error / cascade-ready /
cascade-auto labels were silently never applied to issues.
Brings Linear to the same UX as Trello:
Backend
- linearClient.createLabel(teamId, name, color?) wraps the issueLabelCreate
GraphQL mutation, returning the new label's { id, name, color }.
- integrationsDiscovery.createLinearLabel + createLinearLabels tRPC
mutations mirror the Trello equivalents (single + batch with
per-label error reporting).
Wizard
- LinearFieldMappingStep replaces the free-text label inputs with a
dropdown sourced from linearTeamDetails.labels (already fetched by
discovery). Saves label UUIDs, not names.
- Per-slot "Create" button and a batch "Create All Missing" button use
LINEAR_LABEL_DEFAULTS (name + hex color per slot).
- useLinearLabelCreation hook mirrors useTrelloLabelCreation (single +
batch mutation, ADD_LINEAR_TEAM_LABEL dispatch on success).
Adapter hardening
- LinearPMProvider.resolveLabelId validates the resolved value is UUID-
shaped. If the mapping is missing or holds a name (from a pre-existing
configuration), addLabel/removeLabel short-circuit with a diagnostic
warn instead of passing a bad value to Linear and failing opaquely.
- createWorkItem filters out non-UUID label values (same warn).
Operator note: projects configured before this PR have names stored
(e.g. processing: "cascade-processing"). Re-open the PM wizard → Label
Mappings step; dropdowns will show empty because the saved name no
longer matches a dropdown value. Pick from the dropdown — or click
"Create All Missing" to provision defaults in one click.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced Apr 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings Linear label configuration to full parity with the Trello wizard. Replaces the Linear free-text label inputs with a dropdown of the team's existing labels, plus per-slot and batch "Create" buttons that provision CASCADE's default labels in one click.
This also fixes the silent bug where
cascade-processing/cascade-processed/ etc. were never actually applied to Linear issues: the wizard stored names, but Linear'sissueUpdate.labelIdsrequires UUIDs — Linear silently rejected the writes and the worker's label operations no-op'd.What's shipped
Backend
linearClient.createLabel(teamId, name, color?)wraps Linear'sissueLabelCreateGraphQL mutation, returning{ id, name, color }. 6 new unit tests.integrationsDiscovery.createLinearLabelandcreateLinearLabels(batch) tRPC mutations mirror the Trello equivalents — single-label creation and batch creation with per-label error reporting.Wizard
LinearFieldMappingSteplabel UI now matches Trello:linearTeamDetails.labels(already fetched by existing discovery).LINEAR_LABEL_DEFAULTS(name + hex color per slot).useLinearLabelCreationhook mirrorsuseTrelloLabelCreation— single + batch mutation, dispatchesADD_LINEAR_TEAM_LABELandSET_LINEAR_LABELon success.INITIAL_LINEAR_LABELSis now{}— the wizard populates mappings via selection or creation, not seeded names.Adapter hardening
LinearPMProvider.resolveLabelIdvalidates the resolved value is UUID-shaped. If the config mapping is missing or holds a name (from a pre-existing broken configuration),addLabel/removeLabelshort-circuit with a clear warn instead of silently passing a bad value to Linear.createWorkItem.labelIdsfilters out non-UUID values with the same warn.Per-provider parity after this PR
Operator action required
Existing Linear-backed projects have names stored in
project.linear.labels(e.g.processing: "cascade-processing"). After this PR deploys:Going forward the wizard persists UUIDs and
cascade-processingwill actually attach to issues.Tests
linearClient.createLabel— 6 new tests (returns shape, omits color when absent, passes input, success=false, GraphQL errors, HTTP errors)LinearPMProvider— updated fixture to UUID-shaped values; new test: "skips the API call and warns when the value is neither a mapped slot nor a UUID"LinearFieldMappingStep— new "label slots" describe: dropdown uses UUIDs not names, Create buttons show/hide correctly based on existing labels, persisted mappings reflect as selected option valuesFiles changed
src/linear/client.ts—createLabelmethodsrc/api/routers/integrationsDiscovery.ts—createLinearLabel+createLinearLabelsendpointssrc/pm/linear/adapter.ts—resolveLabelIdvalidation helper wired intocreateWorkItem/addLabel/removeLabelweb/src/components/projects/pm-wizard-state.ts—ADD_LINEAR_TEAM_LABELaction + reducer; empty initial labelsweb/src/components/projects/pm-wizard-linear-steps.tsx— newLinearFieldMappingSteplabel UI +LINEAR_LABEL_DEFAULTSexportweb/src/components/projects/pm-wizard-hooks.ts—useLinearLabelCreationweb/src/components/projects/pm-wizard.tsx— wire handlers intoLinearFieldMappingStepTest plan
npm run lint,npm run typecheck, fullnpm testclean locally (7687 tests)cascade-processinglabel is actually applied to the issue in Linear (visible in the Linear UI).🤖 Generated with Claude Code