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`