feat(pm): integration hardening follow-ups + wizard shared-component migration (specs 010 + 011/1-2)#1148
Merged
zbigniewsobiecki merged 22 commits intodevfrom Apr 18, 2026
Merged
Conversation
…tor dispatch Upgrades the wizard generator from spec-010/1 placeholders to real shared React components for every StandardStepKind. Six new components at web/src/components/projects/pm-providers/steps/*.tsx: credentials, container-pick, status-mapping, label-mapping, webhook-url-display, project-scope. Generator exports STANDARD_STEP_COMPONENTS registry and dispatches through it; unknown kinds still warn-once and render a placeholder. Trello/JIRA/Linear wizards keep their per-provider step adapters from the spec-006 era — a future plan migrates them. The shared path is live for new providers today. new-provider-surface snapshot is tightened to pin the six new files; wizard-generator + per-provider manifest-wizardSpec tests now assert element.type identity against the registry instead of placeholder DOM shapes. 55 new/updated tests, all green. Docs updated: src/integrations/README.md (post-spec-010 additions), root CLAUDE.md (PM-integration summary), spec 009 forward-references spec 010, CHANGELOG entries for specs 009 + 010. Closes plan 010/3 of spec 010. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
All three plans of spec 010 (PM integration hardening follow-ups) shipped. Mutations (010/1) added generic pm.discovery.createLabel / createCustomField endpoints. Read cleanup (010/2) added currentUser discovery capability. Wizard components (010/3) landed real shared React components for every StandardStepKind. Spec marked .done. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Spec 011 (PM Wizard Shared Migration) and its 5-plan decomposition.
Migrates Trello/JIRA/Linear wizards onto the shared StandardStepKind
components landed by spec 010 — closes the "zero per-provider step
code" promise across all three production providers, not just new
providers.
Plans: 1-shared-components (widen container-pick/project-scope with
searchable mode + widen webhook-url-display with optional signing-
secret + add 7th StandardStepKind: custom-field-mapping), 2-trello
(first consumer; OAuth stays kind:'custom'), 3-jira (issue-type stays
kind:'custom'; free-text label mode), 4-linear (retire LinearWebhook-
InfoPanel in favor of widened shared component), 5-cleanup (delete
pm-wizard-{trello,jira,linear}-steps.tsx + final docs rewrite).
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
…d-mapping kind Foundation plan for the wizard migration. Three additive widenings + one new StandardStepKind. All changes dormant until plan 2 activates them; the 31 spec-010 step tests pass unchanged as the backward-compat proof. - container-pick gains optional searchable?: boolean → dispatches to the existing shared Combobox (cmdk + radix) when true. - project-scope gains the same searchable? prop; empty value still means "no scope" in both render paths. - webhook-url-display gains optional secretFieldRole / secretLabel / secretValue / onSecretChange → renders an inline <input type="password"> below the URL when both role + callback are supplied. Defensive: omits the input if role is set but callback is not (avoids uncontrolled secret inputs silently dropping user input). - 7th StandardStepKind: 'custom-field-mapping'. New shared component at web/src/components/projects/pm-providers/steps/custom-field-mapping.tsx renders one row per CASCADE slot with a dropdown of discovered provider custom fields + optional inline "Create…" affordance wired to manifest.createCustomField (spec 010/1). Visual idiom matches status-mapping. - STANDARD_STEP_COMPONENTS registers the new kind; generator dispatch falls through the existing switch path. - new-provider-surface snapshot pins the 7th file. Tests use element-tree identity checks where SSR would hit the React instance mismatch (radix lives in web/node_modules and pulls its own React). 17 new/updated test assertions across 4 files. Full suite 8153/8153, lint 0/0, typecheck + build green. Closes plan 011/1 of spec 011. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
First real consumer of the shared wizard components. Trello's legacy
per-provider step file (pm-wizard-trello-steps.tsx) has no live importers
outside itself; deletion deferred to plan 011/5.
- TrelloOAuthStep: new custom step at pm-providers/trello/oauth-step.tsx.
Lifts the window.open popup + manual-token fallback verbatim from the
legacy TrelloCredentialsStep. Registered as kind:'custom' with
component:'TrelloOAuthStep' in trelloManifest.wizardSpec.
- trelloManifest.wizardSpec.steps: now [custom(TrelloOAuthStep),
container-pick, status-mapping, label-mapping, custom-field-mapping,
webhook-url-display] — 6 steps, one of them custom.
- trelloProviderWizard.steps: rewritten to consume shared components via
thin per-step adapters. useProviderHooks returns the flat shape each
adapter slices (boardOptions, providerStates, providerLabels,
providerCustomFields, onCreate* callbacks). Adapters call shared
components directly with Trello-specific props.
- Adapters file (trello/adapters.tsx): deleted — orphaned after the
wizard rewrite.
- useTrelloCustomFieldCreation: now accepts { name: string } argument
(was hard-coded "Cost"). Enables the shared Create-form UX.
Forward-edit to plan 011/1 (additive, existing tests unchanged):
- label-mapping widened with optional labelDefaults?: Record<slot,
{name, color?}> — pre-populates Create input, threads color to
onCreateLabel. Trello uses it for cascade-ready/processing/etc.
- custom-field-mapping widened with optional fieldDefaults?: Record<slot,
{name}> — pre-populates Create input. Trello uses it for cost field.
Normalize-upward UX changes (user-approved in behavior inventory):
- Dropped retry button on board-picker error (shared component shows
error text; operator refreshes page).
- Dropped "Create All Missing Labels" batch button (per-slot Create
covers the same ground, one click at a time).
AC #9 (no operator regression) marked **deferred** — browser smoke test
pending reviewer verification. Unit tests + conformance harness cover
wire-level invariants; no runtime behavior change in adapters
(discovery / label-creation / custom-field-creation hooks reused
unchanged).
19 Trello tests: 5 wizardSpec + 7 oauth-step + 7 wizard-generator. Plus
2 forward-edit tests on the widened shared steps. Full suite 8169/8169,
lint + typecheck + build all green.
Closes plan 011/2 of spec 011.
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Second real consumer of the shared wizard components. JIRA's legacy
per-provider step file (pm-wizard-jira-steps.tsx) has no live importers
outside itself; deletion deferred to plan 011/5.
- IssueTypeMappingStep: new JIRA-specific custom step at
pm-providers/jira/issue-type-step.tsx. Maps CASCADE task/subtask
roles to JIRA issue types (filtered by the `subtask` flag). Stays
kind:'custom' rather than becoming an 8th StandardStepKind because
JIRA is the sole consumer today — speculative abstraction avoided.
- jiraManifest.wizardSpec.steps: now [credentials, container-pick,
status-mapping, label-mapping, custom-field-mapping,
custom(IssueTypeMappingStep), webhook-url-display] — 7 steps, one
custom.
- jiraProviderWizard.steps: rewritten to consume shared components via
thin per-step adapters. Credentials step uses the shared
`CredentialsStep` with a synthetic `base_url` role alongside email +
api_token — no OAuth popup needed for JIRA (unlike Trello). Label
mapping passes providerLabels: [] so the shared step renders in
free-text mode (JIRA labels are free-form).
- Adapters file (jira/adapters.tsx): deleted — orphaned after rewrite.
- useJiraCustomFieldCreation: now accepts { name: string } argument
(was hard-coded "Cost") so the shared Create affordance works.
Task 1 behavior inventory found the same 4 gap classes Trello
surfaced; all four were already closed by plan 011/2's forward-edit to
plan 011/1 (labelDefaults + fieldDefaults additive widenings). No
additional shared-component changes were required for JIRA.
AC #10 (no operator regression) marked **deferred** — browser smoke
test pending reviewer verification on the deployed branch. Unit tests
+ conformance harness cover wire-level invariants; legacy discovery +
custom-field hooks reused unchanged (only the name-arg tweak on the
custom-field mutation).
17 JIRA tests: 6 manifest + 7 issue-type + 4 wizard-generator. JIRA
had zero dedicated wizard-step tests before this plan — this is the
first JIRA wizard coverage landing. Full suite 8185/8185, lint +
typecheck + build all green.
Closes plan 011/3 of spec 011.
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Third real consumer of the shared wizard components. Plan 011/4 also ships a critical fix for a regression plans 011/2 and 011/3 introduced: pm-wizard.tsx hardcoded 3 manifest step slots (stepIndex 0/1/2) from the spec-006 era. Trello/JIRA wizardSpecs grew to 6+ steps; only the first 3 rendered on the deploy — label-mapping, custom-field-mapping, and issue-type-mapping steps were INVISIBLE in production. Fix: pm-wizard.tsx now iterates over `manifestDef.steps`, rendering one WizardStep slot per entry. Webhook steps (id ends with `-webhook`) are filtered out — the legacy WebhookStep still owns programmatic webhook registration (Trello/JIRA API calls) and Linear's signing-secret UX. The shared `webhook-url-display` component (widened in plan 011/1) remains dormant for the three existing providers until a follow-up plan migrates webhook-creation UX into the manifest path. Linear wizard migration: - linearProviderWizard.steps: rewritten to consume shared components via 6 thin per-step adapters. No kind:'custom' steps — Linear has no OAuth popup (like Trello) and no issue-type mapping (like JIRA). - LinearWebhookDisplayAdapter: Fragment composing shared WebhookUrlDisplayStep + ProjectSecretField (LINEAR_WEBHOOK_SECRET). Currently dormant; activates after legacy WebhookStep migration. - project-scope step (spec 005): uses the shared ProjectScopeStep with `searchable: true`. - label-mapping: uses shared component with LINEAR_LABEL_DEFAULTS (plan 011/1 forward-edit) pre-populating the Create input with cascade-ready/processing/etc. and threading hex colors. - Adapters file (linear/adapters.tsx): deleted — orphaned after rewrite. - Legacy step tests deleted: linear-field-mapping-step.test.ts, linear-team-step.test.ts, linear-webhook-info-panel.test.ts (-450 lines). Replaced by 8-test linear-wizard-generator.test.ts covering the wizard wiring + manifest↔definition parity. AC #3 (inline webhook secret), #6 (LinearWebhookInfoPanel retired), and #11 (no operator regression) marked **partial/deferred** — see Progress section for details. All other ACs green. Full suite 8167/8167, lint + typecheck + build all green. Closes plan 011/4 of spec 011. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Closes spec 011 per user-approved option (a) — tight scope: deletions + docs. Scope-clipped items (full LinearWebhookInfoPanel retirement, Linear inline-secret via shared component) carry over as follow-up work; rationale is captured in the plan's Progress section. Deletions: - web/src/components/projects/pm-wizard-trello-steps.tsx (retired since plan 011/2; no live importers) - web/src/components/projects/pm-wizard-jira-steps.tsx (since 011/3) - web/src/components/projects/pm-wizard-linear-steps.tsx (since 011/4) - pm-wizard.tsx dead comments about transitive imports of the above Audits: - pm-wizard-common-steps.tsx — all three remaining exports (LinearWebhookInfoPanel, WebhookStep, SaveStep) still have live consumers via pm-wizard.tsx. File retained. - Dead-code grep: only doc-comment references to the deleted files remain; no live imports. Docs: - src/integrations/README.md — four-specs preamble (006/009/010/011); "seven kinds" in "Adding a new PM provider" step 3; Post-spec-011 additions table alongside the Post-spec-010 one. - CLAUDE.md (project root) — PM-integration summary references spec 011. - CHANGELOG.md — Internal entry for spec 011 alongside 009/010. - docs/specs/010-pm-integration-hardening-followups.md.done — forward-reference blockquote to spec 011. Verification: - npm test: 8167 passed, 23 skipped - npm run lint: clean - npm run typecheck: green - npm run build: green - Conformance harness: all three providers pass - new-provider-surface guard: 7 step files pinned Closes plan 011/5 of spec 011. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
Five plans of spec 011 (PM Wizard Shared Migration) shipped. Shared components widened (plan 1), Trello migrated (plan 2), JIRA migrated (plan 3), Linear migrated + pm-wizard.tsx parent refactor (plan 4), legacy per-provider step files deleted + docs closed (plan 5). Spec marked .done. Deferred to follow-up spec: - Full migration of webhook-creation UX (Trello/JIRA programmatic webhook registration + Linear signing-secret persistence) into the manifest path. Legacy WebhookStep + LinearWebhookInfoPanel still render for this. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
zbigniewsobiecki
added a commit
that referenced
this pull request
Apr 18, 2026
The dev deploy + CI `Build frontend` step have been failing since PR #1148 (spec 011 merge). Root cause: `cd web && npm run build` runs `tsc -b` which is stricter than the root `npm run typecheck` I've been using for local verification. Three classes of errors surfaced: 1. `steps/webhook-url-display.tsx` + `steps/container-pick.tsx` had a `readonly /** jsdoc */ fieldName: string` pattern (pre-existing from spec 010/3). Stricter tsc parses this as `readonly: any` on its own + bare `fieldName: string` without the readonly modifier (TS7008). Downstream callers couldn't satisfy the broken interface (TS2345). Fixed by moving the JSDoc comment above the `readonly` keyword. 2. `pm-wizard-hooks.ts` verify-button flow passes `capability: 'currentUser'` to `pm.discovery.discover`, but the Zod enum at the tRPC input schema was missing `'currentUser'` (pre-existing from spec 010/2 — type union was updated but the enum wasn't). Every wizard Verify-button call failed at runtime Zod validation. Fixed by promoting the enum to `src/pm/types.ts` as `DISCOVERY_CAPABILITIES` (const array) and deriving both the `DiscoveryCapability` type union and the tRPC Zod enum from it — the two can no longer drift. 3. `jira/wizard.ts` mapped `details?.fields` directly to `providerCustomFields`, but JIRA's discovery shape is `{id, name, custom}` while the shared prop contract expects `{id, name, type}` (introduced by me in plan 011/3 / 012/2). Fixed by mapping `custom: boolean` → `type: 'custom' | 'standard'`. Tests: - New regression in `tests/unit/api/pm-discovery.test.ts`: `accepts currentUser capability (closes Zod-enum / type-union drift)` pins the root-cause invariant. - Existing 13 pm-discovery tests continue to pass. - Full suite: 8187/8187 (+1 vs pre-fix). Verified: `npm test`, `npm run lint`, `npm run typecheck`, `npm run build`, `cd web && npm run build` — all green. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
7 tasks
zbigniewsobiecki
added a commit
that referenced
this pull request
Apr 18, 2026
The dev deploy + CI `Build frontend` step have been failing since PR #1148 (spec 011 merge). Root cause: `cd web && npm run build` runs `tsc -b` which is stricter than the root `npm run typecheck` I've been using for local verification. Three classes of errors surfaced: 1. `steps/webhook-url-display.tsx` + `steps/container-pick.tsx` had a `readonly /** jsdoc */ fieldName: string` pattern (pre-existing from spec 010/3). Stricter tsc parses this as `readonly: any` on its own + bare `fieldName: string` without the readonly modifier (TS7008). Downstream callers couldn't satisfy the broken interface (TS2345). Fixed by moving the JSDoc comment above the `readonly` keyword. 2. `pm-wizard-hooks.ts` verify-button flow passes `capability: 'currentUser'` to `pm.discovery.discover`, but the Zod enum at the tRPC input schema was missing `'currentUser'` (pre-existing from spec 010/2 — type union was updated but the enum wasn't). Every wizard Verify-button call failed at runtime Zod validation. Fixed by promoting the enum to `src/pm/types.ts` as `DISCOVERY_CAPABILITIES` (const array) and deriving both the `DiscoveryCapability` type union and the tRPC Zod enum from it — the two can no longer drift. 3. `jira/wizard.ts` mapped `details?.fields` directly to `providerCustomFields`, but JIRA's discovery shape is `{id, name, custom}` while the shared prop contract expects `{id, name, type}` (introduced by me in plan 011/3 / 012/2). Fixed by mapping `custom: boolean` → `type: 'custom' | 'standard'`. Tests: - New regression in `tests/unit/api/pm-discovery.test.ts`: `accepts currentUser capability (closes Zod-enum / type-union drift)` pins the root-cause invariant. - Existing 13 pm-discovery tests continue to pass. - Full suite: 8187/8187 (+1 vs pre-fix). Verified: `npm test`, `npm run lint`, `npm run typecheck`, `npm run build`, `cd web && npm run build` — all green. Co-authored-by: Claude Opus 4 (1M context) <noreply@anthropic.com>
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
Stack of two spec's worth of PM integration work, one reviewable PR. Spec 010 (PM Integration Hardening Follow-ups) is fully complete; spec 011 (PM Wizard Shared Migration) has plans 1 + 2 of 5 landed.
Spec 010 (complete — 3 plans):
pm.discovery.createLabel/createCustomFieldtRPC endpoints dispatch through optionalcreateLabel/createCustomFieldmanifest hooks. Five previous per-provider wizard caller sites now consume the generic endpoints.currentUseradded toDiscoveryCapability. All three providers declare it (Trello/members/me, JIRA/rest/api/3/myself, Linearviewer). Verify-button wizard UX reads via unifiedpm.discovery.discover.pm-providers/steps/*.tsx, one perStandardStepKind. Generator registry dispatches through them.new-provider-surfaceguard pins the files.Spec 011 (plans 1 + 2 of 5):
container-pick+project-scopeoptionalsearchable?: boolean→ renders via shared cmdk Combobox when true.webhook-url-displayoptionalsecretFieldRole/secretValue/onSecretChange→ inline signing-secret<input type="password">.StandardStepKind:custom-field-mapping— shared component wiresmanifest.createCustomField.kind: 'custom'(TrelloOAuthStep). Legacypm-wizard-trello-steps.tsxretained (plan 011/5 deletes it) but has zero live importers.Forward-edits landed in 011/2 (additive, existing tests unchanged):
label-mappinggainslabelDefaults?prop (pre-populates Create input, threads color toonCreateLabel).custom-field-mappinggainsfieldDefaults?prop.Intentional normalize-upward UX changes in Trello wizard (user-approved):
Test plan
npm test— 444 files / 8169 tests passing / 23 skippednpm run lint— cleannpm run typecheck— greennpm run build— greenpm-conformance.test.ts— 95 tests, Trello/JIRA/Linear all pass the behavioral harnessnew-provider-surface.test.ts— guards the 7 shared step files + registry + router/worker/CLI/dashboard entry pointsFollow-up plans still pending in spec 011
pm-wizard-{trello,jira,linear}-steps.tsx, rewrite README + CLAUDE.md + CHANGELOG, close spec 011🤖 Generated with Claude Code