Benchmark campaign sweeps¶
A campaign runs multiple benchmark harness executions from one campaign definition file. Each member run is a normal benchmark output tree (cells/, matrices/, manifest.json), so results are longitudinal-compatible: point alwm benchmark longitudinal at runs/*/manifest.json under the campaign directory (see longitudinal-reporting.md). The campaign root adds manifest.json (campaign manifest: campaign_definition_fingerprint, campaign_experiment_fingerprints — six axes) and campaign-summary.json / .md (campaign summary).
Walkthrough (committed examples): campaign-walkthrough.md · End-to-end publication: campaign-result-pack-publication.md · Verification: verification.md · MkDocs site: docs-site.md · Wiki: Campaign orchestration (index) · ADR: Benchmark campaign orchestration · Tracking: Campaign orchestration.
Campaign definition¶
YAML or JSON validated by schemas/v1/benchmark_campaign.schema.json and loaded as BenchmarkCampaignDefinitionV1 (see src/agent_llm_wiki_matrix/benchmark/campaign_definitions.py). Synonyms: benchmark_suites → suite_refs, provider_configs → provider_config_refs, scoring_configs → eval_scoring_options, tags → campaign_tags.
| Field | Role |
|---|---|
suite_refs / benchmark_suites |
Repo-relative paths to benchmark definition files (each is a full BenchmarkDefinitionV1). |
provider_config_refs / provider_configs |
Optional list of providers YAML paths; null entries use harness default resolution. Empty list expands to a single null (one run with defaults). |
eval_scoring_options / scoring_configs |
Optional list of eval_scoring overrides; null keeps each suite’s own eval_scoring. Empty list expands to one null. |
execution_modes |
If set, only variants whose execution_mode is in this list are kept (others dropped before the run). |
browser_configs |
Optional list of browser blocks merged into browser_mock variants. Empty list expands to one null. If the suite has no browser_mock variant, only null is used (no extra redundant runs). |
campaign_tags / tags |
Strings appended to each member definition’s tags (plus campaign:<id> and campaign_run:NNNN). |
prompt_registry_ref |
Optional override for all member runs (registry YAML relative to repo root). |
campaign_version, description, owner, created_at, notes |
Metadata copied into the campaign manifest for dashboards and provenance. |
retry_policy, time_budget_seconds, token_budget |
Hints for external agent runners (harness records; does not auto-retry cells yet). |
expected_artifact_kinds |
Expected alwm validate kinds for reviewing outputs (metadata). |
The sweep is the Cartesian product of suites × provider refs × eval_scoring options × (pruned) browser configs.
CLI¶
Execute the full sweep:
uv run alwm benchmark campaign run \
--definition examples/campaigns/v1/minimal_offline.v1.yaml \
--output-dir examples/campaign_runs/minimal_offline
Dry-run (no member runs/; writes campaign-dry-run.json plus top-level manifest and summaries):
uv run alwm benchmark campaign run --dry-run \
--definition examples/campaigns/v1/minimal_offline.v1.yaml \
--output-dir /tmp/campaign-plan
| Option | Default | Meaning |
|---|---|---|
--created-at |
1970-01-01T00:00:00Z |
RFC 3339 timestamp for member runs and the campaign manifest. |
--no-fixture-mock |
off | When set, does not force mock providers in fixture mode (for live integration). |
--dry-run |
off | Plan only: no runs/runNNNN/ trees; still writes manifest.json, campaign-summary.*, campaign-dry-run.json. |
Offline / deterministic (default): omit --no-fixture-mock and use mock backends in suite definitions; keep ALWM_FIXTURE_MODE=1 in CI as today.
Result pack (publish / compare)¶
After a campaign finishes, assemble a markdown-first result pack — the canonical outward-facing unit for a completed campaign: a directory that copies key campaign outputs plus campaign-result-pack.json (machine index) and INDEX.md (human overview). Prefer citing, archiving, and diffing the pack rather than only the raw campaign output tree.
uv run alwm benchmark campaign pack \
examples/campaign_runs/minimal_offline \
-o examples/campaign_result_packs/minimal_offline \
--pack-id minimal-offline \
--source-label examples/campaign_runs/minimal_offline
| Option | Default | Meaning |
|---|---|---|
--pack-id |
(required) | Stable id stored in campaign-result-pack.json. |
--source-label |
off | Optional repo-relative path recorded in the pack (portable provenance). |
--member-depth |
full |
full copies entire member run trees (best for longitudinal cell loads); manifest copies only runs/runNNNN/manifest.json (smaller). |
--run-index |
all | Repeatable 0-based run index filter. |
--include-failed-members |
off | Include failed member runs (default: succeeded only). |
--record-source-abspath |
off | Store absolute source path in JSON (default off for git-friendly bundles). |
Outputs under -o include campaign-result-pack.json (kind campaign_result_pack), INDEX.md, and the same relative layout as a campaign tree so runs/*/manifest.json globs stay familiar. The pack manifest records provenance (campaign created_at, definition path, fixture mode, git pointers), alwm_version (tool that assembled the pack), and pack_identity_fingerprint (stable hash of bundled experiment identity; comparable across pack_id / pack assembly timestamps). Example: examples/campaign_result_packs/minimal_offline/.
Outputs (git-friendly)¶
Under --output-dir:
| Path | Contents |
|---|---|
manifest.json |
Campaign manifest (kinds benchmark_campaign_manifest or campaign_manifest): campaign_definition_fingerprint, campaign_experiment_fingerprints (six axes), timing, git provenance, run_status_summary, runs[] with per-row status and copied six-axis comparison_fingerprints, paths to each run’s benchmark manifest.json. |
runs/runNNNN/ |
Full per-run benchmark directory (same layout as alwm benchmark run). Omitted when using --dry-run. |
campaign-summary.json |
JSON rollup (kinds campaign_summary or legacy validation path). |
campaign-summary.md |
Publication-style index: metadata, experiment fingerprints, execution context, Snapshot digest (short headline copy; full tables in comparative + semantic reports), Member run index, optional Generated reports links. Digest: Judge & semantic signals (one ### with #### confidence + axis hotspots when semantic summary exists), sweep spreads, backends, instability, mode gaps, FT-*. |
campaign-semantic-summary.json |
Semantic / hybrid judge rollup (kind campaign_semantic_summary): per-cell metrics from evaluation + evaluation_judge_provenance; totals split Evaluation.judge_low_confidence vs repeat confidence.low_confidence; criterion_instability (per-criterion score_range from repeat_aggregation.disagreement); instability_highlights (ranked unstable suites / providers / modes + confidence_flag_counts); rollups by suite / provider / mode. Deterministic-only campaigns still emit zeros / empty lists. |
campaign-semantic-summary.md |
Human-readable mirror: Campaign semantic summary title, Executive snapshot, threshold flags, criteria, instability hotspots, detailed rollups, per-cell low-confidence table. |
reports/campaign-report.md |
Comparative report: Executive summary, optional Judge variance (abbreviated) embed (pointer to campaign-semantic-summary.md), --- then sweep dimensions, member mean-score tables, fingerprint-axis interpretation, backends, instability, mode gaps, FT-* tags, failure atlas. browser_mock runs add compact Browser evidence intro + tables. |
reports/campaign-analysis.json |
Machine-readable mirror (fingerprint_compare_axes, fingerprint_axis_insights — per-group run_count when varied; fingerprint_axis_interpretation — attribution_by_axis rows add attribution_label, evidence_strength, uncertainty_notes, metrics (incl. min_bucket_cell_count); differentiation_overview, interpretation_caveats, spread ranking, hotspots, hints with signal_class; schema 1; not alwm validate). May include browser_evidence_member_cells and judge_campaign_semantic. |
campaign-dry-run.json |
Only for --dry-run: planned run count + inputs snapshot + campaign_definition_fingerprint + campaign_experiment_fingerprints (no runs/ trees). |
Validate:
uv run alwm validate examples/campaign_runs/minimal_offline/manifest.json campaign_manifest
# equivalent: benchmark_campaign_manifest
uv run alwm validate examples/campaign_runs/minimal_offline/campaign-summary.json campaign_summary
uv run alwm validate examples/campaign_runs/minimal_offline/campaign-semantic-summary.json campaign_semantic_summary
uv run alwm validate examples/campaign_runs/minimal_offline/runs/run0000/manifest.json benchmark_manifest
Campaign definitions are YAML; for alwm validate on definitions, export to JSON or rely on load_benchmark_campaign_definition in code (schema: campaign_definition).
Longitudinal analysis¶
From the repo root:
uv run alwm benchmark longitudinal \
--runs-glob 'examples/campaign_runs/minimal_offline/runs/*/manifest.json' \
--out-dir /tmp/campaign-longitudinal
Result packs (publishing and comparison)¶
End-to-end publication workflow (run campaign, validate, pack, compare, interpret, publish): campaign-result-pack-publication.md — single checklist with committed example paths; this section remains the detailed CLI and output reference.
A campaign result pack is the canonical outward-facing bundle for a completed campaign: a git-friendly directory that copies the important parts of a finished campaign tree—campaign manifest, summaries, semantic summary (when present), comparative report + analysis JSON (when present), optional campaign-dry-run.json (plan-only campaigns), and selected member runs (full trees by default). The pack root adds campaign-result-pack.json (kind campaign_result_pack) and INDEX.md. The JSON records optional layer paths (for example campaign_dry_run_json) plus derived membership_scope (all_runs / subset / unknown) and optional_layers_present (semantic / comparative / analysis / dry-run). INDEX.md targets cold reviewers: For reviewers (read this first) (what the bundle is, reading order), Scope of this bundle, What is included, Publish-ready checklist, provenance, fingerprints, and validation commands—without repeating the old wide Bundle completeness grid.
What to publish: the pack directory, not only the raw examples/campaign_runs/… output. The pack is what you cite, archive, or attach; it includes pack_identity_fingerprint and a consistent artifact inventory for reviewers.
Completeness (what “done” usually means):
| Check | Command / signal |
|---|---|
| Pack JSON valid | alwm validate …/campaign-result-pack.json campaign_result_pack |
| Campaign manifest valid | alwm validate …/manifest.json campaign_manifest |
| Campaign summary valid | alwm validate …/campaign-summary.json campaign_summary |
| Optional layers | When semantic files exist: alwm validate …/campaign-semantic-summary.json campaign_semantic_summary; confirm optional_layers_present / What is included in INDEX.md matches expectations |
| On-disk layout matches manifest | alwm benchmark campaign pack-check <pack_dir> (--strict for stricter CI) |
| No accidental absolute paths | source_campaign_dir absent unless you used --record-source-abspath on purpose |
| Member trees sufficient for your audience | member_depth: full in pack JSON unless reviewers only need manifests |
| Subset packs explained | If included_member_count < campaign_run_count, document why in notes or the PR |
| Repo contracts unchanged | just validate-artifacts (swept examples/ + fixtures/) |
Assemble from a completed campaign directory:
uv run alwm benchmark campaign pack examples/campaign_runs/minimal_offline \
--output-dir /tmp/campaign-pack \
--pack-id minimal-offline-2026-04-18 \
--source-label examples/campaign_runs/minimal_offline
| Option | Meaning |
|---|---|
--member-depth full (default) |
Copy each member run tree (longitudinal-compatible: evaluations and responses available under runs/runNNNN/). |
--member-depth manifest |
Only manifest.json per member (smaller; longitudinal cell loads may fail). |
--run-index N |
Repeatable filter by member run_index. |
--include-failed-members |
Include runs that did not succeed (default: succeeded only). |
--record-source-abspath |
Store absolute source path in JSON (omit for portable bundles). |
--title |
Override pack title (default: campaign manifest title). |
Validate (schema + registered kinds):
uv run alwm validate /tmp/campaign-pack/campaign-result-pack.json campaign_result_pack
Completeness and portability (paths on disk, manifest/summary campaign_id consistency; --strict flags portability warnings such as manifest-only members):
uv run alwm benchmark campaign pack-check /tmp/campaign-pack
uv run alwm benchmark campaign pack-check /tmp/campaign-pack --strict
Comparing two packs (CLI): emit pack-compare.json (kind campaign_result_pack_comparison) and pack-compare-report.md. Report order: ## At a glance (non-causal summary from JSON reader_interpretation — no duplicate instability/browser/FT prose), ## Member run overlap, identity and artifact tables, then ## Analysis deltas (pooled means; instability collapsed when all zeros; FT-* split into With movement vs No movement; compact browser evidence subsection; semantic Δ), then portability. Optional reader_interpretation in JSON keeps full narrative strings for tooling. Use --repo-root . (from the repo root) for git-friendly relative paths.
uv run alwm benchmark campaign compare-packs \
examples/campaign_result_packs/minimal_offline \
examples/campaign_result_packs/multi_suite \
-o /tmp/pack-compare \
--repo-root .
uv run alwm validate /tmp/pack-compare/pack-compare.json campaign_result_pack_comparison
Example output: examples/campaign_result_packs/compare_minimal_vs_multi/. Manual review: INDEX.md in each pack still lists fingerprints and validation commands.
Comparing two completed campaign directories (CLI): emit campaign-compare.json (kind campaign_compare) and campaign-compare-report.md without building result packs first. Markdown order: ## At a glance, ## Member runs & manifest health (overlap + dry_run + manifest run counts), sweep dimensions, fingerprint insights, standard artifact paths, then ## Analysis deltas (same subsection pattern as pack compare). JSON still includes top-level browser_evidence (rollups) and comparative_analysis.browser_evidence_comparison. Default is offline. Use a fixed --created-at for reproducible committed examples.
uv run alwm benchmark campaign compare \
examples/campaign_runs/minimal_offline \
examples/campaign_runs/multi_suite \
-o /tmp/campaign-compare \
--repo-root .
uv run alwm validate /tmp/campaign-compare/campaign-compare.json campaign_compare
Committed example: examples/campaign_compares/minimal_offline_vs_multi_suite/ (see examples/campaign_compares/README.md).
Longitudinal on a standalone pack: set ALWM_REPO_ROOT to the pack directory and use --runs-glob 'runs/*/manifest.json', or pass a repo-relative glob that points at the pack’s runs/*/manifest.json (see INDEX.md inside the pack).
Examples¶
- Definitions:
examples/campaigns/v1/(includingsweep_modes.v1.yaml,multi_suite.v1.yaml,semantic_repeats_offline.v1.yamlfor semantic judge withjudge_repeats> 1,fingerprint_axes_probe.v1.yamlfor two runs that differ on scoring_config fingerprints) - Fixture suite:
fixtures/benchmarks/campaign_micro.v1.yaml - Sample output:
examples/campaign_runs/minimal_offline/(single member run; regenerate with the CLI above). - Result pack workflow: Result packs section above; example commands in
examples/campaign_result_packs/README.md. - Campaign vs campaign:
examples/campaign_compares/README.md(campaign-compare.json). - Multi-run sample:
examples/campaign_runs/multi_suite/— twosuite_refvalues; shows At a glance spreads, mode-gap rows, and FT-* signals incampaign-summary.md/reports/campaign-report.md(seeexamples/campaign_runs/multi_suite/README.md).