diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs
index 645ee9bb8bc..05097a202c9 100644
--- a/docs/astro.config.mjs
+++ b/docs/astro.config.mjs
@@ -193,7 +193,7 @@ export default defineConfig({
{ label: 'About campaigns', link: '/guides/campaigns/' },
{ label: 'Getting Started', link: '/guides/campaigns/getting-started/' },
{ label: 'Campaign Specs', link: '/guides/campaigns/specs/' },
- { label: 'Flow & Lifecycle', link: '/guides/campaigns/flow/' },
+ { label: 'Campaign Lifecycle', link: '/guides/campaigns/lifecycle/' },
{ label: 'CLI Commands', link: '/guides/campaigns/cli-commands/' },
],
},
diff --git a/docs/src/content/docs/examples/campaigns.md b/docs/src/content/docs/examples/campaigns.md
index 116d41f6ef5..77ef5c46fd4 100644
--- a/docs/src/content/docs/examples/campaigns.md
+++ b/docs/src/content/docs/examples/campaigns.md
@@ -95,7 +95,7 @@ Workers are stored alongside regular workflows, not in campaign-specific folders
## Learn More
- [Campaign Guides](/gh-aw/guides/campaigns/) - Campaign setup and configuration
-- [Flow & lifecycle](/gh-aw/guides/campaigns/flow/) - How the orchestrator runs
+- [Campaign lifecycle](/gh-aw/guides/campaigns/lifecycle/) - How the orchestrator runs
- [Safe Outputs](/gh-aw/reference/safe-outputs/) - dispatch_workflow configuration
## Pattern Analysis
diff --git a/docs/src/content/docs/guides/campaigns/getting-started.md b/docs/src/content/docs/guides/campaigns/getting-started.md
index 3a063a5b912..dd3a8576b01 100644
--- a/docs/src/content/docs/guides/campaigns/getting-started.md
+++ b/docs/src/content/docs/guides/campaigns/getting-started.md
@@ -42,7 +42,7 @@ The orchestrator runs on a schedule (daily by default) and will:
- sync issues/PRs into the Project
- post a Project status update each run
-For details, see [Flow & lifecycle](/gh-aw/guides/campaigns/flow/).
+For details, see [Campaign lifecycle](/gh-aw/guides/campaigns/lifecycle/).
## Keep it simple (best practices)
diff --git a/docs/src/content/docs/guides/campaigns/index.mdx b/docs/src/content/docs/guides/campaigns/index.mdx
index 9aebf71a37c..38ff18c9056 100644
--- a/docs/src/content/docs/guides/campaigns/index.mdx
+++ b/docs/src/content/docs/guides/campaigns/index.mdx
@@ -81,11 +81,11 @@ governance:
The spec is validated and compiled to create the campaign's orchestrator workflow (`.campaign.lock.yml`) that GitHub Actions can execute.
Think of it like compiling code: you write a human-friendly campaign definition, and the compiler produces a hardened, machine-executable workflow.
-**What happens next**: Once merged, the campaign orchestrator runs on schedule (daily by default) to [dispatch worker workflows, discover items, update the Project board, and report status](/gh-aw/guides/campaigns/flow/). The campaign coordinates all work toward your objective while respecting governance limits.
+**What happens next**: Once merged, the campaign orchestrator runs on schedule (daily by default) to [dispatch worker workflows, discover items, update the Project board, and report status](/gh-aw/guides/campaigns/lifecycle/). The campaign coordinates all work toward your objective while respecting governance limits.
## Next steps
- [Getting started](/gh-aw/guides/campaigns/getting-started/) – create your first campaign
- [Campaign specs](/gh-aw/guides/campaigns/specs/) – fields you can configure
-- [Flow & Lifecycle](/gh-aw/guides/campaigns/flow/) – what the orchestrator does each run
+- [Campaign Lifecycle](/gh-aw/guides/campaigns/lifecycle/) – what the orchestrator does each run
- [CLI commands](/gh-aw/guides/campaigns/cli-commands/) – inspect and validate campaigns
diff --git a/docs/src/content/docs/guides/campaigns/flow.md b/docs/src/content/docs/guides/campaigns/lifecycle.md
similarity index 99%
rename from docs/src/content/docs/guides/campaigns/flow.md
rename to docs/src/content/docs/guides/campaigns/lifecycle.md
index 8b3e3feb092..dd76b2c3f84 100644
--- a/docs/src/content/docs/guides/campaigns/flow.md
+++ b/docs/src/content/docs/guides/campaigns/lifecycle.md
@@ -1,5 +1,5 @@
---
-title: Campaign Flow & Lifecycle
+title: Campaign Lifecycle
description: What happens when the campaign orchestrator runs, and how to pause or finish a campaign.
banner:
content: 'Do not use. Campaigns are still incomplete and may produce unreliable or unintended results.'
diff --git a/docs/src/content/docs/guides/campaigns/specs.md b/docs/src/content/docs/guides/campaigns/specs.md
index 9c8881a5e3e..54747dd06d9 100644
--- a/docs/src/content/docs/guides/campaigns/specs.md
+++ b/docs/src/content/docs/guides/campaigns/specs.md
@@ -13,15 +13,19 @@ The campaign spec is a reviewable configuration file that:
- names the campaign
- points to a GitHub Project for tracking
+- defines where to discover worker-created items
- lists the workflows the orchestrator should dispatch
- defines goals (objective + KPIs)
Most users should create specs via the [Getting started flow](/gh-aw/guides/campaigns/getting-started/).
-## Minimal spec
+## Complete spec example
+
+This example shows a complete, working campaign spec with all commonly-used fields:
```yaml
# .github/workflows/framework-upgrade.campaign.md
+---
id: framework-upgrade
version: "v1"
name: "Framework Upgrade"
@@ -30,16 +34,22 @@ description: "Move services to Framework vNext"
project-url: "https://github.com/orgs/ORG/projects/1"
tracker-label: "campaign:framework-upgrade"
-# Optional: Custom GitHub token for Projects v2 operations
-# project-github-token: "${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}"
-
-## Optional: Repositories this campaign can operate on
-## If omitted, defaults to the repository where the campaign spec lives.
-allowed-repos:
+# Discovery: Where to find worker-created issues/PRs
+discovery-repos:
- "myorg/service-a"
- "myorg/service-b"
+# Or use discovery-orgs for organization-wide discovery:
+# discovery-orgs:
+# - "myorg"
+
+# Optional: Custom GitHub token for Projects v2 operations
+# project-github-token: "${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}"
-# Optional: Organizations this campaign can operate on
+# Optional: Restrict which repos this campaign can operate on
+# If omitted, defaults to the repository where the campaign spec lives.
+# allowed-repos:
+# - "myorg/service-a"
+# - "myorg/service-b"
# allowed-orgs:
# - "myorg"
@@ -48,12 +58,19 @@ kpis:
- id: services_upgraded
name: "Services upgraded"
priority: primary
- direction: "increase"
+ unit: count
+ baseline: 0
target: 50
+ time-window-days: 30
+ direction: "increase"
- id: incidents
name: "Incidents caused"
- direction: "decrease"
+ priority: supporting
+ unit: count
+ baseline: 5
target: 0
+ time-window-days: 30
+ direction: "decrease"
workflows:
- framework-upgrade
@@ -61,29 +78,48 @@ workflows:
state: "active"
owners:
- "platform-team"
+---
```
## Core fields (what they do)
### Required
-- `id`: stable identifier used for file naming and reporting.
-- `name`: human-friendly name.
-- `project-url`: GitHub Project used for tracking.
-- `objective`: one sentence describing what “done” means.
-- `kpis`: measures used in status updates.
-- `workflows`: workflow IDs the orchestrator can dispatch (via `workflow_dispatch`).
-- `state`: lifecycle state, typically `active`.
+- `id`: Stable identifier used for file naming and reporting (lowercase letters, digits, hyphens only).
+- `name`: Human-friendly name for the campaign.
+- `project-url`: GitHub Project URL used for tracking.
+
+### Required for discovery
+
+When your campaign uses `workflows` or `tracker-label`, you must specify where to discover worker-created items:
+
+- `discovery-repos`: List of repositories (in `owner/repo` format) where worker workflows create issues/PRs.
+- `discovery-orgs`: List of GitHub organizations where worker workflows operate (searches all repos in those orgs).
+
+At least one of `discovery-repos` or `discovery-orgs` is required when using workflows or tracker labels.
+
+### Commonly used
+
+- `objective`: One sentence describing what success means for this campaign.
+- `kpis`: List of 1-3 KPIs used to measure progress toward the objective.
+- `workflows`: Workflow IDs the orchestrator can dispatch via `workflow_dispatch`.
+- `tracker-label`: Label used to discover worker-created issues/PRs (commonly `campaign:`).
+- `state`: Lifecycle state (`planned`, `active`, `paused`, `completed`, or `archived`).
### Optional
-- `tracker-label`: label used to help discovery across runs (commonly `campaign:`).
-- `allowed-repos`: repositories the campaign can operate on (defaults to the repo containing the spec).
-- `allowed-orgs`: organizations the campaign can operate on.
-- `project-github-token`: token to use for Projects operations when `GITHUB_TOKEN` isn’t enough.
+- `allowed-repos`: Repositories this campaign can operate on (defaults to the repo containing the spec).
+- `allowed-orgs`: Organizations this campaign can operate on.
+- `project-github-token`: Token expression for Projects v2 operations (e.g., `${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}`).
+- `description`: Brief description of the campaign.
+- `version`: Spec version (defaults to `v1`).
+- `owners`: Primary human owners for this campaign.
+- `governance`: Pacing and opt-out policies (see Governance section below).
> [!IMPORTANT]
-> Use `priority: primary` (not `primary: true`) to mark your primary KPI.
+> - Use `priority: primary` (not `primary: true`) to mark your primary KPI.
+> - The `discovery-*` fields control WHERE to search for worker outputs.
+> - The `allowed-*` fields control WHERE the campaign can operate.
## Strategic goals (objective + KPIs)
@@ -94,13 +130,25 @@ Use `objective` and `kpis` to define what “done” means and how progress shou
## KPIs (recommended shape)
-Keep KPIs small and crisp:
+Each KPI requires these fields:
-- Use 1 primary KPI + a few supporting KPIs.
-- Use `direction: increase|decrease|maintain` to describe the desired trend.
-- Use `target` when there is a clear threshold.
+- `name`: Human-readable KPI name.
+- `baseline`: Starting value.
+- `target`: Goal value.
+- `time-window-days`: Rolling window for measurement (e.g., 7, 14, 30 days).
-If you define `kpis`, also define `objective` (and vice versa). It keeps the spec reviewable and makes reports consistent.
+Optional fields:
+
+- `id`: Stable identifier (lowercase letters, digits, hyphens).
+- `priority`: `primary` or `supporting` (exactly one KPI should be primary).
+- `unit`: Unit of measurement (e.g., `count`, `percent`, `days`).
+- `direction`: `increase` or `decrease` (describes improvement direction).
+- `source`: Signal source (`ci`, `pull_requests`, `code_security`, or `custom`).
+
+Keep KPIs small and crisp:
+
+- Use 1 primary KPI + up to 2 supporting KPIs (maximum 3 total).
+- When you define `kpis`, also define `objective` (and vice versa).
## Unified tracking (GitHub Project)
@@ -115,11 +163,7 @@ Project updates are applied by the orchestrator using safe outputs; see [Update
Use `workflows` to list the dispatchable workflows (“workers”) the orchestrator can trigger via `workflow_dispatch`.
-For worker requirements and dispatch behavior, see [Dispatching worker workflows](/gh-aw/guides/campaigns/flow/#dispatching-worker-workflows).
-
-## Governance (pacing)
-
-Use `governance` to cap how much the orchestrator updates per run.
+For worker requirements and dispatch behavior, see [Dispatching worker workflows](/gh-aw/guides/campaigns/lifecycle/#dispatching-worker-workflows).
## Governance (pacing & safety)
@@ -147,5 +191,5 @@ governance:
## Next
-- See [Flow & lifecycle](/gh-aw/guides/campaigns/flow/) for what happens each run.
+- See [Campaign lifecycle](/gh-aw/guides/campaigns/lifecycle/) for what happens each run.
- See [CLI commands](/gh-aw/guides/campaigns/cli-commands/) to validate and inspect campaigns.