Skip to content

feat(linear): full label parity with Trello — dropdown + create-label UX#1121

Merged
zbigniewsobiecki merged 1 commit intodevfrom
feat/linear-label-parity
Apr 16, 2026
Merged

feat(linear): full label parity with Trello — dropdown + create-label UX#1121
zbigniewsobiecki merged 1 commit intodevfrom
feat/linear-label-parity

Conversation

@zbigniewsobiecki
Copy link
Copy Markdown
Member

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's issueUpdate.labelIds requires 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's issueLabelCreate GraphQL mutation, returning { id, name, color }. 6 new unit tests.
  • integrationsDiscovery.createLinearLabel and createLinearLabels (batch) tRPC mutations mirror the Trello equivalents — single-label creation and batch creation with per-label error reporting.

Wizard

  • LinearFieldMappingStep label UI now matches Trello:
    • Dropdown sourced from linearTeamDetails.labels (already fetched by existing discovery).
    • Values are label UUIDs, not names.
    • Per-slot "Create" button when the default isn't present yet.
    • "Create All Missing (N)" batch button at the section header.
    • Exports LINEAR_LABEL_DEFAULTS (name + hex color per slot).
  • useLinearLabelCreation hook mirrors useTrelloLabelCreation — single + batch mutation, dispatches ADD_LINEAR_TEAM_LABEL and SET_LINEAR_LABEL on success.
  • INITIAL_LINEAR_LABELS is now {} — the wizard populates mappings via selection or creation, not seeded names.

Adapter hardening

  • LinearPMProvider.resolveLabelId validates the resolved value is UUID-shaped. If the config mapping is missing or holds a name (from a pre-existing broken configuration), addLabel / removeLabel short-circuit with a clear warn instead of silently passing a bad value to Linear.
  • createWorkItem.labelIds filters out non-UUID values with the same warn.

Per-provider parity after this PR

Provider Wizard UX Stores Auto-create
Trello dropdown + Create button UUIDs
JIRA free-text (JIRA API auto-creates on use) names ✓ (server-side)
Linear dropdown + Create button UUIDs ✓ (via wizard)

Operator action required

Existing Linear-backed projects have names stored in project.linear.labels (e.g. processing: "cascade-processing"). After this PR deploys:

  • Open the project's PM wizard → Label Mappings step.
  • Dropdowns will show empty because the saved name no longer matches any option value.
  • Either pick existing labels from the dropdown, or click Create All Missing to provision CASCADE's defaults in one click.

Going forward the wizard persists UUIDs and cascade-processing will 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 values
  • Full test suite: 7687 passing, lint + typecheck clean

Files changed

  • src/linear/client.tscreateLabel method
  • src/api/routers/integrationsDiscovery.tscreateLinearLabel + createLinearLabels endpoints
  • src/pm/linear/adapter.tsresolveLabelId validation helper wired into createWorkItem / addLabel / removeLabel
  • web/src/components/projects/pm-wizard-state.tsADD_LINEAR_TEAM_LABEL action + reducer; empty initial labels
  • web/src/components/projects/pm-wizard-linear-steps.tsx — new LinearFieldMappingStep label UI + LINEAR_LABEL_DEFAULTS export
  • web/src/components/projects/pm-wizard-hooks.tsuseLinearLabelCreation
  • web/src/components/projects/pm-wizard.tsx — wire handlers into LinearFieldMappingStep

Test plan

  • npm run lint, npm run typecheck, full npm test clean locally (7687 tests)
  • After deploy-dev: re-open the dev project's PM wizard, click "Create All Missing" on the Label Mappings step. Confirm 5 labels are created in Linear with the expected names + colors, and the dropdowns show them as selected.
  • Trigger a Linear status transition that fires an agent. Confirm the agent's cascade-processing label is actually applied to the issue in Linear (visible in the Linear UI).

🤖 Generated with Claude Code

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>
@zbigniewsobiecki zbigniewsobiecki merged commit 7a0ee03 into dev Apr 16, 2026
8 checks passed
@zbigniewsobiecki zbigniewsobiecki deleted the feat/linear-label-parity branch April 16, 2026 06:50
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 61.16505% with 40 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/api/routers/integrationsDiscovery.ts 42.18% 37 Missing ⚠️
src/pm/linear/adapter.ts 85.71% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant