From 248da5961cbaee42aa37e0126f44b620dbba9786 Mon Sep 17 00:00:00 2001 From: closer-lane Date: Fri, 4 Sep 2026 02:29:21 -0500 Subject: [PATCH 1/4] docs: align consumer multi-agent runner guide --- templates/consumer-repo/docs/LABELS.md | 12 ++++++------ tests/docs/test_consumer_ci_system_guide.py | 9 +++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/templates/consumer-repo/docs/LABELS.md b/templates/consumer-repo/docs/LABELS.md index 4e2dd8aa0..55bea5b88 100644 --- a/templates/consumer-repo/docs/LABELS.md +++ b/templates/consumer-repo/docs/LABELS.md @@ -10,8 +10,8 @@ This document describes all labels that trigger automated workflows or affect CI | `autofix:clean` | PR labeled | Triggers clean-mode autofix (more aggressive) | `agent:codex` | Issue or PR labeled | Routes the issue or PR to the Codex agent | `agent:claude` | Issue or PR labeled | Routes the issue or PR to the Claude Code agent -| `agent:cursor` | Issue or PR labeled | Registered routing label; no consumer Gate-followup runner is currently wired -| `agent:gemini` | Issue or PR labeled | Registered routing label; no consumer Gate-followup runner is currently wired +| `agent:cursor` | Issue or PR labeled | Routes consumer Gate-followup keepalive to the Cursor runner +| `agent:gemini` | Issue or PR labeled | Routes consumer Gate-followup keepalive to the Gemini runner | `agent:aider` | Issue or PR labeled | Routes the issue or PR to the Aider agent for cheap, low-complexity tasks — runner lands in a follow-up phase | `agent:auto` | Issue or PR labeled | Delegates routing to the auto-delegation policy; do not combine with concrete `agent:` labels | `agent:retry` | PR labeled | Consolidated consumers require a manual Gate-followups dispatch; the root/non-consolidated keepalive workflow forces a retry and clears recovery labels @@ -140,14 +140,14 @@ This document describes all labels that trigger automated workflows or affect CI **Effect:** 1. Identifies Cursor as the intended route in registry-aware automation -2. Does **not** dispatch a consumer PR keepalive runner: `agents-81-gate-followups.yml` currently has runner jobs only for Codex and Claude +2. Dispatches the `run-cursor` consumer PR keepalive job in `agents-81-gate-followups.yml` 3. Branch prefix `cursor/issue-` is reserved for Cursor work (see `.github/agents/registry.yml`) **Prerequisites:** - Repository has a valid `CURSOR_API_KEY` secret (per `.github/agents/registry.yml`) - Issue or PR should have clear requirements -**Workflow:** Registry-aware workflows may recognize the label, but the consumer Gate-followup workflow has no Cursor runner job. Do not use this label to promise PR keepalive execution until that job is delivered from the canonical Workflows source. +**Workflow:** `agents-81-gate-followups.yml` dispatches `reusable-cursor-run.yml` after registry-backed routing and secret preflight succeed. --- @@ -159,13 +159,13 @@ This document describes all labels that trigger automated workflows or affect CI **Effect:** 1. Identifies Gemini as the intended route in registry-aware automation -2. Does **not** dispatch a consumer PR keepalive runner: `agents-81-gate-followups.yml` currently has runner jobs only for Codex and Claude +2. Dispatches the `run-gemini` consumer PR keepalive job in `agents-81-gate-followups.yml` 3. Branch prefix `gemini/issue-` is reserved for Gemini work **Prerequisites:** - Repository has a valid `GEMINI_API_KEY` secret (per `.github/agents/registry.yml`) -**Workflow:** Registry-aware workflows may recognize the label, but the consumer Gate-followup workflow has no Gemini runner job. Do not use this label to promise PR keepalive execution until that job is delivered from the canonical Workflows source. +**Workflow:** `agents-81-gate-followups.yml` dispatches `reusable-gemini-run.yml` after registry-backed routing and secret preflight succeed. --- diff --git a/tests/docs/test_consumer_ci_system_guide.py b/tests/docs/test_consumer_ci_system_guide.py index f3f963df7..b0bf834d2 100644 --- a/tests/docs/test_consumer_ci_system_guide.py +++ b/tests/docs/test_consumer_ci_system_guide.py @@ -36,6 +36,9 @@ def test_consumer_operator_docs_match_gate_followup_topology() -> None: root_labels = Path("docs/LABELS.md").read_text(encoding="utf-8") labels = Path("templates/consumer-repo/docs/LABELS.md").read_text(encoding="utf-8") setup = Path("templates/consumer-repo/docs/SETUP_CHECKLIST.md").read_text(encoding="utf-8") + gate_followups = Path( + "templates/consumer-repo/.github/workflows/agents-81-gate-followups.yml" + ).read_text(encoding="utf-8") assert "Root/non-consolidated: sets `force_retry=true`" in root_labels assert ".github/workflows/agents-keepalive-loop.yml" in root_labels @@ -45,8 +48,10 @@ def test_consumer_operator_docs_match_gate_followup_topology() -> None: ): assert retired_surface not in labels - assert "no Cursor runner job" in labels - assert "no Gemini runner job" in labels + for agent, display_name in (("cursor", "Cursor"), ("gemini", "Gemini")): + assert f"reusable-{agent}-run.yml@main" in gate_followups + assert f"Routes consumer Gate-followup keepalive to the {display_name} runner" in labels + assert f"dispatches `reusable-{agent}-run.yml`" in labels assert "applying the label does not trigger a retry by itself" in labels assert "Does not set `force_retry`" in labels assert "agents-keepalive-loop.yml" not in labels From 6046661f5774590e449923026b0b54b0785da4d2 Mon Sep 17 00:00:00 2001 From: closer-lane Date: Fri, 4 Sep 2026 02:35:55 -0500 Subject: [PATCH 2/4] test: bind runner docs to delivered jobs --- tests/docs/test_consumer_ci_system_guide.py | 30 +++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/docs/test_consumer_ci_system_guide.py b/tests/docs/test_consumer_ci_system_guide.py index b0bf834d2..d0494455f 100644 --- a/tests/docs/test_consumer_ci_system_guide.py +++ b/tests/docs/test_consumer_ci_system_guide.py @@ -1,5 +1,8 @@ from pathlib import Path +import yaml +from scripts.sync_manifest_compiler import compile_manifest + GUIDE = Path("templates/consumer-repo/docs/CI_SYSTEM_GUIDE.md") @@ -33,12 +36,25 @@ def test_consumer_ci_guide_matches_current_agent_entrypoints() -> None: def test_consumer_operator_docs_match_gate_followup_topology() -> None: + repo_root = Path(__file__).resolve().parents[2] root_labels = Path("docs/LABELS.md").read_text(encoding="utf-8") - labels = Path("templates/consumer-repo/docs/LABELS.md").read_text(encoding="utf-8") setup = Path("templates/consumer-repo/docs/SETUP_CHECKLIST.md").read_text(encoding="utf-8") - gate_followups = Path( - "templates/consumer-repo/.github/workflows/agents-81-gate-followups.yml" - ).read_text(encoding="utf-8") + compiled = compile_manifest(repo_root / ".github/sync-manifest.yml", repo_root=repo_root) + labels_entry = next( + entry for entry in compiled.section("docs") if entry.target == "docs/LABELS.md" + ) + gate_followups_entry = next( + entry + for entry in compiled.section("workflows") + if entry.target == ".github/workflows/agents-81-gate-followups.yml" + ) + assert labels_entry.source_tree == "template" + assert gate_followups_entry.source_tree == "template" + labels = (repo_root / labels_entry.resolved_source).read_text(encoding="utf-8") + gate_followups = yaml.safe_load( + (repo_root / gate_followups_entry.resolved_source).read_text(encoding="utf-8") + ) + jobs = gate_followups["jobs"] assert "Root/non-consolidated: sets `force_retry=true`" in root_labels assert ".github/workflows/agents-keepalive-loop.yml" in root_labels @@ -49,8 +65,12 @@ def test_consumer_operator_docs_match_gate_followup_topology() -> None: assert retired_surface not in labels for agent, display_name in (("cursor", "Cursor"), ("gemini", "Gemini")): - assert f"reusable-{agent}-run.yml@main" in gate_followups + job_id = f"run-{agent}" + job = jobs[job_id] + assert job["uses"] == f"stranske/Workflows/.github/workflows/reusable-{agent}-run.yml@main" + assert f"needs.evaluate.outputs.agent_type == '{agent}'" in job["if"] assert f"Routes consumer Gate-followup keepalive to the {display_name} runner" in labels + assert f"Dispatches the `{job_id}` consumer PR keepalive job" in labels assert f"dispatches `reusable-{agent}-run.yml`" in labels assert "applying the label does not trigger a retry by itself" in labels assert "Does not set `force_retry`" in labels From c2b3a29e0587ab2123f71595bfd6501fd5ff233f Mon Sep 17 00:00:00 2001 From: closer-lane Date: Fri, 4 Sep 2026 02:41:39 -0500 Subject: [PATCH 3/4] test: enforce exclusive consumer runner routes --- tests/docs/test_consumer_ci_system_guide.py | 24 +++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/docs/test_consumer_ci_system_guide.py b/tests/docs/test_consumer_ci_system_guide.py index d0494455f..546b0c773 100644 --- a/tests/docs/test_consumer_ci_system_guide.py +++ b/tests/docs/test_consumer_ci_system_guide.py @@ -68,10 +68,26 @@ def test_consumer_operator_docs_match_gate_followup_topology() -> None: job_id = f"run-{agent}" job = jobs[job_id] assert job["uses"] == f"stranske/Workflows/.github/workflows/reusable-{agent}-run.yml@main" - assert f"needs.evaluate.outputs.agent_type == '{agent}'" in job["if"] - assert f"Routes consumer Gate-followup keepalive to the {display_name} runner" in labels - assert f"Dispatches the `{job_id}` consumer PR keepalive job" in labels - assert f"dispatches `reusable-{agent}-run.yml`" in labels + expected_condition = " ".join( + ( + f"needs.evaluate.outputs.agent_type == '{agent}' &&", + "needs.evaluate.outputs.dispatch_should_run == 'true' &&", + "(needs.evaluate.outputs.action == 'run' ||", + "needs.evaluate.outputs.action == 'fix' ||", + "needs.evaluate.outputs.action == 'conflict')", + ) + ) + assert " ".join(job["if"].split()) == expected_condition + + section_start = labels.index(f"### `agent:{agent}`") + section_end = labels.index("\n---", section_start) + label_section = labels[section_start:section_end] + assert ( + f"| `agent:{agent}` | Issue or PR labeled | " + f"Routes consumer Gate-followup keepalive to the {display_name} runner" + ) in labels + assert f"Dispatches the `{job_id}` consumer PR keepalive job" in label_section + assert f"dispatches `reusable-{agent}-run.yml`" in label_section assert "applying the label does not trigger a retry by itself" in labels assert "Does not set `force_retry`" in labels assert "agents-keepalive-loop.yml" not in labels From 7535743034a9e267a1c2206b65bf31b691cb8dc5 Mon Sep 17 00:00:00 2001 From: closer-lane Date: Fri, 4 Sep 2026 02:49:42 -0500 Subject: [PATCH 4/4] docs: scope runner dispatch to pull requests --- templates/consumer-repo/docs/LABELS.md | 8 ++++---- tests/docs/test_consumer_ci_system_guide.py | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/templates/consumer-repo/docs/LABELS.md b/templates/consumer-repo/docs/LABELS.md index 55bea5b88..9d1b547eb 100644 --- a/templates/consumer-repo/docs/LABELS.md +++ b/templates/consumer-repo/docs/LABELS.md @@ -140,14 +140,14 @@ This document describes all labels that trigger automated workflows or affect CI **Effect:** 1. Identifies Cursor as the intended route in registry-aware automation -2. Dispatches the `run-cursor` consumer PR keepalive job in `agents-81-gate-followups.yml` +2. On PRs, dispatches the `run-cursor` consumer keepalive job in `agents-81-gate-followups.yml` 3. Branch prefix `cursor/issue-` is reserved for Cursor work (see `.github/agents/registry.yml`) **Prerequisites:** - Repository has a valid `CURSOR_API_KEY` secret (per `.github/agents/registry.yml`) - Issue or PR should have clear requirements -**Workflow:** `agents-81-gate-followups.yml` dispatches `reusable-cursor-run.yml` after registry-backed routing and secret preflight succeed. +**Workflow:** On PRs, `agents-81-gate-followups.yml` dispatches `reusable-cursor-run.yml` after registry-backed routing and secret preflight succeed. --- @@ -159,13 +159,13 @@ This document describes all labels that trigger automated workflows or affect CI **Effect:** 1. Identifies Gemini as the intended route in registry-aware automation -2. Dispatches the `run-gemini` consumer PR keepalive job in `agents-81-gate-followups.yml` +2. On PRs, dispatches the `run-gemini` consumer keepalive job in `agents-81-gate-followups.yml` 3. Branch prefix `gemini/issue-` is reserved for Gemini work **Prerequisites:** - Repository has a valid `GEMINI_API_KEY` secret (per `.github/agents/registry.yml`) -**Workflow:** `agents-81-gate-followups.yml` dispatches `reusable-gemini-run.yml` after registry-backed routing and secret preflight succeed. +**Workflow:** On PRs, `agents-81-gate-followups.yml` dispatches `reusable-gemini-run.yml` after registry-backed routing and secret preflight succeed. --- diff --git a/tests/docs/test_consumer_ci_system_guide.py b/tests/docs/test_consumer_ci_system_guide.py index 546b0c773..8169f74a3 100644 --- a/tests/docs/test_consumer_ci_system_guide.py +++ b/tests/docs/test_consumer_ci_system_guide.py @@ -86,8 +86,10 @@ def test_consumer_operator_docs_match_gate_followup_topology() -> None: f"| `agent:{agent}` | Issue or PR labeled | " f"Routes consumer Gate-followup keepalive to the {display_name} runner" ) in labels - assert f"Dispatches the `{job_id}` consumer PR keepalive job" in label_section - assert f"dispatches `reusable-{agent}-run.yml`" in label_section + assert f"On PRs, dispatches the `{job_id}` consumer keepalive job" in label_section + assert f"On PRs, `agents-81-gate-followups.yml` dispatches `reusable-{agent}-run.yml`" in ( + label_section + ) assert "applying the label does not trigger a retry by itself" in labels assert "Does not set `force_retry`" in labels assert "agents-keepalive-loop.yml" not in labels