diff --git a/.github/aw/orchestrate-agentic-campaign.md b/.github/aw/orchestrate-agentic-campaign.md
index e0c5e56a19..343477a35b 100644
--- a/.github/aw/orchestrate-agentic-campaign.md
+++ b/.github/aw/orchestrate-agentic-campaign.md
@@ -128,8 +128,6 @@ and synchronizing campaign state into a GitHub Project board.
body: |
## Campaign Overview
- {{ if .Objective }}**Objective**: {{.Objective}}{{ end }}
-
This Epic issue tracks the overall progress of the campaign. All work items are sub-issues of this Epic.
**Campaign Details:**
@@ -242,7 +240,7 @@ Every campaign run MUST create a status update using `create-project-status-upda
- **Most Important Findings**: Highlight the 2-3 most critical discoveries, insights, or blockers from this run
- **What Was Learned**: Document key learnings, patterns observed, or insights gained during this run
-- **KPI Trends**: Report progress on EACH campaign KPI{{ if .KPIs }} ({{ range $i, $kpi := .KPIs }}{{if $i}}, {{end}}{{ $kpi.Name }}{{end}}){{ end }} with baseline → current → target format, including direction and velocity
+- **Campaign Progress**: Report on campaign metrics and trends with baseline → current → target format, including direction and velocity
- **Campaign Summary**: Tasks completed, in progress, blocked, and overall completion percentage
- **Next Steps**: Clear action items and priorities for the next run
@@ -251,13 +249,6 @@ Every campaign run MUST create a status update using `create-project-status-upda
- Use today's date for start_date and target_date (or appropriate future date for target)
- Body must be comprehensive yet concise (target: 200-400 words)
-{{ if .KPIs }}
-**Campaign KPIs to Report:**
-{{ range .KPIs }}
-- **{{ .Name }}**{{ if .Priority }} ({{ .Priority }}){{ end }}: baseline {{ .Baseline }}{{ if .Unit }} {{ .Unit }}{{ end }} → target {{ .Target }}{{ if .Unit }} {{ .Unit }}{{ end }} over {{ .TimeWindowDays }} days{{ if .Direction }} ({{ .Direction }}){{ end }}
-{{ end }}
-{{ end }}
-
Example status update:
```yaml
create-project-status-update:
@@ -284,19 +275,19 @@ create-project-status-update:
- Documentation updates tied to code changes have higher accuracy and completeness
- Users report fewer issues when examples include error handling patterns
- ## KPI Trends
+ ## Campaign Progress
- **Documentation Coverage** (Primary KPI):
+ **Documentation Coverage** (Primary Metric):
- Baseline: 85% → Current: 88% → Target: 95%
- Direction: ↑ Increasing (+3% this week, +1% velocity/week)
- Status: ON TRACK - At current velocity, will reach 95% in 7 weeks
- **Accessibility Score** (Supporting KPI):
+ **Accessibility Score** (Supporting Metric):
- Baseline: 90% → Current: 91% → Target: 98%
- Direction: ↑ Increasing (+1% this month)
- Status: AT RISK - Slower progress than expected, may need dedicated focus
- **User-Reported Issues** (Supporting KPI):
+ **User-Reported Issues** (Supporting Metric):
- Baseline: 15/month → Current: 12/month → Target: 5/month
- Direction: ↓ Decreasing (-3 this month, -20% velocity)
- Status: ON TRACK - Trending toward target
diff --git a/.github/workflows/security-alert-burndown.campaign.lock.yml b/.github/workflows/security-alert-burndown.campaign.lock.yml
index 710190460e..891055e70d 100644
--- a/.github/workflows/security-alert-burndown.campaign.lock.yml
+++ b/.github/workflows/security-alert-burndown.campaign.lock.yml
@@ -897,10 +897,6 @@ jobs:
This workflow orchestrates the 'Security Alert Burndown' campaign.
- - Objective: Systematically reduce security alerts (code scanning, Dependabot, secret scanning) to zero critical issues and fewer than 5 high-severity issues
- - KPIs:
- - Critical Security Alerts (primary): baseline 5 → target 0 over 90 days alerts
- - High-Severity Alerts (supporting): baseline 15 → target 5 over 90 days alerts
- Associated workflows: code-scanning-fixer, security-fix-pr, dependabot-bundler, secret-scanning-triage
- Memory paths: memory/campaigns/security-alert-burndown/**
- Metrics glob: `memory/campaigns/security-alert-burndown/metrics/*.json`
@@ -1339,8 +1335,6 @@ jobs:
body: |
## Campaign Overview
- **Objective**: Systematically reduce security alerts (code scanning, Dependabot, secret scanning) to zero critical issues and fewer than 5 high-severity issues
-
This Epic issue tracks the overall progress of the campaign. All work items are sub-issues of this Epic.
**Campaign Details:**
@@ -1377,8 +1371,6 @@ jobs:
4) **Record the Epic issue number** in repo-memory for reference (e.g., in cursor file or metadata).
- PROMPT_EOF
- cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT"
**Note:** This step typically runs only on the first orchestrator execution. On subsequent runs, verify the Epic exists and is on the board, but do not recreate it.
---
@@ -1389,6 +1381,8 @@ jobs:
1) Read the precomputed discovery manifest: `./.gh-aw/campaign.discovery.json`
- This manifest contains all discovered worker outputs with normalized metadata
+ PROMPT_EOF
+ cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT"
- Schema version: v1
- Fields: campaign_id, generated_at, discovery (total_items, cursor info), summary (counts), items (array of normalized items)
@@ -1455,7 +1449,7 @@ jobs:
- **Most Important Findings**: Highlight the 2-3 most critical discoveries, insights, or blockers from this run
- **What Was Learned**: Document key learnings, patterns observed, or insights gained during this run
- - **KPI Trends**: Report progress on EACH campaign KPI (Critical Security Alerts, High-Severity Alerts) with baseline → current → target format, including direction and velocity
+ - **Campaign Progress**: Report on campaign metrics and trends with baseline → current → target format, including direction and velocity
- **Campaign Summary**: Tasks completed, in progress, blocked, and overall completion percentage
- **Next Steps**: Clear action items and priorities for the next run
@@ -1464,15 +1458,6 @@ jobs:
- Use today's date for start_date and target_date (or appropriate future date for target)
- Body must be comprehensive yet concise (target: 200-400 words)
-
- **Campaign KPIs to Report:**
-
- - **Critical Security Alerts** (primary): baseline 5 alerts → target 0 alerts over 90 days
-
- - **High-Severity Alerts** (supporting): baseline 15 alerts → target 5 alerts over 90 days
-
-
-
Example status update:
```yaml
create-project-status-update:
@@ -1499,19 +1484,19 @@ jobs:
- Documentation updates tied to code changes have higher accuracy and completeness
- Users report fewer issues when examples include error handling patterns
- ## KPI Trends
+ ## Campaign Progress
- **Documentation Coverage** (Primary KPI):
+ **Documentation Coverage** (Primary Metric):
- Baseline: 85% → Current: 88% → Target: 95%
- Direction: ↑ Increasing (+3% this week, +1% velocity/week)
- Status: ON TRACK - At current velocity, will reach 95% in 7 weeks
- **Accessibility Score** (Supporting KPI):
+ **Accessibility Score** (Supporting Metric):
- Baseline: 90% → Current: 91% → Target: 98%
- Direction: ↑ Increasing (+1% this month)
- Status: AT RISK - Slower progress than expected, may need dedicated focus
- **User-Reported Issues** (Supporting KPI):
+ **User-Reported Issues** (Supporting Metric):
- Baseline: 15/month → Current: 12/month → Target: 5/month
- Direction: ↓ Decreasing (-3 this month, -20% velocity)
- Status: ON TRACK - Trending toward target
diff --git a/.github/workflows/security-alert-burndown.campaign.md b/.github/workflows/security-alert-burndown.campaign.md
index b8c63340f5..65ef362ce3 100644
--- a/.github/workflows/security-alert-burndown.campaign.md
+++ b/.github/workflows/security-alert-burndown.campaign.md
@@ -3,36 +3,11 @@ id: security-alert-burndown
name: Security Alert Burndown
description: Systematically burns down code security alerts with focus on file write issues
project-url: https://github.com/orgs/githubnext/projects/134
-version: v1
-state: planned
workflows:
- code-scanning-fixer
- security-fix-pr
- dependabot-bundler
- secret-scanning-triage
-allowed-repos:
- - githubnext/gh-aw
-discovery-repos:
- - githubnext/gh-aw
-tracker-label: z_campaign_security-alert-burndown
-memory-paths:
- - memory/campaigns/security-alert-burndown/**
-metrics-glob: memory/campaigns/security-alert-burndown/metrics/*.json
-cursor-glob: memory/campaigns/security-alert-burndown/cursor.json
-objective: Systematically reduce security alerts (code scanning, Dependabot, secret scanning) to zero critical issues and fewer than 5 high-severity issues
-kpis:
- - name: Critical Security Alerts
- baseline: 5
- target: 0
- unit: alerts
- time-window-days: 90
- priority: primary
- - name: High-Severity Alerts
- baseline: 15
- target: 5
- unit: alerts
- time-window-days: 90
- priority: supporting
governance:
max-new-items-per-run: 3
max-discovery-items-per-run: 100
@@ -46,24 +21,30 @@ governance:
owners:
- "@mnkiefer"
risk-level: high
-allowed-safe-outputs:
- - create-pull-request
- - create-issue
- - autofix-code-scanning-alert
- - add-comment
- - update-project
-tags:
- - security
- - automated-fixes
- - code-scanning
- - dependabot
- - secret-scanning
---
# Security Alert Burndown Campaign
This campaign systematically burns down code security alerts with the following strategy:
+## Objective
+
+Systematically reduce security alerts (code scanning, Dependabot, secret scanning) to zero critical issues and fewer than 5 high-severity issues.
+
+## Key Performance Indicators (KPIs)
+
+### Primary KPI: Critical Security Alerts
+- **Baseline**: 5 alerts
+- **Target**: 0 alerts
+- **Time Window**: 90 days
+- **Unit**: alerts
+
+### Supporting KPI: High-Severity Alerts
+- **Baseline**: 15 alerts
+- **Target**: 5 alerts
+- **Time Window**: 90 days
+- **Unit**: alerts
+
## Focus Areas
- **Prioritizes file write security issues** (highest risk)
diff --git a/docs/src/content/docs/examples/campaigns/security-audit.campaign.md b/docs/src/content/docs/examples/campaigns/security-audit.campaign.md
index 9880deb93c..f12d160528 100644
--- a/docs/src/content/docs/examples/campaigns/security-audit.campaign.md
+++ b/docs/src/content/docs/examples/campaigns/security-audit.campaign.md
@@ -2,40 +2,13 @@
title: Security Audit Campaign Example
id: security-audit-2026
name: Security Audit 2026
-version: v1
-state: planned
project-url: https://github.com/orgs/example/projects/42
-tracker-label: z_campaign_security-audit-2026
-# Worker workflows that will be discovered and dispatched
workflows:
- security-scanner
- dependency-updater
- vulnerability-reporter
-# Campaign memory storage
-memory-paths:
- - memory/campaigns/security-audit-2026/**
-metrics-glob: memory/campaigns/security-audit-2026/metrics/*.json
-cursor-glob: memory/campaigns/security-audit-2026/cursor.json
-
-# Campaign goals and KPIs
-objective: Reduce security vulnerabilities to zero critical and less than 5 high-severity issues
-kpis:
- - name: Critical Vulnerabilities
- baseline: 3
- target: 0
- unit: issues
- time_window_days: 90
- priority: primary
- - name: High-Severity Vulnerabilities
- baseline: 12
- target: 5
- unit: issues
- time_window_days: 90
- priority: supporting
-
-# Governance
governance:
max-new-items-per-run: 10
max-discovery-items-per-run: 100
@@ -46,7 +19,6 @@ governance:
- no-campaign
- no-bot
-# Team
owners:
- "@security-team"
executive-sponsors:
@@ -58,6 +30,26 @@ risk-level: high
This campaign orchestrates a comprehensive security audit across all repositories, focusing on:
+## Objective
+
+Reduce security vulnerabilities to zero critical and less than 5 high-severity issues.
+
+## Key Performance Indicators (KPIs)
+
+### Primary KPI: Critical Vulnerabilities
+- **Baseline**: 3 issues
+- **Target**: 0 issues
+- **Time Window**: 90 days
+- **Unit**: issues
+
+### Supporting KPI: High-Severity Vulnerabilities
+- **Baseline**: 12 issues
+- **Target**: 5 issues
+- **Time Window**: 90 days
+- **Unit**: issues
+
+## Focus Areas
+
1. **Vulnerability Scanning**: Identify and track security vulnerabilities
2. **Dependency Updates**: Update outdated dependencies with known vulnerabilities
3. **Compliance Reporting**: Generate security compliance reports for stakeholders
diff --git a/docs/src/content/docs/guides/campaigns/specs.md b/docs/src/content/docs/guides/campaigns/specs.md
index 63f3880727..2021603999 100644
--- a/docs/src/content/docs/guides/campaigns/specs.md
+++ b/docs/src/content/docs/guides/campaigns/specs.md
@@ -5,47 +5,44 @@ banner:
content: 'Do not use. Campaigns are still incomplete and may produce unreliable or unintended results.'
---
-Campaign specs are YAML frontmatter configuration files at `.github/workflows/.campaign.md`. The frontmatter defines campaign metadata, goals, workers, and governance. The body can contain narrative context.
+Campaign specs are YAML frontmatter configuration files at `.github/workflows/.campaign.md`. The frontmatter defines pure configuration (id, project-url, workflows, governance, etc.), while the markdown body contains narrative context including objectives, KPIs, timelines, and strategy.
## Spec structure
+A minimal campaign spec requires only `id`, `project-url`, and `workflows`. Most fields have sensible defaults.
+
```yaml
---
id: framework-upgrade
name: "Framework Upgrade"
-description: "Move services to Framework vNext"
-state: active
-
project-url: "https://github.com/orgs/ORG/projects/1"
-tracker-label: "z_campaign_framework-upgrade"
-
-discovery-repos:
- - "myorg/service-a"
- - "myorg/service-b"
-
-objective: "Upgrade all services to Framework vNext with zero downtime."
-kpis:
- - id: services_upgraded
- name: "Services upgraded"
- priority: primary
- unit: count
- baseline: 0
- target: 50
- time-window-days: 30
- direction: "increase"
workflows:
- framework-upgrade-scanner
governance:
max-project-updates-per-run: 10
- max-discovery-items-per-run: 50
-
-owners:
- - "platform-team"
---
-Additional narrative context about the campaign...
+# Framework Upgrade Campaign
+
+## Objective
+
+Upgrade all services to Framework vNext with zero downtime.
+
+## Key Performance Indicators (KPIs)
+
+### Primary KPI: Services Upgraded
+- **Baseline**: 0 services
+- **Target**: 50 services
+- **Time Window**: 30 days
+- **Direction**: Increase
+
+## Timeline
+
+- **Phase 1** (Weeks 1-2): Discovery and planning
+- **Phase 2** (Weeks 3-6): Incremental upgrades
+- **Phase 3** (Week 7+): Validation and monitoring
```
## Required fields
@@ -55,107 +52,109 @@ Additional narrative context about the campaign...
**id** - Stable identifier for file naming and reporting
- Format: lowercase letters, digits, hyphens only
- Example: `security-audit-2025`
+- Auto-generates defaults for: tracker-label, memory-paths, metrics-glob, cursor-glob
**name** - Human-friendly display name
- Example: `"Security Audit 2025"`
+- Default: Uses `id` if not specified
**project-url** - GitHub Project board URL for tracking
- Format: `https://github.com/orgs/ORG/projects/N`
- Example: `https://github.com/orgs/mycompany/projects/1`
-### Discovery scope
+**workflows** - Worker workflows that implement the campaign
+- Format: List of workflow IDs (file names without .md extension)
+- Example: `["security-scanner", "dependency-fixer"]`
-At least one of these is required when using `workflows` or `tracker-label`:
+## Fields with defaults
-**discovery-repos** - Specific repositories to search
-- Format: List of `owner/repo` strings
-- Example: `["myorg/api", "myorg/web"]`
+Many fields have automatic defaults based on the campaign ID:
-**discovery-orgs** - Organizations to search (all repos)
-- Format: List of organization names
-- Example: `["myorg"]`
+**state** - Lifecycle stage
+- Default: `active`
+- Values: `planned`, `active`, `paused`, `completed`, `archived`
-## Common fields
+**tracker-label** - Label for discovering worker outputs
+- Default: `z_campaign_{id}` (e.g., `z_campaign_security-audit`)
+- Can be customized if needed
-**objective** - One-sentence success definition
-- Example: `"Eliminate all critical security vulnerabilities"`
+**memory-paths** - Where campaign writes repo-memory
+- Default: `["memory/campaigns/{id}/**"]`
-**kpis** - Key performance indicators (1-3 maximum)
-- See [KPI specification](#kpi-specification) below
+**metrics-glob** - Glob for JSON metrics snapshots
+- Default: `memory/campaigns/{id}/metrics/*.json`
-**workflows** - Worker workflows to dispatch
-- Format: List of workflow IDs (file names without extension)
-- Example: `["security-scanner", "dependency-fixer"]`
+**cursor-glob** - Glob for durable cursor/checkpoint file
+- Default: `memory/campaigns/{id}/cursor.json`
-**tracker-label** - Label for discovering worker outputs
-- Format: `campaign:`
-- Example: `campaign:security-audit`
+**allowed-repos** - Repositories campaign can operate on
+- Default: Current repository (where campaign is defined)
-**state** - Lifecycle state
-- Values: `planned`, `active`, `paused`, `completed`, `archived`
-- Default: `planned`
+**discovery-repos** - Repositories to search for worker outputs
+- Default: Same as `allowed-repos`
-**governance** - Pacing and safety limits
-- See [Governance fields](#governance-fields) below
+### Discovery scope (optional)
+
+Override discovery scope when operating across multiple repositories:
+
+**discovery-repos** - Specific repositories to search
+- Format: List of `owner/repo` strings
+- Example: `["myorg/api", "myorg/web"]`
+- Default: Same as `allowed-repos` (current repository)
+
+**discovery-orgs** - Organizations to search (all repos)
+- Format: List of organization names
+- Example: `["myorg"]`
+- Overrides `discovery-repos` when specified
## Optional fields
**description** - Brief campaign description
+- Provides context in listings and dashboards
**version** - Spec format version
- Default: `v1`
+- Usually not needed in specs
**owners** - Primary human owners
- Format: List of team or user names
+- Example: `["@security-team", "alice"]`
-**allowed-repos** - Repositories campaign can modify
-- Default: Repository containing the spec
-- Format: List of `owner/repo` strings
+**governance** - Pacing and safety limits
+- See [Governance fields](#governance-fields) below
**allowed-orgs** - Organizations campaign can modify
- Format: List of organization names
+- Alternative to specifying individual `allowed-repos`
**project-github-token** - Custom token for Projects API
- Format: Token expression like `${{ secrets.TOKEN_NAME }}`
- Use when default `GITHUB_TOKEN` lacks Projects permissions
-## KPI specification
-
-Each KPI requires these fields:
-
-```yaml
-kpis:
- - id: vulnerabilities_fixed # Stable identifier
- name: "Vulnerabilities resolved" # Display name
- priority: primary # One KPI must be primary
- unit: count # Measurement unit
- baseline: 50 # Starting value
- target: 0 # Goal value
- time-window-days: 30 # Measurement period
- direction: "decrease" # Improvement direction
-```
-
-### Required KPI fields
-
-- **name** - Human-readable name
-- **baseline** - Starting value
-- **target** - Goal value
-- **time-window-days** - Rolling window (7, 14, 30, or 90 days)
+## Markdown body content
-### Optional KPI fields
+The markdown body contains narrative context and goals. Include:
-- **id** - Stable identifier (defaults to sanitized name)
-- **priority** - `primary` or `supporting` (exactly one primary)
-- **unit** - Measurement unit (`count`, `percent`, `days`, `hours`)
-- **direction** - `increase` or `decrease`
-- **source** - Signal source (`ci`, `pull_requests`, `code_security`, `custom`)
+**Objective** - Clear statement of what the campaign aims to achieve
+- Example: "Reduce all critical security vulnerabilities to zero"
+- Can include multiple paragraphs with context and rationale
-### KPI guidelines
+**Key Performance Indicators (KPIs)** - Measurable success metrics
+- Define 1 primary KPI + up to 2 supporting KPIs
+- Include baseline, target, time window, direction for each
+- Example format:
+ ```markdown
+ ### Primary KPI: Critical Vulnerabilities
+ - **Baseline**: 15 issues
+ - **Target**: 0 issues
+ - **Time Window**: 90 days
+ - **Direction**: Decrease
+ ```
-- Define 1 primary KPI + up to 2 supporting KPIs (3 maximum)
-- Always pair `objective` with `kpis` (define both or neither)
-- Use concrete, measurable targets
-- Choose realistic time windows
+**Timeline** - Campaign phases and milestones
+**Worker Workflows** - Descriptions of automated workflows
+**Success Criteria** - Concrete conditions for completion
+**Risk Management** - Mitigation strategies and approvals
## Governance fields
@@ -236,47 +235,52 @@ gh aw campaign validate
Common validation errors:
-- Missing required fields (`id`, `name`, `project-url`)
-- Missing discovery scope when using `workflows` or `tracker-label`
-- Invalid KPI configuration (no primary, too many KPIs)
+- Missing required fields (`id`, `project-url`, `workflows`)
- Invalid `state` value
- Malformed URLs or identifiers
-## Example: Security audit campaign
+## Minimal example
+
+The simplest possible campaign:
```yaml
---
id: security-audit-q1
-version: "v1"
name: "Security Audit Q1 2025"
-description: "Quarterly security review and remediation"
-state: active
+project-url: "https://github.com/orgs/myorg/projects/5"
+
+workflows:
+ - security-scanner
+ - dependency-updater
+---
+
+# Security Audit Q1 2025 Campaign
+Document your objectives, KPIs, timeline, and strategy here...
+```
+
+This automatically gets:
+- `state: active`
+- `tracker-label: z_campaign_security-audit-q1`
+- `memory-paths: ["memory/campaigns/security-audit-q1/**"]`
+- `metrics-glob: memory/campaigns/security-audit-q1/metrics/*.json`
+- `cursor-glob: memory/campaigns/security-audit-q1/cursor.json`
+- `allowed-repos` and `discovery-repos`: current repository
+
+## Full example
+
+With governance and multi-org scope:
+
+```yaml
+---
+id: security-audit-q1
+name: "Security Audit Q1 2025"
+description: "Quarterly security review and remediation"
project-url: "https://github.com/orgs/myorg/projects/5"
-tracker-label: "campaign:security-audit-q1"
discovery-orgs:
- "myorg"
-objective: "Resolve all high and critical security vulnerabilities"
-kpis:
- - id: critical_vulns
- name: "Critical vulnerabilities"
- priority: primary
- unit: count
- baseline: 15
- target: 0
- time-window-days: 90
- direction: "decrease"
- - id: mttr
- name: "Mean time to resolution"
- priority: supporting
- unit: days
- baseline: 14
- target: 3
- time-window-days: 30
- direction: "decrease"
-
workflows:
- security-scanner
- dependency-updater
@@ -290,8 +294,29 @@ owners:
- "security-team"
---
-This campaign runs weekly to scan for vulnerabilities and track remediation.
-Workers create issues with severity labels and automated fix PRs where possible.
+# Security Audit Q1 2025 Campaign
+
+## Objective
+
+Resolve all high and critical security vulnerabilities across the organization.
+
+## Key Performance Indicators (KPIs)
+
+### Primary KPI: Critical Vulnerabilities
+- **Baseline**: 15 vulnerabilities
+- **Target**: 0 vulnerabilities
+- **Time Window**: 90 days
+- **Direction**: Decrease
+
+### Supporting KPI: Mean Time to Resolution
+- **Baseline**: 14 days
+- **Target**: 3 days
+- **Time Window**: 30 days
+- **Direction**: Decrease
+
+## Timeline
+
+This campaign runs weekly to scan for vulnerabilities and track remediation. Workers create issues with severity labels and automated fix PRs where possible.
```
## Further reading
diff --git a/pkg/campaign/interactive.go b/pkg/campaign/interactive.go
index 1df815b3c5..cddeee81ea 100644
--- a/pkg/campaign/interactive.go
+++ b/pkg/campaign/interactive.go
@@ -30,7 +30,6 @@ type InteractiveCampaignConfig struct {
CreateProject bool
ProjectOwner string
LinkRepo string
- Objective string
Force bool
}
@@ -168,8 +167,7 @@ func promptForObjective(config *InteractiveCampaignConfig) error {
}
config.Description = strings.TrimSpace(objective)
- config.Objective = config.Description
- interactiveLog.Printf("Campaign objective: %s", config.Objective)
+ interactiveLog.Printf("Campaign description: %s", config.Description)
return nil
}
@@ -512,7 +510,6 @@ func generateCampaignFromConfig(rootDir string, config *InteractiveCampaignConfi
ID: config.ID,
Name: config.Name,
Description: config.Description,
- Objective: config.Objective,
ProjectURL: "https://github.com/orgs/ORG/projects/1", // Placeholder
Version: "v1",
State: "planned",
diff --git a/pkg/campaign/loader.go b/pkg/campaign/loader.go
index 0a378f964b..ce1185faeb 100644
--- a/pkg/campaign/loader.go
+++ b/pkg/campaign/loader.go
@@ -82,6 +82,36 @@ func LoadSpecs(rootDir string) ([]CampaignSpec, error) {
spec.Name = spec.ID
}
+ // Default state to "active" if not specified
+ if strings.TrimSpace(spec.State) == "" {
+ spec.State = "active"
+ log.Printf("Defaulted state to 'active' for campaign '%s'", spec.ID)
+ }
+
+ // Default tracker-label based on campaign ID if not specified
+ if strings.TrimSpace(spec.TrackerLabel) == "" {
+ spec.TrackerLabel = fmt.Sprintf("z_campaign_%s", spec.ID)
+ log.Printf("Defaulted tracker-label to '%s' for campaign '%s'", spec.TrackerLabel, spec.ID)
+ }
+
+ // Default memory-paths based on campaign ID if not specified
+ if len(spec.MemoryPaths) == 0 {
+ spec.MemoryPaths = []string{fmt.Sprintf("memory/campaigns/%s/**", spec.ID)}
+ log.Printf("Defaulted memory-paths to '%s' for campaign '%s'", spec.MemoryPaths[0], spec.ID)
+ }
+
+ // Default metrics-glob based on campaign ID if not specified
+ if strings.TrimSpace(spec.MetricsGlob) == "" {
+ spec.MetricsGlob = fmt.Sprintf("memory/campaigns/%s/metrics/*.json", spec.ID)
+ log.Printf("Defaulted metrics-glob to '%s' for campaign '%s'", spec.MetricsGlob, spec.ID)
+ }
+
+ // Default cursor-glob based on campaign ID if not specified
+ if strings.TrimSpace(spec.CursorGlob) == "" {
+ spec.CursorGlob = fmt.Sprintf("memory/campaigns/%s/cursor.json", spec.ID)
+ log.Printf("Defaulted cursor-glob to '%s' for campaign '%s'", spec.CursorGlob, spec.ID)
+ }
+
// Default allowed-repos to current repository if not specified
if len(spec.AllowedRepos) == 0 {
currentRepo, err := getCurrentRepository()
@@ -93,6 +123,12 @@ func LoadSpecs(rootDir string) ([]CampaignSpec, error) {
}
}
+ // Default discovery-repos to allowed-repos if not specified
+ if len(spec.DiscoveryRepos) == 0 && len(spec.DiscoveryOrgs) == 0 {
+ spec.DiscoveryRepos = spec.AllowedRepos
+ log.Printf("Defaulted discovery-repos to allowed-repos for campaign '%s'", spec.ID)
+ }
+
spec.ConfigPath = filepath.ToSlash(filepath.Join(".github", "workflows", name))
specs = append(specs, spec)
}
@@ -199,7 +235,7 @@ func CreateSpecSkeleton(rootDir, id string, force bool) (string, error) {
buf.WriteString("By default, this campaign will target the current repository. To target additional repositories:\n\n")
buf.WriteString("1. **Add allowed-repos** (optional): Specify repositories to target\n")
buf.WriteString("2. **Define workflows**: List workflows to execute (e.g., `vulnerability-scanner`)\n")
- buf.WriteString("3. **Add objective & KPIs**: Define measurable success criteria\n")
+ buf.WriteString("3. **Add narrative context**: Define campaign goals, workflows, and timeline in the markdown body\n")
buf.WriteString("4. **Set owners**: Specify who is responsible for this campaign\n")
buf.WriteString("5. **Compile**: Run `gh aw compile` to generate the orchestrator\n\n")
buf.WriteString("## Example Configuration\n\n")
diff --git a/pkg/campaign/orchestrator.go b/pkg/campaign/orchestrator.go
index ac9d27cfe9..a30d5ccddf 100644
--- a/pkg/campaign/orchestrator.go
+++ b/pkg/campaign/orchestrator.go
@@ -212,32 +212,6 @@ func BuildOrchestrator(spec *CampaignSpec, campaignFilePath string) (*workflow.W
// Track whether we have any meaningful campaign details
hasDetails := false
- if strings.TrimSpace(spec.Objective) != "" {
- fmt.Fprintf(markdownBuilder, "- Objective: %s\n", strings.TrimSpace(spec.Objective))
- hasDetails = true
- }
- if len(spec.KPIs) > 0 {
- markdownBuilder.WriteString("- KPIs:\n")
- for _, kpi := range spec.KPIs {
- name := strings.TrimSpace(kpi.Name)
- if name == "" {
- name = "(unnamed)"
- }
- priority := strings.TrimSpace(kpi.Priority)
- if priority == "" && len(spec.KPIs) == 1 {
- priority = "primary"
- }
- unit := strings.TrimSpace(kpi.Unit)
- if unit != "" {
- unit = " " + unit
- }
- if priority != "" {
- priority = " (" + priority + ")"
- }
- fmt.Fprintf(markdownBuilder, " - %s%s: baseline %.4g → target %.4g over %d days%s\n", name, priority, kpi.Baseline, kpi.Target, kpi.TimeWindowDays, unit)
- }
- hasDetails = true
- }
if len(spec.Workflows) > 0 {
markdownBuilder.WriteString("- Associated workflows: ")
markdownBuilder.WriteString(strings.Join(spec.Workflows, ", "))
@@ -309,15 +283,11 @@ func BuildOrchestrator(spec *CampaignSpec, campaignFilePath string) (*workflow.W
promptData := CampaignPromptData{
CampaignID: spec.ID,
CampaignName: spec.Name,
- Objective: strings.TrimSpace(spec.Objective),
ProjectURL: strings.TrimSpace(spec.ProjectURL),
CursorGlob: strings.TrimSpace(spec.CursorGlob),
MetricsGlob: strings.TrimSpace(spec.MetricsGlob),
Workflows: spec.Workflows,
}
- if len(spec.KPIs) > 0 {
- promptData.KPIs = spec.KPIs
- }
if spec.Governance != nil {
promptData.MaxDiscoveryItemsPerRun = spec.Governance.MaxDiscoveryItemsPerRun
promptData.MaxDiscoveryPagesPerRun = spec.Governance.MaxDiscoveryPagesPerRun
diff --git a/pkg/campaign/orchestrator_test.go b/pkg/campaign/orchestrator_test.go
index 87ba41979d..c97d94a95f 100644
--- a/pkg/campaign/orchestrator_test.go
+++ b/pkg/campaign/orchestrator_test.go
@@ -132,49 +132,6 @@ func TestBuildOrchestrator_WorkflowsInDiscovery(t *testing.T) {
})
}
-func TestBuildOrchestrator_ObjectiveAndKPIsAreRendered(t *testing.T) {
- withTempGitRepoWithInstalledCampaignPrompts(t, func(_ string) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- Description: "A test campaign",
- ProjectURL: "https://github.com/orgs/test/projects/1",
- Workflows: []string{"daily-file-diet"},
- Objective: "Improve CI stability",
- KPIs: []CampaignKPI{
- {
- Name: "Build success rate",
- Priority: "primary",
- Unit: "ratio",
- Baseline: 0.8,
- Target: 0.95,
- TimeWindowDays: 7,
- Direction: "increase",
- Source: "ci",
- },
- },
- }
-
- mdPath := ".github/workflows/test-campaign.campaign.md"
- data, _ := BuildOrchestrator(spec, mdPath)
- if data == nil {
- t.Fatalf("expected non-nil WorkflowData")
- }
-
- // Golden assertions: these should only change if we intentionally change the orchestrator contract.
- expectedPhrases := []string{
- "- Objective: Improve CI stability",
- "- KPIs:",
- "Build success rate",
- }
- for _, expected := range expectedPhrases {
- if !strings.Contains(data.MarkdownContent, expected) {
- t.Errorf("expected markdown to contain %q, got: %q", expected, data.MarkdownContent)
- }
- }
- })
-}
-
func TestBuildOrchestrator_TrackerIDMonitoring(t *testing.T) {
withTempGitRepoWithInstalledCampaignPrompts(t, func(_ string) {
spec := &CampaignSpec{
diff --git a/pkg/campaign/schemas/campaign_spec_schema.json b/pkg/campaign/schemas/campaign_spec_schema.json
index 1b128ce517..56a150129e 100644
--- a/pkg/campaign/schemas/campaign_spec_schema.json
+++ b/pkg/campaign/schemas/campaign_spec_schema.json
@@ -20,68 +20,6 @@
"type": "string",
"description": "Brief description of the campaign"
},
- "objective": {
- "type": "string",
- "description": "Outcome-owned objective statement for the campaign (what success means)",
- "minLength": 1
- },
- "kpis": {
- "type": "array",
- "description": "Up to 3 KPIs used to measure the campaign objective",
- "minItems": 1,
- "maxItems": 3,
- "items": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "id": {
- "type": "string",
- "description": "Optional stable identifier for the KPI (lowercase letters, digits, and hyphens)",
- "pattern": "^[a-z0-9-]+$",
- "minLength": 1
- },
- "name": {
- "type": "string",
- "description": "Human-readable KPI name",
- "minLength": 1
- },
- "priority": {
- "type": "string",
- "description": "KPI priority: primary (exactly one per campaign) or supporting",
- "enum": ["primary", "supporting"]
- },
- "unit": {
- "type": "string",
- "description": "Optional KPI unit (e.g., percent, days, count)",
- "minLength": 1
- },
- "baseline": {
- "type": "number",
- "description": "Baseline KPI value"
- },
- "target": {
- "type": "number",
- "description": "Target KPI value"
- },
- "time-window-days": {
- "type": "integer",
- "description": "Rolling time window, in days, used for KPI measurement (e.g., 7, 14, 30)",
- "minimum": 1
- },
- "direction": {
- "type": "string",
- "description": "Whether improvement means increasing or decreasing the KPI",
- "enum": ["increase", "decrease"]
- },
- "source": {
- "type": "string",
- "description": "Signal source used to compute this KPI",
- "enum": ["ci", "pull_requests", "code_security", "custom"]
- }
- },
- "required": ["name", "baseline", "target", "time-window-days"]
- }
- },
"project-url": {
"type": "string",
"description": "URL of the GitHub Project used as the primary campaign dashboard",
diff --git a/pkg/campaign/spec.go b/pkg/campaign/spec.go
index 9553adcafd..2321b01a26 100644
--- a/pkg/campaign/spec.go
+++ b/pkg/campaign/spec.go
@@ -14,14 +14,6 @@ type CampaignSpec struct {
Name string `yaml:"name" json:"name" console:"header:Name,maxlen:30"`
Description string `yaml:"description,omitempty" json:"description,omitempty" console:"header:Description,omitempty,maxlen:60"`
- // Objective is an optional outcome-owned statement describing what success means
- // for this campaign.
- Objective string `yaml:"objective,omitempty" json:"objective,omitempty" console:"header:Objective,omitempty,maxlen:60"`
-
- // KPIs is an optional list of KPIs used to measure progress toward the objective.
- // Recommended: 1 primary KPI plus up to 2 supporting KPIs.
- KPIs []CampaignKPI `yaml:"kpis,omitempty" json:"kpis,omitempty"`
-
// ProjectURL points to the GitHub Project used as the primary campaign
// dashboard.
ProjectURL string `yaml:"project-url,omitempty" json:"project_url,omitempty" console:"header:Project URL,omitempty,maxlen:40"`
@@ -136,39 +128,6 @@ type CampaignSpec struct {
ConfigPath string `yaml:"-" json:"config_path" console:"header:Config Path,maxlen:60"`
}
-// CampaignKPI defines a single KPI used for campaign measurement.
-type CampaignKPI struct {
- // ID is an optional stable identifier for this KPI.
- ID string `yaml:"id,omitempty" json:"id,omitempty"`
-
- // Name is a human-readable KPI name.
- Name string `yaml:"name" json:"name"`
-
- // Priority indicates whether this KPI is the primary KPI or a supporting KPI.
- // Expected values: primary, supporting.
- Priority string `yaml:"priority,omitempty" json:"priority,omitempty"`
-
- // Unit is an optional unit string (e.g., percent, days, count).
- Unit string `yaml:"unit,omitempty" json:"unit,omitempty"`
-
- // Baseline is the baseline KPI value.
- Baseline float64 `yaml:"baseline" json:"baseline"`
-
- // Target is the target KPI value.
- Target float64 `yaml:"target" json:"target"`
-
- // TimeWindowDays is the rolling time window (in days) used to compute the KPI.
- TimeWindowDays int `yaml:"time-window-days" json:"time-window-days"`
-
- // Direction indicates whether improvement means increasing or decreasing.
- // Expected values: increase, decrease.
- Direction string `yaml:"direction,omitempty" json:"direction,omitempty"`
-
- // Source describes the signal source used to compute the KPI.
- // Expected values: ci, pull_requests, code_security, custom.
- Source string `yaml:"source,omitempty" json:"source,omitempty"`
-}
-
// CampaignGovernancePolicy captures lightweight pacing and opt-out policies.
// This is intentionally scoped to what gh-aw can apply safely and consistently
// via prompts and safe-output job limits.
diff --git a/pkg/campaign/template.go b/pkg/campaign/template.go
index 0bea43a29d..1f21b585ea 100644
--- a/pkg/campaign/template.go
+++ b/pkg/campaign/template.go
@@ -50,12 +50,6 @@ type CampaignPromptData struct {
// CampaignName is the human-readable name of this campaign.
CampaignName string
- // Objective is the campaign objective statement.
- Objective string
-
- // KPIs is the KPI definition list for this campaign.
- KPIs []CampaignKPI
-
// ProjectURL is the GitHub Project URL
ProjectURL string
diff --git a/pkg/campaign/validation.go b/pkg/campaign/validation.go
index 42de7b43e8..d5365ee858 100644
--- a/pkg/campaign/validation.go
+++ b/pkg/campaign/validation.go
@@ -80,14 +80,6 @@ func ValidateSpec(spec *CampaignSpec) []string {
}
}
- // Validate that campaigns with workflows or tracker-label have discovery-repos or discovery-orgs
- // This ensures discovery is properly scoped
- hasDiscovery := len(spec.Workflows) > 0 || spec.TrackerLabel != ""
- hasDiscoveryScope := len(spec.DiscoveryRepos) > 0 || len(spec.DiscoveryOrgs) > 0
- if hasDiscovery && !hasDiscoveryScope {
- problems = append(problems, "campaigns with workflows or tracker-label must specify discovery-repos or discovery-orgs for discovery scoping - configure at least one to define where the campaign can discover worker items")
- }
-
// Validate discovery-repos format if provided
if len(spec.DiscoveryRepos) > 0 {
// Validate each repository format
@@ -210,9 +202,6 @@ func ValidateSpec(spec *CampaignSpec) []string {
}
}
- // Goals/KPIs: optional, but when provided they must be consistent and well-formed.
- problems = append(problems, validateObjectiveAndKPIs(spec)...)
-
if len(problems) == 0 {
validationLog.Printf("Campaign spec '%s' validation passed with no problems", spec.ID)
} else {
@@ -222,67 +211,6 @@ func ValidateSpec(spec *CampaignSpec) []string {
return problems
}
-func validateObjectiveAndKPIs(spec *CampaignSpec) []string {
- var problems []string
-
- objective := strings.TrimSpace(spec.Objective)
- if objective == "" && len(spec.KPIs) > 0 {
- problems = append(problems, "objective should be set when kpis are provided - describe what success looks like for this campaign")
- }
- if objective != "" && len(spec.KPIs) == 0 {
- problems = append(problems, "kpis should include at least one KPI when objective is provided - add measurable metrics (e.g., 'Pull requests merged: 0 → 100 over 30 days')")
- }
- if len(spec.KPIs) == 0 {
- return problems
- }
-
- primaryCount := 0
- for _, kpi := range spec.KPIs {
- name := strings.TrimSpace(kpi.Name)
- if name == "" {
- name = "(unnamed)"
- }
- if strings.TrimSpace(kpi.Priority) == "primary" {
- primaryCount++
- }
- if kpi.TimeWindowDays < 1 {
- problems = append(problems, fmt.Sprintf("kpi '%s': time-window-days must be >= 1 - specify the rolling time window in days (e.g., 30 for monthly)", name))
- }
- if dir := strings.TrimSpace(kpi.Direction); dir != "" {
- switch dir {
- case "increase", "decrease":
- // ok
- default:
- problems = append(problems, fmt.Sprintf("kpi '%s': direction must be one of: 'increase' or 'decrease' - got '%s'", name, dir))
- }
- }
- if src := strings.TrimSpace(kpi.Source); src != "" {
- switch src {
- case "ci", "pull_requests", "code_security", "custom":
- // ok
- default:
- problems = append(problems, fmt.Sprintf("kpi '%s': source must be one of: 'ci', 'pull_requests', 'code_security', or 'custom' - got '%s'", name, src))
- }
- }
- }
-
- // Semantic rule: exactly one primary KPI when there are multiple KPIs.
- // If there is only one KPI and priority is omitted, treat it as implicitly primary.
- if len(spec.KPIs) == 1 {
- if strings.TrimSpace(spec.KPIs[0].Priority) == "" {
- return problems
- }
- }
- if primaryCount == 0 {
- problems = append(problems, "kpis must include exactly one primary KPI (priority: primary) - mark your main success metric as primary")
- }
- if primaryCount > 1 {
- problems = append(problems, fmt.Sprintf("kpis must include exactly one primary KPI (found %d primary KPIs) - choose one main success metric and mark others as 'supporting'", primaryCount))
- }
-
- return problems
-}
-
// suggestValidID converts an invalid campaign ID into a valid one by:
// - Converting to lowercase
// - Replacing invalid characters with hyphens
@@ -376,24 +304,10 @@ func ValidateSpecWithSchema(spec *CampaignSpec) []string {
MaxCommentsPerRun int `json:"max-comments-per-run,omitempty"`
}
- type CampaignKPIForValidation struct {
- ID string `json:"id,omitempty"`
- Name string `json:"name"`
- Priority string `json:"priority,omitempty"`
- Unit string `json:"unit,omitempty"`
- Baseline float64 `json:"baseline"`
- Target float64 `json:"target"`
- TimeWindowDays int `json:"time-window-days"`
- Direction string `json:"direction,omitempty"`
- Source string `json:"source,omitempty"`
- }
-
type CampaignSpecForValidation struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
- Objective string `json:"objective,omitempty"`
- KPIs []CampaignKPIForValidation `json:"kpis,omitempty"`
ProjectURL string `json:"project-url,omitempty"`
ProjectGitHubToken string `json:"project-github-token,omitempty"`
Version string `json:"version,omitempty"`
@@ -416,30 +330,9 @@ func ValidateSpecWithSchema(spec *CampaignSpec) []string {
}
validationSpec := CampaignSpecForValidation{
- ID: spec.ID,
- Name: spec.Name,
- Description: spec.Description,
- Objective: strings.TrimSpace(spec.Objective),
- KPIs: func() []CampaignKPIForValidation {
- if len(spec.KPIs) == 0 {
- return nil
- }
- out := make([]CampaignKPIForValidation, 0, len(spec.KPIs))
- for _, kpi := range spec.KPIs {
- out = append(out, CampaignKPIForValidation{
- ID: strings.TrimSpace(kpi.ID),
- Name: strings.TrimSpace(kpi.Name),
- Priority: strings.TrimSpace(kpi.Priority),
- Unit: strings.TrimSpace(kpi.Unit),
- Baseline: kpi.Baseline,
- Target: kpi.Target,
- TimeWindowDays: kpi.TimeWindowDays,
- Direction: strings.TrimSpace(kpi.Direction),
- Source: strings.TrimSpace(kpi.Source),
- })
- }
- return out
- }(),
+ ID: spec.ID,
+ Name: spec.Name,
+ Description: spec.Description,
ProjectURL: spec.ProjectURL,
ProjectGitHubToken: spec.ProjectGitHubToken,
Version: spec.Version,
diff --git a/pkg/campaign/validation_test.go b/pkg/campaign/validation_test.go
index b2a66484d9..a26a6ee1f5 100644
--- a/pkg/campaign/validation_test.go
+++ b/pkg/campaign/validation_test.go
@@ -268,208 +268,6 @@ func TestValidateSpec_CompleteSpec(t *testing.T) {
}
}
-func TestValidateSpec_ObjectiveWithoutKPIs(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- AllowedRepos: []string{"org/repo1"},
- DiscoveryRepos: []string{"test/repo"},
- Workflows: []string{"workflow1"},
- Objective: "Improve CI stability",
- // KPIs intentionally omitted
- }
-
- problems := ValidateSpec(spec)
- if len(problems) == 0 {
- t.Fatal("Expected validation problems for objective without kpis")
- }
-
- found := false
- for _, p := range problems {
- if strings.Contains(p, "kpis should include at least one KPI") {
- found = true
- break
- }
- }
- if !found {
- t.Errorf("Expected objective/kpis coupling validation problem, got: %v", problems)
- }
-}
-
-func TestValidateSpec_KPIsWithoutObjective(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- AllowedRepos: []string{"org/repo1"},
- DiscoveryRepos: []string{"test/repo"},
- Workflows: []string{"workflow1"},
- KPIs: []CampaignKPI{
- {
- Name: "Build success rate",
- Priority: "primary",
- Baseline: 0.8,
- Target: 0.95,
- TimeWindowDays: 7,
- },
- },
- // Objective intentionally omitted
- }
-
- problems := ValidateSpec(spec)
- if len(problems) == 0 {
- t.Fatal("Expected validation problems for kpis without objective")
- }
-
- found := false
- for _, p := range problems {
- if strings.Contains(p, "objective should be set when kpis") {
- found = true
- break
- }
- }
- if !found {
- t.Errorf("Expected objective/kpis coupling validation problem, got: %v", problems)
- }
-}
-
-func TestValidateSpec_KPIsMultipleWithoutPrimary(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- AllowedRepos: []string{"org/repo1"},
- DiscoveryRepos: []string{"test/repo"},
- Workflows: []string{"workflow1"},
- Objective: "Improve delivery",
- KPIs: []CampaignKPI{
- {Name: "PR cycle time", Priority: "supporting", Baseline: 10, Target: 7, TimeWindowDays: 30},
- {Name: "Open PRs", Priority: "supporting", Baseline: 20, Target: 10, TimeWindowDays: 30},
- },
- }
-
- problems := ValidateSpec(spec)
- if len(problems) == 0 {
- t.Fatal("Expected validation problems for multiple KPIs without a primary")
- }
-
- found := false
- for _, p := range problems {
- if strings.Contains(p, "exactly one primary KPI") && strings.Contains(p, "priority: primary") {
- found = true
- break
- }
- }
- if !found {
- t.Errorf("Expected primary KPI validation problem, got: %v", problems)
- }
-}
-
-func TestValidateSpec_KPIsMultipleWithMultiplePrimary(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- AllowedRepos: []string{"org/repo1"},
- DiscoveryRepos: []string{"test/repo"},
- Workflows: []string{"workflow1"},
- Objective: "Improve delivery",
- KPIs: []CampaignKPI{
- {Name: "Build success rate", Priority: "primary", Baseline: 0.8, Target: 0.95, TimeWindowDays: 7},
- {Name: "PR cycle time", Priority: "primary", Baseline: 10, Target: 7, TimeWindowDays: 30},
- },
- }
-
- problems := ValidateSpec(spec)
- if len(problems) == 0 {
- t.Fatal("Expected validation problems for multiple primary KPIs")
- }
-
- found := false
- for _, p := range problems {
- if strings.Contains(p, "exactly one primary KPI") && strings.Contains(p, "found 2") {
- found = true
- break
- }
- }
- if !found {
- t.Errorf("Expected multiple primary KPI validation problem with count, got: %v", problems)
- }
-}
-
-func TestValidateSpec_SingleKPIOmitsPriorityIsAllowed(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- AllowedRepos: []string{"org/repo1"},
- DiscoveryRepos: []string{"test/repo"},
- Workflows: []string{"workflow1"},
- Objective: "Improve CI stability",
- KPIs: []CampaignKPI{
- {
- Name: "Build success rate",
- // Priority intentionally omitted; should be implicitly primary.
- Baseline: 0.8,
- Target: 0.95,
- TimeWindowDays: 7,
- },
- },
- }
-
- problems := ValidateSpec(spec)
- if len(problems) != 0 {
- t.Errorf("Expected no validation problems for single KPI with omitted priority, got: %v", problems)
- }
-}
-
-func TestValidateSpec_KPIFieldConstraints(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- AllowedRepos: []string{"org/repo1"},
- DiscoveryRepos: []string{"test/repo"},
- Workflows: []string{"workflow1"},
- Objective: "Improve CI stability",
- KPIs: []CampaignKPI{
- {
- Name: "Build success rate",
- Priority: "primary",
- Baseline: 0.8,
- Target: 0.95,
- TimeWindowDays: 0,
- Direction: "up",
- Source: "unknown",
- },
- },
- }
-
- problems := ValidateSpec(spec)
- if len(problems) == 0 {
- t.Fatal("Expected validation problems for invalid KPI fields")
- }
-
- expectSubstrings := []string{
- "time-window-days must be >= 1",
- "'increase' or 'decrease'",
- "'ci', 'pull_requests', 'code_security', or 'custom'",
- }
- for _, needle := range expectSubstrings {
- found := false
- for _, p := range problems {
- if strings.Contains(p, needle) {
- found = true
- break
- }
- }
- if !found {
- t.Errorf("Expected validation problem containing %q, got: %v", needle, problems)
- }
- }
-}
-
func TestValidateSpec_MissingAllowedReposIsValid(t *testing.T) {
spec := &CampaignSpec{
ID: "test-campaign",
@@ -485,29 +283,6 @@ func TestValidateSpec_MissingAllowedReposIsValid(t *testing.T) {
}
}
-func TestValidateSpec_MissingAllowedReposWithWorkflowsIsInvalid(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- Workflows: []string{"workflow1"},
- // DiscoveryRepos intentionally omitted - should fail because workflows need scoping
- }
-
- problems := ValidateSpec(spec)
- // Should have validation problems for missing scope
- hasDiscoveryScopeError := false
- for _, p := range problems {
- if strings.Contains(p, "campaigns with workflows or tracker-label must specify discovery-repos or discovery-orgs") {
- hasDiscoveryScopeError = true
- break
- }
- }
- if !hasDiscoveryScopeError {
- t.Errorf("Expected validation error for missing scope with workflows, got: %v", problems)
- }
-}
-
func TestValidateSpec_InvalidAllowedReposFormat(t *testing.T) {
spec := &CampaignSpec{
ID: "test-campaign",
@@ -550,29 +325,6 @@ func TestValidateSpec_EmptyAllowedReposIsValid(t *testing.T) {
}
}
-func TestValidateSpec_EmptyAllowedReposWithWorkflowsIsInvalid(t *testing.T) {
- spec := &CampaignSpec{
- ID: "test-campaign",
- Name: "Test Campaign",
- ProjectURL: "https://github.com/orgs/org/projects/1",
- Workflows: []string{"workflow1"},
- DiscoveryRepos: []string{}, // Empty list - should fail with workflows
- }
-
- problems := ValidateSpec(spec)
- // Should have validation problems for missing scope
- hasDiscoveryScopeError := false
- for _, p := range problems {
- if strings.Contains(p, "campaigns with workflows or tracker-label must specify discovery-repos or discovery-orgs") {
- hasDiscoveryScopeError = true
- break
- }
- }
- if !hasDiscoveryScopeError {
- t.Errorf("Expected validation error for empty scope with workflows, got: %v", problems)
- }
-}
-
func TestValidateSpec_ValidAllowedOrgs(t *testing.T) {
spec := &CampaignSpec{
ID: "test-campaign",
diff --git a/pkg/cli/templates/orchestrate-agentic-campaign.md b/pkg/cli/templates/orchestrate-agentic-campaign.md
index e0c5e56a19..343477a35b 100644
--- a/pkg/cli/templates/orchestrate-agentic-campaign.md
+++ b/pkg/cli/templates/orchestrate-agentic-campaign.md
@@ -128,8 +128,6 @@ and synchronizing campaign state into a GitHub Project board.
body: |
## Campaign Overview
- {{ if .Objective }}**Objective**: {{.Objective}}{{ end }}
-
This Epic issue tracks the overall progress of the campaign. All work items are sub-issues of this Epic.
**Campaign Details:**
@@ -242,7 +240,7 @@ Every campaign run MUST create a status update using `create-project-status-upda
- **Most Important Findings**: Highlight the 2-3 most critical discoveries, insights, or blockers from this run
- **What Was Learned**: Document key learnings, patterns observed, or insights gained during this run
-- **KPI Trends**: Report progress on EACH campaign KPI{{ if .KPIs }} ({{ range $i, $kpi := .KPIs }}{{if $i}}, {{end}}{{ $kpi.Name }}{{end}}){{ end }} with baseline → current → target format, including direction and velocity
+- **Campaign Progress**: Report on campaign metrics and trends with baseline → current → target format, including direction and velocity
- **Campaign Summary**: Tasks completed, in progress, blocked, and overall completion percentage
- **Next Steps**: Clear action items and priorities for the next run
@@ -251,13 +249,6 @@ Every campaign run MUST create a status update using `create-project-status-upda
- Use today's date for start_date and target_date (or appropriate future date for target)
- Body must be comprehensive yet concise (target: 200-400 words)
-{{ if .KPIs }}
-**Campaign KPIs to Report:**
-{{ range .KPIs }}
-- **{{ .Name }}**{{ if .Priority }} ({{ .Priority }}){{ end }}: baseline {{ .Baseline }}{{ if .Unit }} {{ .Unit }}{{ end }} → target {{ .Target }}{{ if .Unit }} {{ .Unit }}{{ end }} over {{ .TimeWindowDays }} days{{ if .Direction }} ({{ .Direction }}){{ end }}
-{{ end }}
-{{ end }}
-
Example status update:
```yaml
create-project-status-update:
@@ -284,19 +275,19 @@ create-project-status-update:
- Documentation updates tied to code changes have higher accuracy and completeness
- Users report fewer issues when examples include error handling patterns
- ## KPI Trends
+ ## Campaign Progress
- **Documentation Coverage** (Primary KPI):
+ **Documentation Coverage** (Primary Metric):
- Baseline: 85% → Current: 88% → Target: 95%
- Direction: ↑ Increasing (+3% this week, +1% velocity/week)
- Status: ON TRACK - At current velocity, will reach 95% in 7 weeks
- **Accessibility Score** (Supporting KPI):
+ **Accessibility Score** (Supporting Metric):
- Baseline: 90% → Current: 91% → Target: 98%
- Direction: ↑ Increasing (+1% this month)
- Status: AT RISK - Slower progress than expected, may need dedicated focus
- **User-Reported Issues** (Supporting KPI):
+ **User-Reported Issues** (Supporting Metric):
- Baseline: 15/month → Current: 12/month → Target: 5/month
- Direction: ↓ Decreasing (-3 this month, -20% velocity)
- Status: ON TRACK - Trending toward target
diff --git a/pkg/cli/workflows/simple-execution-example.campaign.md b/pkg/cli/workflows/simple-execution-example.campaign.md
index 21cbe78bb2..e626480b09 100644
--- a/pkg/cli/workflows/simple-execution-example.campaign.md
+++ b/pkg/cli/workflows/simple-execution-example.campaign.md
@@ -2,28 +2,12 @@
id: simple-upgrade-example
name: "Simple Framework Upgrade Campaign"
description: "Example showing how campaigns execute workflows to upgrade services"
-version: v1
-state: active
-
project-url: "https://github.com/orgs/myorg/projects/999"
-tracker-label: "campaign:framework-upgrade"
-
-objective: "Upgrade all services to Framework vNext"
-kpis:
- - name: "Services upgraded"
- priority: primary
- unit: count
- baseline: 0
- target: 50
- time-window-days: 30
- direction: increase
-
-# Workflows to execute
+
workflows:
- framework-scanner
- framework-upgrader
-# Governance
governance:
max-project-updates-per-run: 20
@@ -35,6 +19,19 @@ owners:
This campaign demonstrates workflow execution in campaigns.
+## Objective
+
+Upgrade all services to Framework vNext.
+
+## Key Performance Indicators (KPIs)
+
+### Primary KPI: Services Upgraded
+- **Baseline**: 0 services
+- **Target**: 50 services
+- **Time Window**: 30 days
+- **Direction**: Increase
+- **Unit**: count
+
## How It Works
The campaign orchestrator will:
diff --git a/specs/artifacts.md b/specs/artifacts.md
index 32d3cdb975..d9938411fc 100644
--- a/specs/artifacts.md
+++ b/specs/artifacts.md
@@ -24,10 +24,10 @@ This section provides an overview of artifacts organized by job name, with dupli
- `agent-artifacts`
- **Paths**: `/tmp/gh-aw/agent-stdio.log`, `/tmp/gh-aw/aw-prompts/prompt.txt`, `/tmp/gh-aw/aw.patch`, `/tmp/gh-aw/aw_info.json`, `/tmp/gh-aw/mcp-logs/`, `/tmp/gh-aw/safe-inputs/logs/`, `/tmp/gh-aw/sandbox/firewall/logs/`
- - **Used in**: 73 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, chroma-issue-indexer.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, codex-github-remote-mcp-test.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 72 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, chroma-issue-indexer.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, codex-github-remote-mcp-test.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
- `agent-output`
- **Paths**: `${{ env.GH_AW_AGENT_OUTPUT }}`
- - **Used in**: 66 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
- `agent_outputs`
- **Paths**: `/tmp/gh-aw/mcp-config/logs/`, `/tmp/gh-aw/redacted-urls.log`, `/tmp/gh-aw/sandbox/agent/logs/`
- **Used in**: 62 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, chroma-issue-indexer.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, code-scanning-fixer.md, codex-github-remote-mcp-test.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, glossary-maintainer.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, tidy.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
@@ -54,7 +54,7 @@ This section provides an overview of artifacts organized by job name, with dupli
- **Used in**: 9 workflow(s) - agent-performance-analyzer.md, copilot-pr-nlp-analysis.md, daily-copilot-token-report.md, daily-news.md, deep-report.md, metrics-collector.md, pr-triage-agent.md, security-compliance.md, workflow-health-manager.md
- `safe-output`
- **Paths**: `${{ env.GH_AW_SAFE_OUTPUTS }}`
- - **Used in**: 66 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
- `safe-outputs-assets`
- **Paths**: `/tmp/gh-aw/safeoutputs/assets/`
- **Used in**: 12 workflow(s) - copilot-pr-nlp-analysis.md, daily-copilot-token-report.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, github-mcp-structural-analysis.md, poem-bot.md, python-data-charts.md, stale-repo-identifier.md, technical-doc-writer.md, weekly-issue-summary.md
@@ -77,7 +77,7 @@ This section provides an overview of artifacts organized by job name, with dupli
- `agent-output`
- **Download paths**: `/tmp/gh-aw/safeoutputs/`
- - **Used in**: 66 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
### Job: `detection`
@@ -85,16 +85,16 @@ This section provides an overview of artifacts organized by job name, with dupli
- `threat-detection.log`
- **Paths**: `/tmp/gh-aw/threat-detection/detection.log`
- - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 64 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
**Artifacts Downloaded:**
- `agent-artifacts`
- **Download paths**: `/tmp/gh-aw/threat-detection/`
- - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 64 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
- `agent-output`
- **Download paths**: `/tmp/gh-aw/threat-detection/`
- - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 64 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
### Job: `notion_add_comment`
@@ -132,7 +132,7 @@ This section provides an overview of artifacts organized by job name, with dupli
- **Used in**: 16 workflow(s) - changeset.md, ci-coach.md, cloclo.md, code-scanning-fixer.md, craft.md, dictation-prompt.md, glossary-maintainer.md, hourly-ci-cleaner.md, layout-spec-maintainer.md, mergefest.md, poem-bot.md, q.md, slide-deck-maintainer.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md
- `agent-output`
- **Download paths**: `/tmp/gh-aw/safeoutputs/`
- - **Used in**: 66 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, agentic-campaign-generator.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
+ - **Used in**: 65 workflow(s) - agent-performance-analyzer.md, agent-persona-explorer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-observability-report.md, daily-repo-chronicle.md, daily-team-status.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, poem-bot.md, pr-nitpick-reviewer.md, pr-triage-agent.md, python-data-charts.md, q.md, release.md, repo-audit-analyzer.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-review.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, test-create-pr-error-handling.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md
### Job: `super_linter`
@@ -323,62 +323,6 @@ This section provides an overview of artifacts organized by job name, with dupli
- **Download path**: `/tmp/gh-aw/cache-memory`
- **Depends on jobs**: [agent detection]
-### agentic-campaign-generator.md
-
-#### Job: `agent`
-
-**Uploads:**
-
-- **Artifact**: `safe-output`
- - **Upload paths**:
- - `${{ env.GH_AW_SAFE_OUTPUTS }}`
-
-- **Artifact**: `agent-output`
- - **Upload paths**:
- - `${{ env.GH_AW_AGENT_OUTPUT }}`
-
-- **Artifact**: `agent-artifacts`
- - **Upload paths**:
- - `/tmp/gh-aw/aw-prompts/prompt.txt`
- - `/tmp/gh-aw/aw_info.json`
- - `/tmp/gh-aw/mcp-logs/`
- - `/tmp/gh-aw/sandbox/firewall/logs/`
- - `/tmp/gh-aw/agent-stdio.log`
-
-#### Job: `conclusion`
-
-**Downloads:**
-
-- **Artifact**: `agent-output` (by name)
- - **Download path**: `/tmp/gh-aw/safeoutputs/`
- - **Depends on jobs**: [activation agent detection safe_outputs]
-
-#### Job: `detection`
-
-**Uploads:**
-
-- **Artifact**: `threat-detection.log`
- - **Upload paths**:
- - `/tmp/gh-aw/threat-detection/detection.log`
-
-**Downloads:**
-
-- **Artifact**: `agent-artifacts` (by name)
- - **Download path**: `/tmp/gh-aw/threat-detection/`
- - **Depends on jobs**: [agent]
-
-- **Artifact**: `agent-output` (by name)
- - **Download path**: `/tmp/gh-aw/threat-detection/`
- - **Depends on jobs**: [agent]
-
-#### Job: `safe_outputs`
-
-**Downloads:**
-
-- **Artifact**: `agent-output` (by name)
- - **Download path**: `/tmp/gh-aw/safeoutputs/`
- - **Depends on jobs**: [activation agent detection]
-
### ai-moderator.md
#### Job: `agent`