Handbook
Forge Campaign
A Forge Campaign is a multi-repo, branch-aware automation effort governed under a single ForgeRun (frun_*). The campaign is described by a manifest and executed by one or more Forge Agents (AgentRuns), with human review…
Definition
A Forge Campaign is a multi-repo, branch-aware automation effort governed under a single ForgeRun (frun_*). The campaign is described by a manifest and executed by one or more Forge Agents (AgentRuns), with human review and decision in Lenses.
What a Forge Campaign is not
| Term | Distinction |
|---|---|
| Marketing campaign | GTM/channel activity — not a Forge Campaign |
Git charge/* branch |
Charge is a daily Spark view only — never a branch (Forge branching) |
| Fleet job alone | A job is execution; the campaign is the full run including intent, evidence, and decision |
| Ungoverned agent loop | Must attach to frun_* and produce reviewable evidence |
| DecisionPack DAG | Campaign uses manifest phases, not LCDL graph nodes — see Governed workflows and rules |
ForgeRun-backed (day one)
Every campaign opens or extends one ForgeRun:
1. Open ForgeRun (frun_*) — intent, workspace, governance mode
2. Attach campaign manifest — campaign.yaml under .forge/runs/<frun_id>/
3. Record AgentRuns — campaign_orchestrator, fleet_ux_worker, …
4. Fleet execution — optional docker_argv + workspace upload
5. EvidencePacket — audit results, quality gate, artifacts
6. Lenses review — human approves, rejects, or defers
Lenses remains the system of record for run state. See Product boundaries.
Campaign manifest (informal v0)
Authoritative path (pick one convention per workspace):
- Repo template:
forge/campaigns/<campaign-id>.yaml - Run store:
.forge/runs/<frun_id>/campaign.yaml(copy or symlink from template when the run starts)
Illustrative fields (schema forge.campaign.v1 is post-research):
schema_version: 1
campaign_id: ux-20260520-ffw-nav
forge_run_id: frun_ux_20260520_ffw_nav # set when run opens
trunk: main
repos:
- path: forgesdlc-kitchensink
role: upstream
branch: feature/ux-20260520-ffw-nav-ks
- path: forge-fleet-website
role: consumer
branch: feature/ux-20260520-ffw-nav-ffw
depends_on: [forgesdlc-kitchensink]
submodules:
kitchensink: { track_branch: feature/ux-20260520-ffw-nav-ks }
fleet:
requirement_ids: [ux_remediation_worker]
workspace_profile: large_workspace
worker_steps:
- id: audit
skip_cursor_agent: true
- id: remediate
requires_secret: [CURSOR_API_KEY]
integration:
pr_stack_order: [forgesdlc-kitchensink, forge-fleet-website]
auto_merge: false
wait_for_ci: true
# Vision (informal): autonomy level informs assay expectations — not in schema v1 yet
governance:
target_autonomy_level: L2
acceptance_criteria_ref: forge/campaigns/ac/example.yaml
Commit trailers: Forge-Campaign: <campaign-id> on campaign-related commits.
Branching policy: Forge SDLC branching — one commit per repo; submodule bumps as chore(kitchensink): … only.
Lifecycle states (orchestrator)
The campaign orchestrator workcell (campaign_orchestrator) tracks coarse state (local state.json or Lenses projection):
| State | Meaning |
|---|---|
draft |
Manifest written; ForgeRun not yet opened |
branched |
Topic branches exist on origin |
submitted |
Fleet job created |
running |
Job non-terminal |
collected |
worker_result parsed |
integrating |
Applying diffs, commits, pushes |
pr_open |
Stacked PRs created |
verifying |
Build, re-audit, CI |
done / failed |
Terminal; decision updated in ForgeRun |
Agent roles in a campaign
| AgentRun workcell | Where it runs | Role |
|---|---|---|
campaign_orchestrator |
Laptop or CI | Branch, pack tarball, POST/PUT Fleet, watch, integrate, gh pr |
fleet_ux_worker |
Fleet container | Scorer, auditor, remediation sub-agents; workspace_worker_progress |
Fleet does not open pull requests or own git credentials by default. The orchestrator workcell owns git integration policy when explicitly enabled in forge/branching.yml.
Example flow (UX remediation — reference)
Operator → open frun_* + campaign.yaml
→ campaign_orchestrator: create feature/* branches (KS then consumer)
→ pack workspace → POST /v1/jobs + PUT workspace
→ watch GET /v1/jobs/{id}
→ fleet_ux_worker: remediation loop → worker_result
→ campaign_orchestrator: integrate → PR stack → verify
→ EvidencePacket + Lenses decision
Boundary table
| Concern | Owner |
|---|---|
| Run spine, approvals, evidence UI | Lenses |
| Container jobs, workspace extract | Fleet |
| Campaign manifest, AgentRun contracts | Forge Platform |
| Branch/PR policy | Blueprints + repo forge/branching.yml |
| Building blocks (e.g. kitchensink) | forgesdlc-kitchensink first, consumers bump submodule |
Anti-patterns
- Hermes or Fleet owning canonical campaign state instead of Lenses + ForgeRun.
- Auto-merge handbook or product sites without human review.
- One git commit spanning multiple repos.
- Naming Git branches
campaign/*(usefeature/<campaign-slug>-<repo-abbrev>).
MVP vs later
| Phase | Deliverable |
|---|---|
| M0 | Terminology, manifest sketch, samples, ADR |
| M1 | Orchestrator CLI + audit-only Fleet worker |
| M2 | Headless agent in container or hybrid |
| M3 | Multi-repo integrate + stacked PRs |
| M4 | CI gate before campaign done |
Related
- Forge Agent
- Workflows and runs
- ADR-0007: Forge Campaign on ForgeRun
- Sample manifest:
sprints/selfhost-alpha/samples/campaign.yaml - Glossary