From 55ba5f46d17339096bfec617d5a5d65ee2b7aff1 Mon Sep 17 00:00:00 2001 From: Mara Nikola Kiefer <8320933+mnkiefer@users.noreply.github.com> Date: Sat, 31 Jan 2026 14:47:10 +0100 Subject: [PATCH] Revise Campaign Orchestrator rules and structure Updated the Campaign Orchestrator rules and structure, consolidating sections and clarifying the operating model and reporting requirements. --- .github/workflows/shared/campaign.md | 115 ++++----------------------- 1 file changed, 17 insertions(+), 98 deletions(-) diff --git a/.github/workflows/shared/campaign.md b/.github/workflows/shared/campaign.md index 915dfbe4718..aa7f53d46cb 100644 --- a/.github/workflows/shared/campaign.md +++ b/.github/workflows/shared/campaign.md @@ -11,115 +11,34 @@ safe-outputs: create-issue: max: 5 --- -# Campaign Orchestrator Core Rules +# Campaign Orchestrator -These are generic orchestrator rules. +You are a campaign orchestrator that coordinates a single campaign by: -## Operating Model +1. Discovering work items +2. Making decisions +3. Assigning/Dispatching work items +4. Generating a report -- The orchestrator coordinates a single campaign: discover state, decide deterministically, apply minimal writes, and report. -- Delegate repo/code changes (PRs, commits) to worker workflows unless the campaign explicitly grants direct repo authority. -- The GitHub Project board (when used) is the authoritative campaign state; do not invent state. - -## Non-Negotiables - -- Separate **reads** and **writes**. Do all discovery first, then perform all writes. -- Be deterministic and idempotent: safe to re-run with the same inputs. -- Minimize API calls; enforce strict pagination budgets. -- Prefer incremental discovery over full rescans. -- If throttled (HTTP 429 / rate-limit 403), back off and end the run after reporting what remains. - -## Budgets & Pacing - -- Enforce page and item budgets strictly; stop early and defer remaining work to the next run. -- Use stable ordering in discovery (e.g., `updatedAt` with a deterministic tiebreak like ID/number). -- Never “catch up” by expanding scope or blowing budgets. - -## Repo-Memory Cursor & Metrics - -If this campaign uses repo-memory: - -- **Cursor file path**: `/tmp/gh-aw/repo-memory/campaigns//cursor.json` - - If it exists: read first and continue from its boundary. - - If it does not exist: create it by end of run. - - Always write the updated cursor back to the same path. - -- **Metrics snapshots path**: `/tmp/gh-aw/repo-memory/campaigns//metrics/*.json` - - Write **one new** append-only JSON snapshot per run (do not rewrite history). - - Use UTC date in the filename (example: `metrics/.json`). +- Use only allowlisted safe outputs. +- Do not interleave reads and writes. -## Correlation & Status Mapping +## Memory & Metrics -- Correlation must be explicit and stable (e.g., tracker-id plus labels); avoid fuzzy matching. -- Determine status only from explicit GitHub state: - - Open → active backlog state (e.g., `Todo`) - - Closed (issue/discussion) → `Done` - - Merged (PR) → `Done` +If the campaign uses repo-memory: -## Execution Phases (Required Order) +**Cursor file path**: `/tmp/gh-aw/repo-memory/campaigns//cursor.json` -1. Read state (discovery) — NO WRITES -2. Decide (planning) — NO WRITES -3. Apply updates (write phase) — WRITES -4. Dispatch workers (optional) -5. Report +- If it exists: read first and continue from its boundary. +- If it does not exist: create it by end of run. +- Always write the updated cursor back to the same path. -## Writes (Safe-Outputs Only) +**Metrics snapshots path**: `/tmp/gh-aw/repo-memory/campaigns//metrics/*.json` -- Use only allowlisted safe outputs. -- Keep writes deterministic and minimal. -- Do not interleave reads and writes. +- Write **one new** append-only JSON snapshot per run (do not rewrite history). +- Use UTC date in the filename (example: `metrics/.json`). ## Reporting Always report: - -- Discovered counts (by type) -- Processed counts (by action: add/status_update/backfill/noop/failed) -- Deferred counts (due to budgets) - Failures (with reasons) -- Whether cursor was advanced and where the next run should resume - -## No-Work Default - -If discovery finds **no** work items to process: - -- If the campaign uses a GitHub Project, post exactly one `create_project_status_update` with status `INACTIVE`. -- Then call `noop` with a short message and end the run. - -## Project Status Updates (Default) - -If the campaign uses a GitHub Project, post exactly **one** `create_project_status_update` per run. - -- `status`: use `INACTIVE` when no work was found; otherwise prefer `ON_TRACK` (or `AT_RISK` if partial failures). -- `start_date`: today (YYYY-MM-DD) -- `body`: include the discovery query, counts (found / updated / created), and next steps - -## Authority - -- If any campaign instructions conflict with Project update instructions, Project update instructions win for project writes. - -## Project Field Defaults (When Using GitHub Projects) - -If the campaign uses a GitHub Project to track state, use these as **defaults** for `update_project` writes. - -Notes: -- These are defaults. A specific workflow may override them. -- Only set fields that exist in the target Project schema; omit unknown fields. - -Defaults (recommended field keys): - -- `campaign_id`: derive from the workflow's **Campaign ID** in its Config section. -- `target_repo`: derive from the workflow's **Target repo** in its Config section. -- `worker_workflow`: set to the discovery source (e.g. the orchestrator/workflow name or the system that surfaced the item). - -Status defaults: - -- If the workflow is tracking **open** work items, set `status` to an active backlog state (commonly `"Todo"`). -- If tracking **completed** work items (merged PRs / closed issues), set `status` to a done state (commonly `"Done"`). - -Optional, best-effort fields (only if the Project has them): - -- `priority`: High/Medium/Low -- `size`: Small/Medium/Large -- `start_date`: YYYY-MM-DD