Documentation
¶
Index ¶
- func BuildOrchestrator(spec *CampaignSpec, campaignFilePath string) (*workflow.WorkflowData, string)
- func ComputeCompiledState(spec CampaignSpec, workflowsDir string) string
- func CreateSpecSkeleton(rootDir, id string, force bool) (string, error)
- func FetchCursorFreshnessFromRepoMemory(cursorGlob string) (cursorPath string, cursorUpdatedAt string)
- func FetchItemCounts(trackerLabel string) (issuesOpen, issuesClosed, prsOpen, prsMerged int)
- func NewCommand() *cobra.Command
- func RenderClosingInstructions() string
- func RenderOrchestratorInstructions(data CampaignPromptData) string
- func RenderProjectUpdateInstructions(data CampaignPromptData) string
- func ValidateSpec(spec *CampaignSpec) []string
- func ValidateSpecWithSchema(spec *CampaignSpec) []string
- func ValidateWorkflowsExist(spec *CampaignSpec, workflowsDir string) []string
- type CampaignApprovalPolicy
- type CampaignGovernancePolicy
- type CampaignMetricsSnapshot
- type CampaignPromptData
- type CampaignRuntimeStatus
- type CampaignSpec
- type CampaignValidationResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildOrchestrator ¶
func BuildOrchestrator(spec *CampaignSpec, campaignFilePath string) (*workflow.WorkflowData, string)
BuildOrchestrator constructs a minimal agentic workflow representation for a given CampaignSpec. The resulting WorkflowData is compiled via the standard CompileWorkflowDataWithValidation pipeline, and the orchestratorPath determines the emitted .lock.yml name.
func ComputeCompiledState ¶
func ComputeCompiledState(spec CampaignSpec, workflowsDir string) string
ComputeCompiledState inspects the compiled state of all workflows referenced by a campaign. It returns:
"Yes" - all referenced workflows exist and are compiled & up-to-date "No" - at least one workflow exists but is missing a lock file or is stale "Missing workflow" - at least one referenced workflow markdown file does not exist "N/A" - campaign does not reference any workflows
func CreateSpecSkeleton ¶
CreateSpecSkeleton creates a new campaign spec YAML file under .github/workflows/ with a minimal skeleton definition. It returns the relative file path created.
func FetchCursorFreshnessFromRepoMemory ¶ added in v0.33.10
func FetchCursorFreshnessFromRepoMemory(cursorGlob string) (cursorPath string, cursorUpdatedAt string)
FetchCursorFreshnessFromRepoMemory finds the latest cursor/checkpoint file matching cursorGlob in the memory/campaigns branch and returns the matched path along with a best-effort freshness timestamp derived from git history.
Errors are treated as "no cursor" rather than failing the command.
func FetchItemCounts ¶
FetchItemCounts uses gh CLI (via workflow.ExecGH) to fetch basic counts of issues and pull requests tagged with the given tracker label.
If trackerLabel is empty or any errors occur, it falls back to zeros and logs at debug level instead of failing the command.
func NewCommand ¶
NewCommand creates the `gh aw campaign` command that surfaces first-class campaign definitions from YAML files.
func RenderClosingInstructions ¶ added in v0.33.2
func RenderClosingInstructions() string
RenderClosingInstructions renders the closing instructions
func RenderOrchestratorInstructions ¶ added in v0.33.2
func RenderOrchestratorInstructions(data CampaignPromptData) string
RenderOrchestratorInstructions renders the orchestrator instructions with the given data
func RenderProjectUpdateInstructions ¶ added in v0.33.2
func RenderProjectUpdateInstructions(data CampaignPromptData) string
RenderProjectUpdateInstructions renders the project update instructions with the given data
func ValidateSpec ¶
func ValidateSpec(spec *CampaignSpec) []string
ValidateSpec performs lightweight semantic validation of a single CampaignSpec and returns a slice of human-readable problems.
It uses JSON schema validation first, then adds additional semantic checks.
func ValidateSpecWithSchema ¶
func ValidateSpecWithSchema(spec *CampaignSpec) []string
ValidateSpecWithSchema validates a CampaignSpec against the JSON schema. Returns a list of validation error messages, or an empty list if valid.
func ValidateWorkflowsExist ¶
func ValidateWorkflowsExist(spec *CampaignSpec, workflowsDir string) []string
ValidateWorkflowsExist checks that all workflows referenced in a campaign spec actually exist in the .github/workflows directory. Returns a list of problems for workflows that don't exist.
Types ¶
type CampaignApprovalPolicy ¶
type CampaignApprovalPolicy struct {
RequiredApprovals int `yaml:"required-approvals,omitempty" json:"required-approvals,omitempty"`
RequiredRoles []string `yaml:"required-roles,omitempty" json:"required-roles,omitempty"`
ChangeControl bool `yaml:"change-control,omitempty" json:"change-control,omitempty"`
}
CampaignApprovalPolicy captures basic approval expectations for a campaign. It is intentionally lightweight and advisory; enforcement is left to workflows and organizational process.
type CampaignGovernancePolicy ¶ added in v0.33.10
type CampaignGovernancePolicy struct {
// MaxNewItemsPerRun caps how many new items (issues/PRs) the launcher should
// add to the Project board per run. 0 means "use defaults".
MaxNewItemsPerRun int `yaml:"max-new-items-per-run,omitempty" json:"max_new_items_per_run,omitempty"`
// MaxDiscoveryItemsPerRun caps how many candidate issues/PRs the launcher
// and orchestrator may scan during discovery in a single run.
// 0 means "use defaults".
MaxDiscoveryItemsPerRun int `yaml:"max-discovery-items-per-run,omitempty" json:"max_discovery_items_per_run,omitempty"`
// MaxDiscoveryPagesPerRun caps how many pages of results the launcher and
// orchestrator may fetch in a single run.
// 0 means "use defaults".
MaxDiscoveryPagesPerRun int `yaml:"max-discovery-pages-per-run,omitempty" json:"max_discovery_pages_per_run,omitempty"`
// OptOutLabels is a list of labels that opt an issue/PR out of campaign
// tracking. Items with any of these labels should be ignored by launcher/
// orchestrator.
OptOutLabels []string `yaml:"opt-out-labels,omitempty" json:"opt_out_labels,omitempty"`
// DoNotDowngradeDoneItems prevents moving Project status backwards (e.g.
// Done -> In Progress) if the underlying issue/PR is reopened.
DoNotDowngradeDoneItems *bool `yaml:"do-not-downgrade-done-items,omitempty" json:"do_not_downgrade_done_items,omitempty"`
// MaxProjectUpdatesPerRun controls the update-project safe-output maximum
// for generated coordinator workflows. 0 means "use defaults".
MaxProjectUpdatesPerRun int `yaml:"max-project-updates-per-run,omitempty" json:"max_project_updates_per_run,omitempty"`
// MaxCommentsPerRun controls the add-comment safe-output maximum for
// generated coordinator workflows. 0 means "use defaults".
MaxCommentsPerRun int `yaml:"max-comments-per-run,omitempty" json:"max_comments_per_run,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.
type CampaignMetricsSnapshot ¶
type CampaignMetricsSnapshot struct {
Date string `json:"date,omitempty"`
CampaignID string `json:"campaign_id,omitempty"`
TasksTotal int `json:"tasks_total,omitempty"`
TasksCompleted int `json:"tasks_completed,omitempty"`
TasksInProgress int `json:"tasks_in_progress,omitempty"`
TasksBlocked int `json:"tasks_blocked,omitempty"`
VelocityPerDay float64 `json:"velocity_per_day,omitempty"`
EstimatedCompletion string `json:"estimated_completion,omitempty"`
}
CampaignMetricsSnapshot describes the JSON structure used by campaign metrics snapshots written into the memory/campaigns branch.
This mirrors the example in the campaigns guide:
{
"date": "2025-01-16",
"campaign_id": "security-q1-2025",
"tasks_total": 200,
"tasks_completed": 15,
"tasks_in_progress": 30,
"tasks_blocked": 5,
"velocity_per_day": 7.5,
"estimated_completion": "2025-02-12"
}
func FetchMetricsFromRepoMemory ¶
func FetchMetricsFromRepoMemory(metricsGlob string) (*CampaignMetricsSnapshot, error)
FetchMetricsFromRepoMemory attempts to load the latest JSON metrics snapshot matching the provided glob from the memory/campaigns branch. It is best-effort: errors are logged and treated as "no metrics" rather than failing the command.
type CampaignPromptData ¶ added in v0.33.2
type CampaignPromptData struct {
// ProjectURL is the GitHub Project URL
ProjectURL string
// TrackerLabel is the label used to associate issues/PRs with this campaign.
TrackerLabel string
// CursorGlob is a glob for locating the durable cursor/checkpoint file in repo-memory.
CursorGlob string
// MaxDiscoveryItemsPerRun caps how many candidate items may be scanned during discovery.
MaxDiscoveryItemsPerRun int
// MaxDiscoveryPagesPerRun caps how many pages may be fetched during discovery.
MaxDiscoveryPagesPerRun int
}
CampaignPromptData holds data for rendering campaign orchestrator prompts
type CampaignRuntimeStatus ¶
type CampaignRuntimeStatus struct {
ID string `json:"id" console:"header:ID"`
Name string `json:"name" console:"header:Name"`
TrackerLabel string `json:"tracker_label,omitempty" console:"header:Tracker Label,omitempty"`
Workflows []string `json:"workflows,omitempty" console:"header:Workflows,omitempty"`
Compiled string `json:"compiled" console:"header:Compiled"`
IssuesOpen int `json:"issues_open,omitempty" console:"header:Issues Open,omitempty"`
IssuesClosed int `json:"issues_closed,omitempty" console:"header:Issues Closed,omitempty"`
PRsOpen int `json:"prs_open,omitempty" console:"header:PRs Open,omitempty"`
PRsMerged int `json:"prs_merged,omitempty" console:"header:PRs Merged,omitempty"`
// Optional metrics from repo-memory (when MetricsGlob is set and a
// matching JSON snapshot is found on the memory/campaigns branch).
MetricsTasksTotal int `json:"metrics_tasks_total,omitempty" console:"header:Tasks Total,omitempty"`
MetricsTasksCompleted int `json:"metrics_tasks_completed,omitempty" console:"header:Tasks Completed,omitempty"`
MetricsVelocityPerDay float64 `json:"metrics_velocity_per_day,omitempty" console:"header:Velocity/Day,omitempty"`
MetricsEstimatedCompletion string `json:"metrics_estimated_completion,omitempty" console:"header:ETA,omitempty"`
// Optional durable cursor/checkpoint info from repo-memory.
CursorPath string `json:"cursor_path,omitempty" console:"header:Cursor Path,omitempty,maxlen:40"`
CursorUpdatedAt string `json:"cursor_updated_at,omitempty" console:"header:Cursor Updated,omitempty,maxlen:30"`
}
CampaignRuntimeStatus represents the live status of a campaign, including compiled workflow state and basic issue/PR counts derived from the tracker label.
func BuildRuntimeStatus ¶
func BuildRuntimeStatus(spec CampaignSpec, workflowsDir string) CampaignRuntimeStatus
BuildRuntimeStatus builds a CampaignRuntimeStatus for a single campaign spec.
type CampaignSpec ¶
type CampaignSpec struct {
ID string `yaml:"id" json:"id" console:"header:ID"`
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"`
// 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"`
// Version is an optional spec version string (for example: v1).
// When omitted, it defaults to v1 during validation.
Version string `yaml:"version,omitempty" json:"version,omitempty" console:"header:Version,omitempty"`
// Workflows associates this campaign with one or more workflow IDs
// (basename of the Markdown file without .md).
Workflows []string `yaml:"workflows,omitempty" json:"workflows,omitempty" console:"header:Workflows,omitempty,maxlen:40"`
// MemoryPaths documents where this campaign writes its repo-memory
// (for example: memory/campaigns/incident-*/**).
MemoryPaths []string `yaml:"memory-paths,omitempty" json:"memory_paths,omitempty" console:"header:Memory Paths,omitempty,maxlen:40"`
// MetricsGlob is an optional glob (relative to the repository root)
// used to locate JSON metrics snapshots stored in the
// memory/campaigns branch. When set, `gh aw campaign status` will
// attempt to read the latest matching metrics file and surface a few
// key fields.
MetricsGlob string `yaml:"metrics-glob,omitempty" json:"metrics_glob,omitempty" console:"header:Metrics Glob,omitempty,maxlen:30"`
// CursorGlob is an optional glob (relative to the repository root)
// used to locate a durable cursor/checkpoint file stored in the
// memory/campaigns branch. When set, generated coordinator workflows
// will be instructed to continue incremental discovery from this cursor
// and `gh aw campaign status` will surface its freshness.
CursorGlob string `yaml:"cursor-glob,omitempty" json:"cursor_glob,omitempty" console:"header:Cursor Glob,omitempty,maxlen:30"`
// Owners lists the primary human owners for this campaign.
Owners []string `yaml:"owners,omitempty" json:"owners,omitempty" console:"header:Owners,omitempty,maxlen:30"`
// ExecutiveSponsors lists executive stakeholders or sponsors who are
// accountable for the outcome of this campaign.
ExecutiveSponsors []string `` /* 127-byte string literal not displayed */
// RiskLevel is an optional free-form field (e.g. low/medium/high).
RiskLevel string `yaml:"risk-level,omitempty" json:"risk_level,omitempty" console:"header:Risk Level,omitempty"`
// TrackerLabel describes the label used to associate issues/PRs with
// this campaign (for example: campaign:incident-response).
TrackerLabel string `yaml:"tracker-label,omitempty" json:"tracker_label,omitempty" console:"header:Tracker Label,omitempty"`
// State describes the lifecycle stage of the campaign definition.
// Valid values are: planned, active, paused, completed, archived.
State string `yaml:"state,omitempty" json:"state,omitempty" console:"header:State,omitempty"`
// Tags provide free-form categorization for reporting (for example:
// security, modernization, rollout).
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty" console:"header:Tags,omitempty,maxlen:30"`
// AllowedSafeOutputs documents which safe-outputs operations this
// campaign is expected to use (for example: create-issue,
// create-pull-request). This is currently informational but can be
// enforced by validation in the future.
AllowedSafeOutputs []string `` /* 133-byte string literal not displayed */
// ProjectGitHubToken is an optional GitHub token expression (e.g.,
// ${{ secrets.GH_AW_PROJECT_GITHUB_TOKEN }}) used for GitHub Projects v2
// operations. When specified, this token is passed to the update-project
// safe output configuration in the generated orchestrator workflow.
ProjectGitHubToken string `` /* 126-byte string literal not displayed */
// Governance configures lightweight pacing and opt-out policies for campaign
// orchestrator workflows. These guardrails are primarily enforced through
// generated prompts and safe-output maxima.
Governance *CampaignGovernancePolicy `yaml:"governance,omitempty" json:"governance,omitempty"`
// ApprovalPolicy describes high-level approval expectations for this
// campaign (for example: number of approvals and required roles).
ApprovalPolicy *CampaignApprovalPolicy `yaml:"approval-policy,omitempty" json:"approval-policy,omitempty"`
// ConfigPath is populated at load time with the relative path of
// the YAML file on disk, to help users locate definitions.
ConfigPath string `yaml:"-" json:"config_path" console:"header:Config Path,maxlen:60"`
}
CampaignSpec defines a first-class campaign configuration loaded from YAML frontmatter in Markdown files.
Files are discovered from the local repository under:
.github/workflows/*.campaign.md
This provides a thin, declarative layer on top of existing agentic workflows and repo-memory conventions.
func FilterSpecs ¶
func FilterSpecs(specs []CampaignSpec, pattern string) []CampaignSpec
FilterSpecs filters campaigns by a simple substring match on ID or Name (case-insensitive). When pattern is empty, all campaigns are returned.
func LoadSpecs ¶
func LoadSpecs(rootDir string) ([]CampaignSpec, error)
LoadSpecs scans the repository for campaign spec files and returns a slice of CampaignSpec. Campaign specs are stored as .campaign.md files in .github/workflows/. If the workflows directory does not exist, it returns an empty slice and no error.
func ValidateSpecFromFile ¶
func ValidateSpecFromFile(filePath string) (*CampaignSpec, []string, error)
ValidateSpecFromFile validates a campaign spec file by loading and validating it. This is useful for validation commands that operate on files directly.
type CampaignValidationResult ¶
type CampaignValidationResult struct {
ID string `json:"id" console:"header:ID"`
Name string `json:"name" console:"header:Name"`
ConfigPath string `json:"config_path" console:"header:Config Path"`
Problems []string `json:"problems,omitempty" console:"header:Problems,omitempty"`
}
CampaignValidationResult represents the result of validating a campaign spec.