Documentation
¶
Overview ¶
Package campaign implements the PromptZero Campaigns feature (roadmap P2-19) — declarative, YAML-authored multi-step engagement specs that compose the existing agent tool surface.
A campaign file describes scope, an ordered list of steps, and a report template. The Runner executes each step against a StepExecutor (typically the agent's dispatch path) and emits a RunResult that slots cleanly into internal/report for human- readable output.
This ships the foundation. Cron scheduling, a web UI, and expression-based when-conditions beyond substring containment are explicit future work — the types are forward-compatible with those additions.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AgentExecutor ¶
type AgentExecutor struct {
Dispatcher ToolDispatcher
}
AgentExecutor adapts a ToolDispatcher to the campaign StepExecutor interface. Production wiring passes the agent's dispatch (see cmd/promptzero). Keeping the adapter here avoids pulling the agent package into internal/campaign.
type Campaign ¶
type Campaign struct {
Name string `yaml:"campaign"`
Scope Scope `yaml:"scope,omitempty"`
Schedule string `yaml:"schedule,omitempty"`
Steps []Step `yaml:"steps"`
Report ReportConfig `yaml:"report,omitempty"`
}
Campaign is the top-level document a campaign YAML decodes into. Name, Scope, Schedule, Steps, Report all survive round-trip.
type ReportConfig ¶
type ReportConfig struct {
Template string `yaml:"template,omitempty"`
Signed bool `yaml:"signed,omitempty"`
}
ReportConfig controls how RunResult is summarised. Template is an informational label today (the Markdown renderer is the only implementation); Signed hints whether the operator wants a cosign signature on the final report — wired when the Campaigns runner integrates with the release-style signing path.
type RunResult ¶
type RunResult struct {
Campaign string
StartedAt time.Time
EndedAt time.Time
StepResults []StepResult
Err error // fatal run error (validator, executor panic); per-step errors live on StepResult
}
RunResult is the outcome of one Runner.Run. Carries the per-step log, wall-clock span, and a roll-up pass/fail flag. Designed so a future /report template (or the Campaigns runner's own renderer) can format it without re-walking individual steps.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner executes a Campaign against a StepExecutor. Safe to reuse across multiple Run() calls — no cached state between invocations.
func NewRunner ¶
func NewRunner(exec StepExecutor) *Runner
NewRunner constructs a Runner. Nil executor is acceptable at construction time but will cause Run to fail fast when invoked.
func (*Runner) Run ¶
Run executes every step in order. Steps with DependsOn wait for their predecessor to complete; a failed predecessor marks the dependent step Skipped with SkipReason="dependency <id> failed". When clauses are evaluated against the predecessor's output and default to pass when no predecessor is referenced.
Ctx cancellation aborts the run between steps — an in-flight executor call observes the same ctx and is expected to honour it.
type Scope ¶
type Scope struct {
AuthorizedNetworks []string `yaml:"authorized_networks,omitempty"`
AuthorizedDevices []string `yaml:"authorized_devices,omitempty"`
OutOfScope []string `yaml:"out_of_scope,omitempty"`
}
Scope captures the authorisation envelope the campaign operates under. Runner does not enforce scope — it's metadata for the report + for human review before kick-off — but the types are here so a future Runner.EnforceScope pass can grow without reshuffling YAML.
type Step ¶
type Step struct {
ID string `yaml:"id"`
Tool string `yaml:"tool"`
Params map[string]interface{} `yaml:"params,omitempty"`
DependsOn string `yaml:"depends_on,omitempty"`
When string `yaml:"when,omitempty"`
// Timeout caps per-step execution. Zero means "no limit" and
// the executor's own timeout policy governs. Example: "30s",
// "2m".
Timeout string `yaml:"timeout,omitempty"`
}
Step is one ordered campaign action. Tool is the agent tool name (e.g. "wifi_scan_ap"); Params is its JSON-object arguments. When a Step has DependsOn, it runs only after the predecessor completed successfully; When, if non-empty, gates execution on the predecessor's output matching the condition.
type StepExecutor ¶
type StepExecutor interface {
Run(ctx context.Context, tool string, params map[string]interface{}) (output string, err error)
}
StepExecutor is the interface the Runner uses to invoke an agent tool. Production wiring passes the agent's dispatch path; tests pass a stub. Keeping the interface minimal means a future Web / MCP surface can plug its own executor without touching the Runner.
type StepResult ¶
type StepResult struct {
StepID string
Tool string
Output string
Err error
Duration time.Duration
Skipped bool
SkipReason string
StartedAt time.Time
}
StepResult captures the outcome of one step in a RunResult. Skipped fires when a step's When clause evaluated false or its DependsOn predecessor failed.
func (StepResult) Succeeded ¶
func (r StepResult) Succeeded() bool
Succeeded reports whether the step ran to completion without error.
type ToolDispatcher ¶
type ToolDispatcher interface {
RunTool(ctx context.Context, tool string, params map[string]interface{}) (string, error)
}
ToolDispatcher is the narrow interface Campaigns asks of an agent- backed executor — one method that runs a named tool with params and returns (output, error). Mirrors the shape of the rules engine's RunTool callback so both surfaces can share an adapter.