Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All notable user-visible changes to CASCADE are documented here. The format is l

### Internal

- **PM webhook-UX manifest migration complete (spec 012).** Closes the final gap from spec 011 — every PM wizard step, without exception, now renders via the manifest path. Plans 012/1-3 migrated Trello, JIRA, and Linear webhook steps into per-provider adapters composed of the shared `WebhookUrlDisplayStep` + provider-specific UX: Trello and JIRA each wrap the shared step with a programmatic "Create Webhook" button + active-webhooks list + per-webhook delete + curl fallback template (via existing `webhooks.*` tRPC endpoints with the `{trelloOnly|jiraOnly}` discriminator); Linear wraps it with a "Manual Webhook Setup Required" banner + `ProjectSecretField` (self-managing `LINEAR_WEBHOOK_SECRET` persistence) + 5-step manual-setup instructions. Plan 012/4 deleted the legacy `WebhookStep`, `LinearWebhookInfoPanel`, `useWebhookManagement`, `useLinearWebhookInfo`, the legacy `pm-wizard-webhooks-step.test.ts` file, and the `-webhook` id-skip filter introduced by plan 011/4. `pm-wizard-common-steps.tsx` now only exports `SaveStep`. `pm-wizard.tsx` iterates `manifestDef.steps` without exception; the legacy webhook slot is gone. No operator-visible regression. See spec [012](docs/specs/012-pm-webhook-manifest-migration.md.done).
- **PM wizard shared-component migration complete (spec 011).** Migrates the three production PM provider wizards (Trello, JIRA, Linear) off their per-provider step files and onto the shared `StandardStepKind` components landed by spec 010. Five plans landed: shared-components widenings (`container-pick` / `project-scope` `searchable?: boolean` → cmdk `Combobox`; `webhook-url-display` optional inline signing-secret input; 7th `StandardStepKind: custom-field-mapping` wired to `manifest.createCustomField`); Trello migration (OAuth popup stays as `kind: 'custom'` via `TrelloOAuthStep`; `labelDefaults?` + `fieldDefaults?` forward-edit additive widenings pre-populate Create inputs); JIRA migration (task/subtask mapping stays as `kind: 'custom'` via `IssueTypeMappingStep`; free-text label mode exercises the empty-`providerLabels` path); Linear migration (credentials, team picker, status/label/project-scope all shared; webhook step composes shared `WebhookUrlDisplayStep` with `ProjectSecretField` for `LINEAR_WEBHOOK_SECRET`); cleanup (the three `pm-wizard-{trello,jira,linear}-steps.tsx` files deleted, ≈1,085 lines of legacy UI retired). Plan 011/4 also fixed a latent regression plans 011/2 + 011/3 introduced: `pm-wizard.tsx` hardcoded 3 manifest step slots from the spec-006 era; it now iterates over `manifestDef.steps` dynamically, rendering one `WizardStep` per entry. Legacy `WebhookStep` (programmatic webhook registration for Trello/JIRA + Linear signing-secret UX) retained in its own slot — migration into the manifest path is follow-up scope. No operator-visible wizard-UX change beyond consistency: every provider now has searchable pickers, and Trello/JIRA gain inline custom-field create affordances. See spec [011](docs/specs/011-pm-wizard-shared-migration.md.done).
- **PM integration hardening follow-ups complete (spec 010).** Finishes the PM-layer cleanup started by spec 009. Three plans landed: generic `pm.discovery.createLabel(providerId, containerId, name, color?)` and `pm.discovery.createCustomField(providerId, containerId, name)` tRPC mutation endpoints + optional `createLabel` / `createCustomField` manifest hooks replace five per-provider wizard call sites; the `currentUser` `DiscoveryCapability` is declared on all three real providers (Trello `/members/me`, JIRA `/rest/api/3/myself`, Linear `viewer`) and served through the unified `pm.discovery.discover` endpoint; six real shared React step components (`credentials`, `container-pick`, `status-mapping`, `label-mapping`, `webhook-url-display`, `project-scope`) now live at `web/src/components/projects/pm-providers/steps/*.tsx` and the wizard generator dispatches to them via a `STANDARD_STEP_COMPONENTS` registry. Existing Trello/JIRA/Linear wizards continue to use their spec-006-era per-provider step adapters; the shared path is additive — a new PM provider with purely-standard steps now writes zero per-provider step components. The `new-provider-surface` snapshot guard is tightened to include the six step files. No operator-visible changes. See spec [010](docs/specs/010-pm-integration-hardening-followups.md.done).
- **PM integration hardening (spec 009).** Makes the `PMProviderManifest` a behavioral contract rather than a wiring convention. Five plans landed: branded `StateId` / `LabelId` / `ContainerId` types in `src/pm/ids.ts` (state-name-vs-ID confusion is now a compile error at direct-adapter call sites); manifest-owned Zod `configSchema` for each provider (the central `src/config/schema.ts` imports from `src/integrations/pm/<provider>/config-schema.ts` — #1138/#1142 drift class becomes a round-trip CI failure); unified `pm.discovery.discover(providerId, capability, args)` tRPC endpoint driven by `manifest.discoveryCapabilities`; behavioral conformance harness (`tests/unit/integrations/pm-conformance.test.ts`) runs round-trip + lifecycle + webhook-verify + trigger-self-hook against every registered provider; single registration entrypoint at `src/integrations/entrypoint.ts` (router, worker, CLI, dashboard all import one file — guarded by `entrypoint-usage.test.ts`); shared `_shared/auth-headers.ts` helpers enforced by provenance test; `tests/unit/pm/linear/regression-2026-04.test.ts` locks in fixes for six Linear bug classes (#1112/#1117/#1118/#1119/#1131/#1133/#1134/#1137/#1138/#1139/#1142). No operator-visible changes. See spec [009](docs/specs/009-pm-integration-hardening.md.done).
- **PM integration plug-and-play (infrastructure).** Introduced `PMProviderManifest` as the canonical per-provider contract — one object declares credentials, webhook route and verifier, router adapter, trigger handlers, platform client, job-id extractor, and optional label-creation hook. Landed `pmProviderRegistry`, a conformance test harness (`tests/unit/integrations/pm-conformance.test.ts`), shared helpers (`_shared/auth-headers.ts`, `_shared/webhook-verifier.ts`, `_shared/label-id-resolver.ts`, `_shared/project-id-extractor.ts`), a new `pm.discovery` tRPC router, and a frontend provider-wizard registry with a generic step renderer. Dormant in this release — Trello, JIRA, and Linear continue to register through the legacy path; they migrate onto the manifest in follow-up PRs. No operator-visible changes. Closes plan 006/1 of spec [006](docs/specs/006-pm-integration-plug-and-play.md).
- **PM integration plug-and-play (Trello migrated).** Trello's webhook signature verifier, router adapter, triggers, platform client, job-id extractor, wizard steps, and label/custom-field creation hooks are now composed via a single `trelloManifest` + `trelloProviderWizard`. Extended the `ProviderWizardDefinition` contract with an optional `useProviderHooks` field so provider-specific React hooks run inside a shell component — `ManifestProviderWizardSection` — rather than at the wizard root; this is how we satisfy the React rules-of-hooks while still keeping Trello's Discovery/LabelCreation/CustomFieldCreation hook composition per-provider. The conformance harness now exercises Trello alongside the test fixture (22 shared tests × provider). Trello's legacy registrations in `bootstrap.ts` stay for now because nine-plus call sites still use `pmRegistry.get('trello')` — plan 006/5 migrates those callers and deletes the legacy lines. No operator-visible changes. Closes plan 006/2 of spec [006](docs/specs/006-pm-integration-plug-and-play.md).
- **PM integration plug-and-play (JIRA migrated).** JIRA joins Trello on the manifest pattern with `jiraManifest` + `jiraProviderWizard`. `verifyWebhookSignature` uses the shared `makeHmacSha256Verifier` factory (Trello's bespoke scheme didn't fit, so this is the first consumer). Wizard steps + discovery / custom-field hooks moved into `jiraProviderWizard.useProviderHooks`; the JIRA-specific branches and hook instantiations are gone from `pm-wizard.tsx`. `worker-env.ts::extractProjectIdFromJob` JIRA branch removed (registry path handles it). Conformance harness now exercises Trello + JIRA + TestProvider (33 shared assertions × provider). Same deferrals as 006/2: `bootstrap.ts` JIRA registration stays until plan 006/5 migrates the `pmRegistry.get('jira')` callers. No operator-visible changes. Closes plan 006/3 of spec [006](docs/specs/006-pm-integration-plug-and-play.md).
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Three separate services, **no monolithic server mode**:

Flow: `PM/SCM/alerting webhook → Router → Redis → Worker → TriggerRegistry → Agent → Code → PR`.

Integration abstraction lives in `src/integrations/`. For **adding a new PM provider**, see @src/integrations/README.md — PM providers (Trello, JIRA, Linear) use the `PMProviderManifest` registry with a **behavioral conformance harness** (spec 009 — config round-trip, discovery shape, full lifecycle scenario, auth-header provenance, single-entrypoint invariant). Each provider owns its Zod config schema (`src/integrations/pm/<provider>/config-schema.ts`) as the single source of truth — the central `src/config/schema.ts` imports it. PM adapter method signatures use branded `StateId` / `LabelId` / `ContainerId` from `src/pm/ids.ts` to make state-name-vs-ID confusion a compile error at direct-adapter call sites. All runtime surfaces (router, worker, CLI, dashboard) register integrations through a single entrypoint at `src/integrations/entrypoint.ts`. SCM (GitHub) and alerting (Sentry) still use the legacy `IntegrationModule` pattern via self-registration in `src/github/register.ts` + `src/sentry/register.ts`. Don't improvise; the README covers both patterns.
Integration abstraction lives in `src/integrations/`. For **adding a new PM provider**, see @src/integrations/README.md — PM providers (Trello, JIRA, Linear) use the `PMProviderManifest` registry with a **behavioral conformance harness** (spec 009 — config round-trip, discovery shape, full lifecycle scenario, auth-header provenance, single-entrypoint invariant). Each provider owns its Zod config schema (`src/integrations/pm/<provider>/config-schema.ts`) as the single source of truth — the central `src/config/schema.ts` imports it. PM adapter method signatures use branded `StateId` / `LabelId` / `ContainerId` from `src/pm/ids.ts` to make state-name-vs-ID confusion a compile error at direct-adapter call sites. All runtime surfaces (router, worker, CLI, dashboard) register integrations through a single entrypoint at `src/integrations/entrypoint.ts`. **Spec 010 follow-ups** added generic `pm.discovery.createLabel` / `createCustomField` mutation endpoints + `currentUser` discovery capability + real shared React components for every `StandardStepKind` under `web/src/components/projects/pm-providers/steps/`. **Spec 011** migrated all three production providers (Trello, JIRA, Linear) onto those shared components, added a 7th `StandardStepKind: custom-field-mapping`, widened `container-pick` / `project-scope` / `webhook-url-display` with optional props, and deleted the three legacy `pm-wizard-{trello,jira,linear}-steps.tsx` files. **Spec 012** migrated each provider's webhook UX (programmatic create for Trello/JIRA, signing-secret + instructions for Linear) into per-provider manifest webhook adapters (Fragment compositions around the shared `WebhookUrlDisplayStep`); deleted the legacy `WebhookStep` + `LinearWebhookInfoPanel` + `useWebhookManagement` + `useLinearWebhookInfo`. Every PM wizard step now renders via the manifest path without exception. A new PM provider writes zero edits to shared orchestration (`pm-wizard.tsx`, `pm-wizard-common-steps.tsx`, `pm-wizard-hooks.ts`); provider-specific UI ships either as `kind: 'custom'` steps or as Fragment compositions inside the provider folder's wizard adapters. SCM (GitHub) and alerting (Sentry) still use the legacy `IntegrationModule` pattern via self-registration in `src/github/register.ts` + `src/sentry/register.ts`. Don't improvise; the README covers both patterns.

## PR checkout (worker) — gotcha

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ This is enforced by commitlint via lefthook pre-commit hooks.
See [CLAUDE.md](./CLAUDE.md) for a detailed architecture overview. Key directories:

- `src/router/` — Webhook receiver (enqueues jobs to Redis)
- `src/triggers/` — Event handlers (Trello, GitHub, JIRA)
- `src/triggers/` — Event handlers (Trello, JIRA, Linear, GitHub)
- `src/agents/` — AI agent implementations
- `src/gadgets/` — Tools agents can use
- `src/api/` — Dashboard API (tRPC)
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node.js 22+](https://img.shields.io/badge/node-%3E%3D22-brightgreen)](https://nodejs.org/)

> **Cascade orchestrates AI agents (Claude Code, Codex, opencode, LLMist) across your workflows in GitHub, Trello, and Jira.**
> **Cascade orchestrates AI agents (Claude Code, Codex, opencode, LLMist) across your workflows in GitHub, Trello, Jira, and Linear.**

Cascade is an open-source platform that automates the full software development lifecycle. Connect your PM tool and GitHub repository, and Cascade drives work items from plan to merge:

Expand Down Expand Up @@ -38,7 +38,7 @@ For the full setup walkthrough — projects, credentials, webhooks, and triggers

## ⚡ Features

- **Multi-PM support** — Works with Trello and JIRA out of the box
- **Multi-PM support** — Works with Trello, JIRA, and Linear out of the box
- **11 agent types** — Splitting, planning, implementation, review, debug, respond-to-review, respond-to-CI, and more
- **Dual-persona GitHub model** — Separate implementer and reviewer bot accounts to prevent feedback loops
- **Web dashboard + CLI** — Monitor runs, manage projects, configure triggers
Expand Down Expand Up @@ -151,7 +151,7 @@ All project-level credentials (GitHub tokens, PM keys, LLM API keys) are stored

**Dual-persona GitHub model** — Cascade uses two separate GitHub bot accounts per project (implementer and reviewer) to prevent feedback loops. The implementer writes code and creates PRs; the reviewer reviews and approves them.

**Trigger system** — Events from Trello, JIRA, and GitHub webhooks are matched against registered `TriggerHandler` instances. Triggers are configured per-project in the database.
**Trigger system** — Events from Trello, JIRA, Linear, and GitHub webhooks are matched against registered `TriggerHandler` instances. Triggers are configured per-project in the database.

**Agent engines** — Agents run through a shared execution lifecycle with a pluggable engine registry. Default engine is `claude-code` (Anthropic Claude Code SDK). Alternatives: `llmist` (supports OpenRouter, Anthropic, OpenAI), `codex` (OpenAI Codex CLI), `opencode` (OpenCode server).

Expand Down
10 changes: 7 additions & 3 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CASCADE Architecture

CASCADE is a PM-to-Code automation platform that connects project management tools (Trello, JIRA), source control (GitHub), and monitoring (Sentry) to AI-powered agents that autonomously implement features, review PRs, debug failures, and manage backlogs. Webhooks from external providers flow through a router, get queued in Redis, and are processed by ephemeral worker containers that run agents against cloned repositories.
CASCADE is a PM-to-Code automation platform that connects project management tools (Trello, JIRA, Linear), source control (GitHub), and monitoring (Sentry) to AI-powered agents that autonomously implement features, review PRs, debug failures, and manage backlogs. Webhooks from external providers flow through a router, get queued in Redis, and are processed by ephemeral worker containers that run agents against cloned repositories.

> **Relationship to CLAUDE.md**: `CLAUDE.md` is the operational reference (commands, env vars, how-to). This document and its deep-dives cover the *system design* — how components fit together and why.

Expand All @@ -11,6 +11,7 @@ graph TB
subgraph External["External Providers"]
Trello
JIRA
Linear
GitHub
Sentry
end
Expand All @@ -30,6 +31,7 @@ graph TB

Trello -->|webhook| Router
JIRA -->|webhook| Router
Linear -->|webhook| Router
GitHub -->|webhook| Router
Sentry -->|webhook| Router

Expand All @@ -39,6 +41,7 @@ graph TB
Worker -->|PRs, comments| GitHub
Worker -->|status updates| Trello
Worker -->|status updates| JIRA
Worker -->|status updates| Linear

Router <--> DB
Worker <--> DB
Expand All @@ -65,7 +68,7 @@ The canonical path from webhook to pull request:

```mermaid
sequenceDiagram
participant P as Provider<br/>(Trello/GitHub/JIRA/Sentry)
participant P as Provider<br/>(Trello/JIRA/Linear/GitHub/Sentry)
participant R as Router
participant Q as Redis/BullMQ
participant W as Worker
Expand Down Expand Up @@ -110,10 +113,11 @@ sequenceDiagram
| `src/backends/` | LLM execution engines: Claude Code, LLMist, Codex, OpenCode |
| `src/gadgets/` | Tool implementations agents use (file ops, PM, SCM, alerting, shell) |
| `src/integrations/` | Unified integration interfaces, registry, bootstrap |
| `src/pm/` | PM abstraction layer: provider interface, Trello/JIRA adapters, lifecycle |
| `src/pm/` | PM abstraction layer: provider interface, Trello/JIRA/Linear adapters, lifecycle |
| `src/github/` | GitHub API client, dual-persona model, PR operations |
| `src/trello/` | Trello API client |
| `src/jira/` | JIRA API client (jira.js wrapper) |
| `src/linear/` | Linear GraphQL API client |
| `src/sentry/` | Sentry API client, alerting integration |
| `src/config/` | Configuration provider, caching, credential resolution, integration roles |
| `src/db/` | Drizzle ORM schema, repositories, migrations |
Expand Down
4 changes: 3 additions & 1 deletion docs/architecture/01-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The router is the webhook ingestion point. It receives HTTP POST requests from e
| `POST /trello/webhook` | Trello | HEAD/GET returns 200 for Trello's verification |
| `POST /github/webhook` | GitHub | Injects `X-GitHub-Event` header into payload |
| `POST /jira/webhook` | JIRA | HEAD/GET returns 200 for JIRA verification |
| `POST /linear/webhook` | Linear | HMAC-SHA256 via `linear-signature` header |
| `POST /sentry/webhook/:projectId` | Sentry | Project ID in URL for unambiguous routing |
| `GET /health` | Internal | Queue stats, active worker count |

Expand Down Expand Up @@ -94,7 +95,7 @@ The router passes job data to workers via Docker container env vars:
| Variable | Purpose |
|----------|---------|
| `JOB_ID` | Unique job identifier |
| `JOB_TYPE` | `trello`, `github`, `jira`, `sentry`, `manual-run`, `retry-run`, `debug-analysis` |
| `JOB_TYPE` | `trello`, `github`, `jira`, `linear`, `sentry`, `manual-run`, `retry-run`, `debug-analysis` |
| `JOB_DATA` | JSON-encoded job payload |
| `CASCADE_CREDENTIAL_KEYS` | Comma-separated list of credential env var names |
| Individual credential vars | Pre-loaded project credentials (e.g., `GITHUB_TOKEN_IMPLEMENTER`) |
Expand All @@ -106,6 +107,7 @@ type JobData =
| TrelloJobData // Trello webhook payload
| GitHubJobData // GitHub webhook payload
| JiraJobData // JIRA webhook payload
| LinearJobData // Linear webhook payload
| SentryJobData // Sentry webhook payload
| ManualRunJobData // Dashboard-initiated run
| RetryRunJobData // Retry a failed run
Expand Down
Loading
Loading